{"id":190,"date":"2018-10-16T02:42:50","date_gmt":"2018-10-16T02:42:50","guid":{"rendered":"https:\/\/www.appservgrid.com\/paw93\/index.php\/2018\/10\/16\/create-an-iot-sensor-with-nodemcu-and-lua\/"},"modified":"2018-10-16T03:15:03","modified_gmt":"2018-10-16T03:15:03","slug":"create-an-iot-sensor-with-nodemcu-and-lua","status":"publish","type":"post","link":"https:\/\/www.appservgrid.com\/paw93\/index.php\/2018\/10\/16\/create-an-iot-sensor-with-nodemcu-and-lua\/","title":{"rendered":"Create an IoT sensor with NodeMCU and Lua"},"content":{"rendered":"<p>In this post I want to show you how to create your own IoT sensor with the NodeMCU and the Lua programming language. The device called the NodeMCU makes it easy to start reading sensor data, sending it back to another location for processing or aggregation, such as the cloud. We&#8217;ll also compare the NodeMCU to the Raspberry Pi and talk about the pros\/cons of each for an IoT sensor.<\/p>\n<h2>Introduction<\/h2>\n<p><img decoding=\"async\" src=\"https:\/\/upload.wikimedia.org\/wikipedia\/commons\/thumb\/7\/7e\/NodeMCU_DEVKIT_1.0.jpg\/640px-NodeMCU_DEVKIT_1.0.jpg\" alt=\"\" \/><\/p>\n<blockquote><p>Picture <a href=\"https:\/\/commons.wikimedia.org\/wiki\/File:NodeMCU_DEVKIT_1.0.jpg\">Wikipedia<\/a> Creative Commons<\/p><\/blockquote>\n<blockquote><p>NodeMCU is an open source IoT platform. It includes firmware which runs on the ESP8266 Wi-Fi SoC from Espressif Systems, and hardware which is based on the ESP-12 module.<\/p><\/blockquote>\n<p>via <a href=\"https:\/\/en.wikipedia.org\/wiki\/NodeMCU\">Wikipedia<\/a><\/p>\n<p>The device looks similar to an Arduino or Raspberry Pi Zero featuring a USB port for power or programming and features a dedicated chip for communicating over WiFi. Several firmwares are available (similar to an Operating System) for programming the device in Lua, C (with the Arduino IDE) or even <a href=\"https:\/\/micropython.org\/\">MicroPython<\/a>. Cursory reading showed the Lua firmware to support the most amount of modules\/functionality including HTTP, MQTT and popular sensors such as the BME280.<\/p>\n<p>The <a href=\"https:\/\/nodemcu.readthedocs.io\/en\/master\/\">documentation for the NodeMCU<\/a> with Lua is detailed and thorough giving good examples and I found it easy to work with. In my opinion the Lua language feels similar to Node.js, but may take some getting used to. Fortunately it&#8217;s easy to <a href=\"https:\/\/www.lua.org\/start.html\">install Lua locally<\/a> to learn about flow control, loops, functions and other constructs.<\/p>\n<h3>NodeMCU vs Raspberry Pi<\/h3>\n<p>The Raspberry Pi Zero runs a whole Operating System which is usually Linux and is capable of acting as a desktop PC, but the NodeMCU runs a firmware with a much more limited remit. A Raspberry Pi Zero can be a good basis for an IoT sensor, but also is rather over-qualified for the task. The possibilities it brings come at a cost, such as relatively high power consumption and unreliable flash storage, which can become corrupted over time.<\/p>\n<p><a href=\"https:\/\/www.jeffgeerling.com\/blogs\/jeff-geerling\/raspberry-pi-zero-power\">Its power consumption with WiFi<\/a> enabled could be anything up to 120 mA even with HDMI and LEDs disabled. In contrast the NodeMCU runs a much more specialised chip with power-saving features such as a deep sleep mode that can make the board run for <a href=\"https:\/\/openhomeautomation.net\/esp8266-battery\">up to a year with a standard 2500mAh LiPo battery<\/a>.<\/p>\n<p>Here&#8217;s my take:<\/p>\n<blockquote><p>I&#8217;m a big fan of the Raspberry Pi and own more than anyone else I know (maybe you have more?), but it does need maintenance such as OS upgrades, package updates and the configuration to set up I2c or similar can be time-consuming. For IoT sensors, if you are willing to learn some Lua the NodeMCU can send readings over HTTP or MQTT and is low-powered and low hassle at the same time.<\/p><\/blockquote>\n<p>If you already have a Raspberry Pi and can&#8217;t wait to get your NodeMCU then you can follow <a href=\"https:\/\/blog.alexellis.io\/environmental-monitoring-dashboard\/\">my tutorial with InfluxDB here<\/a>.<\/p>\n<blockquote><p>yep, saw your <a href=\"https:\/\/twitter.com\/pimoroni?ref_src=twsrc%5Etfw\">@pimoroni<\/a> EnviroPhat piece and thought it was Grafana to start with-this is my version <a href=\"https:\/\/t.co\/YlRjuLMfBk\">pic.twitter.com\/YlRjuLMfBk<\/a><\/p>\n<p>\u2014 Alex Ellis (@alexellisuk) <a href=\"https:\/\/twitter.com\/alexellisuk\/status\/771814387262816256?ref_src=twsrc%5Etfw\">2 September 2016<\/a><\/p><\/blockquote>\n<h2>Tutorial overview<\/h2>\n<ul>\n<li>Bill of materials<\/li>\n<li>Create a firmware<\/li>\n<li>Flash firmware to NodeMCU<\/li>\n<li>Test the REPL<\/li>\n<li>Connect to WiFi<\/li>\n<li>Connect and test the BME280 sensor<\/li>\n<li>Upload init.lua<\/li>\n<li>Upload sensor readings to MQTT<\/li>\n<li>Observe reported MQTT readings on PC\/Laptop<\/li>\n<\/ul>\n<p>The finished IoT sensor:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/blog.alexellis.io\/content\/images\/2018\/07\/mcu_setup.jpg\" alt=\"mcu_setup\" \/><\/p>\n<h3>Bill of materials<\/h3>\n<ul>\n<li>NodeMCU<\/li>\n<\/ul>\n<p>You will need to purchase a <a href=\"https:\/\/en.wikipedia.org\/wiki\/NodeMCU\">NodeMCU board<\/a>. I recommend buying that on eBay, with pre-soldered pins. Aim to spend 4-6 USD.<\/p>\n<ul>\n<li>Micro-USB cable<\/li>\n<li>BME280 (<a href=\"https:\/\/www.aliexpress.com\/item\/BME280-Digital-Sensor-Temperature-Humidity-Barometric-Pressure-Sensor-New\/32665342978.html?src=google&amp;albslr=227945310&amp;isdl=y&amp;aff_short_key=UneMJZVf&amp;source=%7Bifdyn:dyn%7D%7Bifpla:pla%7D%7Bifdbm:DBM&amp;albch=DID%7D&amp;src=google&amp;albch=shopping&amp;acnt=494-037-6276&amp;isdl=y&amp;albcp=658432961&amp;albag=33762888219&amp;slnk=&amp;trgt=61865531738&amp;plac=&amp;crea=en32665342978&amp;netw=g&amp;device=c&amp;mtctp=&amp;aff_platform=google&amp;gclid=CjwKCAjwj4zaBRABEiwA0xwsPzNq9L9UljS1W7KOwq77eFHXmZwM2p66w9-jl9CuibTnWrsHR6t03hoCEYEQAvD_BwE&amp;gclsrc=aw.ds\">AliExpress<\/a>)<\/li>\n<\/ul>\n<p>I buy these for 3-5 USD on eBay, branded versions are much more expensive.<\/p>\n<ul>\n<li>Short male-to-male and male-to-female jumpers<\/li>\n<li>Small bread-board<\/li>\n<\/ul>\n<h3>Create a firmware<\/h3>\n<p>The NodeMCU chip is capable of supporting dozens of different firmware modules, but has limited space, so we will create a firmware using a free cloud service and then upload to the chip.<\/p>\n<ul>\n<li>Head over to <a href=\"https:\/\/nodemcu-build.com\/\">https:\/\/nodemcu-build.com\/<\/a><\/li>\n<li>Select the stable 1.5 firmware version<\/li>\n<li>Pick the following modules: adc, bme280, cjson, file, gpio, http, i2c, mqtt, net, node pwm, tmr, uart, wifi.<\/li>\n<\/ul>\n<p>You will receive an email with a link to download the firmware.<\/p>\n<h3>Flash the firmware<\/h3>\n<p>You will need to install a Python script to flash the firmware over the USB serial port. There are various options available and I used esptool.py on a Linux box.<\/p>\n<p><a href=\"https:\/\/nodemcu.readthedocs.io\/en\/master\/en\/flash\/\">https:\/\/nodemcu.readthedocs.io\/en\/master\/en\/flash\/<\/a><\/p>\n<p>This means I typed in:<\/p>\n<p>$ sudo .\/esptool\/esptool.py -p \/dev\/ttyUSB0 write_flash 0x00000 nodemcu-1.5.4.1-final-15-modules-2018-07-01-20-30-09-float.bin<\/p>\n<p>final-12-modules-2018-07-01-19-38-04-float.bin<br \/>\nesptool.py v2.4.1<br \/>\nSerial port \/dev\/ttyUSB0<br \/>\nConnecting&#8230;.<br \/>\nDetecting chip type&#8230; ESP8266<br \/>\nChip is ESP8266EX<br \/>\nFeatures: WiFi<br \/>\nMAC: 18:fe:34:a2:8b:0d<br \/>\nUploading stub&#8230;<br \/>\nRunning stub&#8230;<br \/>\nStub running&#8230;<br \/>\nConfiguring flash size&#8230;<br \/>\nAuto-detected Flash size: 4MB<br \/>\nFlash params set to 0x0040<br \/>\nCompressed 480100 bytes to 313202&#8230;<br \/>\nWrote 480100 bytes (313202 compressed) at 0x00000000 in 27.6 seconds (effective 139.0 kbit\/s)&#8230;<br \/>\nHash of data verified.<\/p>\n<p>Leaving&#8230;<br \/>\nHard resetting via RTS pin&#8230;<\/p>\n<h3>Test the REPL<\/h3>\n<p>Now that the NodeMCU has the Lua firmware flashed you can connect with Linux or Mac to the device in a terminal to enter commands on the REPL.<\/p>\n<p>The device starts off at a baud rate of 115200 which is not useable for typing.<\/p>\n<p>sudo screen -L \/dev\/ttyUSB0 115200<\/p>\n<p>&gt; uart.setup(0,9600,8,0,1,1)<\/p>\n<p>Now type in Control + A + : then type in quit<\/p>\n<p>Next you can connect at the lower speed and try out a few commands from the docs.<\/p>\n<p>sudo screen -L \/dev\/ttyUSB0 9600<\/p>\n<p>&gt; print(&#8220;Hello world&#8221;)<br \/>\nHello world<br \/>\n&gt;<\/p>\n<p>Keep the screen session open, you can suspend it at any time by typing Control A + D and resume with screen -r.<\/p>\n<h3>Connect to WiFi<\/h3>\n<p>Next let&#8217;s try to connect to the WiFi network and get an I.P. address so that we can access the web.<\/p>\n<p>ssid=&#8221;SSID&#8221;<br \/>\nkey=&#8221;key&#8221;<\/p>\n<p>wifi.setmode(wifi.STATION)<br \/>\nwifi.sta.config(ssid, key)<br \/>\nwifi.sta.connect()<br \/>\ntmr.delay(1000000)<\/p>\n<p>print(string.format(&#8220;IP: %s&#8221;,wifi.sta.getip()))<\/p>\n<p>IP: 192.168.0.52<\/p>\n<p>Now that you have the device IP you should be able to ping it with ping -c 3 192.168.0.52<\/p>\n<p>Since we built-in the HTTP stack we can now access a web-page.<\/p>\n<p>Go to https:\/\/requestbin.fullcontact.com\/ and create a &#8220;Request Bin&#8221;<\/p>\n<p>Now type in the code below changing the URL to the one provided to you by the website. When you refresh the web-page, you should see the data appear on the page showing the WiFi signal &#8220;RSSI&#8221;.<\/p>\n<p>binURL=&#8221;http:\/\/requestbin.fullcontact.com\/13651yq1&#8243;<br \/>\nhttp.post(binURL,<br \/>\n&#8216;Content-Type: application\/json&#8217;,<br \/>\nstring.format(&#8216;{&#8220;rssi&#8221;: %d}&#8217;, wifi.sta.getrssi()),<br \/>\nfunction(code, data)<br \/>\nif (code &lt; 0) then<br \/>\nprint(&#8220;HTTP request failed&#8221;)<br \/>\nelse<br \/>\nprint(code, data)<br \/>\nend<br \/>\nend)<\/p>\n<p>In my example I saw the data {&#8220;rssi&#8221;: -64} appear on the UI showing a good\/low noise level due to proximity to my access point.<\/p>\n<h3>Connect and test the BME280 sensor<\/h3>\n<p>According to <a href=\"https:\/\/mqtt.org\">mqtt.org<\/a>, MQTT is:<\/p>\n<blockquote><p>.. a machine-to-machine (M2M)\/&#8221;Internet of Things&#8221; connectivity protocol. It was designed as an extremely lightweight publish\/subscribe messaging transport. It is useful for connections with remote locations where a small code footprint is required and\/or network bandwidth is at a premium.<\/p><\/blockquote>\n<p>If you&#8217;ve ever used a message queue before then this will be familiar territory, but if it&#8217;s new then you can either publish messages or subscribe to them for a given topic.<\/p>\n<p>Example: a base station subscribes to a topic called &#8220;sensor-readings&#8221; and a series of NodeMCU \/ IoT devices publish sensor readings to the &#8220;sensor-readings&#8221; topic. This de-couples the base-station\/receiver from the IoT devices which broadcast their sensor readings as they become available.<\/p>\n<p>We can use the public Mosquitto test MQTT server called test.mosquitto.com &#8211; all readings will be publicly available, but you can run your own Mosquitto MQTT server with Docker or Linux later on.<\/p>\n<p>Now power off the device by unplugging the USB cable and connect the BME280 sensor.<\/p>\n<p>I suggest making all these connections via the breadboard, but you could also connect them directly:<\/p>\n<ul>\n<li>Connect positive on the BME280 to 3v3 on the NodeMCU<\/li>\n<li>Connect GND on the BME280 to GND on the NodeMCU<\/li>\n<li>Connect SDA on the BME280 to to pin D3 on the NodeMCU<\/li>\n<li>Connect SDC on the BME280 to to pin D3 on the NodeMCU<\/li>\n<\/ul>\n<p>Now power up and get into <em>9600 baud<\/em> again, opening the screen and REPL so we can test the sensor.<\/p>\n<p>sda, scl = 3, 4<br \/>\nmode = bme280.init(sda, scl)<br \/>\nprint(mode)<br \/>\ntmr.delay(1000000)<br \/>\nH, T = bme280.humi()<br \/>\nt = T \/ 100<br \/>\nh = H \/ 1000<br \/>\nip = wifi.sta.getip()<br \/>\nif ip == nil then<br \/>\nip = &#8220;127.0.0.1&#8221;<br \/>\nend<br \/>\nRSSI=wifi.sta.getrssi()<br \/>\nif RSSI == nil then<br \/>\nRSSI=-1<br \/>\nend<\/p>\n<p>msg = string.format(&#8216;{&#8220;sensor&#8221;: &#8220;s1&#8221;, &#8220;humidity&#8221;: &#8220;%.2f&#8221;, &#8220;temp&#8221;: &#8220;%.3f&#8221;, &#8220;ip&#8221;: &#8220;%s&#8221;, &#8220;rssi&#8221;: %d}&#8217;, h, t, ip, RSSI)<br \/>\nprint(msg)<\/p>\n<p>If the connections were made correctly then you will now see a JSON message on the console.<\/p>\n<h3>Upload init.lua<\/h3>\n<p>Download init.lua from my GitHub Gist and then update the WiFi SSID (mySsid) and Password settings (myKey).<\/p>\n<p><a href=\"https:\/\/gist.github.com\/alexellis\/6a4309b316a1bc650e212d6d4f47deea\">https:\/\/gist.github.com\/alexellis\/6a4309b316a1bc650e212d6d4f47deea<\/a><\/p>\n<p>Find a compatible tool to upload the init.lua file, or on Linux use the same tool I used:<\/p>\n<p>sudo nodemcu-uploader &#8211;port=\/dev\/ttyUSB0 upload .\/init.lua<\/p>\n<p>Various tools are available to upload code: <a href=\"https:\/\/nodemcu.readthedocs.io\/en\/dev\/en\/upload\/\">https:\/\/nodemcu.readthedocs.io\/en\/dev\/en\/upload\/<\/a><\/p>\n<h3>Upload sensor readings to MQTT<\/h3>\n<p>Now unplug your NodeMCU and find a small USB power pack or phone charger and plug the device in. It will run init.lua and start transmitting messages to <a href=\"https:\/\/test.mosquitto.com\">test.mosquitto.com<\/a> over MQTT.<\/p>\n<h3>Observe reported MQTT readings on PC\/Laptop<\/h3>\n<p>Install an MQTT client on Linux or find a desktop application for MacOS\/Windows.<\/p>\n<p>On Debian\/Ubuntu\/RPi you can run: sudo apt-get install mosquitto-clients<\/p>\n<p>Then listen to the server on the topic &#8220;sensor-readings&#8221;:<\/p>\n<p>mosquitto_sub -h test.mosquitto.org -p 1883 -t sensor-readings -d<\/p>\n<p>Example of data coming in from my sensor in my garden:<\/p>\n<p>Subscribed (mid: 1): 0<br \/>\n&#8230;<br \/>\nClient mosqsub\/19950-alexellis received PUBLISH (d0, q0, r0, m0, &#8216;sensor-readings&#8217;, &#8230; (108 bytes))<br \/>\n{&#8220;sensor&#8221;: &#8220;s1&#8221;, &#8220;humidity&#8221;: &#8220;58.38&#8221;, &#8220;temp&#8221;: &#8220;24.730&#8221;, &#8220;ip&#8221;: &#8220;192.168.0.51&#8221;, &#8220;vdd33&#8221;: &#8220;65535&#8221;, &#8220;rssi&#8221;: -75}<br \/>\nClient mosqsub\/19950-alexellis received PUBLISH (d0, q0, r0, m0, &#8216;sensor-readings&#8217;, &#8230; (108 bytes))<br \/>\n{&#8220;sensor&#8221;: &#8220;s1&#8221;, &#8220;humidity&#8221;: &#8220;57.96&#8221;, &#8220;temp&#8221;: &#8220;24.950&#8221;, &#8220;ip&#8221;: &#8220;192.168.0.51&#8221;, &#8220;vdd33&#8221;: &#8220;65535&#8221;, &#8220;rssi&#8221;: -75}<br \/>\n&#8230;<\/p>\n<h2>Wrapping up<\/h2>\n<p>You&#8217;ve now built a robust IoT sensor that can connect over your WiFi network to broadcast sensor readings around the world.<\/p>\n<p>Take it further by trying some of these ideas:<\/p>\n<ul>\n<li>Add WiFi re-connection code<\/li>\n<li>Use deep sleep to save power between readings<\/li>\n<li>Aggregate the readings in a time-series database, or CSV file for plotting charts &#8211; try <a href=\"https:\/\/blog.alexellis.io\/environmental-monitoring-dashboard\/\">my environmental monitoring dashboard<\/a><\/li>\n<li>Run your own MQTT server\/broker<\/li>\n<li>Try another sensor such as an LDR to measure light<\/li>\n<li>Build an external enclosure and run the device in your garden<\/li>\n<\/ul>\n<p>If you liked this tutorial or have questions then follow me <a href=\"https:\/\/twitter.com\/alexellisuk\">@alexellisuk<\/a> on Twitter.<\/p>\n<blockquote><p>Create an IoT environmental sensor with NodeMCU and Lua <a href=\"https:\/\/t.co\/esgaeqrKwq\">https:\/\/t.co\/esgaeqrKwq<\/a> <a href=\"https:\/\/t.co\/hm7sWIi3AF\">pic.twitter.com\/hm7sWIi3AF<\/a><\/p>\n<p>\u2014 Alex Ellis (@alexellisuk) <a href=\"https:\/\/twitter.com\/alexellisuk\/status\/1016256741582016512?ref_src=twsrc%5Etfw\">July 9, 2018<\/a><\/p><\/blockquote>\n<p><a href=\"https:\/\/blog.alexellis.io\/iot-nodemcu-sensor-bme280\/\" target=\"_blank\" rel=\"noopener\">Source<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this post I want to show you how to create your own IoT sensor with the NodeMCU and the Lua programming language. The device called the NodeMCU makes it easy to start reading sensor data, sending it back to another location for processing or aggregation, such as the cloud. We&#8217;ll also compare the NodeMCU &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/www.appservgrid.com\/paw93\/index.php\/2018\/10\/16\/create-an-iot-sensor-with-nodemcu-and-lua\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Create an IoT sensor with NodeMCU and Lua&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-190","post","type-post","status-publish","format-standard","hentry","category-docker"],"_links":{"self":[{"href":"https:\/\/www.appservgrid.com\/paw93\/index.php\/wp-json\/wp\/v2\/posts\/190","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.appservgrid.com\/paw93\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.appservgrid.com\/paw93\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.appservgrid.com\/paw93\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.appservgrid.com\/paw93\/index.php\/wp-json\/wp\/v2\/comments?post=190"}],"version-history":[{"count":1,"href":"https:\/\/www.appservgrid.com\/paw93\/index.php\/wp-json\/wp\/v2\/posts\/190\/revisions"}],"predecessor-version":[{"id":200,"href":"https:\/\/www.appservgrid.com\/paw93\/index.php\/wp-json\/wp\/v2\/posts\/190\/revisions\/200"}],"wp:attachment":[{"href":"https:\/\/www.appservgrid.com\/paw93\/index.php\/wp-json\/wp\/v2\/media?parent=190"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.appservgrid.com\/paw93\/index.php\/wp-json\/wp\/v2\/categories?post=190"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.appservgrid.com\/paw93\/index.php\/wp-json\/wp\/v2\/tags?post=190"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}