小学生
最后登录1970-1-1
在线时间 小时
注册时间2023-8-20
|
本帖最后由 samuraiiisword 于 2023-8-21 22:28 编辑
一、背景
本项目主要设计一个门锁系统,通过板载ESP8266网络将验证码发送至云端,用户通过手机上接受到的验证码打开门锁。
二、设计
(一)硬件设计
绘制拓展板时计划使用到液晶屏,摄像头和指纹模块,扬声器等外设,所以绘制PCB时都加上去了,改了两次板后依旧还有些硬件问题没解决,加上软件没调好,目前只能通过使用触摸屏来驱动舵机。图中的GD32f103芯片打算作为摄像头OV7670和液晶屏的中转,由于我使用的OV7670不带缓存,故打算用GD32将16位的图像数据通过8080时序直接传输给LCD,目前还没调通该部分。
(二)软件设计
该系统中主要使用到了timer控制舵机完成开门和及时关门的操作,使用RNG寄存器实现得到随机的开锁密码,通过ESP8266传输给手机设备,使用RTC更新当前时间。
三、实现
(一)ESP8266
该模块使用Arduino软件进行编程,主要功能为获取时间和MQTT协议通讯,具体代码如下:
- #include <NTPClient.h>
- #include <PubSubClient.h>
- #include <ESP8266WiFi.h>
- #include <WiFiUdp.h>
- #include <String.h>
- 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\n");
- }
- }
- void loop() {
- client.loop();//循环调用回传函数,当订阅的主题有新消息时能马上进入callback函数
- while(Serial.available()>0)//读取串口
- {
- char recvData = Serial.read();
- msg[msg_ind++] = recvData;//逐个字符写入串口接收缓存区
- delay(100);
- if (recvData=='\n'){
- // Serial.print("Time:");
- // Serial.print(msg);
- if (strstr(msg,(char*)"{"))//当串口接受的最后一个字符是'\n'结尾时,对所有缓存区域进行处理
- {
- 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" );
- }
- }
- }
- }
- }
复制代码 (二)上位机部分
该部分使用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 ArrayList<dataBean> datas = 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\nHH:mm:ss");
- 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\nHH:mm:ss");
- 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);
- }
- }
- }
复制代码
(三)单片机部分
该部分使用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\n", 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\n", 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=='\n'){
- 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;
- }
- }
复制代码
四、运行
|
-
拓展板原理图
-
寄存器配置
-
密码输入界面
-
主界面
-
APP界面
|