基于STM32+SIM800C+华为云IoT设计的森林火灾预警系统(联动控制)
493
2022-05-29
1. 前言
随着人们生活水平的提高及科学技术的发展,个人信息保护显得至关重要,设计了一款物联网智能电子密码锁,以STM32单片机为主控制器,由触摸矩阵键盘、ESP8266、步进电机等模块组成,具有远程控制、随机密码生成等功能。经软硬件测试,系统响应迅速,灵敏度高,实时性好,系统识别准确率高达99%,该系统运行稳定,安全可靠,功耗低及具有较好的扩展性。
当前支持的开锁方式:
(1)支持手机APP远程开锁。通过华为云物联网平台实现远程发送指令开锁,设备上的ESP8266通过连接家里路由器,在连接华为云物联网平台,可以在手机APP上对设备端的RTC时间进行校准,设备唯一ID获取,生成随机开锁密码,可以点击APP上的开锁按钮,通过物联网平台提供的API发送指令给STM32设备完成开锁。
(2)随机密码开锁。手机APP与本地设备都采用时间、作为算法种子,采用算法生成开锁密码,每一串的密码有效时间为一分钟。查看手机APP上显示的密码之后,在本地设备上输入完成密码对比开锁。
2. 相关硬件
2.1 WIFI模块
2.2 步进电机模块
2.3 OLED显示屏
2.4 STM32开发板
2.5 矩阵键盘模块
3. 手机APP设计
3.1 开发环境介绍
上位机软件采用Qt框架设计,Qt是一个跨平台的C++图形用户界面应用程序框架。Qt是一个1991年由Qt Company开发的跨平台C++图形用户界面应用程序开发框架。它既可以开发GUI程序,也可用于开发非GUI程序,比如控制台工具和服务器。简单来说,QT可以很轻松的帮你做带界面的软件,甚至不需要你投入很大精力。
QT官网: https://www.qt.io/
3.2 学习教程
QT入门实战专栏: https://blog.csdn.net/xiaolong1126626497/category_11400392.html
QT5环境安装教程:https://xiaolong.blog.csdn.net/article/details/120654599
下载QT5.12.6-:
https://download.qt.io/archive/qt/5.12/5.12.6/
打开链接后选择:
qt-opensource-windows-x86-5.12.6.exe 13-Nov-2019 07:28 3.7G Details
软件安装时断网安装,否则会提示输入账户。
** 安装的时候,勾选一个mingw 32编译器即可。**
3.3 实现效果
4. 创建云端设备
4.1 创建设备
登录官网: https://www.huaweicloud.com/
直接搜索物联网,打开页面。
https://www.huaweicloud.com/product/iothub.html
选择设备接入:
选择免费试用:
在产品页面,点击右上角创建产品:
填上产品信息:
得到产品ID,保存好ID,点击查看详情:
产品ID为:61b9ba3a2b2aa20288c1e7f1.
点击设备页面,注册设备:
填充信息进行注册:
保存设备密匙和设备ID,点击保存关闭会自动下载文件保存,后面生成密码和登录账号需要使用
关闭后就看到创建好的设备了:
点击产品页面,选择刚才创建的产品:
选择自定义模型—创建数据模型服务:
选择新增属性,创建设备的属性
4.2 创建MQTT登录账号和密匙
设备创建完成接来下生成MQTT登录账号、密匙,方便设备登录云端平台。
官网工具地址: https://iot-tool.obs-website.cn-north-4.myhuaweicloud.com/
打开刚才创建设备时,下载的密匙文件,把内容复制出来对应的填进去,生成即可。
4.3 拼接主题订阅与发布的格式
官方文档介绍: https://support.huaweicloud.com/devg-iothub/iot_01_2127.html
在产品页面可以,看到主题的全部格式:
帮助文档:https://support.huaweicloud.com/iothub/index.html
总结的格式如下:
格式: $oc/devices/{device_id}/sys/messages/down //订阅主题: 平台下发消息给设备 $oc/devices/61b9ba3a2b2aa20288c1e7f1_QQ1126626497_0_0_2021121510/sys/messages/down 格式: $oc/devices/{device_id}/sys/properties/report //设备上报数据 $oc/devices/61b9ba3a2b2aa20288c1e7f1_QQ1126626497_0_0_2021121510/sys/properties/report 上属性的数据格式: //上报的属性消息 (一次可以上报多个属性,在json里增加就行了) {"services": [{"service_id": "lock","properties":{"门锁":1}}]}
上面属性里的服务ID和属性里的名称,在设备页面,影子设备页面查看。
4.4 MQTT客户端模拟设备登录云端
下面使用MQTT客户端模拟设备登录服务器测试,看设备创建的是否OK。
服务器的IP地址是: 121.36.42.100
端口号是: 1883
打开MQTT客户端软件,按照提示,输入相关参数后,点击连接,然后再点击订阅主题,发布主题即可:
查看云端服务器的情况: 可以看到设备已经在线了,并且收到上传的数据。
修改一下锁的状态,上报属性再查看:
发现云端的状态也已经改变,现在设备上报已经OK。
接下来测试命令下发,实现远程开锁关锁的功能:
打开产品页面,新增加命令:
命令添加成功:
在设备页面,选择同步命令下发:
点击确定后,查看MQTT客户端,发现已经收到数据了:
$oc/devices/61b9ba3a2b2aa20288c1e7f1_QQ1126626497/sys/commands/request_id=88e2626f-290d-405e-962d-51554445a8fd{"paras":{"lock":1},"service_id":"lock","command_name":"lock"}
设备端解析收到的数据,就可以完成多步进电机的控制,完成开锁关锁。
5. STM32设备端代码设计
5.1 硬件相关原理图
5.2 程序下载配置
5.3 硬件接线
1. 板载ESP8266串口WIFI模块与STM32的串口3相连接。 PB10--RXD 模块接收脚 PB11--TXD 模块发送脚 PB8---CH-PD---悬空 PB9---RST---悬空 GND---GND 地 VCC---VCC 电源(3.3V~5.0V) 2. 触摸按键使用TTP229型号的驱动芯片 SCL接PC11 SDA-OUT接PC10 电源接VCC-3.3 GND接GND 3. ULN2003控制28BYJ-48步进电机接线: ULN2003接线: IN4: PC9 d IN3: PC8 c IN2: PC7 b IN1: PC6 a + : 5V - : GND 4. OLED显示屏 D0----SCK-----PB14 D1----MOSI----PB13 RES—复位(低电平有效)—PB12 DC---数据和命令控制管脚—PB1 CS---片选引脚-----PA7 5. 板载按键 KEY1---PA0 KEY2---PC13 6.板载LED灯 LED1---PB5 LED2---PB0 LED3---PB1 7. 板载蜂鸣器 BEEP---PA8
5.4 服务器连接核心代码
//华为物联网服务器的设备信息 #define MQTT_ClientID "61b9ba3a2b2aa20288c1e7f1_QQ1126626497_0_0_2021121510" #define MQTT_UserName "61b9ba3a2b2aa20288c1e7f1_QQ1126626497" #define MQTT_PassWord "385ce91dfe7da5b7431868d5d87e7998163c493344040935d5a00024d6324242" //订阅与发布的主题 #define SET_TOPIC "$oc/devices/61b9ba3a2b2aa20288c1e7f1_QQ1126626497_0_0_2021121510/sys/messages/down" //订阅 #define POST_TOPIC "$oc/devices/61b9ba3a2b2aa20288c1e7f1_QQ1126626497_0_0_2021121510/sys/properties/report" //发布 char mqtt_message[200];//上报数据缓存区 int main() { u32 time_cnt=0; u32 i; u8 key; LED_Init(); BEEP_Init(); KEY_Init(); USART1_Init(115200); TIMER1_Init(72,20000); //超时时间20ms USART2_Init(9600);//串口-蓝牙 TIMER2_Init(72,20000); //超时时间20ms USART3_Init(115200);//串口-WIFI TIMER3_Init(72,20000); //超时时间20ms USART1_Printf("正在初始化WIFI请稍等.\n"); if(ESP8266_Init()) { USART1_Printf("ESP8266硬件检测错误.\n"); } else { //非加密端口 USART1_Printf("WIFI:%d\n",ESP8266_STA_TCP_Client_Mode("CMCC-Cqvn","99pu58cb","121.36.42.100",1883,1)); } //2. MQTT协议初始化 MQTT_Init(); //3. 连接华为服务器 while(MQTT_Connect(MQTT_ClientID,MQTT_UserName,MQTT_PassWord)) { USART1_Printf("服务器连接失败,正在重试...\n"); delay_ms(500); } USART1_Printf("服务器连接成功.\n"); //3. 订阅主题 if(MQTT_SubscribeTopic(SET_TOPIC,0,1)) { USART1_Printf("主题订阅失败.\n"); } else { USART1_Printf("主题订阅成功.\n"); } .................. .................. ................... }
5.5 随机密码生成
#include
5.6 RTC实时时钟代码
#include "rtc.h" //定义RTC标准结构体 struct RTC_CLOCK rtc_clock; /* 函数功能: RTC初始化函数 */ void RTC_Init(void) { if(BKP->DR1!=0xAB) //表示RTC第一次初始化 { //1. 备份寄存器时钟 RCC->APB1ENR|=1<<27; //备份时钟接口 RCC->APB1ENR|=1<<28; //电源时钟接口 PWR->CR|=1<<8; //允许写入RTC和后备寄存器 //2. 配置RTC时钟源 RCC->BDCR|=1<<0; //开启外部32.768K时钟 while(!(RCC->BDCR&1<<1)){} //等待时钟就绪 RCC->BDCR&=~(0x3<<8); //清空时钟配置 RCC->BDCR|=0x1<<8; //选择外部32.768K时钟 //3. 配置RTC核心寄存器 RCC->BDCR|=1<<15; //开启RTC时钟 while(!(RTC->CRL&1<<5)){} //判断上一次寄存器是否写完成 RTC->CRL|=1<<4; //进入配置模式 RTC->PRLH=0; //预分频高位 RTC->PRLL=0x7FFF; //32767 预分频低位 RTC->CNTH=0; //计数器高位 RTC->CNTL=0; //计数器低位 RTC->ALRH=0; //闹钟寄存器高位 RTC->ALRL=60; //闹钟寄存器低位 RTC->CRL&=~(1<<4);//退出配置模式 while(!(RTC->CRL&1<<5)){} //判断上一次寄存器是否写完成 BKP->DR1=0xAB; //表示配置成功了 } RTC->CRH|=1<<0; //秒中断 RTC->CRH|=1<<1; //闹钟中断 STM32_SetPriority(RTC_IRQn,2,2); //优先级 RTC_SetTime(2022,4,9,0,36,1); } extern void Update_FrameShow(void); /* 函数功能: RTC闹钟中断服务函数 */ void RTC_IRQHandler(void) { u32 SecCnt; if(RTC->CRL&1<<0) { SecCnt=RTC->CNTH<<16;//获取高位 SecCnt|=RTC->CNTL; //获取低位 RTC_GetTime(SecCnt); //转换标准时间 RTC_GetWeek(SecCnt); // printf("%d-%d-%d %d:%d:%d week:%d\n",rtc_clock.year,rtc_clock.mon,rtc_clock.day,rtc_clock.hour,rtc_clock.min,rtc_clock.sec,rtc_clock.week); Update_FrameShow(); //更新显示 RTC->CRL&=~(1<<0); //清除秒中断标志位 } if(RTC->CRL&1<<1) { // printf("闹钟时间到达!....\n"); // BEEP=1; // DelayMs(500); // BEEP=0; RTC->CRL&=~(1<<1); //清除闹钟中断标志位 } } //闰年的月份 static int mon_r[12]={31,29,31,30,31,30,31,31,30,31,30,31}; //平年的月份 static int mon_p[12]={31,28,31,30,31,30,31,31,30,31,30,31}; /* 函数功能: 设置RTC时间 函数形参: u32 year; 2018 u32 mon; 8 u32 day; u32 hour; u32 min; u32 sec; */ void RTC_SetTime(u32 year,u32 mon,u32 day,u32 hour,u32 min,u32 sec) { u32 i; u32 SecCnt=0; //总秒数 /*1. 累加已经过去的年份*/ for(i=2017;i
云端实践 IoT Qt
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。