本文分享自华为云社区《基于STM32+华为云IOT设计的酒驾监控系统【玩转华为云】》,作者: DS小龙哥。
随着人们生活水平的提高,为了减少和杜绝车的现象越来越多,所引发的交通事故也引起了人们的重视,为了减少和杜绝酒后驾车导致事故发生,当前设计了一种安装在驾驶室内,能根据具体功能进行鉴别酒精浓度的系统,当识别到酒驾之后会发出警报,并发送短信给指定紧急联系人,通知家人通知酒驾,一起监督行车安全。并将GPS数据上传到华为云物联网平台,调用地图模块显示具体位置,主控芯片采用STM32单片机,GSM模块采用IM800C。系统还带了一块LCD显示屏,可以实时显示检测的酒精含量,酒精超标后,本地蜂鸣器也会发出警报,提醒驾驶员。
测量酒驾的标准是:
(1)饮酒驾车是指车辆驾驶人员血液中的酒精含量大于或者等于20mg/100ml,小于80mg/100ml的驾驶行为。(2)醉酒驾车是指车辆驾驶人员血液中的酒精含量大于或者等于80mg/100ml的驾驶行为。
需要使用的硬件如下:
(1)STM32系统板
(2)酒精检测传感器
(3)LCD显示屏
(4)供电模块
(5)SIM800C模块
(6)蜂鸣器模块
(7)GPS模块–采用SIM800C内部的GPS功能获取GPS数据。



为了测试,搞了几口二锅头。

上位机采用QT开发,调用华为云的应用侧接口获取设备上传的数据。再调用百度接口,获取GPS定位的位置。

华为运官网: https://www.huaweicloud.com/



在这里可以查看接入的协议的端口号和地址。


MQTT (1883) a161a58a78.iot-mqtts.cn-north-4.myhuaweicloud.com
我们设备接入的协议选择MQTT,端口对应是1883
接下来继续创建产品,点击产品页面,点击右上角创建产品:






这是我的设备信息:
设备ID
625cd29cecf9c41c38215ba5_1126626497
设备密钥
1126626497
{
"device_id": "625cd29cecf9c41c38215ba5_1126626497",
"secret": "1126626497"
}
这一步就是设置上报设备的属性,也就是设备的数据类型定义。




创建完产品、设备之后,接下来就需要知道如何通过MQTT协议登陆华为云服务器。


MQTT设备登陆密匙生成地址: Huaweicloud IoTDA Mqtt ClientId Generator

下面就得到了MQTT协议设备登录的参数。
所有的参数已经得到,接下来采用MQTT客户端登录华为云进行测试。
华为云物联网平台的域名是: a161a58a78.iot-mqtts.cn-north-4.myhuaweicloud.com
华为云物联网平台的IP地址是: 121.36.42.100
在软件里参数填充正确之后,就看到设备已经连接成功了。
接下来打开设备页面,可以看到设备已经在线了。
官方文档: 使用MQTT.fx调测_设备接入 IoTDA_开发指南_设备侧开发_使用MQTT Demo接入_华为云
在这个文档里介绍了MQTT上报数据的格式。


总结的格式:
//订阅主题: 平台下发消息给设备
$oc/devices/625cd29cecf9c41c38215ba5_1126626497/sys/messages/down
//设备上报数据
$oc/devices/625cd29cecf9c41c38215ba5_1126626497/sys/properties/report
//上报的属性消息 (一次可以上报多个属性,在json里增加就行了)
{"services": [{"service_id": "MQ3","properties":{"MQ3":50}}]}
到此,设备数据已经上报成功,如果需要增加更多的属性,按照流程继续增加即可。
酒精浓度传感器的预热时间要20秒~1分钟左右,这段时间之后采集的数据才会稳定。预热模块会发热,烫手,这个是正常现象。


通过USB进行程序下载: 下载软件在软件包目录下。
点击开始编程之后,点击板子上的复位键即可下载程序,如果失败,重试几次即可。正常的效果如下。

正常程序运行之后,打开串口调试助手看到的初始化信息如下:


