本项目是基于启明6M5开发板设计一个门锁系统,通过板载ESP8266网络将验证码发送至云端,用户通过手机上接受到的验证码打开门锁。项目功能演示如下:
一 硬件设计
拓展板原理图:
绘制拓展板时计划使用到液晶屏,摄像头和指纹模块,扬声器等外设,所以绘制PCB时都加上去了,改了两次板后依旧还有些硬件问题没解决,加上软件没调好,目前只能通过使用触摸屏来驱动舵机。图中的GD32f103芯片打算作为摄像头OV7670和液晶屏的中转,由于我使用的OV7670不带缓存,故打算用GD32将16位的图像数据通过8080时序直接传输给LCD,目前还没调通该部分。
二 软件设计
该系统中主要使用到了timer控制舵机完成开门和及时关门的操作,使用RNG寄存器实现得到随机的开锁密码,通过ESP8266传输给手机设备,使用RTC更新当前时间。
(1)ESP8266
该模块使用Arduino软件进行编程,主要功能为获取时间和MQTT协议通讯,具体代码如下:
上下滑动查看完整内容
左右滑动即可查看完整代码
#include#include #include #include #include const char *ssid = "CMCC-416";// const char *password = "12345678";// const char* mqtt_server = "114.55.65.118";//MQTT服务器地址 char msg[200]; int msg_ind=0; WiFiUDP ntpUDP; NTPClient timeClient(ntpUDP, "ntp1.aliyun.com", 60*60*8, 30*60*1000); WiFiClient espClient; PubSubClient client(espClient); void setup(){ Serial.begin(115200); WiFi.begin(ssid, password); while ( WiFi.status() != WL_CONNECTED ) { delay ( 500 ); Serial.print ( "." ); } client.setServer(mqtt_server, 1883);//设置MQTT服务器和端口号 client.setCallback(callback); //设置MQTT回传函数 timeClient.begin(); while (!client.connect("ESP8266Client")) { Serial.print ( "-" ); delay ( 500 ); }//以ESP8266Client身份连接MQTT服务器 Serial.print ("MQTTsuccess" ); client.subscribe("RA6M5/1"); } void callback(char* topic, byte* payload, unsigned int length) { if (strstr((char*)payload,(char*)"askInfo")!=NULL)//从单片机中获取当前信息 { Serial.print("ANDROID_ASKINFO "); } } void loop() { client.loop();//循环调用回传函数,当订阅的主题有新消息时能马上进入callback函数 while(Serial.available()>0)//读取串口 { char recvData = Serial.read(); msg[msg_ind++] = recvData;//逐个字符写入串口接收缓存区 delay(100); if (recvData==' '){ // Serial.print("Time:"); // Serial.print(msg); if (strstr(msg,(char*)"{"))//当串口接受的最后一个字符是' '结尾时,对所有缓存区域进行处理 { if (client.connect("ESP8266Client")) {//以ESP8266Client身份连接MQTT服务器 client.publish("RA6M5/2", msg,msg_ind-1); //将缓存区数据以RA6M5/2主题发布 } msg_ind=0;//刷新串口接收缓存 } else if (strstr(msg,(char*)"GETTIME")){ timeClient.update(); //获取时间戳 //unsigned long epochTime = timeClient.getFormattedTime(); Serial.print("Time:"); Serial.println(timeClient.getEpochTime()); msg_ind=0;//刷新串口接收缓存 } else if (strstr(msg,(char*)"WIFISTATE")){ if ( WiFi.status() == WL_CONNECTED ) { int rss=WiFi.RSSI(); if (rss<=0&&rss>=-50) Serial.println ( "WIFI:3" ); else if (rss<=-50&&rss>=-70) Serial.println ( "WIFI:2" ); else if (rss<=-70&&rss>=-80) Serial.println ( "WIFI:1" ); else if (rss<=-80&&rss>=-100) Serial.println ( "WIFI:0" ); }else{ Serial.println ( "WIFI:No" ); } } } } }
(2)上位机部分
该部分使用Android Studio编写,主要代码如下:
上下滑动查看完整内容
左右滑动即可查看完整代码
public class MainActivity extends AppCompatActivity { private static IntentFilter action; RecyclerView recycler; private final String payloadJson1="{"ParkingState":1}"; final int POST_DEVICE_PROPERTIES_SUCCESS = 1002; final int POST_DEVICE_PROPERTIES_ERROR = 1003; final int UPDATE_UI = 1004; private MqttClient mqttClient=null; private String responseBody = ""; private static final String TAG =MainActivity.class.getSimpleName(); private ArrayListdatas = new ArrayList<>(); private String temper_str="未知"; private String humdity_str="未知"; private String passwd_str="未知"; private dataBean bean = new dataBean(); MyAdapter adapter; private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case POST_DEVICE_PROPERTIES_SUCCESS: showToast("发送数据成功"); break; case POST_DEVICE_PROPERTIES_ERROR: showToast("post数据失败"); break; case UPDATE_UI: SimpleDateFormat formatter = new SimpleDateFormat("yyyy.MM.dd HHss"); Date curDate = new Date(System.currentTimeMillis()); String str_time = formatter.format(curDate); datas.clear(); bean = new dataBean("湿度",humdity_str,str_time,getResources().getDrawable(R.drawable.ic_humdity, null)); datas.add(bean); bean = new dataBean("温度",temper_str,str_time,getResources().getDrawable(R.drawable.ic_temperature, null)); datas.add(bean); bean = new dataBean("验证码",passwd_str,str_time,getResources().getDrawable(R.drawable.ic_temperature, null)); datas.add(bean); adapter.notifyDataSetChanged(); break; } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); recycler = findViewById(R.id.recyclerView); RefreshLayout refreshLayout = (RefreshLayout) findViewById(R.id.refreshLayout); refreshLayout.setRefreshHeader(new ClassicsHeader(this)); refreshLayout.setRefreshFooter(new ClassicsFooter(this)); refreshLayout.setOnRefreshListener(new OnRefreshListener() { @Override public void onRefresh(RefreshLayout refreshlayout) { refreshlayout.finishRefresh(2000/*,false*/);//传入false表示刷新失败 mHandler.postDelayed(() -> postDeviceProperties1(), 1000); } }); refreshLayout.setOnLoadMoreListener(new OnLoadMoreListener() { @Override public void onLoadMore(RefreshLayout refreshlayout) { refreshlayout.finishLoadMore(2000/*,false*/);//传入false表示加载失败 mHandler.postDelayed(() -> postDeviceProperties1(), 1000); } }); new Thread(() -> initMQTTClient()).start(); SimpleDateFormat formatter = new SimpleDateFormat("yyyy.MM.dd HHss"); Date curDate = new Date(System.currentTimeMillis()); String str_time = formatter.format(curDate); bean = new dataBean("湿度",temper_str,str_time,getResources().getDrawable(R.drawable.ic_humdity, null)); datas.add(bean); bean = new dataBean("温度",humdity_str,str_time,getResources().getDrawable(R.drawable.ic_temperature, null)); datas.add(bean); bean = new dataBean("验证码",passwd_str,str_time,getResources().getDrawable(R.drawable.ic_temperature, null)); datas.add(bean); //适配器 adapter = new MyAdapter(this, datas); //布局 LinearLayoutManager manager = new LinearLayoutManager(this); //设置布局 recycler.setLayoutManager(manager); //设置动画 recycler.setItemAnimator(new DefaultItemAnimator()); //设置适配器 recycler.setAdapter(adapter); } private void initMQTTClient() { try { // cn-shanghai String targetServer ="tcp://114.55.65.118:1883"; String mqttclientId = "RA6M5_Android1"; String mqttUsername = "RA6M5_Android_User1"; String mqttPassword = "123456"; connectMqtt(targetServer, mqttclientId, mqttUsername, mqttPassword); } catch (Exception e) { e.printStackTrace(); responseBody = e.getMessage(); mHandler.sendEmptyMessage(POST_DEVICE_PROPERTIES_ERROR); } } public void connectMqtt(String url, String clientId, String mqttUsername, String mqttPassword) throws Exception { MemoryPersistence persistence = new MemoryPersistence(); mqttClient = new MqttClient(url, clientId, persistence); MqttConnectOptions connOpts = new MqttConnectOptions(); // MQTT 3.1.1 connOpts.setMqttVersion(4); connOpts.setAutomaticReconnect(true); connOpts.setCleanSession(true); connOpts.setUserName(mqttUsername); connOpts.setPassword(mqttPassword.toCharArray()); connOpts.setKeepAliveInterval(60); mqttClient.connect(connOpts); mqttClient.setCallback(new MqttCallback() { @Override public void connectionLost(Throwable cause) { Log.e(TAG, "cause ---> " + cause); } @Override public void messageArrived(String topic, MqttMessage message) throws Exception { Log.e(TAG, "topic ---> " + topic + " message--->" + message); if (topic.equals("RA6M5/2")){ String mqtt_str = new String(message.getPayload()); JSONObject json = new JSONObject(mqtt_str); temper_str = json.getString("temper"); humdity_str = json.getString("humdity"); passwd_str = json.getString("passwd"); mHandler.sendEmptyMessage(UPDATE_UI); Log.e(TAG, "update--finish "); } } @Override public void deliveryComplete(IMqttDeliveryToken token) { Log.e(TAG, "token ---> " + token); } }); mqttClient.subscribe("RA6M5/2"); Log.d(TAG, "connected " + url); } private void showToast(String msg) { Toast.makeText(MainActivity.this, msg,Toast.LENGTH_SHORT).show(); } private void postDeviceProperties1() { try { Random random = new Random(); //上报数据 String payload = "askInfo"; responseBody = payload; MqttMessage message = new MqttMessage(payload.getBytes("utf-8")); message.setQos(1); String pubTopic = "RA6M5/1"; mqttClient.publish(pubTopic, message); Log.d(TAG, "publish topic=" + pubTopic + ",payload=" + payload); mHandler.sendEmptyMessage(POST_DEVICE_PROPERTIES_SUCCESS); } catch (Exception e) { e.printStackTrace(); responseBody = e.getMessage(); mHandler.sendEmptyMessage(POST_DEVICE_PROPERTIES_ERROR); Log.e(TAG, "postDeviceProperties error " + e.getMessage(), e); } } }
(3)单片机部分
该部分使用Android Studio编写,主要代码如下:
1、屏幕显示部分
上下滑动查看完整内容
左右滑动即可查看完整代码
void LCD_thread_entry(void * pvParameters) { uint32_t lValueToRece; uint16_t pos_x=0,pos_y=0; EventBits_t Eventbits; BaseType_t err = pdFALSE; unsigned char touch_vals[4]; unsigned char touch_tmp=0; xEventGroupClearBits(g_new_event_LCD,0x7); xEventGroupSetBits(g_new_event_LCD,0x1); FSP_PARAMETER_NOT_USED(pvParameters); R_IOPORT_Open(&g_ioport_ctrl, g_ioport.p_cfg); LCD_Init(); WIFI_Init(); PWM_Init(); R_GPT_Open(&g_timer0_ctrl, &g_timer0_cfg); R_GPT_Start(&g_timer0_ctrl); R_GPT_Disable(&g_timer0_ctrl); LCD_Clean(BLUE);//BLUE Draw_Square_Back(18,180,100,56,BRRED,LIGHTBLUE,array_renlian); Draw_Square_Back(18,240,100,56,BRRED,LIGHTBLUE,array_mima); // LCD_ShowPic(18,180,27,40,gImage_temp,BLUE); // LCD_ShowPic(18,240,27,40,gImage_humdity,BLUE); R_SCI_UART_Write(&g_uart9_wifi_ctrl, (const uint8_t*)"GETTIME ", 8); mbedtls_platform_setup(&ctx); RM_PSA_CRYPTO_TRNG_Read(passwd_Byte+6,6,&passwd_num); /* TODO: add your own code here */ while(1) { Eventbits = xEventGroupGetBits(g_new_event_LCD); if ((Eventbits&0x1)==0x1){//显示时间 //更新wifi数据 wifi_analysis(); DHT11_Read(); err = xQueueReceive(g_touch_queue,&lValueToRece,20); if (err==pdTRUE){ pos_x = lValueToRece>>16; pos_y = lValueToRece & 0xffff; if ((pos_x>18)&&(pos_x<118)) { if ((pos_y>180)&&(pos_y<236)) { taskENTER_CRITICAL(); LCD_Fill(0,0,239,319,WHITE);//BLUE taskEXIT_CRITICAL(); }else if ((pos_y>240)&&(pos_y<316)) { xSemaphoreGive(g_rtc_binSem); xEventGroupClearBits(g_new_event_LCD,0x7); xEventGroupSetBits(g_new_event_LCD,0x4); taskENTER_CRITICAL(); LCD_Fill(0,0,239,319,WHITE);//BLUE LCD_Disp_KeyBoard(); getKeyBoardTRNG(); taskEXIT_CRITICAL(); } } } }else if((Eventbits&0x4)==0x4){ err = xQueueReceive(g_touch_queue,&lValueToRece,20); if (err==pdTRUE){ touch_tmp = LCD_Read_KeyBoard((unsigned short)(lValueToRece>>16),lValueToRece&0xffff); if (touch_tmp==0xff){ minLCD_Key_Loc(); }else if (touch_tmp<10) { if (getLCD_Key_Loc()>0) touch_vals[getLCD_Key_Loc()-1] = touch_tmp; } LCD_Disp_Passwd(touch_vals,getLCD_Key_Loc()); if (getLCD_Key_Loc()==4) { //校验 if ((touch_vals[0]==(passwd_Byte[0]-'0')) &&(touch_vals[1]==(passwd_Byte[1]-'0')) &&(touch_vals[2]==(passwd_Byte[2]-'0')) &&(touch_vals[3]==(passwd_Byte[3]-'0')) ) { lockState=false; R_GPT_Enable(&g_timer0_ctrl); xEventGroupClearBits(g_new_event_LCD,0x7); xEventGroupSetBits(g_new_event_LCD,0x1); taskENTER_CRITICAL(); LCD_Fill(0,0,239,319,BLUE);//BLUE taskEXIT_CRITICAL(); xSemaphoreGive(g_flush_semaphore); R_SCI_UART_Write(&g_uart9_wifi_ctrl, (const uint8_t*)"GETTIME ", 8); } } } } if (lockState){//关着 PWM_Update(5); } else{ PWM_Update(10);//打开 } } } void uart9_wifi_callback(uart_callback_args_t * p_args) { switch(p_args->event) { case UART_EVENT_RX_CHAR: wifi_rece_buff[wifi_rece_len++] = p_args->data&0xff; if (p_args->data==' '){ flag_wifi_rece=true; } break; case UART_EVENT_TX_COMPLETE: break; default: break; } } void lock_timer0_callback(timer_callback_args_t * p_args) { if (TIMER_EVENT_CYCLE_END == p_args->event) { lockState=true; R_GPT_Disable(&g_timer0_ctrl); }
2、触摸部分
上下滑动查看完整内容
左右滑动即可查看完整代码
void Touch_thread_entry(void * pvParameters) { FSP_PARAMETER_NOT_USED(pvParameters); bool Touch_flag_time=true; bsp_io_level_t state; fsp_err_t err = FSP_SUCCESS; /* Open ICU module */ err = R_ICU_ExternalIrqOpen(&g_external_irq4_ctrl, &g_external_irq4_cfg); /* 允许中断 */ err = R_ICU_ExternalIrqEnable(&g_external_irq4_ctrl); /* TODO: add your own code here */ while(1) { if (flag_touch_start){ if (Touch_num==6){ uint32_t lValueToSend; flag_touch_start = false; Touch_coordinate_xsum = Touch_coordinate_xsum-Touch_coordinate_xmax-Touch_coordinate_xmin; Touch_coordinate_xsum >>=2; Touch_coordinate_ysum = Touch_coordinate_ysum-Touch_coordinate_ymax-Touch_coordinate_ymin; Touch_coordinate_ysum >>=2; Touch_corrdinate_pixel(Touch_coordinate_xsum,Touch_coordinate_ysum); lValueToSend = Touch_coordinate_xpix; lValueToSend <<=16; lValueToSend |= Touch_coordinate_ypix; xQueueSendToBack(g_touch_queue,&lValueToSend,100000); Touch_num=0; vTaskDelay(100); }else{ taskENTER_CRITICAL(); //进入基本临界区 touch_curr_x = Touch_Write_CMD(READ_CHANNEL_X); touch_curr_y = Touch_Write_CMD(READ_CHANNEL_Y); taskEXIT_CRITICAL(); if (Touch_num==0) { Touch_coordinate_xmax=touch_curr_x; Touch_coordinate_xmin=touch_curr_x; Touch_coordinate_ymax=touch_curr_y; Touch_coordinate_ymin=touch_curr_y; Touch_coordinate_xsum = touch_curr_x; Touch_coordinate_ysum = touch_curr_y; }else{ Touch_coordinate_average(touch_curr_x,0); Touch_coordinate_average(touch_curr_y,1); } Touch_num++; } }else{ if (Touch_flag_time) R_IOPORT_PinWrite(&g_ioport_ctrl, LCD_SCK, BSP_IO_LEVEL_LOW); else R_IOPORT_PinWrite(&g_ioport_ctrl, LCD_SCK, BSP_IO_LEVEL_HIGH); R_IOPORT_PinRead(&g_ioport_ctrl, LCD_IRQ, &state); if (state==BSP_IO_LEVEL_LOW){ flag_touch_start=true; } vTaskDelay(10); } //退出基本临界区 vTaskDelay(10); // xSemaphoreTake(g_touch_binary_semaphore,portMAX_DELAY); } }
3、RTC部分
上下滑动查看完整内容
左右滑动即可查看完整代码
void RTC_thread_entry(void * pvParameters) { FSP_PARAMETER_NOT_USED(pvParameters); EventBits_t Eventbits; BaseType_t err = pdFALSE; /* TODO: add your own code here */ while(1) { Eventbits = xEventGroupGetBits(g_new_event_LCD); if ((Eventbits&0x1)==0x1)//显示时间 { xSemaphoreTake(g_rtc_binSem,portMAX_DELAY); taskENTER_CRITICAL(); Time_Update(); taskEXIT_CRITICAL(); err = xSemaphoreTake(g_flush_semaphore,20); if (err==pdTRUE) { taskENTER_CRITICAL(); Draw_Square_Back(18,180,100,56,BRRED,LIGHTBLUE,array_renlian); Draw_Square_Back(18,240,100,56,BRRED,LIGHTBLUE,array_mima); taskEXIT_CRITICAL(); } } else{ if (first_Disp){ LCD_Fill(0,131,239,50,WHITE); Draw_Square(10,140,60,50,RED,GREEN,4);//4 Draw_Square(90,140,60,50,RED,GREEN,5);//5 Draw_Square(170,140,60,50,RED,GREEN,6);//6 first_Disp--; } vTaskDelay(1000); } } } void rtc_lcd_callback(rtc_callback_args_t * p_args) { switch (p_args->event) { /*若是周期中断,则更新日期*/ case RTC_EVENT_PERIODIC_IRQ: /*获取当前时间*/ R_RTC_CalendarTimeGet (g_rtc_lcd.p_ctrl, lcd_time); xSemaphoreGiveFromISR(g_rtc_binSem,NULL); break; default: break; } }
三 项目效果图
审核编辑:汤梓红
-
原理图
+关注
关注
1296文章
6326浏览量
233207 -
mcu
+关注
关注
146文章
17040浏览量
350511 -
开发板
+关注
关注
25文章
4979浏览量
97272 -
ESP8266
+关注
关注
50文章
962浏览量
44875 -
智能门锁
+关注
关注
17文章
1850浏览量
43062
原文标题:【瑞萨RA MCU创意氛围赛作品赏析】项目18——智能门锁
文章出处:【微信号:瑞萨MCU小百科,微信公众号:瑞萨MCU小百科】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
相关推荐
评论