NodeMCU具有较为丰富的对外接口和多个IO,可驱动多种传感器使用,本次例程将使用NodeMCU实现温湿度传感器DHT11的数据采集,以及数据的阿里云物联网平台上报。
DHT11温湿度传感器使用
学习过TinyEngine的同学可能看过DeveloperKit shtc1传感器的驱动脚本:
发现全是16进制的数据以及+-x/各类数据变化,看到这里别见怪,传感器就是能够将真实世界的物理量映射成为电信号,再通过数字电路(甚至模拟电路)进行编码或映射得到的数据,部分售价较高的传感器传输的数据为已经编码好的(即在传感器内部再加变送器模块,实现数据的误差消除、格式封装、传输协议适配等等),而一些性价比高的传感器往往没有复杂的电路,类似shtc1,只是将温度和湿度使用数字电路封装成字节码就给送出来了,需要开发者在外置程序中对数据进行处理和变换。
类似于在线TinyEngine和在线JavaScript开发工作台提供的转换驱动程序脚本,在Arduino环境一些主流的传感器都有驱动库支持,免去了开发者再查找各类datasheet对数据进行转换的痛苦。
接线图
请参照以下接线方式进行:
安装DHT11驱动库
在这里我们使用Adafruit提供的DHT系列传感器库,在库管理器搜索DHT11,选择安装即可(示例安装1.3.4版本)
这个库部分程序依赖Adafruit_seneor包(本人在github找到,但是觉得麻烦,这里直接在库文件中将相关依赖部分删除—并不用到)。
在Arduino IDE中找到DHT_Sensor库提供的例程。
修改传感器引脚、传感器型号、通信波特率后下载代码至NodeMCU,观察串口输出。

