Since I am the proud owner of five ESP8266 modules I was wondering how to make best use of them. After trying NodeMCU and Arduino I finaly tipped over to the NodeMCU side. I don't really like NodeMCU since I want more control over the hardware but it is simple enough and has some working libraries that really speed things up.
For starters I uploaded the firmware that I downloaded from nodemcu-build.com with only the absolutely essential modules enabled, plus mqtt and ow in order to be able to read from a Dallas DS18B20S OneWire digital temperature sensor. MQTT is the protocol developed for the Internet of Things (IoT) and it is a really convenient way for communication between the server and the IoT device. Further information on MQTT you can find here.
Then I set up the server. I am using an old Pentium4@3GHz PC with 1GB RAM with Ubuntu Server 14.04 LTS operating system installed. I installed mosquito which is the MQTT server, mysql for data persistence and openhab which is the main framework that provides the user interface and binds everything together.
On the ESP8266 side I used the two GPIO. GPIO0 was used to read the DS18B20S and GPIO2 was used to control a MOSFET, through a resistor of course, connected to the LEDs. The files I uploaded to the module are the following:
init.lua
ds18b20.lua
Of course I changed the MQTT broker (which is another name for server) address to the real one. Also there is a modification I made in the ds18b20.lua file, which I downloaded from the NodeMCU site, because I installed the firmware which does not support float point numbers, and this is a choice I have absolutely no good reason for making it. There are two more things to be done, firstly provide a way to store the dimming percentage value and recall it on the ON command, and secondly add some error handling code. The fortunate thing about NodeMCU is that when it runs into an unhandled error it just restarts.
Now it is time to set up the server side of things. Below are the three configuration files :
default.sitemap
default.items
mysql.persist
After everything is setup I can now sit on my favorite sofa and enjoy staring at the charts below for hours on end.
Thanks for reading this
For starters I uploaded the firmware that I downloaded from nodemcu-build.com with only the absolutely essential modules enabled, plus mqtt and ow in order to be able to read from a Dallas DS18B20S OneWire digital temperature sensor. MQTT is the protocol developed for the Internet of Things (IoT) and it is a really convenient way for communication between the server and the IoT device. Further information on MQTT you can find here.
Then I set up the server. I am using an old Pentium4@3GHz PC with 1GB RAM with Ubuntu Server 14.04 LTS operating system installed. I installed mosquito which is the MQTT server, mysql for data persistence and openhab which is the main framework that provides the user interface and binds everything together.
ESP-01 module |
On the ESP8266 side I used the two GPIO. GPIO0 was used to read the DS18B20S and GPIO2 was used to control a MOSFET, through a resistor of course, connected to the LEDs. The files I uploaded to the module are the following:
init.lua
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 56 57 58 59 60 61 62 | --Init DeviceID="esp01" RoomID="LR" gpio0 = 3 gpio2 = 4 Broker="192.168.X.X" t = require("ds18b20") t.setup(gpio0)addrs = t.addrs() pwm.setup(gpio2,100,0) m = mqtt.Client("ESP8266".. DeviceID, 180, "user", "password") m:lwt("/lwt", "ESP8266", 0, 0) m:on("offline", function(con) print ("Mqtt Reconnecting...") tmr.alarm(1, 10000, tmr.ALARM_SINGLE, function() m:connect(Broker, 1883, 0, function(conn) print("Mqtt Connected to:" .. Broker) mqtt_sub() --run the subscription function end) end) end) tmr.alarm(2,10000,tmr.ALARM_AUTO, function() lrtemp = t.read() print ("Temperature: "..lrtemp.."'C") m:publish("/home/".. RoomID .."/" .. DeviceID .. "/p2/state",lrtemp,0,0) end) -- on publish message receive event m:on("message", function(conn, topic, data) print("Recieved:" .. topic .. ":" .. data) if (data=="ON") then print("Enabling Output") pwm.setduty(gpio2,1023) m:publish("/home/".. RoomID .."/" .. DeviceID .. "/p1/state","ON",0,0) elseif (data=="OFF") then print("Disabling Output") pwm.setduty(gpio2,0) m:publish("/home/".. RoomID .."/" .. DeviceID .. "/p1/state","OFF",0,0) elseif ((tonumber(data)>=0) and (tonumber(data)<=100)) then print("Setting PWM to " .. data) pwm.setduty(gpio2,((data * 1024) / 100) - 1) m:publish("/home/".. RoomID .."/" .. DeviceID .. "/p1/state",data .. "%",0,0) else print("Invalid - Ignoring") end end) function mqtt_sub() m:subscribe("/home/".. RoomID .."/" .. DeviceID .. "/p1/com",0, function(conn) print("Mqtt Subscribed to OpenHAB feed for device " .. DeviceID) end) end tmr.alarm(0, 1000, tmr.ALARM_AUTO, function() if wifi.sta.status() == 5 and wifi.sta.getip() ~= nil then tmr.stop(0) m:connect(Broker, 1883, 0, function(conn) print("Mqtt Connected to:" .. Broker) mqtt_sub() --run the subscription function end) end end) |
ds18b20.lua
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 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | -------------------------------------------------------------------------------- -- DS18B20 one wire module for NODEMCU -- NODEMCU TEAM -- LICENCE: http://opensource.org/licenses/MIT -- Vowstar <vowstar@nodemcu.com> -- 2015/02/14 sza2 <sza2trash@gmail.com> Fix for negative values -------------------------------------------------------------------------------- -- Set module name as parameter of require local modname = ... local M = {} _G[modname] = M -------------------------------------------------------------------------------- -- Local used variables -------------------------------------------------------------------------------- -- DS18B20 dq pin local pin = nil -- DS18B20 default pin local defaultPin = 9 -------------------------------------------------------------------------------- -- Local used modules -------------------------------------------------------------------------------- -- Table module local table = table -- String module local string = string -- One wire module local ow = ow -- Timer module local tmr = tmr -- Limited to local environment setfenv(1,M) -------------------------------------------------------------------------------- -- Implementation -------------------------------------------------------------------------------- C = 0 F = 1 K = 2 function setup(dq) pin = dq if(pin == nil) then pin = defaultPin end ow.setup(pin) end function addrs() setup(pin) tbl = {} ow.reset_search(pin) repeat addr = ow.search(pin) if(addr ~= nil) then table.insert(tbl, addr) end tmr.wdclr() until (addr == nil) ow.reset_search(pin) return tbl end function readNumber(addr, unit) result = nil setup(pin) flag = false if(addr == nil) then ow.reset_search(pin) count = 0 repeat count = count + 1 addr = ow.search(pin) tmr.wdclr() until((addr ~= nil) or (count > 100)) ow.reset_search(pin) end if(addr == nil) then return result end crc = ow.crc8(string.sub(addr,1,7)) if (crc == addr:byte(8)) then if ((addr:byte(1) == 0x10) or (addr:byte(1) == 0x28)) then -- print("Device is a DS18S20 family device.") ow.reset(pin) ow.select(pin, addr) ow.write(pin, 0x44, 1) -- tmr.delay(1000000) present = ow.reset(pin) ow.select(pin, addr) ow.write(pin,0xBE,1) -- print("P="..present) data = nil data = string.char(ow.read(pin)) for i = 1, 8 do data = data .. string.char(ow.read(pin)) end -- print(data:byte(1,9)) crc = ow.crc8(string.sub(data,1,8)) -- print("CRC="..crc) if (crc == data:byte(9)) then t = (data:byte(1) + data:byte(2) * 256) if (t > 32767) then t = t - 65536 end if (addr:byte(1) == 0x28) then t = t * 625 -- DS18B20, 4 fractional bits else t = t * 5000 -- DS18S20, 1 fractional bit end if(unit == nil or unit == 'C') then else return nil end t = t / 10000 return t end tmr.wdclr() else -- print("Device family is not recognized.") end else -- print("CRC is not valid!") end return result end function read(addr, unit) t = readNumber(addr, unit) if (t == nil) then return nil else return t end end -- Return module table return M |
OpenHAB Main Menu |
default.sitemap
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | sitemap default label="Main Menu" { Frame label="Home" { Switch item=lamp1 label="Living Room LEDs" Slider item=led1 label="Living Room Dimmer" } Frame label="Temperatures" { Text item=lrtemp { Frame { Chart item=lrtemp period=D refresh=30000 Chart item=lrtemp period=W refresh=30000 } } } } |
default.items
1 2 3 4 5 6 7 | Group All Switch lamp1 "Living Room LEDs" (all) {mqtt=">[broker:/home/LR/esp01/p1/com:command:on:ON],>[broker:/home/LR/esp01/p1/com:command:off:OFF],<[broker:/home/LR/esp01/p1/state:state:default]"} Dimmer led1 "LR Dimmer [%s %%]" (all) {mqtt=">[broker:/home/LR/esp01/p1/com:command:*:default"} Number lrtemp "Living Room Temperature [%.1f]" (all) {mqtt="<[broker:/home/LR/esp01/p2/state:state:default]"} |
mysql.persist
1 2 3 4 5 6 7 8 9 10 11 12 | Strategies { everyHour : "0 0 * * * ?" everyDay : "0 0 0 * * ?" everyMinute : "0 * * * * ?" // if no strategy is specified for an item entry below, the default list will be used default = everyChange } Items { lrtemp : strategy = everyMinute } |
After everything is setup I can now sit on my favorite sofa and enjoy staring at the charts below for hours on end.
OpenHAB Living Room temperature chart |
No comments:
Post a Comment