基于启明6M5开发板的智能门锁设计

描述

本项目是基于启明6M5开发板设计一个门锁系统,通过板载ESP8266网络将验证码发送至云端,用户通过手机上接受到的验证码打开门锁。项目功能演示如下:

一   硬件设计

拓展板原理图:

mcu

绘制拓展板时计划使用到液晶屏,摄像头和指纹模块,扬声器等外设,所以绘制PCB时都加上去了,改了两次板后依旧还有些硬件问题没解决,加上软件没调好,目前只能通过使用触摸屏来驱动舵机。图中的GD32f103芯片打算作为摄像头OV7670和液晶屏的中转,由于我使用的OV7670不带缓存,故打算用GD32将16位的图像数据通过8080时序直接传输给LCD,目前还没调通该部分。

二   软件设计

该系统中主要使用到了timer控制舵机完成开门和及时关门的操作,使用RNG寄存器实现得到随机的开锁密码,通过ESP8266传输给手机设备,使用RTC更新当前时间。

mcu

(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 ArrayList 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
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;
          }
}

 

三   项目效果图

mcu

mcu

mcu

审核编辑:汤梓红

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分