本帖最后由 Litthins 于 2021-1-23 17:43 编辑
物趣系列第二弹! LPC55S69之③:温湿度上云,网页实时显示
第二弹的目标是实现一款基于Web控制的超声雾化器(北方的冬天真干燥!)。 第一步,LPC55S69-EVK适配L610模块实现4G联网,使用HTTP协议POST方法上传数据至服务器。 第二步,LPC55S69-EVK搭配光耦实现本地超声雾化器控制。 第三步,LPC55S69-EVK获取温度湿度数据上传云端,网页远程显示温湿度波形,控制雾化器开关。 本贴!
本贴可帮助大家彻底掌握DHT11通信,包学会。直接开干!先上个完整系统照,如图。 在上一篇帖子中,我们已经实现了使用按键中断控制超声雾化器工作的功能。这一篇帖子主要解决温度湿度传感器的通讯问题和温湿度信息格式转换问题。通讯问题很好理解,什么是格式转换呢?因为微控制器获取的信息Web服务器无法直接解析,需要将其转换成可以理解的格式上传,这就是格式转换。 DHT11相信大家都很熟悉了。考虑到部分朋友可能没有接触过该类总线,这里先用Master-Slave模型梳理一下DHT11的单总线工作方式,再介绍使用LPC55S69单引脚外部中断配合定时器的通讯方法。 DHT11和微控制器构成Master-Slave关系,通信只能由Master发起,Master发出起始信号后,Slave才会响应。由于DHT11的DATA引脚使用1k~10k电阻进行了上拉处理,总线默认电平为高电平。先上个时序图,该图截自奥松电子DHT11数据手册。 整个通信由4部分组成,分别是Master-Start、Slave-Ack、Slave-Data、Slave-End。以上是DHT11单总线的特征。 ①Master-Start:通讯开始时,Master将总线拉低,然后释放。这里拉低的时间有明确的要求,在18~30ms内,Slave将判定为有效起始信号,并产生响应。这里使用的是22ms。 ②Slave-Ack:接收到起始信号后,Slave会产生一个响应信号。Slave先将总线拉低83us,再释放总线。从总线被Slave释放,至数据开始输出,这个时间是87us。所以整个响应是170us。 ③Slave-Data:这部分输出传感器数据。数据有5个字节,以40个bit的形式发送。如果输出54us低电平,24us高电平,则该bit为0;如果输出54us低电平,71us高电平,则该bit为1。 为方便表述,下文以Data[0~4]表示这5字节数据。数据可分为三个部分。第一部分为湿度,Data[0]代表湿度高八位,Data[1]代表湿度低八位。由于湿度低八位为0,湿度可用Data[0]表示。第二部分为温度,Data[2]代表温度高八位,Data[3]代表温度低八位。高八位为温度整数部分,低八位为温度小数部分,温度用Data[2]+0.1*Data[3]表示。需要注意,如果温度低八位的最高位为1,则该温度为负数。例如,0000 0001 1000 0001代表-1.1℃。Data[4]为校验字节,若Data[0]+Data[1]+Data[2]+Data[3]=Data[4],则以上数据接收正确。 ④Slave-End:数据传输完成后,Slave继续将引脚拉低54us,随后释放总线。通信完成。 有点晕乎?没关系,看下面两个图: Master-Start为负脉冲,在图中用大圆标出,宽度22us,其后密集的脉冲是Slave-ACK、Slave-Data和Slave-End,用小圆标出。 将时间跨度调小,可以看到,Master-Start后,紧跟着Slave-ACK,约170us,其后为Slave-Data阶段,数据逐bit输出。窄脉冲代表0,宽脉冲代表1。有了这两个图,是不是好理解很多? 经过以上梳理可知,欲使用单引脚实现通信功能,首先需要将引脚配置为输出模式,待第一阶段Master-Start完成后,切换到输入模式方可获取数据。输入模式须要开漏。 观察时序特点,数据bit值由该bit传输时间决定,因此只要能获取传输40个bit对应的时间开销序列,就能成功获取数据。这里使用PINT外部引脚下降沿中断来获取bit传输状态,使用CTIMER实现计时功能。 通信引脚选用PIO1_11,其位于LPC55S69-EVK P17连接器第6引脚。中断配置见下图。
通过每次进入中断,停止定时器,读取定时器值,清空定时器,启动定时器四个步骤,即可获取当前bit传输的时间开销。定时器使用CTIMER0,采用1MHz时钟,通过下图配置可实现1us定时器计数+1。 声明一个uint8_t型数组ctimer_cnt_us存放每次进入中断读取的定时器计数值,ctimer_cnt_round为数据bit索引,以下为代码片段: - CTIMER_StopTimer (CTIMER0_PERIPHERAL);
- ctimer_cnt_us[ctimer_cnt_round] = CTIMER_GetTimerCountValue (CTIMER0_PERIPHERAL);
- CTIMER_Reset (CTIMER0_PERIPHERAL);
- CTIMER_StartTimer (CTIMER0_PERIPHERAL);
复制代码 为时间开销建立一个整形比较标准Countref,通过比较取得bit值,并循环获得完整的字节数据: - for (...)
- data_byte = (data_byte << 1) | (ctimer_cnt_us[索引值] > Countref ? 1 : 0);
复制代码 最后对所得5个字节进行校验: - if (sensor_data[0] + sensor_data[1] + sensor_data[2] + sensor_data[3] == sensor_data[4])
复制代码 若校验通过,即接收数据正确,通信完成!下图是作者调试程序时的校验结果,28+0+24+4=56,正确。大冬天24℃?身为南方人的我表示北方暖气太棒了! 完成传感器通信后,最重要一步即是对数据格式进行调整,使其能被服务器解析。 由于Web服务器被设计成分别接收4位16进制数作为温湿度数据。支持的湿度范围为0~100%,温度范围为-20~+80摄氏度。湿度计算公式:网页湿度=上传数据值/0xFFFF*100,网页温度=上传数据值/0xFFFF*100-20。 又DHT11的湿度范围为5~95%,温度范围为-20~+60摄氏度,落在设计范围内,故仅通过以下算法调整格式:上传湿度数据值=本地湿度*0xFFFF/100,上传温度数据值=(本地温度+20)*0xFFFF/100,数值使用itoa函数转化为字符串。 - itoa ((uint32_t) (sensor_data[0] * 0xFFFF / 100), humidity_coded, 16);
- itoa ((uint32_t) ((float) sensor_data[2] + (float) sensor_data[3] * 0.1 + 50) * 0xFFFF / 100, temperature_coded, 16);
复制代码 如此便可将数据上传到服务器端,以下为网页测试效果。 实时上传: 数据浏览:
作战成功! 敬请期待视频大更新,物趣系列第二弹!LPC55S69基于Web控制的超声雾化器设计。谢谢大家!
|