I have been experimenting with the ESP8266 for creating Wifi sensors.
The nodemcu firmware makes programming it very easy.
Lua modules are available for creating web services and for accessing many common sensors.
The nodemcu devkit has a micro usb connector which can be used to program the device and to power it. ESPlorer seems the simplest tool to program it with, but there are many others. You just connect to it at 9600 baud and send it Lua commands terminated by CR LF.
When the device boots it runs, init.lua. Here is my init.lua:
wifi.setmode(wifi.STATION) wifi.sta.config('ssid','password') wifi.sta.connect() tmr.alarm(1, 5000, 1, function() if wifi.sta.getip()== nil then print('IP unavaiable, waiting...') else tmr.stop(1) print('IP is '..wifi.sta.getip()) dofile('mqtt.lc') dofile('publish.lc') end end)
It often takes a few goes to connect to my access point.
I am publishing the pressure and temperature data from a BMP180 sensors to an MQTT server running on a Raspberry Pi. I am also running nodered on the Raspberry Pi. Nodered is a Javascirpt based visual programming environment for creating transformation data flows for IoT devices. Amongst other things, it allows you to read raw data published to MQTT, transform it, and republish it.
The mqtt.lua script connects to my MQTT server. “mqtt.lc” is a compiled version of “mqtt.lua”, produced by executing node.compile(“mqtt.lua”).
Here is mqtt.lua:
m = mqtt.Client('nodemcu', 120) c = false m:on('offline', function(con) print ('mqtt offline');c = false end) m:connect('192.168.0.101', 1883, 0, function(conn) print('mqtt connected');c = true end)
The “publish.lua” script publishes the temperature and pressure data:
f = false tmr.alarm(1, 10000, 1, function() if not c then print('Reconnecting') m:close() c = false m:connect('192.168.0.101', 1883, 0, function(conn) print('connected'); c = true end) end dofile('bmp180test.lc') if c then if f then m:publish('/weather/pressure',p,0,0, function(conn) print('pressure published') end) else m:publish('/weather/temperature',t,0,0, function(conn) print('temperature published') end) end f = not f end end)
I publish the items on alternate timer interrupts as publishing one after the other causes a PANIC error. I am not sure how useful the reconnection stuff is, as I think the reconnection will happen automatically. It often fails to connect to my MQTT server on the first try.
Reading the BMP180 i2c barometric pressure sensor uses the BMP085 module. The BMP180 is a fully compatible newer version of the BMP085.
bmp085 = require('bmp085') sda = 1 scl = 2 bmp085.init(sda, scl) p = bmp085.getUP(oss) print('Pressure is '..p) t = bmp085.getUT(true) print('Temperature is '..t) bmp085 = nil package.loaded['bmp085']=nil
You can connect the ESP8266 to ESPlorer or any serial terminal such as the Arduino IDE, or Coolterm, and see the diagnostics. Or you can just plug it in to a USB charger and it runs free-standing. You can see the published data using nodered or anything that can subscribe to MQTT topics.
My nodered debugging gives the following output:
/weather/temperature : [msg.payload] : (string)
Temperature is 19.15 degrees C
/weather/pressure : [msg.payload] : (string)
Pressure is 1027.36 millibars
I have also produced sensors based on the DHT22 humidity sensor, the ds18b20 onewire temperature sensor and the MQ-2 gas sensor. The latter is an ADC sensor; the ESP8266 has one ADC pin. I also have ADC sensors for sound level, rain water measurement, and soil humidity, but as the ESP8266 has only one ADC pin, it’s only easy to do one of these at a time, unless I use an I/O expander chip, or just have a digital trigger at a specified value. A PIR motion detector should also be straightforward.
It is also very easy to publish the sensor data on IoT sites, such as thingspeak.