极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 30862|回复: 14

攀藤G5空气质量上报乐联网教程,PM2.5 HCHO NodeMcu(8266) si7021

[复制链接]
发表于 2016-4-1 15:56:49 | 显示全部楼层 |阅读模式
本帖最后由 wetnt 于 2016-12-10 12:56 编辑

   空气质量上报乐联网—攀藤G5(PM2.5)+NodeMcu(8266)+si7021+Lewei

   乐为物联网的活动提供的套件,借机学习下NodeMcu(8266)的用法。之前开工贴在此:[url]http://www.geek-workshop.com/thread-26378-1-1.html[/url]

一、模块介绍


    NodeMcu带一个扩展板,支持si7021传感器和攀藤G5传感器。


    攀藤G5(PM2.5)传感器,采用串口输出数据模式,每秒钟输出一次数据,串口监听就好。


    si7021采用了IIC总线,利用si7021库可以方便读取数据。


    甲醛传感器,也是采用串口输出数据的方式,不过需要发送特定的字段请求数据。NodeMcu只有一个串口,这次实验暂时没有把它的数据集成进去。(另外一个帖子里有介绍:甲醛测试仪+ESP8266+LeWei

    在另外一个帖子里,将采用Arduino MEGA上传所有传感器数据。


二、制作过程

    制作过程很简单了,配套的扩展板很完善,直接将模块、传感器插在上面就ok了。

    不过需要注意的是,NodeMcu是和Arduino完全不同的一款设备,Arduino像是个电脑,而NodeMcu则像是一个操作系统,Arduino直接烧录软件,而NodeMcu是对上传到Flash的文件进行解释运行;使用习惯上有非常的不同。真正使用过程中遇到很多问题,纠结了很久才都解决。回头从新开贴说下“NodeMcu的使用心得”。

步骤如下:

1、NodeMcu连上手机USB线,插入电脑USB口,就等系统识别硬件,自动安装驱动程序好了。如果安装不成功,需要手动安装。


2、烧录bin文件。需要下载烧录软件、bin文件。

    其中bin文件下载地址:http://bbs.nodemcu.com/t/nodemcu-firmware-download-build-20150318-new-location/27,也可以在GitHUB上下载:https://github.com/nodemcu/nodemcu-firmware/releases/tag/0.9.6-dev_20150704,不过国家防火墙问题,经常访问不到。



    其中有两个版本:nodemcu_float_0.9.6-dev_20150704.bin、nodemcu_integer_0.9.6-dev_20150704.bin,一个是具备浮点功能,另外一个只是整数功能。差别呢就是“integer”版本不能处理小数,精度要求高的地方的用“float”版本,但我的NodeMcu板子float版本老刷入不成功。建议两个版本都下载,后面有用处。

烧录软件下载,之前在网络上搜索了很多版本,这些版本都可以刷入bin,但板子却没反应,建议大家下载最新的 “ESP8266Flasher.exe”版本。界面如图:





刷入波特率是:230400,而连接波特率是:9600,有些模块需要RST按键才能响应串口连接

如果烧录成功之后板子没有回显响应,应该是有init.lua文件嵌入,你换刚才提到的另外一个bin刷下就ok,不然板子永远不受你控制!这个地方浪费了我大量的时间和精力!

3、下载IDE。NodeMcu官网IDE是垃圾建议不要用,问询了群里许多朋友,推荐用“ESPlorer”,JAVA软件写的需要java环境。




三、软件代码

init.lua

  1. -- init.lua
  2. --=============================================================
  3. print("\nBBK_Lewei_Started_si7021_pm2.5_init.lua")
  4. require("bbk_log")
  5. require("bbk_ip_info")
  6. lg("require_ok")
  7. --=============================================================
  8. function Do_Next_File()
  9.      lg("Do_Next_File")
  10.      dofile("bbk_si7021_pm25_lewei_ok.lua")
  11. end
  12. --=============================================================
  13. wifi.setmode(wifi.STATION)
  14. wifi.sta.disconnect()
  15. Connect2AP("ssid","pass")
  16. --=============================================================
复制代码


bbk_log.lua

  1. --bbk_log
  2. --=============================================================
  3. function GetRunTime()
  4.      local t = tmr.now()/1000000        --print(t)
  5.      local h = t/3600 t = t - h * 3600  --print(h,t)
  6.      local f = t/60                     --print(f,t)
  7.      local s = t%60                     --print(s,t)
  8.      local u = tmr.now()/1000%1000      --print(s,t)
  9.      return string.format("%02d:%02d:%02d.%03d",h,f,s,u)
  10. end
  11. --=============================================================
  12. function lg(s)
  13.      if s==nil then
  14.           print("-------- "..GetRunTime().." --------")
  15.      else
  16.           print("-------- "..GetRunTime().." = "..s)
  17.      end
  18. end
  19. --=============================================================
复制代码


bbk_ip_info.lua

  1. -- Connect2AP
  2. function Connect2AP(ssid,pass)
  3.      ---------------------------------------------------------
  4.      lg("Connect2AP("..ssid..","..pass..")")
  5.      ---------------------------------------------------------
  6.      tmr.alarm(0, 3000, 1, function()
  7.           ----------------------------------------------------
  8.           wifi.sta.config(ssid,pass)
  9.           wifi.sta.connect()
  10.           wifi.sta.autoconnect(1)
  11.           ----------------------------------------------------
  12.           if wifi.sta.getip() == nil then
  13.                print("Connecting to AP...\n")           
  14.           else
  15.                local ip, nm, gw = wifi.sta.getip() print(ip) --IP_Info_Show()               
  16.                tmr.stop(0)
  17.                Do_Next_File()
  18.           end
  19.           ----------------------------------------------------
  20.      end)
  21.      ---------------------------------------------------------
  22. end
  23. function IP_Info_Show()
  24.      ---------------------------------------------------------
  25.      ip, nm, gw = wifi.sta.getip()
  26.      if wifi.sta.getip() == nil then
  27.           print("IP Info:",ip,nm,gw,'\n')
  28.      else
  29.           print("IP Info:")
  30.           print("IP Address: ",ip)
  31.           print("Netmask   : ",nm)
  32.           print("Gateway Ad: ",gw,'\n')
  33.      end
  34.      ---------------------------------------------------------
  35. end
  36. function Do_Next_File()
  37.      lg("Do_Next_File")
  38. end
  39. ---------------------------------------------------------
  40. --wifi.setmode(wifi.STATION)
  41. --wifi.sta.disconnect()
  42. --Connect2AP("acDev","AbroadCar2015()")
  43. ---------------------------------------------------------
复制代码


bbk_si7021_pm25_lewei_ok.lua

  1. --=============================================================
  2. print("\nBBK_Lewei_Started_si7021_pm2.5")
  3. --=============================================================
  4. require("bbk_log")
  5. require("bbk_ip_info")
  6. ---------------------------------
  7. require("bbk_http_get_post")
  8. require("bbk_lewei")
  9. require("bbk_string")
  10. ---------------------------------
  11. require("si7021")
  12. require("bbk_si7021")
  13. --=============================================================
  14. lg("require_ok")
  15. --=============================================================
  16. function httpResponse(s)
  17.      ----------------------------------------------------------
  18.      conn=nil
  19.      local n = string.len(s)
  20.      if(n<10) then return end
  21.      ----------------------------------------------------------     
  22.      local z = StringGetAB(s,"{","}") s = nil n = nil
  23.      print("{"..z.."}","\r\n")
  24.      ----------------------------------------------------------
  25. end
  26. --=============================================================
  27. --=============================================================
  28. pm25 = 0
  29. upkey = 0
  30. ----------------------------------------------------------
  31. si7021_Init()
  32. uart.setup( 0, 9600, 8, 0, 1, 0 )
  33. ----------------------------------------------------------
  34. uart.on("data", 0,
  35. function(data)
  36.      if((string.len(data)==32) and (string.byte(data,1)==0x42) and (string.byte(data,2)==0x4d))  then
  37.           ----------------------------------------------------------
  38.           pm25 = (string.byte(data,13)*256+string.byte(data,14))
  39.           print("pm25 = "..pm25)
  40.           ----------------------------------------------------------
  41.           upkey = upkey + 1
  42.           if upkey>15 then upkey=0 updateLoop() end
  43.           ----------------------------------------------------------
  44.      end
  45. end, 0)
  46. --=============================================================
  47. function updateLoop()
  48.      lg("updateLoop")
  49.      si7021_Loop() si7021_Integer_Show()
  50.      local d,l = buildValueJson("WD",si7021_T,"SD",si7021_H,"PM",pm25)
  51.      lewei_httpPOST("02",d) d=nil l=nil
  52.      collectgarbage()
  53. end
  54. --=============================================================
复制代码


bbk_http_get_post.lua

  1. --=============================================================
  2. conn=nil
  3. --=============================================================
  4. function httpResponse(s)
  5.      conn=nil
  6.      print("back==")
  7.      print(s)
  8. end
  9. function httpPOST(h,p,u,o,d)
  10.      ----------------------------------------------------------
  11.      local l=string.len(d)     
  12.      ----------------------------------------------------------   
  13.      local s="POST "..u.." HTTP/1.1\r\n"      
  14.      .."Host:"..h.."\r\n"
  15.       ..o
  16.      .."Connection:close\r\n"
  17.      .."Content-Length: " ..l.. "\r\n"
  18.      .."\r\n"..d.."\r\n"
  19.      .."\r\n"
  20.      --print(str)
  21.      ----------------------------------------------------------
  22.      httpCONNECT(h,p,s)
  23.      ----------------------------------------------------------
  24. end
  25. function httpGET(h,p,u)
  26.      local s="GET "..u.." HTTP/1.1\r\n"
  27.      .."Host:"..h.."\r\n"
  28.      .."Connection:close\r\n"
  29.      .."Accept: */*\r\n\r\n"
  30.      --print(s)
  31.      httpCONNECT(h,p,s)
  32. end
  33. function httpCONNECT(h,p,s)
  34.      conn=net.createConnection(net.TCP, false)
  35.      conn:on("connection",function(conn,r) conn:send(s) end)
  36.      conn:on("receive", function(conn,r) httpResponse(r) end)
  37.      conn:connect(p,h)
  38. end
  39. --=============================================================
复制代码


bbk_lewei.lua

  1. --=============================================================
  2. port = 80
  3. host = "www.lewei50.com"
  4. urls = "/api/V1/gateway/UpdateSensors/"
  5. usek = "userkey:xxxxxxx\r\n"
  6. --=============================================================
  7. function buildValueJson(...)
  8.    local arg={...} local s=""
  9.    local n = table.getn(arg)
  10.    for i=1,n,2 do
  11.       s = s.."{"Name":""..arg[i].."","Value":"" ..arg[i+1].. ""}"
  12.       if(i~=n-1)then s = s.."," end
  13.    end
  14.    s="["..s.."]"
  15.    return s,string.len(s)
  16. end
  17. function lewei_httpPOST(g,d)
  18.      httpPOST(host,port,urls..g,usek,d)
  19. end
  20. --=============================================================
复制代码


bbk_string.lua

  1. function StringGetAB(s,a,b)
  2.      local ln = string.len(s)
  3.      local ai,an=string.find(s,a) --print(ai.."="..an)
  4.      local bi,bn=string.find(s,b) --print(bi.."="..bn)
  5.      local ax=0 local bx=0
  6.      if(ai~=nil) then ax=ai end
  7.      if(an~=nil) then ax=an end
  8.      if(bn~=nil) then bx=bn end
  9.      if(bi~=nil) then bx=bi end
  10.      if(ax+1>bx-1) then return "" end
  11.      return string.sub(s,ax+1,bx-1),string.sub(s,bx+1,ln)
  12. end
复制代码


bbk_si7021.lua

  1. ----------------------------------------------------------
  2. si7021_H = 0
  3. si7021_T = 0
  4. si7021 = require("si7021")
  5. ----------------------------------------------------------
  6. function si7021_Init()
  7.      local SDA_PIN = 5 -- sda pin, GPIO12
  8.      local SCL_PIN = 6 -- scl pin, GPIO14
  9.      si7021.init(SDA_PIN, SCL_PIN)
  10. end
  11. function si7021_Loop()
  12.      si7021.read()
  13.      si7021_H = si7021.getHumidity()
  14.      si7021_T = si7021.getTemperature()
  15. end
  16. function si7021_Integer_Show()
  17.      print("si7021: ",si7021_T.."C ",si7021_H.."%")
  18. end
  19. function si7021_Float_Show()
  20.      local t = string.format("%.1f",si7021_T)
  21.      local h = string.format("%.1f",si7021_H)
  22.      print("si7021: ",t.."C ",h.."%")
  23. end
  24. ----------------------------------------------------------
  25. --si7021_Init()
  26. --si7021_Loop()
  27. --si7021_Show()
  28. ----------------------------------------------------------
复制代码


si7021.lua

  1. -- ***************************************************************************
  2. -- SI7021 module for ESP8266 with nodeMCU
  3. -- Si7021 compatible tested 2015-1-22
  4. --
  5. -- Written by VIP6
  6. --
  7. -- MIT license, [url]http://opensource.org/licenses/MIT[/url]
  8. -- ***************************************************************************

  9. local moduleName = ...
  10. local M = {}
  11. _G[moduleName] = M

  12. --I2C slave address of Si70xx
  13. local Si7021_ADDR = 0x40

  14. --Commands
  15. local CMD_MEASURE_HUMIDITY_HOLD = 0xE5
  16. local CMD_MEASURE_HUMIDITY_NO_HOLD = 0xF5
  17. local CMD_MEASURE_TEMPERATURE_HOLD = 0xE3
  18. local CMD_MEASURE_TEMPERATURE_NO_HOLD = 0xF3


  19. -- temperature and humidity
  20. local t,h

  21. local init = false

  22. -- i2c interface ID
  23. local id = 0

  24. -- 16-bit  two's complement
  25. -- value: 16-bit integer
  26. local function twoCompl(value)
  27. if value > 32767 then value = -(65535 - value + 1)
  28. end
  29. return value
  30. end



  31. -- read data from si7021
  32. -- ADDR: slave address
  33. -- commands: Commands of si7021
  34. -- lenght: bytes to read
  35. local function read_data(ADDR, commands, length)
  36.   i2c.start(id)
  37.   i2c.address(id, ADDR, i2c.TRANSMITTER)
  38.   i2c.write(id, commands)
  39.   i2c.stop(id)
  40.   i2c.start(id)
  41.   i2c.address(id, ADDR,i2c.RECEIVER)
  42.   tmr.delay(20000)
  43.   c = i2c.read(id, length)
  44.   i2c.stop(id)
  45.   return c
  46. end

  47. -- initialize module
  48. -- sda: SDA pin
  49. -- scl SCL pin
  50. function M.init(sda, scl)
  51.   i2c.setup(id, sda, scl, i2c.SLOW)
  52.   --print("i2c ok..")
  53.   init = true
  54. end

  55. -- read humidity from si7021
  56. local function read_humi()
  57.   dataH = read_data(Si7021_ADDR, CMD_MEASURE_HUMIDITY_HOLD, 2)
  58.   UH = string.byte(dataH, 1) * 256 + string.byte(dataH, 2)
  59.   h = ((UH*12500+65536/2)/65536 - 600)
  60.   UH = nil
  61.   dataH = nil
  62.   return(h)
  63. end

  64. -- read temperature from si7021
  65. local function read_temp()
  66.   dataT = read_data(Si7021_ADDR, CMD_MEASURE_TEMPERATURE_HOLD, 2)
  67.   UT = string.byte(dataT, 1) * 256 + string.byte(dataT, 2)
  68.   t = ((UT*17572+65536/2)/65536 - 4685)
  69.   UT = nil
  70.   dataT = nil
  71.   return(t)
  72. end

  73. -- read temperature and humidity from si7021
  74. function M.read()
  75.   if (not init) then
  76.      print("init() must be called before read.")
  77.   else
  78.          read_humi()
  79.          read_temp()
  80.   end
  81. end;

  82. -- get humidity
  83. function M.getHumidity()
  84.   return string.sub(h, 1, 4)/100
  85. end

  86. -- get temperature
  87. function M.getTemperature()
  88.   return string.sub(t, 1, 4)/100
  89. end

  90. return M
复制代码


    (待补充)

    将这些文件都传入NodeMcu,就可以开始你的“空气质量上传乐联网”之旅了!

四、网页展示

    空气质量地图



五、注意事项

    1、NodeMcu的悖论

NodeMcu的悖论: 刷入了一个uart监控串口的程序,一启动就运行。但接下来重启操作、刷bin都不能停止这个监控串口的程序,这块NodeMcu就不能操作,也不能再写入程序了。

    悖论解决办法: nodemcu_integer_0.9.6-dev_20150704.bin、nodemcu_float_0.9.6-dev_20150704.bin 两个版本互相刷能够冲掉内嵌lua文件。

    核心关键 —— NodeMcu 只能支持一个UART,而且上传文件、程序都是使用这个串口,因此遇到串口传感器,特别是发送数据特别密的传感器,NodeMcu立马就不受控制了!

    NodeMcu看到有朋友写了软件串口的库,回头试试能否用软件虚拟串口来解决!

    2、调试时候先不要使用init.lua文件,如果init.lua文件中使用了串口监听,那么基本上板子就不能再调试了,必须得重新刷bin才能用,非常浪费时间!只有确定代码完全没问题了,再写入init.lua文件!!!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复

使用道具 举报

发表于 2016-4-1 17:02:19 | 显示全部楼层
学习了。谢谢,连代码都放出来了,真不错
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-4-6 16:42:35 | 显示全部楼层
自己顶贴!自己顶贴!
回复 支持 反对

使用道具 举报

发表于 2016-4-6 23:56:32 | 显示全部楼层
我是来顶贴的
回复 支持 反对

使用道具 举报

发表于 2016-4-7 10:40:18 | 显示全部楼层
超级赞!!!!
回复 支持 反对

使用道具 举报

发表于 2016-4-7 10:43:19 | 显示全部楼层
楼主好厉害,膜拜
回复 支持 反对

使用道具 举报

发表于 2016-4-7 10:45:13 | 显示全部楼层
我也来顶啊
回复 支持 反对

使用道具 举报

发表于 2016-4-7 10:45:33 | 显示全部楼层
不错,山寨之,哈哈
回复 支持 反对

使用道具 举报

发表于 2016-6-4 19:31:27 | 显示全部楼层
学习学习支持支持
回复 支持 反对

使用道具 举报

发表于 2016-7-25 23:38:17 | 显示全部楼层
NodeMcu看到有朋友写了软件串口的库,回头试试能否用软件虚拟串口来解决!

大神,求库共同研究
[email protected]
非常感谢
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-9-17 10:25:53 | 显示全部楼层
回复 支持 反对

使用道具 举报

发表于 2016-11-18 12:48:54 | 显示全部楼层
程序运行起来不能再写入程序这样解决: 在代码uart.on("data"  加段逻辑,如果遇到+++退出回调函数,大概这样: if data==“+++" then      uart.on("data") 。。。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-12-10 13:08:16 | 显示全部楼层
点亮板子上的蓝牙灯

  1. wifi.setmode(wifi.STATION)  
  2. wifi.sta.config("xxxx","xxxx")  
  3. print(wifi.sta.getip())  
  4. led1 = 3  
  5. led2 = 4  
  6. gpio.mode(led1, gpio.OUTPUT)  
  7. gpio.mode(led2, gpio.OUTPUT)  
  8. srv=net.createServer(net.TCP)  
  9. srv:listen(80,function(conn)  
  10.     conn:on("receive", function(client,request)  
  11.         local buf = "";  
  12.         local _, _, method, path, vars = string.find(request, "([A-Z]+) (.+)?(.+) HTTP");  
  13.         if(method == nil)then  
  14.             _, _, method, path = string.find(request, "([A-Z]+) (.+) HTTP");  
  15.         end  
  16.         local _GET = {}  
  17.         if (vars ~= nil)then  
  18.             for k, v in string.gmatch(vars, "(%w+)=(%w+)&*") do  
  19.                 _GET[k] = v  
  20.             end  
  21.         end  
  22.         buf = buf.."<h1> ESP8266 Web Server</h1>";  
  23.         buf = buf.."<p>GPIO0 <a href="?pin=ON1"><button>ON</button></a> <a href="?pin=OFF1"><button>OFF</button></a></p>";  
  24.         buf = buf.."<p>GPIO2 <a href="?pin=ON2"><button>ON</button></a> <a href="?pin=OFF2"><button>OFF</button></a></p>";  
  25.         local _on,_off = "",""  
  26.         if(_GET.pin == "ON1")then  
  27.               gpio.write(led1, gpio.HIGH);  
  28.         elseif(_GET.pin == "OFF1")then  
  29.               gpio.write(led1, gpio.LOW);  
  30.         elseif(_GET.pin == "ON2")then  
  31.               gpio.write(led2, gpio.LOW);  
  32.         elseif(_GET.pin == "OFF2")then  
  33.               gpio.write(led2, gpio.HIGH);  
  34.         end  
  35.         client:send(buf);  
  36.         client:close();  
  37.         collectgarbage();  
  38.     end)  
  39. end)
复制代码
回复 支持 反对

使用道具 举报

发表于 2017-2-1 17:26:42 | 显示全部楼层
先收藏在学习
回复 支持 反对

使用道具 举报

发表于 2017-2-12 11:21:51 | 显示全部楼层
本帖最后由 lipper 于 2017-3-26 18:36 编辑

这个代码有几个BUG。
1.表示“;P”
2.表示“:0”
嗯,是的,是网页的问题,
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-4-19 12:57 , Processed in 0.050520 second(s), 30 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表