位置: IT常识 - 正文
推荐整理分享基于STM32F103C8T6与ESP8266的物联网智能温度采集与蓝牙OLED数字钟的设计与实现(基于stm32f103c8t6的毕业设计),希望有所帮助,仅作参考,欢迎阅读内容。
文章相关热门搜索词:基于stm32f103c8t6的自动关闭,基于stm32f103r6的电子密码锁设计,基于stm32f103c8t6的毕业设计,基于stm32f103c8t6的esp8266,基于stm32f103c8t6的自动关闭,基于stm32f103c8t6的自动关闭,基于stm32f103c8t6的毕业设计,基于stm32f103c8t6的环境监测原理图,内容如对您有帮助,希望把文章链接给更多的朋友!
作者: 颜孙炜
文章目录基于STM32F103C8T6与ESP8266的物联网智能温度采集与蓝牙OLED**数字钟的设计与实现**概述项目需求**开发环境**[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B7FerB5H-1673843611067)(概述 {#概述-1}.assets/image-20230110223740107.png)]主控芯片传感层搭建通信部分**软件框架****功能开发**主函数设计万年历设计显示时间功能配置:软件开发:2.12/24小时转换功能配置:扫描:时制转化:电压检测:配置:ADC转化:波形绘制:**温度检测:**测温电路:ADC转温度:跳跃游戏思路:任务图形的绘制与取模:游戏逻辑控制:蓝牙时间修改:APP端:APP组件开发:APP逻辑功能如下:配置:软件开发:联网显示:WED端开发:数据库的设计接口的设计WEB端前端页面的开发ESP8266的开发:主控芯片的开发:主控芯片串口的配置:软件开发:****调试部分蓝牙通信的调试WIFI通信的调试主控与8266通信的调试:ESP8266与WEB之间的调试:****项目的部署其余硬件设计****部分软件模块说明演示效果**异常处理**Web客户端崩溃WEB显示中出现异常值OLED绘制移动图形显示时出现闪烁**不足**温度值偶尔会偏高或偏低单片机资源利用率低通信时会出现乱码**视频地址****代码地址****网站地址****感悟****感悟**概述[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wC12xZrc-1673843611066)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20230110223524043.png)]
用STM32F103C8T6自有的RTC功能实现一款数字钟的设计,包括温度输入检测和显示模块、数字钟显示模块、定时提醒模块等。完成了,万年历,计时器,温度检测,电压监测等功能,此外随着科技的进步,物联网技术获得了飞速的发展,其已渗透到当前的多个行业领域。而温度作为我们生活中非常重要的一个环境参数,其变化情况会给我们的生产生活造成关键性的影响,这就要求我们必须做好温度的实时监测,本产品在完善其他功能的前提下,通过STM32监测温度并通过物联网系统储存温度检测的数据,并加以计算和显示在网页上。
项目需求此项目旨在开发一款,集万年历,温度检测,数字显示,且较为智能的产品
故罗列出以下开发需求
具有12/24小时切换的万年历
通过蓝牙及手机APP进行时间的设置
具有温度检测的功能
数据可以在云端储存和查看
开发环境硬件:STM32F103C8T6,ESP8266,BT04-E蓝牙模块
服务器:华为云
WEB:FLASK框架
数据库:SQLITE3
开发工具及版本:KEIL 5,ARDUINOIDE,VSCODE,STM32CUBEMX
调试工具:SSCOM5.13.1,APIPOST-POSTMAN
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B7FerB5H-1673843611067)(概述 {#概述-1}.assets/image-20230110223740107.png)]主控芯片本项目采用的芯片为 STM32F103C8T6 STM32F103C8T6是一款基于ARM CORTEX-M 内核STM32系列的32位的微控制器,程序存储器容量是64KB,需要电压2V~3.6V,工作温度为-40°C ~ 85°C。本项目使用 HAL 库编写,在芯片的资源利用上,采用了 IO 高低电平输出控 ISP驱动OLED,串口 3 将数据发送至WIFI 模块通信。通用定时器TIM2用于定时中断,设置高速外部时钟HSE 选择外部时钟源。定时器的时钟频率为16MHZPRTSCALER (定时器分频系数)16COUNTER MODE(计数模式)UP(向上计数模式)COUNTER PERIOD(自动重装载值)1000CKD(时钟分频因子)NO DIVISION 不分频 定时器溢出时间: TOUT = (16*1000)/16/1000/1000=0.5S
传感层搭建温度作为我们生活中非常重要的一个环境参数, 其变化情况会给我们的生产生活造成关键性的影响, 这就要求我们必须做好温度的实时监测。热敏电阻是一种传感器电阻,其电阻值随着温度的变化而改变。按照温度系数不同分为正温度系数热敏电阻(ptc thermistor,即 positive temperature coefficient thermistor)和负温度系数热敏电阻(ntc thermistor,即 negative temperature coefficient thermistor)。正温度系数热敏电阻器的电阻值随温度的升高而增大,负温度系数热敏电阻器的电阻值随温度的升高而减小,它们同属于半导体器件。本项目温度检测采用10K热敏电阻,通过ADC1通道1(PA1)进行转换变为具体数值。
通信部分WIFI通信部分采用 ESP8266 ,ESP8266 是一款适用于物联网和家庭自动化项目的 WI-FI 模块。本项目将主控芯片STM32获取的数据处理后通过串口3发送至ESP8266,ESP8266再将数据通过WIFI发送至云端。同时为了减少遗漏,防止数据丢包漏包,ESP8266接收数据的间隔需要得到控制,使得数据完整被发送至云端。蓝牙通信选择BT04-E蓝牙模块,BT04-E蓝牙模块可通过与单片机的串口相连,借助电脑或手机的蓝牙与单片机实现异步全双工通信。此项目中我们采用该蓝牙模块将APP与主控芯片进行数据的传输。从而实现手机端对设备的控制
软件框架[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gPOdeKef-1673843611068)(概述 {#概述-1}.assets/image-20230110223755155.png)]
功能开发主函数设计整体框架采用循环加switch函数,每当设备运行的时候,程序进入主函数先进行所有功能以及变量的初始化,然后进入while循环,并且进入switch函数,并在中断中执行按键的检测,用于控制进入switch函数的各个分支。Switch各分支实现不同的功能,如果在进入switch函数时刷新界面,则会造成屏幕的闪烁,本项目采用在中断检测按键触发时刷新屏幕,当按键按下切换功能时,进行屏幕的刷新,使屏幕显示更加稳定。
万年历设计显示时间功能为了使oled上能显示时间并时刻更新,我们采用RTC时钟进行该功能的开发,实时时钟芯片是日常生活中应用最为广泛的消费类电子产品之一。它为人们提供精确的实时时间,或者为电子系统提供精确的时间基准。在设置好RTC后RTC每次中断都会产生一组新的时间数据供开发者使用,初始化系统时钟RTC时钟第一次设置RTC(查询标记)配置RTC(产生秒中断)设置当前时间(年/月/日/小时/分/秒)以此作为RTC计数器的初值计算并显示时间秒中断循环,该功能较为简单,只需简单的配置加显示即可,配置及显示方案如下:
配置:在CUBEMX中将时钟源RCC设为外部中断
在RTC时钟中打开ACTIVATE CLOCK SOURCE以及ACTIVATE CALENDAR,同时打开中断
对于初始时间可以不进行设置,后续使用蓝牙进行设置。
软件开发:在配置完环境后在主函数中添加HAL_RTC_GETTIME,HAL_RTC_GETDATE函数,该函数可以在每次中断时更新GETTIME与GETDATE的值,在后续代码中,通过"."访问HOURS,MONTH等储存时间的变量。
为了实现万年历的时钟功能,只需要以"时:分"格式将数据显示在OLED屏上即可。主要代码如下:
OLED_ShowNum(0, 20, GetTime.Hours, 2, 16);OLED_ShowString(16, 20, (unsigned char *)":", 16);OLED_ShowNum(20, 20, GetTime.Minutes, 2, 16);OLDE显示时间X:Y
2.12/24小时转换功能为了使产品与用户之间产生良好的人机交互,对于时钟类产品,满足各类用户的需求,应当具有转换12/24小时制的功能,其原理是按键检测,当检测到按键按下,运行12/24转换函数,显示转换后的时间如13:02转换后为1:02,该功能需要对按键进行配置与扫描,然后对时制进行转化,方案如下:
配置:在CUBEMX中将按键设置为GPIO_INPUT,作为输入。
扫描:在该功能中,需要实现按键按下切换为12小时制,抬起切换为24小时制。仅用独立按键就可以实现.由于按键按下会产生抖动,可以使用DELAY进行消抖。
按键检测代码如下:
if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_8) == GPIO_PIN_RESET) {HAL_Delay():if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_8) == GPIO_PIN_RESET) {}}时制转化:先判断输入的24小时制是属于AM时间段的还是PM时间段的。
如果是AM,就不用改变小时的数据;如果是PM的,就需要换算小时的数据
换算小时时仅需将24小时制减去12即为12小时制时间。此外24点需要额外进行考虑,在英文的习惯中,中午12点被认为是下午,所以24小时制的12:00就是12小时制的12:0 PM;而0点被认为是第二天的时间,所以是0:0 AM
只需要将转化后的变量代替原来的GETTIME.HOUR即可实现12/24小时的转化。
电压检测:为了利用ADC资源以及为后续的温度采集功能做出铺垫,并且能观测到电压变化的趋势,项目中使用ADC对电压进行采集,并且将电压值处理为可观测的坐标形式设计了以下功能,PA1输入电压,STM32内部AD进行转换,通过函数计算为电压值,并显示在OLED屏上,将AD转换的数值进行处理为OLED Y轴坐标,X轴为时间,即可模拟出电压变化的波形。该功能需对ADC进行配置,软件得到ADC值后转为电压在OLED上显示,并通过对ADC值的处理进行波形的绘制,方案如下:
配置:在CUBEMX中将时钟源RCC设为外部中断
打开ADC设置,本项目中打开的是ADC1的通道1。
ADC的其他配置默认即可。
最后还需设置HCLK,本项目设置的HCLK为16MHZ。
ADC转化:首先以中断方式启动ADC。在程序中通过ADC_VALUE = HAL_ADC_GETVALUE(&HADC1)获取AD值。其次确定基准电压,本项目中使用的主控芯片ADC的基准电压为3.3V,所以可以通过ADC_VALUE * 3.3 / 4095计算出电压值并提供OLED加以显示。
波形绘制:在波形绘制中,以X为时间轴,以Y为数据轴,但发现ADC值值过大,超过了OLED屏幕的尺寸,因此成像成为问题,想到ADC转化为电压值的方案,计划对ADC的值进行缩小。尝试对ADC值统一减小,产生如下图像
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OPdJ4Ca1-1673843611070)(概述 {#概述-1}.assets/image-20230110224151834.png)]
发现无法行成波形,原因是ADC值的个位与十位快速变化,因此对ADC数据进行35 + (ADC_VALUE - 1280) / 10处理,使ADC始终处于屏幕中线上下摆动,在电压值不发生大改变的情况下,可以观察到屏幕上随电压值改变产生曲线。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x9V1HExG-1673843611070)(概述 {#概述-1}.assets/image-20230110224203739.png)]
温度检测:搭建测温电路,测量10K热敏电阻的电压,通过公式T(℃)={(VN-VSENSE)/AVG_SLOPE}+N计算出温度,为了防止温度时刻变化,每一秒采集一次AD值并进行转换。在此功能中涉及传感电路的搭建,ADC的配置与上一个功能相同,不需要重复配置,但需要ADC值转为温度。
测温电路:PA1为ADC1通道1引脚,本项目R1采用10KNTC热敏电阻,电路如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oVMjXia8-1673843611071)(概述 {#概述-1}.assets/image-20230110224230011.png)]
ADC转温度:通过公式T(℃)={(VN-VSENSE)/VSENSE}+N进行转化
这里:V N = V SENSE 在N °C时的数值AVG_SLOPE = 温度与V SENSE 曲线的平均斜率(单位为MV/ °C 或 ΜV/ °C)N,VSENSE,VSENSE的典型值分别为25,1.43, 4.3MV/℃
只需将ADC值通过公式转化后显示在OLED上即可完成温度检测的功能。
跳跃游戏思路:为了利用按键资源和熟悉oled屏幕的开发,项目中开发了一个模仿谷歌恐龙的跳跃游戏,其原理是,BMP1,BMP2储存游戏人物跳跃和落下的两种状态图片,用画直线和画方块函数绘制障碍,并定时刷新屏幕避免重影。设置两个变量,模拟障碍和人物坐标,当坐标相碰切任务处于落下状态时,游戏结束,蜂鸣器响,OLED显示"GAME OVER",具体方案如下:
任务图形的绘制与取模:这里我们使用PCTOLCD2002进行取模,图形的平移较为复杂,为了简单模拟跳起和落下两种状态,我们对两种状态的分别作图,分别进行显示。
当绘制完第一幅图后,为了不改变像素点间的位置,仅改变高度时,可以点击PCTOLCD2002上的上移按钮,上升合适的高度,得到第二幅图形
障碍的绘制:
障碍与人物图形不同,每一刻都在移动,即每一帧的障碍都是截然不同的,显然一帧一帧的绘制不仅麻烦,而且占用大量的单片机储存资源。因此,这里使用两种方法绘制障碍,一是通过坐标绘制线条,改变坐标改变每一帧的图形,二是通过平移图像来实现障碍的移动。本项目中采用的是第二种方法,我们需要获得四个点的坐标,并以此点为左上角点绘制正方形表示障碍,通过中断改变起始点的坐标,实现正方形的移动即障碍的移动,这里需要注意的是如何使障碍可以无限的循环下去,使障碍可以无限的循环下去需要对坐标进行计算
我们将两个屏幕进行拼接,一个屏幕长度为128,两个长度为128*2=256
如图为了使障碍可以衔接,屏幕最前方后最后方应当各存在半个空白。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vnEwlhRw-1673843611072)(概述 {#概述-1}.assets/image-20230110224322880.png)]
设需要3个障碍列出方程
5X+X/2*2=128
X=21.3
故得到障碍的初始坐标
游戏逻辑控制:虽然在屏幕是小人是静止的,但对于障碍来说小人是相对运动的,那么设置一个变量代表小人的运动轨迹,由于障碍的坐标不是随机的而是我们事先计算好的,所以我们可以判断小人坐标是否达到我们设置的障碍的坐标,如果相等,则代表小人与障碍在X方向上相遇,同时判断在Y方向上小人是否跳起,若小人没有跳起,则判断小人与障碍在X与Y方向上同时相遇,对于二维平面,可以以此判定小人与障碍相撞。则游戏结束。
这里给出功能代码如下:
OLED_DrawSquare((0 + start_point_x) % 127, 50, (10 + start_point_x) % 127, 60);OLED_DrawSquare((50 + start_point_x) % 127, 50, (60 + start_point_x) % 127, 60);OLED_DrawSquare((100 + start_point_x) % 127, 50, (110 + start_point_x) % 127, 60);if (jump_mark == 0) {OLED_ShowPicture(0, 0, 128, 8, BMP4);} else {OLED_ShowPicture(0, 0, 128, 8, BMP5);n++;if (n > 30) {jump_mark = 0;n = 0;}}speed++;if (speed > 5) {start_point_x = start_point_x + 2;speed = 0;OLED_Clear();}if (start_point_x == 128) {start_point_x = 0;}if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_8) == GPIO_PIN_RESET) {jump_mark = 1;}if (jump_mark == 0 && start_point_x % 65 == 0) {flag = 4;}蓝牙时间修改:在日常生活中发现对于传统的电子时钟,时间的校验和设置比较复杂和烦琐,因此本项目采用蓝牙对时间进行校验和设置,用户只需要切换到时间设置模式,并在app上连接蓝牙,即可对当前时间进行设置,开启串口2,按下KEY2与KEY3进入修改时间模式,在手机端APP上设置需要修改的时间,点击确定,OLED上显示修改后的时间,并继续计时。修改后的时间支持12/24转化。该功能分为APP端的开发和主控芯片软件的开发,方案如下:
APP端:APP端分为界面组件的开发,以及功能逻辑的开发
APP组件开发:APP做使用的组件及功能如下表:
组件名称功能列表选择框选择蓝牙标签提示时间选择框获取时间,选择时间按钮提交数字滑动条数据选择蓝牙客户端提供蓝牙通信服务计时器计时APP逻辑功能如下:1.蓝牙连接:
当列表选择框准备选择时,执行设列表选择框的文本为蓝牙客户端的地址及名称,当列表选择框完成选择时执行设蓝牙客户瑞连接设备 地址为列表选择框的选中项。
当用户点击列表框就会显示蓝牙的列表,选择BT04-E蓝牙模块的蓝牙进行后APP会自动连接蓝牙。
时间设置当时间选择框完成时间设定时执行
设时间选择框显示时间选择框的"时"+":“加"分”。
当用户点击时间选择按钮后会弹出时间选择器,当用户完成选择后,时间选择框的文本会变成选中的时间,供用户加以确定
数据的发送当按钮被按下时,蓝牙客户端发送数据,特别注意的是,数据的格式为时加分,
由于在后续的蓝牙与主控芯片的开发中,对串口的进行了重定向,所以要在数据的末尾加上空格,并且由于是HAL库进行开发,串口接收的数据为字符,发送的数据应当文字符串,所以完整的数据格式应为,时加分加空格,型如"1325 ","0108 "。
配置:蓝牙模块与主控芯片之间采用串口进行通信,首先连接好串口与主控芯片,连接方式如下表
STM32F103BT04-E蓝牙模块RXTXTXRX5V5VGNDGND连接完成后开始串口的配置,本项目蓝牙通信采用UART2即串口2进行通信。
启动串口2,将串口2的模式改为ASYNCHRONOUS,CUBEMX串口波特率默认为115200,但在与BT04-E蓝牙模块进行时,波特率需选择9600。
软件开发:通过串口接收蓝牙从APP上获取的数据,处理后作为变量添加到RTC初始化函数中,通过RTC的初始化进行时间的重新设置。
HAL库中可以使用HAL_UART_TRANSMIT与HAL_UART_RECEIVE进行数据的收发,但HAL_UART_TRANSMIT与HAL_UART_RECEIVE接收变量的参数为UINT8_T数组,UINT8_T为无符号1个字节的整型,不能接收字节和数值,UINT8_T类似CHAR但不同,因此我们在这里利用FPUTS和FGETS的重定向对将参数类型改为CHAR数组接收字符串,那么数组中的每一个元素都是常见的CHAR变量。
对于如"1,2,3,4…“的CHAR类型我们通过格式化输出(”%D",X[N])将其转变为ASCII码,可以发现对于如"1,2,3,4…"的CHAR类型ASCLL码-48就是其代表的数值,我们从APP中收到的字符串以"XYZW "储存在CHAR类型数组中,我们按个十位取出并重新计算为一个数值
如((“%D”,X[0])-48)*10+(“%D”,X[1])-48)代表XY所代表的数值
我们通过上述方法分别取得时和分的值,但在RTC初始化函数中,STIME所接收的变量类型为16进制数,因此我们还需要将所得的10进制数转为16进制数,才能被RCT初始化函数正确的接收。
按照以下的流程,我们就实现了通过蓝牙连接从而快速设置时间的功能
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l51138G3-1673843611072)(概述 {#概述-1}.assets/image-20230110224605913.png)]
联网显示:在上文中通过绘制电压温度的波形,可以观察到短时间内电压及温度变化的状态,那能否使数据更长久的进行储存和利用成为该功能的出发点,为了良好利用数据及储存数据,项目中使用ESP8266模块对数据进行上上传,并提供数据库对数据进行保存,通过web前后端对数据进行处理和显示,思路如下:开启串口3,为了不给服务器造成过大压力,在定时器中每隔15S秒发送一次数据到ESP8266,再由ESP8266将数据拼接到GET请求中,后端程序获取GET请求参数,并添加到数据库中,客户端页面显示将调用数据库中的信息并显示在设计好的页面上。此功能需要进行WEB端的开发,ESP8266的开发,以及主控芯片的开发。
WED端开发:WEB开发分为三个部分前端开发用于显示数据,后端开发负责数据库的连接操作,和数据的处理,接口开发用于给ESP8266提供通信的通道。
后端和接口的开发我们使用FLASK框架进行开发,FLASK是一个使用 PYTHON 编写的轻量级 WEB 应用框架。其 WSGI 工具箱采用 WERKZEUG ,模板引擎则使用 JINJA2 。本项目的数据较为单一简单,在数据库的设计上,我们采用SQLITE3数据库进行数据的储存。SQLITE,是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它包含在一个相对小的C库中。它是D.RICHARDHIPP建立的公有领域项目。它的设计目标是嵌入式的。在实际项目的开发中,发现flask对各个文件的划分有较为严格的规定
本项目flask的文件结构如下
├─static
└─templates
其中项目文件夹下存放数据库,项目启动文件,static文件夹下存放图片和组件库,template文件夹下放置HTML文件。
数据库的设计,我们这次所实现的是将单片机发送的温度值存入数据库,因此数据库结构较为简单
在文件目录下打开终端
输入SQLITE3
创建数据库.OPEN DATA.DB
通过CREATE TABLE TEMS(DAT TEXT NOT NULL);创建一个含有TEXT类型的DAT值的数据表TEMS。
接口的设计,ESP8266通过发送带参数的GET请求,向客户端发送请求,再接口设计中ROUTE()装饰器来告诉 FLASK 触发函数 的 URL,我们本项目中接口的URL为IP+/自定义字符/+<参数>
当接口接收到设备发送来的GET请求时,我们将GET请求的参数通过INSERT语句插入数据库中从而实现了一个简单接收储存数据的接口。
然后是显示页面后端开发,后端逻辑较为简单,连接数据库,通过SELECT*FROM TEMS语句将所有的数据调用出来,CONN.ROW_FACTORY=SQLITE3.ROW和FETCHALL()函数可以使数据像PYTHON字典一样便于操作。
为了使数据可以利用起来,项目中以计算平均值来进行数据的利用,通过设计数据库的步骤我们可以看出数据库中DAT类型为TEXT类型,在PYTHON中为字符串STR类型,为了使DAT可以进行计算,我们需要对其类型进行转化,PYTHON 是弱类型语言,相对于强类型语言,它不需要
下一篇:zero-shot, one-shot和few-shot
友情链接: 武汉网站建设