esp8266实验:搭建最小系统,刷nodemcu固件,dht11温度读取并上传服务器

1.材料清单

  • esp8266-12E模块
  • esp8266转接板
  • cp2102模块 or ch304g模块
  • 轻触开关
  • 洞洞板
  • HT7533A-1 3.3v稳压芯片
  • 3.7v锂电池
  • DHT11温度湿度模块

2.焊接esp8266转接板,制作测试底板

esp8266模块不是特别小,实际使用可以直接把它焊在洞洞板上,但是作为反复使用的话,建议焊接到转接板上。洞洞板上主要元件有左右各两排排针,引出所有io口,两个按钮,左边按钮按下拉低rest口,实现重启,右边按钮拉低GPIO0(模块右边第五个引脚)口,刷入固件的时候需要按下该按钮。左边有一个ht7533稳压管和2个10uf的电容组成的稳压电路。下面有个排针,用来插入cp2102 usb转串口模块。


3.下载nodemcu固件,并刷入esp8266模块中

nodemcu固件有很多个模块,所有功能都编译的话,有可能esp8266Flash空间不够,所以需要根据应用需要编译所需功能,推荐使用在线编译服务,和jquery ui一样,通过网页打钩选择需要的功能,填写你的邮箱,提交后等待后台生成完毕会发送邮件通知你,并在邮件里附上下载地址。https://nodemcu-build.com/ 。邮件里会提供2个版本的固件,我是选择浮点的版本。
到乐鑫的官网下载Flash Download Tools,该工具可以用来刷固件用,windows下使用,nodemcu文档里也提到了另外的刷固件工具,如esptools,跨平台的,不过我在linux mint下使用ch340G模块并不能刷入成功,而使用Flash Download Tools在windows下则成功,原因没有细究,能成功即可。
最上面的Download Path Config 勾选一项即可,选择nodemcu固件位置,并在右边的地址填写“0x00000”,其他如图:

刷固件的方法是:

1.点击下方的Star,显示等待

2.先按下洞洞板上的右边按钮(拉低GPIO0),再按下左边的按钮(拉低rest),然后放开左边按钮,再放开右边按钮。这样就进入刷固件模式。

3.如无意外,软件会显示下载进度条,等100%完成了,重新按下左边按钮重启esp8266模块。

4.第一次刷完固件重启,模块需要格式化flash,这需要一分钟时间吧,所以第一次刷完固件按重启后需要等等。如果你使用putty或者minicom连接着串口(比特率115200),应该会看到正在格式化的文字.

遇到的坑

我购买的usb转串口模块型号是cp2102,win10下无法下载固件,而且其3.3v电压口,实测电压高达3.9V。因为没法使用所以改为ch304g模块。

4.编写代码,实现读取dht11的温度

使用工具ESPlorer,跨平台,提供代码编写上传和串口功能,分左右2个界面,左边写代码,写完通过下面的按钮发送到esp8266上,然后右边的串口窗口可以看数据。

约定

dht11的数据引脚接在GPIO12口,即左边第六个。

服务器端

服务器端我使用python+django,在百度的bae上部署,实现简单的接收http post请求,校验数据并入库。

通讯逻辑

服务器端保存传感器的2个信息:mac地址加密密码。esp8266模块通过http post请求将5个参数发送到服务器:

  • humi:湿度,单位整数。

  • mac:模块的mac地址。

  • rnd:随机数。

  • temp:温度,单位整数。

  • sign:以上4个参数按字母升序排序的post数据,使用保存在服务器的密码进行hmac-sha1加密得到的字符。
    这样可以有效的防止伪造数据,但是有一个小缺点,就是里面没有时间戳,会导致回放。

esp8266模块的代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
print("init.lua script run")
function startup()
print("startup run")
if not tmr.create():alarm(180000,tmr.ALARM_AUTO,task) then
print("tmr task start faild")
else
task()
end
end
function task(cb_timer)
print("task run")
pin=6
status,temp,humi,temp_dec,humi_dec=dht.read11(pin)
if status == dht.OK then
print(string.format("DHT Temperature:%d.%03d;Humidity:%d.%03d\r\n",
math.floor(temp),
temp_dec,
math.floor(humi),
humi_dec
))
mac=wifi.sta.getmac()
rnd=node.random(1000)
data=string.format("humi=%d&mac=%s&rnd=%d&temp=%d",
math.floor(humi),
mac,
rnd,
math.floor(temp))
signature = crypto.toHex(crypto.hmac("sha1",data,"密码"))
http.post("http://bae的域名.duapp.com/life/dht",'Content-Type:application/x-www-form-urlencoded\r\n',data..'&sign='..signature,function(code,data)
if (code ==404) then
print("device not found")
elseif code ~=200 then
print("HTTP request failed")
end
end)
elseif status == dht.ERROR_CHECKSUM then
print("DHT Checksum error.")
elseif status ==dht.ERROR_TIMEOUT then
print("DHT timed out.")
end
end
wifi.setmode(wifi.STATION)
wifi.sta.config("wifi名字","wifi密码")
tmr.create():alarm(1000,tmr.ALARM_AUTO,function(cb_timer)
if wifi.sta.getip()==nil then
print("Waiting for IP address...")
else
cb_timer:unregister()
print("Wifi connection,IP address:".. wifi.sta.getip())
tmr.create():alarm(3000,tmr.ALARM_SINGLE,startup)
end
end)

