-
2020-05-31 23:08:14
第一次写博客,可能有很多地方写的不好,请大家见谅,这次想分享一下毕业做的一个毕业设计《基于STM32F407四旋翼无人机控制系统》的一些过程。我会最开始的模块程序编写来较为详细的讲解。
刚开始先说一下飞控都用到了那些知识和选用了哪些模块选择STM32F407作为飞控的主控芯片,在此飞控开发中用到了IIC通信,串口通信,使用的是匿名飞控的上位机进行查看姿态数据和控制数据。硬件的选型为MPU6050模块,MS5611气压计和AK8975磁力计,遥控器使用的为福斯I6X的和配套的10通接收机。
接下来就开始说一下无人机的一些基础知识,因为在大学的时候大二就开始接触无人机了,常用的飞控比如PIX或者APM,基本都在玩四旋翼或者六旋翼,个人觉得如果有空或者有能力可以去扒一下pix的代码去看一下,虽然代码量很多,但是耐心看的话还是有很大收获的。
(一)无人机术语
1、解锁:无人机准备飞行前进行解锁之后才可飞行。
2、加锁:无人机降落后进行加锁,防止误操作造成的安全隐患。
3、罗盘:飞控上的电子指南针,也可指磁力计。
4、电调:电子调速计,可以驱动无刷电机。
5、UBEC电源模块:一个可以将12-16V转为5V的电源转换器
(二)无人机装配
1、电池:电池为聚合物锂电池,单芯下限电压3.7V(1S表示一个电芯),上限电压是4.2V,有点与没电之间只差0.5V。
2、电调:电调全称电子调速器,电调种类非常多,有双向电调(用于车船、坦克等)、飞机电调、多轴电调等等,电调对应使用的电机类型不同,也分无刷电调和有刷电调。上面说到,有刷电机转动时可以不用电调,但并不意味着:用有刷电机做模型飞机可以不用电调,如果没有电调,就无法控制电机工作时的转速。多轴电调均为单向电调, 电调分带UBEC和不带UBEC,UBEC输出一般5V左右为飞控或者接收机供电。
3、无刷电机:是指没有碳刷的电机 ,一般我们都可以在电机身上看到有比如1400kv的标识,电机的KV值越高,意味着转速越高;提供的扭力越小。电机的KV值越低,意味着转速比较低;提供的扭力越大。
电机转速(空载)=KV值X电压
如KV1400的电机在12V电压下它的转速是16800转/分钟。
4、桨叶:再买桨叶的时候我们都会看到有1047或者8045的标识,拿8045来说,80是指80英寸长(80 * 25.4mm =2032mm ),45是螺距(螺距是指螺旋桨旋转一周在轴向移动的距离)。
5.BB响电池报警器:可以显示此时电池的总电压和每个电芯的电压,并且可以设置报警电压。
(三)无人机原理结构组成
1、ROLL:横滚,将机体绕X轴旋转;
2、PITCH:俯仰,将物体绕Y轴旋转;
3、YAW:航向,将物体绕Z轴旋转;
4、各种机型桨叶的安装方向和顺序:(四)无人机各项检查
1、首先检查螺丝和螺旋桨是否牢固,电机轴有无变形,检查机架是否牢固,电池是否固定好,检查桨叶方向是否正确,有时候起飞的侧翻一般有三种情况,第一种是最常见的桨叶装反或者方向有误,第二种是飞控放置不水平,第三种是姿态矫正有误。
2、检查各个插头连接是否完好,焊接部分是否松动,电池电量是否充足。(最好是上电前对加速度计、陀螺仪和磁力计进行一个校准)上电后观察各个电子设备有无不正常发热现象,观察各个指示灯是否正常。
3,飞行前合一轻微推动油门,观察各个电机工作是否正常,检查桨叶转向是否正确,起飞后进行前后左右飞行,观察无人机飞行是否正常,检查遥控器舵量是否正确(若舵量有误则需要校准电调行程,不同的电调有不同的校准方法)。下一次开始对于各个模块进行一些讲解,并且有获取数据的代码供参考!!!
更多相关内容 -
基于STM32F407的流水灯
2020-12-22 16:46:341.用systick时钟实现流水灯延时,LED的 切换有明显视觉停留过程 2、用定时器中断方式实现1的效果 3、用定时器查询方式实现1的效果 -
基于stm32f407的示波器.zip
2022-05-14 13:55:49基于stm32f407的示波器.zip 计算机专业,软件工程专业,通信工程大学生课程设计 自己大三的时候写的 适合大家做课程设计,写毕业设计也可以参考 基于STM32的课程设计 -
基于STM32F407ZGT6-FreeRTOS和ESP32的智能家居控制系统(毕业设计展示作品源代码)
2022-06-10 15:51:45本套操作系统作为毕业生...下位机设计方案:STM32F407ZGT6+FreeRTOS操作系统+ESP32通信模块; 下位机作用:发送传感器数据、接收控制指令,执行动作。 物联网平台:EMQx; 物联网平台作用:作为上下位机通信的中转站。 -
基于STM32的远程温控系统设计
2020-10-22 13:07:26温度控制是工业控制的主要对象之一,常用的温控数学模型是一阶惯性加上纯滞后环节,但其随着加热对象和环境 -
基于STM32的家用甲醛检测仪的设计.pdf
2021-06-24 12:25:33该设计基于低功耗的主控芯片STM32微控制器,利用传感器检测技术对室内的温度、湿度和甲醛浓度进行实时检测和显示。当室内空气中的甲醛含量达到警戒值时会触发报警,同时将检测到的数据通过无线模块发送至智能终端。该... -
基于STM32F407的路径识别智能小车设计_苏元楷
2018-05-18 19:32:50基于STM32F407的路径识别智能小车设计_苏元楷 -
基于STM32F4的智能门锁超详细解析(矩阵键盘、OLED、舵机、HC-05蓝牙、F407ZG最小系统)可用于毕业设计
2021-08-31 20:01:33基于STM32F4的智能门锁超详细解析(矩阵键盘、OLED、舵机、HC-05蓝牙、F407ZG最小系统)可用于毕业设计 -
一种基于STM32的智能窗帘系统设计.pdf
2021-06-27 20:08:32一种基于STM32的智能窗帘系统设计.pdf -
基于STM32的数字语音存储与回放
2019-03-03 19:49:47以STM32F407ZGT6为核心,由拾音器、放大器、有源滤波电路模块、音频功率放大器、喇叭等模块组成。语音声波信号经STM32ADC存储到FLASH中,再通过DAC输出。 -
毕业设计| STM32F407智能汽车:功能全网最全,代码开源。看评论区领相关项目资料
2022-05-31 13:50:44小车的硬件部分使用了以STM32F407VET6最小开发板为核心板,内部结合:温湿度模块、烟雾浓度模块、RFID模块、GSM模块、GPS定位模块、语音识别模块、超声波模块、蓝牙模块、OLED模块、舵机模块、电机驱动模块、电机...这大概是全网功能最多的小车了,做个毕设,有必要这么卷吗?最近咱们的毕设分享和车杠上了
小车8大功能演示
STM32小车功能介绍
小车的硬件部分使用了以STM32F407VET6最小开发板为核心板,内部结合:温湿度模块、烟雾浓度模块、RFID模块、GSM模块、GPS定位模块、语音识别模块、超声波模块、蓝牙模块、OLED模块、舵机模块、电机驱动模块、电机模块、蜂鸣器模块、电压数码管显示模块和电源模块,外结合四个麦克纳姆轮,构成一个完整可靠的硬件系统。
软件控制系统包括了智能显示系统、语音智能控制系统、无线控制系统、车灯智能控制系统、安全报警系统、智能避撞系统、智能温控系统和一键报警系统,在一定程度上提高汽车的安全性、控制性和防盗性。
各个功能分解
语音智能控制系统:通过语音识别模块识别驾驶员的语音来控制汽车车内基本的电气设备,实现功能有打开车门、开启室内照明灯、开启车牌灯、拨打电话和发送报警信息。
无线控制系统:终端在蓝牙的连接下无线发送移动指令给主控制器,主控制器来控制电机驱动板,电机驱动板进而驱动智能汽车四个直流减速电机的转速以及转速方向,灵活地控制智能汽车的各种移动状态。移动状态包括前移、后移、左移、右移、中心左转和中心右转。
车灯智能控制系统:车灯会自动随着智能汽车的移动状态改变而变化,车灯分为刹车灯、倒车灯、左转向灯、右转向灯、双闪灯、近光灯和危险报警灯。有效的提示前方车辆和后方车辆,有效的减少各种道路交通事故的频繁发生。
安全报警系统:安全报警系统分为主动安全报警系统和被动安全报警系统。主动安全报警系统为驾驶员按下按键开关,便可以实现开启危险报警灯,给紧急联系人发送定位信息并拨打紧急电话一系列动作,迅速有效解决事故后安全问题。被动安全报警系统为当车内温湿度和烟雾浓度超过设定阈值时或者驾驶员刷卡失败三次以上时,将触发报警系统。智能汽车自动给紧急联系人发送定位信息并拨打紧急电话。若驾驶员刷卡成功,则舵机旋转,打开车门。
智能避撞系统:智能汽车搭建四个超声波模块,分别位于智能汽车的前、后、左、右,实时监测与其他汽车的车距并智能控制车速的速度和转向,并在必要的情况下实现变道。
智能温控系统:当汽车内温度超过阈值时,将自动启动风扇进行降温处理;当汽车内温度低于阈值时,将自动启动电热丝进行加温处理;设计中设计电热丝的过程中,存在安全隐患,故没有设计,但会在智能显示系统的OLED屏中显示。
智能显示系统:智能汽车通过OLED显示屏显示智能汽车上的各种数据,数据的显示有温度、湿度、烟雾浓度、车距和经纬度,车灯的显示有室内照明灯、车牌灯、倒车灯和危险报警灯。确保驾驶员了解当前汽车的各种状态并做出正确驾驶选择。
电源模块系统:智能汽车的动力之源,电源将给主控制器和电机驱动板供电,以及其他传感器的供电,输入电压5-35v,输出10路3.3v、10路5 v和 5路等输入电压输出。
系统整体框图如下:
硬件模块bom清单
主控板: STM32F407 VET6开发板
温湿度模块:DHT11
烟雾浓度模块:MQ-2
RFID模块:MFRC-522,S50(带全套)
GSM模块:SIM800C
GPS定位模块:正点原子带天线GPS北斗
语音识别模块:LD3320
超声波模块:HC-SR04 宽电压
蓝牙模块:CC2540
OLED模块:四针0.96寸iic通讯
舵机模块:SG90 9g
电机驱动模块:L298N(买大的,7元左右)
蜂鸣器模块:有源蜂鸣器
电压数码管显示模块:028寸三位直流电压表(接输入电压处,显示总电压)
小车底盘:有四个轮子就好
杜邦线:至少120根(母对母)
串口调试器:USB转TTL
所有硬件成本预算是700左右。
电源模块:
电源模块采用的是LM2596芯片和AMS1117芯片,输入电压可为5-35V,输出10路5v电压、10路3.3电压和五路等输入电压。输入电压经过LM2596芯片降压为5v,5v电压经过AMS1117芯片降压为3.3v,然后稳定供电于智能汽车的多个传感器以及电机驱动板。
软件介绍
代码编写:keil5 mdk版本
电源模块设计:AD20(大学生可免费使用正版,官网申请)
串口调试:XCOM2.6
蓝牙调试:蓝牙调试器
在分享的代码里面,包含了这些:全部终极调试代码;keil5使用固件包搭建;语音模块改好代码;各个模块的相关资料。代码读懂之外,大家可以根据自己的需求改动。
不足以及建议
1. GPS模块室内无法定位,无法接受定位数据
2. 电源模块没有总开关,需要在我的板子上加一个
3. 语音模块内置51单片机,需另外烧写,keil5mdk不能烧写。
4. 制作路线:先让小车动起来,然后显示OLED,接着就是调通其他传感器,其他传感器的参数可通过OLED直观显示出来。
-
基于STM32的便携式数字示波器设计
2021-01-13 00:35:31为降低成本和技术难度,提高系统操控性能,本文提出了基于 STM32 的便携式数字示波器的设计和实现方法。该方法通过STM32微处理器作为控制核心,加入外部信号处理单元,利用 DMA 技术进行采样数据输送,FSMC 接口来... -
基于STM32设计的LCD指针式电子钟与万年历项目.zip
2021-08-04 17:47:08这是基于STM32设计的LCD指针式电子钟与万年历项目完整源码。 代码采用寄存器风格编写,注释齐全。 代码硬件部分兼容正点原子战舰开发板,下载即可编译运行。 硬件部分: (1). 采用 STM32F103ZET6作为主控芯片, ... -
基于STM32F407xx的PID温湿度监控系统设计,蔬菜大棚、仓库,包含原理图,代码,连线图,器件选型
2021-12-31 10:14:51基于STM32F407xx的PID温湿度监控系统设计,包含原理图,代码,连线图,期间选型 -
基于stm32俄罗斯和贪吃蛇游戏keil源代码+ad原理图(stm32+lcd12864液晶屏)
2018-10-04 22:13:30该设计是985以及211学校本科生的毕业论文设计,是学生客户的毕业设计,由作者开发以及设计,本文件包含俄罗斯方块+贪吃蛇游戏的keil源代码和ad设计的原理图文件,采用作者自行设计的游戏算法,算法高效可靠稳定,亲... -
第九届全国大学生机械设计创新大赛基于STM32F407的HMI USART串口屏智能药箱设计
2021-07-24 16:21:12二、stm32部分代码 1.main.c 2.usart.c 3.其余代码 总结:程序工程+屏幕文件链接 前言 前段时间花3天时间做的大创项目智能药箱,做完总结一下。 一、屏幕设计 主界面: 时钟设置: 、 ...目录
前言前段时间花3天时间做的大创项目智能药箱,做完总结一下。
一、屏幕设计主界面:
时钟设置:
、
服药设置:
出药测试:
短信测试:
二、stm32部分代码
1.main.c#include "stm32f4xx.h" #include "usart.h" #include "delay.h" #include "servo.h" #include "motor.h" #include "thumb.h" #include "worm.h" #include "stepmotor.h" #include "infrared.h" #include "ds18b20.h" //#include "exti.h" #include "key.h" #include "LD3320.h" #include "jetson.h" #include "rubbish.h" #include "voice.h" #include "rtc.h" #include "usmart.h" //#include "lcd.h" //#include "sram.h" //#include "malloc.h" //#include "w25qxx.h" //#include "sdio_sdcard.h" //#include "ff.h" //#include "exfuns.h" //#include "fontupd.h" #include "text.h" //#include "touch.h" #include "usart3.h" #include "sim800c.h" /********************************************************************************************************* * 全局变量 *********************************************************************************************************/ /********************************************************************************************************* * 函数声明 *********************************************************************************************************/ void tablet(int medicine_count)//药片 { int i; for(i=0;i<medicine_count;i++) { set_Angle_2(0);//药片 TIM4 通道2 B7 delay_ms(1000); set_Angle_2(100);//胶囊 TIM4 通道2 B7 delay_ms(2000); } } void pill_1(int medicine_count)//药丸1 { int i; for(i=0;i<medicine_count;i++) { TIM_SetCompare1(TIM4,800);//药丸1 TIM4 通道1 B6 delay_ms(1000); set_Angle_1(70);//药丸1 TIM4 通道1 B6 delay_ms(2000); } } void pill_2(int medicine_count)//药丸2 { int i; for(i=0;i<medicine_count;i++) { TIM_SetCompare4(TIM4,700);//药丸2 TIM4 通道4 B9 delay_ms(1000); set_Angle_4(80);//药丸2 TIM4 通道4 B9 delay_ms(2000); } } void capsule(int medicine_count)//胶囊 { int i; for(i=0;i<medicine_count;i++) { set_Angle_3(0);//药片 TIM4 通道3 B8 delay_ms(1000); set_Angle_3(100);//药片 TIM4 通道3 B8 delay_ms(2000); } } void Medicien(int medicine_box,int medicine_count) { switch(medicine_box) { case(1):pill_1(medicine_count);break; case(2):tablet(medicine_count);break; case(3):capsule(medicine_count);break; case(4):pill_2(medicine_count);break; } } void Medicien_star(void) { int i; if(page==16) { while(page==16); } if(page==17) { while(page==17) { if(medicine_flag==7) { for(i=0;i<8;i+=2) { Medicien(medicinebuf[i],medicinebuf[i+1]); } page=0; break; } } } if(page==18) { pill_1(2); tablet(2); capsule(2); pill_2(2); page=0; } } int main(void) { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); delay_init(168); uart_init(9600); //串口初始化为9600 usart3_init(115200); //初始化串口3 KEY_Init(); TIM4_PWM_Init(); My_RTC_Init(); //初始化RTC NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2 RTC_Set_WakeUp(RTC_WakeUpClock_CK_SPRE_16bits,0); //配置WAKE UP中断,1秒钟中断一次 set_Angle_1(70);//药丸1 TIM4 通道1 B6 set_Angle_2(100);//胶囊 TIM4 通道2 B7 set_Angle_3(100);//药片 TIM4 通道3 B8 set_Angle_4(80);//药丸2 TIM4 通道4 B9 delay_ms(1000); while(1) { switch(page) { case 0:break; case 1:main_interface_show();break; case 2:rtc_show_set();break; case 7:voice_IO(1);break; // case 8:play_back();break; // case 9:play_back();break; // case 10:play_back();break; // case 11:play_back();break; case 16:Medicien_star();break; case 17:Medicien_star();break; case 18:pill_1(2); tablet(2); capsule(2); pill_2(2);page=1;break; case 19:voice_IO(7);break; case 20://usmart_dev.init(168);//初始化USMART sim800c_test(1);break; case 21:sim800c_test(2);break; } } }
2.usart.cvoid USART1_IRQHandler(void) //串口1中断服务程序 { u8 Res; #if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS为真,则需要支持OS. OSIntEnter(); #endif if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾) { Res =USART_ReceiveData(USART1);//(USART1->DR); //读取接收到的数据 if((USART_RX_STA&0x8000)==0)//接收未完成 { if(USART_RX_STA&0x4000)//接收到了0x0d { if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始 else USART_RX_STA|=0x8000; //接收完成了 } else //还没收到0X0D { if(Res==0x0d)USART_RX_STA|=0x4000; else { USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ; USART_RX_STA++; if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收 } } } if((page==5||page==6)&&time_flag<=3) { timebuf[time_flag]=Res; time_flag++; } else if((page==10)&&tea_flag<=4) { teabuf[tea_flag]=Res; if(teabuf[0]<10) { page=teabuf[0]; } tea_flag++; } else if((page==17)&&tea_flag<=7) { medicinebuf[medicine_flag]=Res; medicine_flag++; } else if(page!=5&&page!=6&&page!=10&&page!=17) { switch(Res) { case 0x01:page=1;break; case 0x02:page=2;break; case 0x03:page=3;break; case 0x04:page=4;break; case 0x05:page=5;break; case 0x06:page=6;break; case 0x07:page=7;break; case 0x08:page=8;break; case 0x09:page=9;break; case 0x0a:page=10;break; case 0x0b:page=11;break; case 0x0c:page=12;break; case 0x0d:page=13;break; case 0x0e:page=14;break; case 0x10:page=16;break; case 0x11:page=17;break; case 0x12:page=18;break; case 0x13:page=19;break; case 0x14:page=20;break; case 0x15:page=21;break; case 0x16:page=22;break; case 0x17:page=23;break; case 0x18:page=24;break; case 0x19:page=25;break; } } } #if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS为真,则需要支持OS. OSIntExit(); #endif } #endif
3.其余代码
这个工程是基于正点原子的SMI600短信模块测试程序,工程代码我已经打包好上传,有需要的小伙伴可以在评论区留言。
总结:程序工程+屏幕文件链接程序代码工程链接:基于STM32F407的HMI USART串口屏智能药箱设计.zip
-
基于STM32的智能水产养殖系统电路+代码+论文
2022-05-10 00:08:55适用于基于Stm32的毕业设计参考,论文内容完整,丰富,格式规范。 本系统是基于Cortex-M4内核的STM32F407VGT6微控制器的水产养殖自动化控制装置,在硬件方面主要有无线传输以及电机驱动,抽水机,温湿度模块,OV7670... -
基于stm32智能手环.zip
2020-08-20 15:58:20基于stm32f407下的智能手环开发,使用mpu6050实现计步,max30102心率传感器测血氧心率,rtc时钟,可通过按键或者蓝牙修改时间日期,设置闹钟,olcd显示步数,时间,闹钟,血氧,心率图等 -
基于STM32的音乐播放器设计
2015-01-06 20:43:45详情请查看CSDNPeOS博客:毕业设计——基于STM32的音乐播放器设计(一) -
基于STM32的智能手表及论文说明
2020-04-21 17:44:56主要设计一个基于STM32的智能手表,除满足查看时间的基本功能外,用户还能实时了解到外部环境状态、自己的运动状态和健康状态,并且可将相关数据发送至手机端,实现手表的智能化,便利不同人群。以及论文说明! -
毕业设计——基于STM32的家庭健康监测系统
2021-08-15 14:57:05这是本科时的毕业设计,想着之后读研了,研究方向是机器学习了,可能不会这么再碰32或者51之类的板子了,就想趁着还没有忘记就来梳理一下,纪念陪伴了我两年的硬件朋友们,作为的一个足迹。 二、项目背景及资源分享 ...文章目录
一、前言
这是本科时的毕业设计,想着之后读研了,研究方向是机器学习了,可能不会这么再碰32或者51之类的板子了,就想趁着还没有忘记就来梳理一下,纪念陪伴了我两年的硬件朋友们,也作为一个足迹。
二、项目背景及资源分享
这次毕业设计的灵感来源于20年的电赛,当时因为考研时间紧张的原因,在做一个《无线传感器结点》题目的时候,当时是使用的无线传感器模块将数据传到电脑作为一个上位机的展示。但当时想做的是使用wifi模块来实现无线传输功能,传到一个自己写的web服务器,在页面上进行展示的,由于时间原因最终还是选择了前者。因此毕业设计就选择这个相近的题目,也算是弥补当时的遗憾。
本次的课题是数据传送至onenet云平台上的,之前看到一个up主讲的stm32连接onenet的详细步骤,这里给大家分享一下:
链接:https://www.bilibili.com/video/BV1y54y1q7uT?from=search&seid=4104843828856938758
第一个可能失效了,这里重新找了一个:
https://www.bilibili.com/video/BV1Yb411T7D1?from=search&seid=3711635156906757806&spm_id_from=333.337.0.0这是onenet平台的官方MQTT协议连接手册:
链接:https://open.iot.10086.cn/doc/mqtt/相关资源的百度云链接:
链接:https://pan.baidu.com/s/1D_iBAe5bqnejGoVDDlOpjg?pwd=zckc
提取码:zckc三、项目介绍
1、项目名称
基于STM32的家庭健康监测系统
2、系统框架
根据需求,该系统可以实时监测被测者的心率、体温以及周遭环境的温度,也同时可以通过姿态解算来判断被测者是否摔倒。该系统可以将被测者的心率、体温等数据既在本地显示,也可以通过WI-FI传输至云平台以实现远程显示。当被测者摔倒时会发出蜂鸣声,以便引起周围人向被测者施以援手;当被测者吸烟时则会发出警报直至香烟熄灭,可以让被测者远离不健康的生活习惯。
3、功能简介
该设计是主要功能如下:
(1) 实时的采集心率、温度、烟雾浓度等信息;
(2) 实时的显示心电图以及温度数值信息;
(3) 实现跌倒的判断,并且在跌倒时发出报警;
(4) 实现吸烟警告,在吸烟时发出报警;
(5) 实现将温度、心率、姿态解算数据、烟雾浓度等发送至云平台;
(6) 通过登录云平台查看心率、温度、烟雾浓度的折线图。
4、控制核心
STM32C8T6(最小核心板),当然,用其他型号的32,如STM32ZET6也是可以的。
5、外围模块
心率模块:ADS1292R
温度模块:LMT70
姿态解算模块:MPU6050
WIFi模块:ATK-ESP8266
液晶显示模块:OLED12864
6、上位机
OneNET云平台
四、相关设计及框图
1、系统总统设计
基于本系统的需求,本设计提出了分层的设计思想,将系统分为:硬件采集层、网络传输层、数据展示层,提高了软硬件之间的耦合性,便于分工与维护。其中,硬件采集层负责收集心率、温度、烟雾浓度、姿态解算数据,网络传输层负责将前一层采集到的数据通过WI-FI传输到数据展示层,而数据展示层分为本地数据展示和云端数据展示。
2、数据采集层设计框图
3、数据传输层设计框图
4、数据展示层设计框图
五、各功能模块详细设计
1、心率监测功能
在检测的时候,会有许噪音对检测的结果带来干扰,比如人体自身以及电路的干扰都会对检测结果产生影响,当许多干扰信号和心电信号混在一起的时候就可能会使有用信号发生变形甚至被淹没,因此滤波是非常必要的,而滤波可以分为代码实现的软件滤波和芯片自带的硬件滤波,ADS1292R是一款医用级的前端芯片。该模块按照以下的工作时序与STM32进行全双工的SPI通讯。
该模块在系统中的工作流程图:
当ADS1292R上电后至少需要等待1s,当寄存器稳定后再进入ADS1292R的引脚初始化,其中包含了CS、START、RESET、DRYDY控制引脚,当引脚初始化超时则会重新初始化,其次是SPI通讯端口的初始化,然后继续对ADS1292R进行采集操作的一系列配置就可以获得心率的原始数据。该段是对ADS1292R初始化的配置函数
/* 初始化ads1292r,超时时间为timeout*100ms,返回0表示初始化失败 */ uint8_t ads1292r_init( uint8_t timeout) { uint8_t id ; /* gpio接口初始化,针对非hal库版本需要再此添加代码 */ port_gpio_init() ; /* spi接口初始化 */ port_spi_init() ; ADS1292_CS_SET() ; ADS1292_REST_RESET() ; ADS1292_START_RESET() ; port_delay_ms(1000) ; ADS1292_REST_SET() ; port_delay_ms(100) ; /* 硬件复位 */ ads1292r_send_cmd(ADS1292R_COMMAND_SDATAC) ; /* 软件复位,并停止连续读状态 */ port_delay_ms(100) ; ads1292r_send_cmd(ADS1292R_COMMAND_RESET) ; port_delay_ms(1000) ; ads1292r_send_cmd(ADS1292R_COMMAND_SDATAC) ; port_delay_ms(100) ; while( ( id != ads1292r_reg.id) && ( timeout > 0)) /* 识别芯片型号,1292r为0x73 */ { id = ads1292r_rw_reg(ADS1292R_COMMAND_RREG|ADS1292R_REG_ID, 0) ; timeout-- ; port_delay_ms(100) ; } /* 500sps采样率 */ ads1292r_reg.cfg1 = ADS1292R_SET_BITS(ads1292r_reg.cfg1, ADS1292R_DR, ADS1292R_OVERSAMPLING_500SPS) ; /* 导联脱落比较器开,内部2.42v参考电压 */ ads1292r_reg.cfg2 = ADS1292R_SET_BITS(ads1292r_reg.cfg2, ADS1292R_PDB_LOFF_COMP, ADS1292R_PDB_LOFF_COMP_ON) ; ads1292r_reg.cfg2 = ADS1292R_SET_BITS(ads1292r_reg.cfg2, ADS1292R_PDB_REFBUF, ADS1292R_PDB_REFBUF_ON) ; ads1292r_reg.cfg2 = ADS1292R_SET_BITS(ads1292r_reg.cfg2, ADS1292R_VREF_4V, ADS1292R_VREF_2420MV) ; /* 通道二导联脱落检测功能开 */ ads1292r_reg.loff_sens = ADS1292R_SET_BITS(ads1292r_reg.loff_sens, ADS1292R_LOFF2N, ADS1292R_LOFF2N_ON) ; ads1292r_reg.loff_sens = ADS1292R_SET_BITS(ads1292r_reg.loff_sens, ADS1292R_LOFF2P, ADS1292R_LOFF2P_ON) ; /* pga斩波频率4分频,右腿驱动电源开,开启通道二的右腿驱动输出 */ ads1292r_reg.rld_sens = ADS1292R_SET_BITS(ads1292r_reg.rld_sens, ADS1292R_CHOP, ADS1292R_CHOP_FREQ_DIV4) ; ads1292r_reg.rld_sens = ADS1292R_SET_BITS(ads1292r_reg.rld_sens, ADS1292R_PDB_RLD, ADS1292R_PDB_RLD_ON) ; ads1292r_reg.rld_sens = ADS1292R_SET_BITS(ads1292r_reg.rld_sens, ADS1292R_RLD2N, ADS1292R_RLD2N_ON) ; ads1292r_reg.rld_sens = ADS1292R_SET_BITS(ads1292r_reg.rld_sens, ADS1292R_RLD2P, ADS1292R_RLD2P_ON) ; /* 右腿驱动参考电压选择内部信号 */ ads1292r_reg.resp2 = ADS1292R_SET_BITS(ads1292r_reg.resp2, ADS1292R_RLDREF_INT, ADS1292R_RLDREF_INT) ; return timeout ; }
其他的关于芯片识别和采样频率设置、开启导联脱落比较器、开启二联导脱落检测功能、开启通道二右腿驱动输出并选择内部信号的代码这里就不放了,这些可以通过官方给的芯片资料是可以移植的。
然后来说一下软件滤波的操作:
初始化函数返回的timeout的是初始化失败次数,如果超过则会一直卡在这里不能继续往下。流程图的原始数据是仅仅只是硬件滤波后的ADC原始数据,为了能够得到符合正常范围的心电信号,还需要对数据进行软件滤波,处于过于偏大或者偏小的波形,最后才能将滤波后的心率值存到数组中。以下为软件滤波的部分代码:ads1292r_get_value(ad_b); ecg_data = i24toi32(ad_b+6); /* 转换原始数据 */ ecg_sum = 0; for(i = 0; i < 8; i++) { ecg_data_s[i] = ecg_data_s[i+1]; ecg_sum += ecg_data_s[i]; } ecg_data_s[8] = ecg_data; ecg = (ecg_sum + ecg_data) / 9; ecg_min = 5000000; ecg_max = -5000000; for(i=0; i < 29; i++) { ecg_buf[i]=ecg_buf[i+1]; ecg_max = ecg_max < ecg_buf[i] ? ecg_buf[i] : ecg_max; ecg_min = ecg_min > ecg_buf[i] ? ecg_buf[i] : ecg_min; } ecg_buf[29]=ecg; ecg_max = ecg_max < ecg ? ecg : ecg_max; ecg_min = ecg_min > ecg ? ecg : ecg_min; if((ecg_max - ecg_min > 30000)&&(tim3_tick > 200)) { if((60000/tim3_tick < 200) && (60000/tim3_tick > 40)) { Heart_buff[0] = Heart_buff[1]; Heart_buff[1] = Heart_buff[2]; Heart_buff[2] = Heart_buff[3]; Heart_buff[3] = Heart_buff[4]; Heart_buff[4] = Heart_buff[5]; Heart_buff[5] = Heart_buff[6]; Heart_buff[6] = Heart_buff[7]; Heart_buff[7] = Heart_buff[8]; Heart_buff[8] = Heart_buff[9]; Heart_buff[9] = 60000/tim3_tick; Heart_rate=(Heart_buff[0]+Heart_buff[1]+Heart_buff[2]+Heart_buff[3]+Heart_buff[4] +Heart_buff[5]+Heart_buff[6]+Heart_buff[7]+Heart_buff[8]+Heart_buff[9])/10; } tim3_tick = 0; }
从流程图中可以看到在定时器中断的作用下,每隔100ms就会将获得滤波后的心电信号以串口的方式传输到主控的STM32芯片再对心率数据进行下一步的处理。
2、温度采集功能
LMT70是一款高精度的医用级温度传感器,其仅需3.3V的电压就可以驱动,且功耗极低,可以检测的温度范围是-55摄氏度到150摄氏度。温度模块与主控STM32采用的是IIC通信,其具体的引脚连接图如下:
以下为该模块在系统中的流程图:
由于在硬件电路中,ADS115和LMT70是合在一起的,共同算作温度模块,因此,在流程图中的ADS115初始化是指整个温度模块的初始化,以下为ADS115初始化函数:void ads1115_Init(void) { ads1115_I2C_INIT(); // ads1115_I2C init /* 增益 */ m_gain = GAIN_ONE; /* config the config reg */ if (ConfigeRegister(m_channel)) { // deal error printf("init configreg error\r\n"); } }
该初始化函数完成了IIC引脚的初始化以及寄存器的配置。通过对convert寄存器的处理,可以获得原始的ADC数据,最后再通过对该数据进行才得到最终温度数值,再把该数据通过IIC传给STM32进行进一步的处理。
具体的式子如下:
//采集ADC数 (温度) adcx=GetAds1115Values();//采集ADC数据 temp=(float)adcx*0.125f; tem = (-0.0000084515f)*temp*temp+(-0.176928f)*temp+203.393f;
3、跌倒监测功能(姿态解算)
MPU6050是整合性六轴运动处理组件,其中组合了三轴陀螺仪和三轴加速器。加速度传感器是用来检查空集中的6个面(前后左右上下)中的哪些面受到了力的作用,陀螺仪是检测3个方向的欧拉角,以水平摊开的手掌为例,判断手掌上下摆动幅度的角度叫俯仰角用pitch表示,判断手掌左右水平移动的角度叫偏航角用yaw表示,判断手掌左右翻滚的角度叫滚转角用roll表示。本模块所需要实现简单的跌倒检测的功能,首先得知道什么算跌倒或者如何表示跌倒的状态。跌倒是指突发、不自主的、非故意的体位改变,倒在地上或更低的平面上[4]。人体在跌倒瞬间,身体的加速度和角速度在水平和垂直方向都会发生巨大的变化[5]。因此,通过判断三个方向的欧拉角以及三个方向的综合加速度综合考虑来判断是否摔倒。
MPU6050的初始化代码是可以根据官方资料移植的,所以这里就不贴初始化了,这里介绍一下跌倒监测的实现。
首先知道DMP功能移植DMP是MPU6050内部的运动引擎,由Inven Sence公司自主提供,用于从内部传感器中直接解算出四元数,大幅降低运算复杂度。由于DMP可直接输出四元数,从而可以减轻外围微处理器的工作负担,且能避免繁琐的滤波和数据融合处理,能降低系统运算的复杂度。以为为四元组转换公式的转换公式,其中四元单位数的平方和为1。
然后通过四元组转化得到三个方向的欧拉角,代码实现如下:if(sensors&INV_WXYZ_QUAT) { q0 = quat[0] / q30; //q30格式转换为浮点数 q1 = quat[1] / q30; q2 = quat[2] / q30; q3 = quat[3] / q30; //计算得到俯仰角/横滚角/航向角 *pitch = asin(-2 * q1 * q3 + 2 * q0* q2)* 57.3; // pitch *roll = atan2(2 * q2 * q3 + 2 * q0 * q1, -2 * q1 * q1 - 2 * q2* q2 + 1)* 57.3; // roll *yaw = atan2(2*(q1*q2 + q0*q3),q0*q0+q1*q1-q2*q2-q3*q3) * 57.3; //yaw
得到三个方向的欧拉角之后,再结合人体加速度向量幅值SVM来综合判断是否跌倒。
其中SVM是三个方向的综合加速度值,式子如下:
S V M = a = a x 2 + a y 2 + a z 2 \mathbf{SVM}=a=\sqrt{a_x^2+a_y^2+a_z^2} SVM=a=ax2+ay2+az2以下为跌倒监测的代码实现:
void fall(){ MPU_Get_Accelerometer(&aacx,&aacy,&aacz); //得到加速度传感器数据 SVM = sqrt(pow(aacx,2)+ pow(aacy,2) + pow(aacz,2)); //printf("pitch:%0.1f roll:%0.1f yaw:%0.1f SVM:%u\r\n",fabs(pitch),fabs(roll),fabs(yaw),SVM); //分析x、y、z角度的异常判断 if( fabs(pitch)>40 || fabs(roll)>40 || fabs(yaw)>40 )//倾斜角度的“绝对值”大于70°,SVM大于设定的阈值时,即认为摔倒 mpu_1_flag = 1; else mpu_1_flag = 0; //分析加速度SVM的异常判断 if( SVM>22000 || SVM<12000 ){i = 0;} i++; if( i<=3 ){mpu_2_flag = 1;} else { i = 3; mpu_2_flag = 0; } //综合欧拉角、SVM异常判断异常 if( mpu_2_flag || mpu_1_flag){mpu_flag = 1;} else {mpu_flag = 0;} BEEP=0; delay_ms(300);//延时300ms if(mpu_flag==1) { BEEP=1; LED2=0; LED1=1; delay_ms(300);//延时300ms } BEEP=0; delay_ms(300); LED1=0; LED2=1; }
4、WI-FI模块
该模块的工作流程如下:
系统上电后对首先是对WI-FI模块引脚进行初始化包括WI-FI模块的RESET引脚,在本设计中WI-FI模块通过USART3串口与主控STM32进行通信,因此还需要对USART3(串口3)进行初始化,串口初始化代码是基本功这里就也不贴代码啦。紧接着是 然后是对WI-FI模块的配置,首先是主控STM32通过串口3向ESP8266发送RST复位指令,然后清除ESP8266中的缓存,根据本设计的需求是要把硬件采集层所获取的所有数据传输到云平台,因此配置其工作模式为“STA”模式(WI-FI模式)。配置为STA模式后需要连接手机热点,通过串口3发送AT指令到ESP8266配置WIFI的名称和密码,命令格式为: AT+CWJAP=“名称”,“密码”,为了方便串口3发送命令,本设计将热点名称和密码做了宏定义,宏定义如下:
#define ESP8266_WIFI_INFO "AT+CWJAP=\"ONTNET\",\"lyycz1314\"\r\n"
能上网之后接下来访问云平台公网IP,因为ESP8266模块内部自带了TCP/IP协议栈,因此通过AT命令连接到云平台,命令格式为:AT+CIPSTART= “TCP”,“IP”,“端口”,为了方便串口3发送命令,本设计将云平台的IP地址、端口做了宏定义,宏定义如下:
#define ESP8266_ONENET_INFO "AT+CIPSTART=\"TCP\",\"183.230.40.39\",6002\r\n"
以上这两个每个人的都不一样,根据自己的具体情况配置,如果直接复制就会访问到别人的云平台创建的项目上,这样就尴尬啦。
配置完成后就可以向云平台发送MQTT协议包,等待平台回应后就可以将各种数据打包发送至云平台了,以下为ESP8266初始化的具体代码:
void ESP8266_Init(void) { GPIO_InitTypeDef GPIO_Initure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //ESP8266复位引脚 GPIO_Initure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Initure.GPIO_Pin = GPIO_Pin_1; //GPIOB1-复位 GPIO_Initure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_Initure); GPIO_WriteBit(GPIOB, GPIO_Pin_1, Bit_RESET); delay_ms(250); GPIO_WriteBit(GPIOB, GPIO_Pin_1, Bit_SET); delay_ms(500); ESP8266_Clear(); printf("AT\r\n"); while(ESP8266_SendCmd("AT\r\n\r", "OK", 100)) delay_ms(500); printf("CWMODE\r\n"); while(ESP8266_SendCmd("AT+CWMODE=1\r\n", "OK", 100)) delay_ms(500); printf("AT+CWDHCP\r\n"); while(ESP8266_SendCmd("AT+CWDHCP=1,1\r\n", "OK", 200)) delay_ms(500); printf("CWJAP\r\n"); while(ESP8266_SendCmd(ESP8266_WIFI_INFO, "GOT IP", 200)) delay_ms(500); printf("CIPSTART\r\n"); while(ESP8266_SendCmd(ESP8266_ONENET_INFO, "CONNECT", 200)) delay_ms(500); printf("ESP8266 Init OK\r\n"); }
上段代码也是可以移植的,以下是ESP8266向云平台发送数据的具体代码:
void OneNet_SendData(void) { MQTT_PACKET_STRUCTURE mqttPacket = {NULL, 0, 0, 0}; //协议包 char buf[128]; short body_len = 0, i = 0; // printf("Tips: OneNet_SendData-MQTT\r\n"); memset(buf, 0, sizeof(buf)); body_len = OneNet_FillBuf(buf); //获取当前需要发送的数据流的总长度 if(body_len) { if(MQTT_PacketSaveData(DEVID, body_len, NULL, 5, &mqttPacket) == 0) //封包 { for(; i < body_len; i++) mqttPacket._data[mqttPacket._len++] = buf[i]; ESP8266_SendData(mqttPacket._data, mqttPacket._len); //上传数据到平台 // printf("Send %d Bytes\r\n", mqttPacket._len); MQTT_DeleteBuffer(&mqttPacket); //删包 } else printf("WARN: EDP_NewBuffer Failed\r\n"); } }
这里是定义ONENET平台收数据的数据流的名称,上面的视频链接中如何配置云平台也会说到,并且更加详细。
//上传数据流(名称及值) unsigned char OneNet_FillBuf(char *buf) { char text[32]; memset(text, 0, sizeof(text)); strcpy(buf, ",;"); memset(text, 0, sizeof(text)); sprintf(text, "Temperature,%.3lf;", tem+0.05f); strcat(buf, text); memset(text, 0, sizeof(text)); sprintf(text, "Heart rate,%d;", Heart_rate);//(上传的数据流的名称) strcat(buf, text); memset(text, 0, sizeof(text)); sprintf(text, "The Falls,%d;",mpu_flag); strcat(buf, text); memset(text, 0, sizeof(text)); sprintf(text, "The Smoke,%lf;",temp2); strcat(buf, text); return strlen(buf); }
5、显示模块、烟雾报警模块
由于这两个模块比较简单,尤其是OLED12864是最常见的模块,移植也直接用IIC协议,包括配置文件都是一起移植的,所以这里这两个模块间便不在赘述。
六、实物测试及效果展示
1、总体效果
2、网络测试
通过串口调试助手,将WIFI模块与云平台连接情况打印出来,就可以清楚的知道问题出在哪一步。
3、开始界面:
4、心率、温度、烟雾浓度测试:
其中第一个数字表示的是心率值,第二个是当前室温,第三个是烟雾浓度值,第四个只有0\1,0表示没有跌倒,1表示跌倒。
后是对跌倒检查功能的测试,首先默认水平是正常的状态,当把设计快速立放则会被视作摔了,液晶显示器的最后一位数字也会从0变成1,蜂鸣器会发出报警,以及下面的指示灯会变成红色,以下为测试结果:
5、oneNET平台测试
以下为平台接收到单片机传上来的各数据:
折线图显示:
七、总结
终于写完啦,这个应该是我目前最长的一个帖子了哈,以上就是我的毕业设计了。当时本来还想加语音识别以及播报和北斗GPS定位的,测试了一下,加语音识别播报最小板引脚的勉强刚刚够,但如果加GPS的话由于硬件限制,stm32c8t6只有128k,不够存GPS数据,换zet6测试就可以,由于时间原因没有换核心板子(换了代码很多地方都要改,工作量有点大)后来还是没有用c8t6调出来,这也是遗憾的一点。有问题或者有兴趣进一步了解的同学,可以私聊,在能力范围内的会尽力帮助大家~~~
那啥,都看到这儿了,点个关注在走呗~ 谢谢!(鞠躬)
八、元器件清单
显示模块:OLED128564
心率模块:ADS1292R
温度模块:LMT70
姿态解算模块:MPU6050
WIFi模块:ATK-ESP8266
烟雾浓度检测模块:MQ-2
降压稳压模块:LM2596S(可调降压带显示版)
主控芯片:STM32F103C8T6(最小版) -
基于STM32的智能管家门控系统设计与实现-电路设计原理图.zip
2019-12-14 18:39:58毕业设计的电路包含以下几部分,电路功能完成验证:电源部分、电子锁控制部分、TF卡SDIO电路、HMI 串口触摸屏、指纹识别模块部分、GSM模块、下载&调试、MCU部分、LED显示、蜂鸣器、按键输入。 毕设相关文档(论文等)... -
基于STM32+OV7670的照相机设计.rar
2022-05-10 00:52:06基于STM32+OV7670的照相机 【原理图、PCB、参考源码】 内含四个资源①STM32F407ZET6摄像机(不覆铜)更新日志.rar②SSD1289 stm32 FSMC驱动.rar③emWin带触屏模板(坐标校准测试).rar④【程序】STM32 OV7725照相机源... -
基于STM32F429智能搬运小车.zip
2022-05-14 14:04:36基于STM32F429智能搬运小车.zip 计算机专业,软件工程专业,通信工程大学生课程设计 自己大三的时候写的 适合大家做课程设计,写毕业设计也可以参考 基于STM32的课程设计 -
毕业设计--2020.02.13-----基于Stm32F407的 BME680传感器库函数的迁移
2020-02-13 22:34:15毕业设计准备用 博世的 BME680 传感器来获取温湿度以及气压 空气质量信息。我选用的传感器是这样的 短期内可能不会上传代码,这是毕设的一部分 需要代码的小伙伴留言吧 传感器使用的是IIC协议进行通讯的 接线... -
STM32项目设计:基于STM32指纹密码锁
2022-03-29 10:33:03资料下载地址:基于STM32指纹密码锁 二、材料选择 1、正点原子F103精英板 2、正点原子3.5寸TFTLCD屏 3、正点原子LB301电容式指纹模块 4、DHT11温湿度模块 三、原理图设计 LB301模块连接图 DHT11模块连接图 VCC DATA... -
基于STM32 嵌入式实验DHT11温湿度传感器测量湿度
2018-06-25 14:58:39DTH11测量实时湿度,最大湿度,最小湿度,通过矩阵键盘设置报警湿度值,在LCD彩屏上显示 -
STM32项目设计:基于STM32F4的电子阅读器制作教程
2020-12-08 09:58:13基于STM32F4的电子阅读器 一、项目功能要求 项目说明: 项目偏软件,但是要依赖于自己对硬件的熟悉和驱动才能完成 用到的主要技术: SD卡驱动(难–不过可移植 SD卡驱动细节可在用完再了解其驱动协议) FatFs文件... -
基于stm32和ad9850的dds信号源
2019-03-17 21:47:53本代码是基于stm32f103zet6和ad9850的dds信号源设计,乃本人毕业设计制作,代码可移植性好,亲测可用,频率可通过按键进行步进,并通过oled实时显示 -
STM32F407+ESP8266实现DHT11 MQ135采集及手机控制
2022-05-02 11:26:37STM32F407+ESP8266实现DHT11 MQ135实时传输 最近在进行毕业设计,题目是有关智能家居方面的,在esp8266与手机通信方面下了很多功夫,找了许多资料,在此进行总结,方便友友进行学习。若有任何问题欢迎留言,讨论。...