本文參考 NodeMCU 官網 API : http://nodemcu.readthedocs.org/en/dev/,將 DHT22 的感測資料透過 http 呼叫傳送給SQL server,為了支援浮點運算,須使用韌體版本為支援浮點數運算之nodemcu_float_0.9.6-dev_20150704.bin,與先前使用的整數版本不同,請先自行更新韌體。
1. DHT模組 API 測試
NodeMCU DHT API: http://nodemcu.readthedocs.org/en/dev/en/modules/dht/ ,
DHT 模組 API 可以自行判斷 DHT11 (整數)與其他 DHT (浮點數) 之結果
函數 | 功能 |
讀取以下型號之DHT感測器: DHT11, 21, 22, 33, 44 | |
讀取DHT11感測器 | |
讀取DHT11以外之感測器 |
回應結果:dht.OK (0),dht.ERROR_CHECKSUM (1),dht.ERROR_TIMEOUT (2)
Lua程式測試範例:
pin = 2 status, temp, humi, temp_dec, humi_dec = dht.read(pin) if status == dht.OK then -- Integer firmware using this example print(string.format("DHT Temperature:%d.%03d;Humidity:%d.%03d\r\n", math.floor(temp), temp_dec, math.floor(humi), humi_dec )) -- Float firmware using this example print("DHT Temperature:"..temp..";".."Humidity:"..humi) elseif status == dht.ERROR_CHECKSUM then print( "DHT Checksum error." ) elseif status == dht.ERROR_TIMEOUT then print( "DHT timed out." ) end |
2. 將 DHT 感測資料上傳至 MySQL 伺服器
這部分有 init.lua、user.lua、dht22_report.lua 三個模組。 init.lua 於開機時會自動執行,程式碼如下:
local timerID=0 -- LED閃滅用的 timer編號 local pinLED=4 local lighton=0 -- -- flashLED() -- function flashLED() if (wifi.sta.getip()==nil) then gpio.write(pinLED,gpio.LOW) else if (lighton==1) then gpio.write(pinLED,gpio.HIGH) lighton = 0 else gpio.write(pinLED,gpio.LOW) lighton = 1 end end end -- -- checkWifi() -- function checkWifi() local ip = wifi.sta.getip() if(ip==nil) then print("Connecting...") else tmr.stop(timerID) print("Connected to AP!") print(ip) tmr.alarm(timerID, 500, tmr.ALARM_AUTO, flashLED) end end -- -- main() -- -- init LED status gpio.mode(pinLED, gpio.OUTPUT) gpio.write(pinLED,gpio.LOW) -- connect Wifi wifi.setmode(wifi.STATION) wifi.sta.config("SSID","PASSWORD") -- 這裡要替換成自己 AP 的 SSID 與密碼 wifi.sta.autoconnect(1) tmr.stop(timerID) -- stop previous timer tmr.unregister(timerID) tmr.register(timerID, 2000, tmr.ALARM_AUTO,checkWifi) if not tmr.start(timerID) then print("tmr.start("..timerID..") failed!") end -- start user file dofile("user.lua") |
user.lua負責啟動所有服務,程式碼如下:
dofile("dht22_report.lua"); |
dht22_report.lua 每隔 10 秒讀取 DHT 的感測值,並用 POST 方式上傳至 MySQL 伺服器:
-- -- DHT22_report -- -- Note: this module needs the float version firmware : -- nodemcu_float_0.9.6-dev_20150704.bin -- local timerID=1 -- 讀取 DHT22用的計時器編號 local pinDHT=2 local sqlServer="XXX.XXX.XXX.XXX" --這裡要替換成伺服器的 IP local Location="NodeMCU" -- -- sendDHT(temp, humi) -- function postDHT(temp, humi) local conn = nil -- receive() function receive(conn, payloadout) if (string.find(payloadout, "Status: 200 OK") ~= nil) then print("Posted OK"); end end --connection() function connection(conn, payloadout) local params = "loc="..Location.."&temp="..temp.."&hum="..humi --post paramaters -- Post local httpString = "POST /SensorReport.php HTTP/1.1\n" .. "Host: "..sqlServer.."\n" .. "Content-Type: application/x-www-form-urlencoded\n" .. "Content-Length: "..string.len(params).."\n\n" .. params print("***postDHT:\n"..httpString.."\n") conn:send(httpString) end -- function disconnection(conn, payloadout) conn:close(); collectgarbage(); end -- create connection and register callback funciton conn = net.createConnection(net.TCP, 0) conn:on("receive", receive) conn:on("connection", connection) conn:on("disconnection", disconnection) -- connect to server conn:connect(80,sqlServer) end -- -- readDHT() -- function readDHT() status, temp, humi, temp_dec, humi_dec = dht.read(pinDHT) if status == dht.OK then local t = temp + temp_dec/1000 local h = humi + humi_dec/1000 print(string.format("***DHT: Temperature : %.1f Humidity : %.1f",t,h)) --debug if(wifi.sta.getip()==nil) then print("***DHT: Wifi is not connected") else postDHT(t,h) end elseif status == dht.ERROR_CHECKSUM then print( "***DHT: Checksum error." ) elseif status == dht.ERROR_TIMEOUT then print( "***DHT: timed out." ) end end -- -- main() -- tmr.stop(timerID) -- stop previous timer tmr.unregister(timerID) tmr.register(timerID, 10000, tmr.ALARM_AUTO, readDHT) if not tmr.start(timerID) then print("tmr.start("..timerID..") failed!") end --- start message print("start DHT report service") |
3. MySQL 伺服器的 http API
最後是 SensorReport.php,雖然是只用 POST 傳資料,但仍將 GET 放進來,網頁單獨測試時,可以直接在瀏覽器網址輸入測試資料, root 與 password 要替換成 mysql 的帳密 :
<?php //The 'root' and 'password' is required to be setup according to your own mysql installation $db = mysql_pconnect("localhost","root","password") or die('[{"Msg":"'.mysql_error().'"}]'); mysql_query("SET CHARACTER SET 'UTF8';"); mysql_query('SET NAMES UTF8;'); mysql_query('SET CHARACTER_SET_CLIENT=UTF8;'); mysql_query('SET CHARACTER_SET_RESULTS=UTF8;'); mysql_select_db("HomeDB"); date_default_timezone_set('Asia/Taipei'); $loc=""; $temp=-999; $hum=-999; if (isset($_GET['loc'])) { $loc= $_GET['loc']; } if (isset($_GET['temp'])) { $temp = $_GET['temp']; } if (isset($_GET['hum'])) { $hum = $_GET['hum']; } if (isset($_POST['loc'])) { $loc = $_POST['loc']; } if (isset($_POST['temp'])) { $temp= $_POST['temp']; } if (isset($_POST['hum'])) { $hum= $_POST['hum']; } if ($loc=="") { // invalid location die( '[{"Msg":"loc is null"}]'); //result code } $query = 'INSERT INTO `HomeDB`.`sensor` '. '(`Date`, `Time`, `Location`, `Temperature`, `Humidity`)'. ' VALUES '. '(CURDATE(), CURTIME(),"'.$loc. '","' .$temp. '","' .$hum.'");'; if(mysql_query($query)>0) { //create successfully print '{"Msg":"OK"},'; } else { print '{"Msg":"FAIL"},'; } mysql_close(); ?> |
參考資料
[1] “NodeMCU Documentation”, http://nodemcu.readthedocs.org/en/dev/
文章標籤
全站熱搜
留言列表