keil工程可以在这里get: https://download.csdn.net/download/xiaolong1126626497/81993720
#include "stm32f10x.h"
#include "led.h"
#include "delay.h"
#include "key.h"
#include "usart.h"
#include <string.h>
#include "timer.h"
#include "oled.h"
#include "adc.h"
#include <string.h>
#include <stdlib.h>
#include "font.h"
#include "sim800c.h"
#include "mqtt.h"
/*
硬件连接方式:
1. TFT 1.44 寸彩屏接线
GND 电源地
VCC 接5V或3.3v电源
SCL 接PC8(SCL)
SDA 接PC9(SDA)
RST 接PC10
DC 接PB7
CS 接PB8
BL 接PB11
2. 蜂鸣器
VCC--->3.3V
DAT--->PA6
GND--->GND
3. 酒精检测传感器MQ3
VCC--->3.3V
GND--->GND
DAT--->PA1
4. 板载LED灯接线
LED1---PA8
LED2---PD2
5. 板载按键接线
K0---PA0
K1---PC5
K2---PA15
6. SIM800C--GSM模块
GND----GND
VCC--->3.3V
PA2----SIM800C_RXD
PA3----SIM800C_TXD
*/
//华为物联网服务器的设备信息
#define MQTT_ClientID "62381267575fb713ee164ad2_xl_1_0_0_2022032106"
#define MQTT_UserName "62381267575fb713ee164ad2_xl_1"
#define MQTT_PassWord "124344feff3e3d96ff6af13cf36af36766619ff1eeee40e99cbae9b7b9739fe4"
//订阅与发布的主题
#define SET_TOPIC "$oc/devices/62381267575fb713ee164ad2_xl_1/sys/messages/down" //订阅
#define POST_TOPIC "$oc/devices/62381267575fb713ee164ad2_xl_1/sys/properties/report" //发布
//设置连接的路由器信息
#define CONNECT_WIFI "Xiaomi_meizi6" //将要连接的路由器名称 --不要出现中文、空格等特殊字符
#define CONNECT_PASS "12170307yu" //将要连接的路由器密码
#define CONNECT_SERVER_IP "a161a58a78.iot-mqtts.cn-north-4.myhuaweicloud.com" //服务器IP地址
#define CONNECT_SERVER_PORT 1883 //服务器端口
//JTAG模式设置,用于设置JTAG的模式
//mode:jtag,swd模式设置;00,全使能;01,使能SWD;10,全关闭;
#define JTAG_SWD_DISABLE 0X02
#define SWD_ENABLE 0X01
#define JTAG_SWD_ENABLE 0X00
void JTAG_Set(u8 mode)
{
u32 temp;
temp=mode;
temp<<=25;
RCC->APB2ENR|=1<<0; //开启辅助时钟
AFIO->MAPR&=0XF8FFFFFF; //清除MAPR的[26:24]
AFIO->MAPR|=temp; //设置jtag模式
}
u16 MQ3_data=0; //酒精浓度
float MQ3_data_float=0; //mg/l
char data_buff[100];
//酒精超标提示
u8 sim800c_buff[100]="Drunk driving reminder";
int main()
{
u8 state=0;
u8 key=0;
u32 time_cnt=0;
JTAG_Set(JTAG_SWD_DISABLE); //释放PA15
LED_Init(); //LED灯初始化
BEEP_Init(); //蜂鸣器初始化
KEY_Init(); //按键初始化
USART1_Init(115200); //串口1初始化-打印调试信息
Lcd_Init(); //LCD初始化
Lcd_Clear(0); //清屏为黑色
LCD_LED_SET; //通过IO控制背光亮
AdcInit(); //ADC初始化--检测酒精传感器的值
TIMER2_Init(72,20000);//辅助串口2接收,超时时间为20ms
USART2_Init(115200); //可能的波特率(测试): 57600 、9600、115200
USART3_Init(115200);//串口-WIFI
TIMER3_Init(72,20000); //超时时间20ms
//预热视频
LCD_ShowChineseFont(0,16*3,16,HZ_FONT_16[20],RED,0);
LCD_ShowChineseFont(16,16*3,16,HZ_FONT_16[21],RED,0);
LCD_ShowChineseFont(16*2,16*3,16,HZ_FONT_16[22],RED,0);
LCD_ShowChineseFont(16*3,16*3,16,HZ_FONT_16[23],RED,0);
LCD_ShowChineseFont(16*4,16*3,16,HZ_FONT_16[24],RED,0);
LCD_ShowChineseFont(16*5,16*3,16,HZ_FONT_16[25],RED,0);
LCD_ShowChineseFont(16*6,16*3,16,HZ_FONT_16[26],RED,0);
LCD_ShowChineseFont(16*7,16*3,16,HZ_FONT_16[27],RED,0);
//delay_ms(30000); //初始化时间30秒
delay_ms(5000); //初始化时间5秒
Lcd_Clear(0); //清屏为黑色
//采集数据的真实数据
LCD_ShowChineseFont(0,16*2,16,HZ_FONT_16[0],RED,0);
LCD_ShowChineseFont(16,16*2,16,HZ_FONT_16[1],RED,0);
LCD_ShowChineseFont(16*2,16*2,16,HZ_FONT_16[2],RED,0);
LCD_ShowChineseFont(16*3,16*2,16,HZ_FONT_16[3],RED,0);
//酒精含量计算结果
LCD_ShowChineseFont(0,16*3,16,HZ_FONT_16[4],RED,0);
LCD_ShowChineseFont(16,16*3,16,HZ_FONT_16[5],RED,0);
LCD_ShowChineseFont(16*2,16*3,16,HZ_FONT_16[6],RED,0);
LCD_ShowChineseFont(16*3,16*3,16,HZ_FONT_16[7],RED,0);
//酒精超标显示
Gui_DrawFont_GBK16(0,16*4,RED,0,(u8*)" ");
LCD_ShowChineseFont(0,16*4,16,HZ_FONT_16[16],RED,0);
LCD_ShowChineseFont(16,16*4,16,HZ_FONT_16[17],RED,0);
LCD_ShowChineseFont(16*2,16*4,16,HZ_FONT_16[18],RED,0);
LCD_ShowChineseFont(16*3,16*4,16,HZ_FONT_16[19],RED,0);
//初始化SIM800C
state=SIM800C_InitCheck();
printf("SIM800C初始化状态:%d\r\n",state);
DelayMs(1000);
//设置文本模式
state=SIM800C_SetNoteTextMode();
printf("设置文本模式状态:%d\r\n",state);
DelayMs(1000);
//
printf("正在初始化WIFI请稍等.\r\n");
for(i=0;i<5;i++)
{
if(ESP8266_Init()==0)
{
esp8266_state=1;
break;
}
else
{
esp8266_state=0;
printf("ESP8266硬件检测错误.\n");
}
}
if(esp8266_state)
{
printf("准备连接服务器....\r\n");
//非加密端口
printf("WIFI:%d\n",ESP8266_STA_TCP_Client_Mode(CONNECT_WIFI,CONNECT_PASS,CONNECT_SERVER_IP,CONNECT_SERVER_PORT,1));
//2. MQTT协议初始化
MQTT_Init();
//3. 连接服务器
for(i=0;i<5;i++)
{
if(MQTT_Connect(MQTT_ClientID,MQTT_UserName,MQTT_PassWord)==0)
{
esp8266_state=1;
break;
}
esp8266_state=0;
printf("服务器连接失败,正在重试...\n");
delay_ms(500);
}
printf("服务器连接成功.\n");
//3. 订阅主题
if(MQTT_SubscribeTopic(SET_TOPIC,0,1))
{
printf("主题订阅失败.\n");
}
else
{
printf("主题订阅成功.\n");
}
}
while(1)
{
key=KEY_Scan();
if(key)
{
printf("key=%d\r\n",key);
}
//控制LED灯
if(key==2)
{
LED2=!LED2;
}
//手动控制蜂鸣器测试
//手动发送短信测试
if(key==1)
{
BEEP=1;
delay_ms(100);
BEEP=0;
sprintf((char*)sim800c_buff,"Drunk driving reminder:%d",MQ3_data);
//发送短信
if(SIM800C_SendNote((u8*)"13800138000",sim800c_buff,strlen((char*)sim800c_buff))==0)
printf("短信发送成功\r\n");
else
printf("短信发送失败\r\n");
}
//轮询时间到达
if(time_cnt>300)
{
time_cnt=0;
LED1=!LED1;
//获取空气质量
MQ3_data=GetAdcCHxDATA(1);
printf("采集MQ3数据:%d\r\n",MQ3_data);
//上报数据
sprintf(data_buff,"{\"services\": [{\"service_id\":\"STM32\",\"properties\":{\"MQ3\":%d}]}",
MQ3_data);
MQTT_PublishData(POST_TOPIC,data_buff,0);
//上报数据
sprintf(data_buff,"{\"services\": [{\"service_id\":\"STM32\",\"properties\":{\"MQ3\":%d}]}",
MQ3_data);
MQTT_PublishData(POST_TOPIC,data_buff,0);
//LCD屏实时显示酒精浓度
//采集数据
sprintf(data_buff,"%d",MQ3_data);
Gui_DrawFont_GBK16(72,16*2,RED,0,(u8*)" ");
Gui_DrawFont_GBK16(72,16*2,RED,0,(u8*)data_buff);
//酒精含量
//MQ3_data_float=((float)MQ3_data*(5.0/4096))*0.36-1.08;
MQ3_data_float=((float)MQ3_data*(5.0/4096))*0.36;
sprintf(data_buff,"%0.2f mg/L",MQ3_data_float);
printf("计算酒精浓度:%s\r\n",data_buff);
Gui_DrawFont_GBK16(72,16*3,RED,0,(u8*)" ");
Gui_DrawFont_GBK16(72,16*3,RED,0,(u8*)data_buff);
//判断酒精浓度是否超标,设置阀值
if(MQ3_data>2000)
{
sprintf((char*)sim800c_buff," :%d",MQ3_data);
//发送短信
if(SIM800C_SendNote((u8*)"18171571217",sim800c_buff,strlen((char*)sim800c_buff))==0)
printf("短信发送成功\r\n");
else
printf("短信发送失败\r\n");
}
//采集的值越小,表明酒精浓度越高。反之越大。
//根据阀值显示不同的文字提示
if(MQ3_data>2000)
{
//你已酒驾
Gui_DrawFont_GBK16(0,16*4,RED,0,(u8*)" ");
LCD_ShowChineseFont(0,16*4,16,HZ_FONT_16[8],RED,0);
LCD_ShowChineseFont(16,16*4,16,HZ_FONT_16[9],RED,0);
LCD_ShowChineseFont(16*2,16*4,16,HZ_FONT_16[10],RED,0);
LCD_ShowChineseFont(16*3,16*4,16,HZ_FONT_16[11],RED,0);
}
//正常稳定范围采集的值是500左右
else
{
//安全范围
Gui_DrawFont_GBK16(0,16*4,RED,0,(u8*)" ");
LCD_ShowChineseFont(0,16*4,16,HZ_FONT_16[16],RED,0);
LCD_ShowChineseFont(16,16*4,16,HZ_FONT_16[17],RED,0);
LCD_ShowChineseFont(16*2,16*4,16,HZ_FONT_16[18],RED,0);
LCD_ShowChineseFont(16*3,16*4,16,HZ_FONT_16[19],RED,0);
}
}
DelayMs(10);
time_cnt++;
}
}
华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o
system-view进入系统视图quit退到系统视图sysname交换机命名vlan20创建vlan(进入vlan20)displayvlan显示vlanundovlan20删除vlan20displayvlan20显示vlan里的端口20Interfacee1/0/24进入端口24portlink-typeaccessvlan20把当前端口放入vlan20undoporte1/0/10删除当前VLAN端口10displaycurrent-configuration显示当前配置02配置交换机支持TELNETinterfacevlan1进入VLAN1ipaddress192.168.3.100
这篇文章是继上一篇文章“Observability:从零开始创建Java微服务并监控它(一)”的续篇。在上一篇文章中,我们讲述了如何创建一个Javaweb应用,并使用Filebeat来收集应用所生成的日志。在今天的文章中,我来详述如何收集应用的指标,使用APM来监控应用并监督web服务的在线情况。源码可以在地址 https://github.com/liu-xiao-guo/java_observability 进行下载。摄入指标指标被视为可以随时更改的时间点值。当前请求的数量可以改变任何毫秒。你可能有1000个请求的峰值,然后一切都回到一个请求。这也意味着这些指标可能不准确,你还想提取最小/
Unity自动旋转动画1.开门需要门把手先动,门再动2.关门需要门先动,门把手再动3.中途播放过程中不可以再次进行操作觉得太复杂?查看我的文章开关门简易进阶版效果:如果这个门可以直接打开的话,就不需要放置"门把手"如果门把手还有钥匙需要旋转,那就可以把钥匙放在门把手的"门把手",理论上是可以无限套娃的可调整参数有:角度,反向,轴向,速度运行时点击Test进行测试自己写的代码比较垃圾,命名与结构比较拉,高手轻点喷,新手有类似的需求可以拿去做参考上代码usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;u
文章目录1.开发板选择*用到的资源2.串口通信(个人理解)3.代码分析(注释比较详细)1.主函数2.串口1配置3.串口2配置以及中断函数4.注意问题5.源码链接1.开发板选择我用的是STM32F103RCT6的板子,不过代码大概在F103系列的板子上都可以运行,我试过在野火103的霸道板上也可以,主要看一下串口对应的引脚一不一样就行了,不一样的就更改一下。*用到的资源keil5软件这里用到了两个串口资源,采集数据一个,串口通信一个,板子对应引脚如下:串口1,TX:PA9,RX:PA10串口2,TX:PA2,RX:PA32.串口通信(个人理解)我就从串口采集传感器数据这个过程说一下我自己的理解,
动漫制作技巧是很多新人想了解的问题,今天小编就来解答与大家分享一下动漫制作流程,为了帮助有兴趣的同学理解,大多数人会选择动漫培训机构,那么今天小编就带大家来看看动漫制作要掌握哪些技巧?一、动漫作品首先完成草图设计和原型制作。设计草图要有目的、有对象、有步骤、要形象、要简单、符合实际。设计图要一致性,以保证制作的顺利进行。二、原型制作是根据设计图纸和制作材料,可以是手绘也可以是3d软件创建。在此步骤中,要注意的问题是色彩和平面布局。三、动漫制作制作完成后,加工成型。完成不同的表现形式后,就要对设计稿进行加工处理,使加工的难易度降低,并得到一些基本准确的概念,以便于后续的大样、准确的尺寸制定。四、
所有题目均有五种语言实现。C实现目录、C++实现目录、Python实现目录、Java实现目录、JavaScript实现目录题目n行m列的矩阵,每个位置上有一个元素你可以上下左右行走,代价是前后两个位置元素值差的绝对值.另外,你最多可以使用一次传送阵(只能从一个数跳到另外一个相同的数)求从走上角走到右下角最少需要多少时间。输入描述:第一行两个整数n,m,分别代表矩阵的行和列。后面n行,每行m个整数,分别代表矩阵中的元素。输出描述:一个整数,表示最少需要多少时间。
西安华为OD面试体验开始投简历技术面试进展工作进展开始投简历去年一整年一直在考研和工作之间纠结,感觉自己的状态好像当时的疫情一样差劲。之前刚毕业的时候投了个大厂的简历,结果一面写算法的时候太拉跨了,虽然知道时dfs但是代码熟练度不够,放在平时给足时间自己可以调试通过,但是熟练度不够那面试当时就写不出来被刷了。说真的算法学到后期我感觉最重要的是熟练度和背板子(对于我这种普通玩家来说),面试题如果一上来短时间内想不出思路就完蛋了。然后由于当时找的工作不是很理想就又想考研了。但是考研是有风险的,我自我感觉自己可能冲不上那个学校,而找工作一个没成可以继续找嘛。本着抱着试试看的态度在boss上投了简历,
LL库和HAL库简介LL:Low-Layer,底层库HAL:HardwareAbstractionLayer,硬件抽象层库LL库和hal库对比,很精简,这实际上是一个精简的库。LL库的配置选择如下:在STM32CUBEMX中,点击菜单的“ProjectManager”–>“AdvancedSettings”,在下面的界面中选择“AdvancedSettings”,然后在每个模块后面选择使用的库总结:1、如果使用的MCU是小容量的,那么STM32CubeLL将是最佳选择;2、如果结合可移植性和优化,使用STM32CubeHAL并使用特定的优化实现替换一些调用,可保持最大的可移植性。另外HAL和L
我有一个关于多维数组的初学者ruby问题。我想按年份和月份对条目进行排序。所以我想创建一个包含年->月->月条目的多维数组所以数组应该是这样的:2009->08->Entry1->Entry209->Entry32007->10->Entry5现在我有:@years=[]@entries.eachdo|entry|timeobj=Time.parse(entry.created_at.to_s)year=timeobj.strftime("%Y").to_imonth=timeobj.strftime("%m").to_itmparr=[]tmparrentry}@years.pu