没想到在模块到手的当天就能做出demo来。
看到了么,就是这么硬核的捆绑。传感器和电源模块之间用了纸隔离,尽可能地减少干扰并绝缘。这个作品实际就是个典型的物联网案例,网上的教程也是多到不知道哪里去了。不过大多数是用各种云来实现数据储存和远程可视化,用到自己服务器的例子并不多。
代码最后再放出,先讲讲这次经历的一些小问题。
传感器用的是AM2302,这个系列还挺多的。功能差不多,这个量程对于室内环境够用。温度零下40到80摄氏度,湿度0到100,精度0.2。最关键的,价格超级便宜。美中不足的就是他的汇报率比较低,不能毫秒级的获取数据。
另外,这次用的开发板也不一样。你可以叫他8266mini,你也可以叫他WeMos。就当他是个副厂WeMos吧,毕竟芯片相同,编译器来都以一样的。相比NoedeMCU,这个留的接口少了很多,但GPIO都在,只是和某些其他接口共用了,代码里可以具体定义。然后就是少了很多供电,只剩下一个3.3和GND了。多了个5v,直接从USB接过来的,不知道能不能用它反向供电。
这个体积非常妙,做不复杂的项目非常合适。再小就要用8266芯片加烧录器了,可以用它先做个过渡。
供电当然是用最简单粗暴的18650,网传芯片功耗大这电池顶不住主要还是看跑了什么。经过测试不加休眠代码,一小时50mah左右,所以一节电池直接跑大概就是两天左右。当然不要忘了,还有很多休眠代码,可以在执行任务期间保持最低的功耗,具体还测试,但估计还可以续一段时间。
说来蛋疼,买了两个8266的电池盒模块,上来第一个就接反了。其实我是看到正负的,开始正常插上去,发现USB口不输出,觉得很奇怪,习惯性的开始反接,怀疑是本来板子上就印错了。哪知反向一接,背后瞬间烫了我一下。当时想这东西估计歇逼了,果不其然,用万用表测了一下,倒也不是说全是0,只是输出的电压很低,并且开关不再起作用,充电也充不进去。
用第二个模块测试,正常接,还是没输出。插一下外接供电,再拔掉,这突然就有输出了。哪门子情况,难道是里面有拿个电容还需要充个电?当时就猜想,刚才被我反接的那个也不一定真就不行了。电子元件没那么脆弱,只要没烧糊,都有可能生还。
过了几个小时,再去测电压,不错,电压已经有些回来了,但还达不到5v。于是无聊开始拨弄开关,拨了几下,再测,恢复了。原因?未知。
好了,说回单片机Sniper再半个月前其实就做出了一摸一样的东西,只不过用了不一样的库,那时候它实际上给过我一份源码。然而,那份源码被我删了。
仿照示例,get到环境信息并不困难。问题还是出在了上传数据库这个环节。在之前,用8266传粉丝数据的时候就提到过,对char字符串进行了转换。
这次我们获取到的数据时浮点(float),这个东西比较蛋疼,当你直接定义值为INT的时候,他会四舍五入但能正常的传入数据库,INT是整形,没法在它上面添加小数点。最好还是能把float直接存入数据库,经过多种方法尝试,未果。所以最后还是决定把float转化为char,这个操作具体可以看下面的代码,也并不是太容易。
#include <ESP8266WiFi.h> // esp8266库
#include <MySQL_Connection.h> // Arduino连接Mysql的库
#include <MySQL_Cursor.h>
#include <ESP8266HTTPClient.h>
#include <Wire.h>
#include <WiFiUdp.h>
#include <Ethernet.h>
#include <Dns.h>
#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <DHT_U.h>
#define DHTPIN 2 // Digital pin connected to the DHT sensor
#define DHTTYPE DHT22 // DHT 22 (AM2302)
DHT_Unified dht(DHTPIN, DHTTYPE);
uint32_t delayMS;
char deviceid[] = "XXXXX";
char domain[] = "XXXXXXX"; //server host
char user[] = "XXXXX"; // Mysql的用户名
char password[] = "XXXXX"; // 登陆Mysql的密码
char INSERT_SQL[] = "INSERT INTO XXXXX.XXXX(Temp, Humi, Device) VALUES (%s, %s, %d)";
char ssid[] = "XXXXX"; // WiFi名
char pass[] = "XXXXXXX"; // WiFi密码
char Temp[15];
char Humi[15];
const unsigned long HTTP_TIMEOUT = 5000;
IPAddress server_ip;
WiFiClient client;
HTTPClient http;
WiFiUDP udp;
MySQL_Connection conn((Client *)&client);
MySQL_Cursor* cursor;
DNSClient dns_client;
void setup() {
Serial.begin(9600);
// Initialize device.
dht.begin();
Serial.println(F("Sensor"));
// Print temperature sensor details.
sensor_t sensor;
dht.temperature().getSensor(&sensor);
Serial.println(F("------------------------------------"));
Serial.println(F("Temperature Sensor"));
Serial.print (F("Sensor Type: ")); Serial.println(sensor.name);
Serial.print (F("Driver Ver: ")); Serial.println(sensor.version);
Serial.print (F("Unique ID: ")); Serial.println(sensor.sensor_id);
Serial.print (F("Max Value: ")); Serial.print(sensor.max_value); Serial.println(F("°C"));
Serial.print (F("Min Value: ")); Serial.print(sensor.min_value); Serial.println(F("°C"));
Serial.print (F("Resolution: ")); Serial.print(sensor.resolution); Serial.println(F("°C"));
Serial.println(F("------------------------------------"));
// Print humidity sensor details.
dht.humidity().getSensor(&sensor);
Serial.println(F("Humidity Sensor"));
Serial.print (F("Sensor Type: ")); Serial.println(sensor.name);
Serial.print (F("Driver Ver: ")); Serial.println(sensor.version);
Serial.print (F("Unique ID: ")); Serial.println(sensor.sensor_id);
Serial.print (F("Max Value: ")); Serial.print(sensor.max_value); Serial.println(F("%"));
Serial.print (F("Min Value: ")); Serial.print(sensor.min_value); Serial.println(F("%"));
Serial.print (F("Resolution: ")); Serial.print(sensor.resolution); Serial.println(F("%"));
Serial.println(F("------------------------------------"));
// Set delay between sensor readings based on sensor details.
delayMS = sensor.min_delay / 10000;
Serial.println("Device ID:");
Serial.print(deviceid);
Serial.printf("\nConnecting to WiFi");
WiFi.begin(ssid, pass); // 连接WiFi
while (WiFi.status() != WL_CONNECTED)
{ // 如果WiFi没有连接,一直循环打印点
delay(500);
Serial.print(".");
}
Serial.printf("\nConnected to %s", ssid);
Serial.print("\nLocal IP address: ");
Serial.print(WiFi.localIP()); // 打印开发板的IP地址
Serial.print("\nDevice MAC:");
Serial.println(WiFi.macAddress());
Serial.printf("DNS Server getting IP from hostname: %s", domain);
delay(1000);
dns_client.begin(Ethernet.dnsServerIP());
WiFi.hostByName(domain, server_ip);
Serial.print("\nDNS Process Successed !");
Serial.print("\nServer IP address: ");
Serial.println(server_ip);
Serial.print("Connecting to Database... \n");
delay(1000);
}
void pushsql()
{
char query[128];
sprintf(query, INSERT_SQL, Temp, Humi, deviceid);
delay(1000);
Serial.print("Ready to Push: ");
Serial.println(query);
delay(1000);
MySQL_Cursor *cur_mem = new MySQL_Cursor(&conn);
cur_mem->execute(query);
delay(1000);
Serial.print("Data Pushed !");
delay(1000);
delete cur_mem;
}
void umweltdata()
{
// Delay between measurements.
delay(2000);
delay(delayMS);
// Get temperature event and print its value.
sensors_event_t event;
dht.temperature().getEvent(&event);
if (isnan(event.temperature)) {
Serial.println(F("Error reading temperature!"));
}
else {
float tem = event.temperature;
dtostrf(tem,1,2,Temp);
Serial.print(Temp);
Serial.print(F("Temperature: "));
Serial.print(event.temperature);
Serial.println(F("°C"));
}
// Get humidity event and print its value.
dht.humidity().getEvent(&event);
if (isnan(event.relative_humidity)) {
Serial.println(F("Error reading humidity!"));
}
else {
float hum = event.relative_humidity;
dtostrf(hum,1,2,Humi);
Serial.print(Humi);
Serial.print(F("Humidity: "));
Serial.print(event.relative_humidity);
Serial.println(F("%"));
}
}
void loop() {
umweltdata();
delay(5000);
if (WiFi.status() == WL_CONNECTED)
{
if (conn.connect(server_ip, 3306, user, password)) // 连接数据库
Serial.print("Start getting Data!");
else
Serial.print("Connection to Server FAILED !!!");
cursor = new MySQL_Cursor(&conn); // 创建一个数据库游标实例
pushsql();
}
Serial.print("\nWaiting for next Push... 5min remaining!");
Serial.print("\n");
delay(15000);
}
可以看看SHTC3,精度挺高的,价格也比DHT22便宜,具体可以看我博客
看了一下,对比DHT22确实不错,目前使用BME的传感器。体积很小。