本篇目标:驱动温湿度传感器SI7021,并把温湿度数据上传到物联网平台ONENET平台上,然后在平台上建立应用,使之能够分享。
材料准备:
- STM32F407接入ONENET平台代码:上一篇文章最终修改代码(STM32F4接入ONENET)
- STM32F407上传温湿度至ONENET平台代码:为了下载方便,把温湿度SI7021驱动代码和最终修改代码放在了一起(温湿度上传平台最终代码)
温湿度SI7021硬件连接与接口
温湿度SI7021的接线比较简单:
SI7021通信用的是I2C接口,所以将SCL和SDA引脚对应接到STM32F4的I2C硬件接口引脚上,或者简单点就接到任意IO口引脚上,建议接到IO口上,对于这些低速模块化的设备,通用的模拟I2C代码可以非常快速的驱动传感器,只需要会MCU的IO口操作即可。
I2C接口协议简单介绍
这里推荐一篇博客(I2C协议解析),博客里,已经把I2C的基本概念讲的比较清楚了,主要就包括几个信号:
- 起始信号
- 写数据信号
- 读数据信号
- 应答信号
- 非应答信号
- 终止信号
把这几个信号了解后,可以来了解I2C协议的通信过程,如图:
主发从收:
主收从发:
移植温湿度SI7021驱动
将上面的准备材料 stm32f4温湿度上传onenet 文件夹打开,将temp文件夹复制到上一篇的最终修改代码文件夹中的dev文件夹下。
- 用keil打开工程。
- 在Manage Project Items添加文件夹temp,然后添加刚才拷贝文件下的C文件。
- 在Options->C/C++->Include Paths添加刚才复制文件的路径。
- 修改SI7021.h文件中对应的I2C引脚,应该用注释标出。
- 在main.c中添加头文件:
#include "SI7021.h"
- 定位main.c第62行,往Sys_Config();后面添加初始化函数:
/* stm32系统配置 */
Sys_Config();
/* SI7021温度传感器IO初始化配置 */
SI_IO_Init(); //新添加
/* WIFI模块IO初始化配置 */
NET_DEVICE_IO_Init();
- 在初始化函数后面先添加SI7021温湿度转换读取函数:
SI7021_measure();
- 查看一下打印结果:
发现温度与湿度已经能够正常地读取出来了,接下来就把数据传到ONENET平台上。
温湿度SI7021代码解析
先来看一下SI7021数据手册的命令和数据I2C发送过程:
再看下SI7021有哪些指令:
以及SI7021的ID:
再来对着代码观察一下:
uchar SI70XX_Sensor_Measure( uchar Config, uint *Value )
{
uchar Data[2];
SI_start();
SI_W_Byte(0x80);// si7021的id为0x40,最后一位为写,加起来为0x80
if(Slave_acknowledge())//等待应答,无反应直接退出
{
//容错处理,防止死等
return(0);
}
SI_W_Byte(Config); //发送命令
Slave_acknowledge(); //等待应答
delay_ms(20);//>=20ms等待转换
SI_start();
SI_W_Byte(0x81); //ID+读命令
Slave_acknowledge(); //等待应答
Data[0]=SI_R_Byte(); //读数据高位
Master_acknowledge(); //等待应答
Data[1]=SI_R_Byte(); //读数据低位
No_ack(); //非应答
SI_stop(); //停止
/* Swap the bytes and clear the status bits */
*Value = (Data[0]<<8) + Data[1]; //组成16位温度或湿度数据
return(1);
}
再来看看温度和湿度的计算公式:
温度:
湿度:
对比代码:
uchar SI7021_measure(void)
{
uint Value;
// uchar temp;
uchar ucConversion_OK=0;//转换成功标记
//开启测试
SI_stop();//以防万一,先弄条停止位
ucConversion_OK=SI70XX_Sensor_Measure(CMD_MEASURE_TEMPERATURE_NO_HOLD, &Value ); //温度转换命令及读取
if(!ucConversion_OK)
{
//转换失败,直接退出,方便模块热插拔
SI70XX.inTemp = 0;
SI70XX.unHumi = 0;
return(0);//错误=0
}
SI70XX.inTemp = ((((long)Value)*1757)>>16) - 469;
Temp_buf = (((((float)Value)*175.72f)/65536.0f) - 46.85f); //温度计算,按照数据手册公式
SI70XX_Sensor_Measure(CMD_MEASURE_HUMIDITY_NO_HOLD, &Value ); //湿度转换命令及读取
SI70XX.unHumi = ((((long)Value)*625)>>15) - 60;
Humi_buf = (((((float)Value)*125.0f)/65535.0f) - 6.0f); //湿度计算,按照数据手册公式
printf("\r\nTemp:%.2f\r\n",Temp_buf);
printf("Humi:%.2f\r\n",Humi_buf);
return(1);//正常=1
}
温湿度上传ONENET
- 定位main.c第97行,在case SEND_TYPE_DATA:后面添加代码:
case SEND_TYPE_DATA:
//新添加
if (!SI7021_measure())
{
printf("\r\nTemp Data Error!\r\n");
}
OneNet_SendData(FORMAT_TYPE3, NULL, NULL, dataStream, dataStreamCnt);//上传数据到平台
printf("\r\nOnenet Data Ready.\r\n");
break;
这样在每次可以发送数据的时候就转换一次温湿度。
- 定位main.c第45-50行,替换变量,主要用于定义上传平台的变量:
extern float Temp_buf;
extern float Humi_buf;
DATA_STREAM dataStream[] = {
{"Home_Temp", &Temp_buf, TYPE_FLOAT, 1}, //温度上传结构体
{"Home_Humi", &Humi_buf, TYPE_FLOAT, 1}, //湿度上传结构体
};
unsigned char dataStreamCnt = sizeof(dataStream) / sizeof(dataStream[0]);
- 优化一下代码,定位onenet->dStream.c第87行,把 %f 改为 %.1f 这样就只显示一位小数。
- 看一下打印数据:
- 再登录ONENET自己的设备中心查看一下数据,如图:
湿度:
温度:
好啦,温湿度就这样上传到平台啦,但是这样看好看不太习惯,接下来就来简单创建个应用来显示这些数据。
ONENET建立应用
- 登录ONENET平台->开发者中心->设备管理->点进自己的设备->找到关联应用->立即创建。
- 填写相关内容创建应用
- 点击第二个小按钮编辑
- 可以看到里面可以添加很多东西,添加折线图,属性数据流选择自己设备的数据流,比如温度曲线选择Temp,湿度曲线选择Humi,完成如图:
- 右上方点击发布即可
- 返回到应用主页有个“发布链接”,把这个地址发给别人,别人就可以通过浏览器看数据了:
小结:在物联网时代,任何数据都可以上传物联网平台,这样很方面自己检测一些自己想要的数据或者环境,今后有什么特别的想法继续探讨,共勉~