提示

DHT11的精度并不是很好,精度为1摄氏度,我有2个模块,一个单独淘宝购买的,一个在某块开发板上面的,同样的代码2个模块读书相差3度,湿度则相差更多。

5.锂电池上电,电源问题

电源部分的内容我还掌握的不够好,本次使用了HT7533A-1的稳压模块,它的封装像三极管一样比较好插在洞洞板上进行焊接,根据基本电路在两端加上10uf的电容,接上锂电池后,测得输出端电压为3.29V,正常。esp8266模块插入洞洞板,发觉模块的led等快速闪烁,模块不能正常运行,猜测是在不断重启,至于原因,我猜测是外围电路不对,例如哪些引脚没有接电阻上拉或下拉,或者电压不足电流不足。通过测量上电后模块电压,发现电压下降到2.7V,整个电路电流170mA。于是拔出锂电池,使用外部3.3V直接接入模块,模块正常,且电流为70mA左右。那么初步判断是稳压管模块的供电问题。手里头有662k稳压芯片,但是那个封装太小,放在洞洞板上不容易焊接,还有ams1117-3.3V模块,但是那个需要的压差大概1V,单块锂电池无法使用。最后没有好方法的情况下,直接锂电池供电,模块手册说输入电压最大不超过3.6V,实测锂电池电压3.9V,并没有烧坏。

6.持续测试

最后使用锂电池(标称1000mA)直接供电模式运行,从上面的代码看到,模块使用了定时器大概3分钟执行一次读取温度湿度并上传,但是没有使用休眠,wifi也应该一直连接着,看看能用多久。

2017年02月15日:模块停止工作了,查看后台最后的数据,经过计算运行了39小时,但是和水银温度计(一刻度为2摄氏度,总量程200度)对比,存在2度误差。

7.改进休眠,继续测试

2017年02月20日

上面的代码并没有使用休眠功能,所以对代码进行改造,增加休眠功能。

增加休眠功能的代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
function task(cb_timer)
print("task run")
pin=6
status,temp,humi,temp_dec,humi_dec=dht.read11(pin)
if status == dht.OK then
print(string.format("DHT Temperature:%d.%03d;Humidity:%d.%03d\r\n",
math.floor(temp),
temp_dec,
math.floor(humi),
humi_dec
))
mac=wifi.sta.getmac()
rnd=node.random(1000)
data=string.format("humi=%d&mac=%s&rnd=%d&temp=%d",
math.floor(humi),
mac,
rnd,
math.floor(temp))
signature = crypto.toHex(crypto.hmac("sha1",data,"密码"))
http.post("http://<域名>.duapp.com/life/dht",'Content-Type:application/x-www-form-urlencoded\r\n',data..'&sign='..signature,function(code,data)
if (code ==404) then
print("device not found")
elseif code==200 then
print("upload success")
elseif code ~=200 then
print("HTTP request failed")
end
print("sleep")
node.dsleep(180000000)
end)
elseif status == dht.ERROR_CHECKSUM then
print("DHT Checksum error.")
elseif status ==dht.ERROR_TIMEOUT then
print("DHT timed out.")
end
end
wifi.setmode(wifi.STATION)
wifi.sta.config("wifi","wifi密码")
tmr.create():alarm(1000,tmr.ALARM_AUTO,function(cb_timer)
if wifi.sta.getip()==nil then
print("Waiting for IP address...")
else
cb_timer:unregister()
print("Wifi connection,IP address:".. wifi.sta.getip())
tmr.create():alarm(4000,tmr.ALARM_SINGLE,task)
end
end)

关键字:node.dsleep(180000000)

这次修改主要是增加了dsleep功能。需要注意,使用休眠功能,需要将rest脚(左边第一个)和GPIO16(左边第四个)连接。继续测试功耗。

实际模块运行了77小时左右。由于dht11模块是一直供电而且还有一个led灯一直亮着,估计这里可以再优化,其次查询文档,发现还有其他休眠方式如rtctime.dsleep(),接下来慢慢测试。