程序输出
程序正常输出后,在串口监视器将自动打印传感器采集到的温湿度数据,传感器调试完成。
程序粗略分析
在setup()函数中,进行串口初始化以及传感器对象的初始化设置,在loop()函数中进行温湿度数据的读取和打印,其中:
- 温度:
float t = dht.readTemperature(); - 相对湿度:
float h = dht.readHumidity();
温湿度数据上云
通过DHT11传感器数据以及前面设备上云的例程之后,相信你可以很快地将两个程序整合在一起,按照阿里云物联网平台的设备模型,封装成Alink JSON格式的数据进行上报,阿里云物联网平台依据设备模型进行解析。
设备模型定义
我们在物联网平台上定义一款空气盒子产品,包含“当前温度”、“相对湿度”两个属性。
设备端开发
设备端程序开发,在NodeMCU上云例程的基础上进行代码修改。
- 修改设备三元组信息以及MQTT连接信息(略)
- 在程序最上方引入DHT11库
#include "DHT.h" 在程序开始加入传感器定义
#define DHTPIN 13 // Digital pin connected to the DHT sensor#define DHTTYPE DHT11 // DHT 11DHT dht(DHTPIN, DHTTYPE);
在初始化添加dht初始化:
dht.begin();- 在mqttIntervalPost()函数中封装温湿度Alink JSON格式数据:
//mqtt循环发送内容void mqttIntervalPost(){//读取传感器数据float h = dht.readHumidity();// Read temperature as Celsius (the default)float t = dht.readTemperature();// Read temperature as Fahrenheit (isFahrenheit = true)float f = dht.readTemperature(true);// Check if any reads failed and exit early (to try again).if (isnan(h) || isnan(t) || isnan(f)) {Serial.println(F("Failed to read from DHT sensor!"));return;}char param[32];char jsonBuf[128];//注意设备模型定义的属性小数点位数需要符合才可以被平台解析sprintf(param, "{\"CurrentHumidity\":%.0f,\"CurrentTemperature\":%.1f }",h,t);sprintf(jsonBuf, ALINK_BODY_FORMAT, ALINK_METHOD_PROP_POST, param);Serial.println(jsonBuf);client.publish(ALINK_TOPIC_PROP_POST, jsonBuf);}
待设备持续上报时,在阿里云物联网平台即可看到设备实时运行属性:
完整参考代码
#include <ArduinoJson.h>#include <ESP8266WiFi.h>#include <PubSubClient.h>#include "DHT.h"#define DHTPIN 13 // Digital pin connected to the DHT sensor#define DHTTYPE DHT11 // DHT 11/* 连接您的WIFI SSID和密码,这个9个设备可以一致 */#define WIFI_SSID "mimi8"#define WIFI_PASSWD "123456788"/* 产品的三元组信息,根据9个测试设备的三元组,每个设备都烧录不同的*/#define PRODUCT_KEY "换"#define DEVICE_NAME "换"#define DEVICE_SECRET "换"/* LD线上环境域名和端口号,不需要改 */#define MQTT_SERVER PRODUCT_KEY".iot-as-mqtt.cn-shanghai.aliyuncs.com"#define MQTT_PORT 1883#define MQTT_USRNAME DEVICE_NAME "&" PRODUCT_KEY// TODO: MQTT连接的签名信息,哈希加密请以"clientIdtestdeviceName"+设备名称+"productKey"+设备模型标识+“timestamp123456789”前往http://tool.oschina.net/encrypt?type=2进行加密//clientId可以随意命名,以下为test,加密生成MQTT_PASSWD的秘钥为设备的deviceSecret// HMACSHA1_SRC clientIdtestdeviceNamehuman04productKeya1rezUVs103timestamp123456789#define CLIENT_ID "hello|securemode=3,timestamp=123456789,signmethod=hmacsha1|"#define MQTT_PASSWD "换"#define ALINK_BODY_FORMAT "{\"id\":\"123\",\"version\":\"1.0\",\"method\":\"%s\",\"params\":%s}"#define ALINK_TOPIC_PROP_POST "/sys/" PRODUCT_KEY "/" DEVICE_NAME "/thing/event/property/post"#define ALINK_TOPIC_PROP_POSTRSP "/sys/" PRODUCT_KEY "/" DEVICE_NAME "/thing/event/property/post_reply"#define ALINK_TOPIC_PROP_SET "/sys/" PRODUCT_KEY "/" DEVICE_NAME "/thing/service/property/set"#define ALINK_METHOD_PROP_POST "thing.event.property.post"unsigned long lastMs = 0;DHT dht(DHTPIN, DHTTYPE);WiFiClient espClient;PubSubClient client(espClient);//下行消息的回调函数void callback(char *topic, byte *payload, unsigned int length){Serial.print("Message arrived [");Serial.print(topic);Serial.print("] ");payload[length] = '\0';Serial.println((char *)payload);if (strstr(topic, ALINK_TOPIC_PROP_SET)){StaticJsonBuffer<100> jsonBuffer;JsonObject& root = jsonBuffer.parseObject(payload);if (!root.success()){Serial.println("parseObject() failed");return ;}}}//wifi初始化连接函数void wifiInit(){WiFi.mode(WIFI_STA);WiFi.begin(WIFI_SSID, WIFI_PASSWD);while (WiFi.status() != WL_CONNECTED){delay(1000);Serial.println("WiFi not Connect");}Serial.println("Connected to AP");Serial.println("IP address: ");Serial.println(WiFi.localIP());client.setServer(MQTT_SERVER, MQTT_PORT); /* 连接WiFi之后,连接MQTT服务器 */client.setCallback(callback);}//mqtt连接检查函数void mqttCheckConnect(){while (!client.connected()){Serial.println("Connecting to MQTT Server ...");if (client.connect(CLIENT_ID, MQTT_USRNAME, MQTT_PASSWD)){Serial.println("MQTT Connected!");// client.subscribe(ALINK_TOPIC_PROP_POSTRSP);client.subscribe(ALINK_TOPIC_PROP_SET);Serial.println("subscribe done");}else{Serial.print("MQTT Connect err:");Serial.println(client.state());delay(5000);}}}//mqtt循环发送内容void mqttIntervalPost(){//读取传感器数据float h = dht.readHumidity();// Read temperature as Celsius (the default)float t = dht.readTemperature();// Read temperature as Fahrenheit (isFahrenheit = true)float f = dht.readTemperature(true);// Check if any reads failed and exit early (to try again).if (isnan(h) || isnan(t) || isnan(f)) {Serial.println(F("Failed to read from DHT sensor!"));return;}char param[32];char jsonBuf[128];sprintf(param, "{\"CurrentHumidity\":%.0f,\"CurrentTemperature\":%.1f }",h,t);sprintf(jsonBuf, ALINK_BODY_FORMAT, ALINK_METHOD_PROP_POST, param);Serial.println(jsonBuf);client.publish(ALINK_TOPIC_PROP_POST, jsonBuf);}//初始化函数void setup(){/* initialize serial for debugging */Serial.begin(115200);Serial.println("Demo Start");wifiInit();dht.begin();}//主函数// the loop function runs over and over again forevervoid loop(){if (millis() - lastMs >= 5000){lastMs = millis();mqttCheckConnect();Serial.println("start once!");/* 上报 */mqttIntervalPost();}client.loop();}
