ESP8266 NodeMCU - Enabling modules in firmware

ESP8266 NodeMCU - Enabling modules in firmware

I previously wrote a post about using the ESP8266 NodeMCU firmware to measure temperature and humidity. I used a lua library to read the values from the DHT22 sensor, but then found out that many of the modules I need for my projects are already included in the NodeMCU firmware! Even better, at frightanic.com you can customise the NodeMCU firmware and the site will build the version for you and send a download link in a few minutes. Want the latest and greatest firmware? Choose the dev branch. Need more free memory? Choose only the modules you need.

Customise NodeMCU firmware

Choose which branch and which modules to enable and in a few minutes you will have a custom NodeMCU firmware emailed to you.

As you can see from the screenshot there are plenty of libraries for various components you might need. For this post I choose the “DHT” and “MQTT” module in addition to the default ones. Then click the download link in the mail to download the integer version. Follow my instructions in this post to flash the firmware and be sure to read the troubleshooting section if you run into problems. Connect to the ESP8266 and you should see something like this:

> 0�~?�4�R���OCE�a��_&E�������

NodeMCU custom build by frightanic.com
	branch: dev
	commit: 093a895980fbd4ab8b3ebedcd6efe36e26419887
	SSL: true
	modules: node,file,gpio,wifi,net,tmr,adc,mqtt,dht
 	built on: 2015-10-13 18:26
  powered by Lua 5.1.4
lua: cannot open init.lua
>

You are now running a custom-made NodeMCU firmware!

Test setup using a DHT22 sensor

To test that we can actually use the built-in modules I wire up my ESP8266 with a DHT sensor as shown here:

ESP8266 with a DHT22 sensor

Disclaimer

This post contains links to Amazon where I get a small commission if you purchase anything after clicking on these links - at no extra cost to you! I have purchased all the mentioned products myself and I only link to products that I believe are the best for my readers. If you want to help out even more, take a look here.

The parts used are

You can get these items from Amazon but the price is higher just take a look at the prices for a ESP8266 development board.

The test code

Now we are ready to write some code! I have modified the code from my previous post to use the built-in DHT library. It will wake up every 60 seconds, measure the temperature and humidity and send the data to a MQTT server. In addition I added a watchdog timer to deep sleep the device the logic does not complete within 4 seconds, e.g. if the wifi is down. Upload the code as 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
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
-- MQTT connect script with deep sleep
-- Remember to connect GPIO16 and RST to enable deep sleep
-- TODO: Log error codes to server

--############
--# Settings #
--############

--- MQTT ---
mqtt_broker_ip = "192.168.1.66"     
mqtt_broker_port = 1883
mqtt_username = ""
mqtt_password = ""
mqtt_client_id = ""

--- WIFI ---
wifi_SSID = "wifi-ssid"
wifi_password = "wifi-password"
-- wifi.PHYMODE_B 802.11b, More range, Low Transfer rate, More current draw
-- wifi.PHYMODE_G 802.11g, Medium range, Medium transfer rate, Medium current draw
-- wifi.PHYMODE_N 802.11n, Least range, Fast transfer rate, Least current draw
wifi_signal_mode = wifi.PHYMODE_N
-- If the settings below are filled out then the module connects
-- using a static ip address which is faster than DHCP and
-- better for battery life. Blank "" will use DHCP.
-- My own tests show around 1-2 seconds with static ip
-- and 4+ seconds for DHCP
client_ip="192.168.1.100"
client_netmask="255.255.255.0"
client_gateway="192.168.1.1"

--- INTERVAL ---
-- In milliseconds. Remember that the sensor reading,
-- reboot and wifi reconnect takes a few seconds
time_between_sensor_readings = 60000

--################
--# END settings #
--################

-- Setup MQTT client and events
m = mqtt.Client(client_id, 120, username, password)
temperature = 0
humidity = 0

-- Connect to the wifi network
wifi.setmode(wifi.STATION)
wifi.setphymode(wifi_signal_mode)
wifi.sta.config(wifi_SSID, wifi_password)
wifi.sta.connect()
if client_ip ~= "" then
    wifi.sta.setip({ip=client_ip,netmask=client_netmask,gateway=client_gateway})
end

-- DHT22 sensor logic
function get_sensor_Data()
    dht=require("dht")
    status,temp,humi,temp_decimial,humi_decimial = dht.read(2)
        if( status == dht.OK ) then
            -- Prevent "0.-2 deg C" or "-2.-6"          
            temperature = temp.."."..(math.abs(temp_decimial)/100)
            humidity = humi.."."..(math.abs(humi_decimial)/100)
            -- If temp is zero and temp_decimal is negative, then add "-" to the temperature string
            if(temp == 0 and temp_decimial<0) then
                temperature = "-"..temperature
            end
            print("Temperature: "..temperature.." deg C")
            print("Humidity: "..humidity.."%")
        elseif( status == dht.ERROR_CHECKSUM ) then          
            print( "DHT Checksum error" )
            temperature=-1 --TEST
        elseif( status == dht.ERROR_TIMEOUT ) then
            print( "DHT Time out" )
            temperature=-2 --TEST
        end
    -- Release module
    dht=nil
    package.loaded["dht"]=nil
end

function loop()
    if wifi.sta.status() == 5 then
        -- Stop the loop
        tmr.stop(0)
        m:connect( mqtt_broker_ip , mqtt_broker_port, 0, function(conn)
            print("Connected to MQTT")
            print("  IP: ".. mqtt_broker_ip)
            print("  Port: ".. mqtt_broker_port)
            print("  Client ID: ".. mqtt_client_id)
            print("  Username: ".. mqtt_username)
            -- Get sensor data
            get_sensor_Data()
            m:publish("ESP8266/temperature",temperature, 0, 0, function(conn)
                m:publish("ESP8266/humidity",humidity, 0, 0, function(conn)
                    print("Going to deep sleep for "..(time_between_sensor_readings/1000).." seconds")
                    node.dsleep(time_between_sensor_readings*1000)             
                end)          
            end)
        end )
    else
        print("Connecting...")
    end
end

tmr.alarm(0, 100, 1, function() loop() end)

-- Watchdog loop, will force deep sleep the operation somehow takes to long
tmr.alarm(1,4000,1,function() node.dsleep(time_between_sensor_readings*1000) end)

You should see a message like this every 60 seconds if you have set everything up correctly.

0�~?�4�R���OCE�a��O6E�����

NodeMCU custom build by frightanic.com
	branch: dev
	commit: 093a895980fbd4ab8b3ebedcd6efe36e26419887
	SSL: true
	modules: node,file,gpio,wifi,net,tmr,adc,mqtt,dht
 	built on: 2015-10-13 18:26
  powered by Lua 5.1.4
> Connecting...
Connected to MQTT
  IP: 192.168.1.66
  Port: 1883
  Client ID:
  Username:
Temperature: 23.0 deg C
Humidity: 44.1%
Going to deep sleep for 60 seconds

The code is now using the built-in modules for the DHT22 library rather than a lua script library!

UPDATE: 19-04-2016
A reader pointed out that the code could not handle negative temperatures with an integer build of NodeMCU, e.g. “-1.-5” instead of “-1.5”. This has now been corrected.

Enjoyed this Content?

Help keep it free by sending a donation or purchase something using my affiliate links. You can also subscribe to various site feeds to get notified of new posts, follow me on social media, and more.

11 Comments

patrick

Okay, ich habe das ganze genauso gemacht wie beschrieben erhalte in der Console des LuaLoaders aber nur:

NodeMCU 0.9.6 build 20150704 powered by Lua 5.1.4
** You’ve got 1 sec to stop timer **
> Executing user.lua
Connecting…
Connecting…
Connecting…
Connecting…
Connecting…
Connecting…
Connecting…
Connecting…
Connecting…
Connecting…
Connecting…
Connecting…
Connecting…
Connecting…
Connecting…
Connecting…
Connecting…
Connecting…
Connecting…
Connecting…
PANIC: unprotected error in call to Lua API (user.lua:73: already connected)

dann resettet das nodemcu und es passiert erneut.

gruß patrick

Poul Serek

Hi Patrick

Try modifying user.lua by adding tmr.stop(0) right after the line if wifi.sta.status() == 5 then. If that does not work you could try changing tmr.alarm(0, 100, 1, function() loop() end) to tmr.alarm(0, 1000, 1, function() loop() end). Since you get an already connected error that might solve it

/Poul

Sonny

I run this latest code from you and it works great, not a single stop for two weeks now :)
as i am not a programmer i wonder if its possible to upload to thingspeak to in the same code? that would be awesome if it did.
thanks for sharing this.
BR
Sonny

Poul Serek

Hi Sonny

Great that you can use my code! I have written a new post here with a guide on how to upload to ThingSpeak instead. Do you need the code to both upload to a MQTT server and ThingSpeak, or just ThingSpeak?

/Poul

ender

I generate custom firmware for Nodemcu from the site you mentioned but I have a problem.
With custom firmware I couldn’t blink a led. :) but with official firmware, led blink code works well.
Here you can find the error output from esplorer.

With 9600 baud rate
—————————
Communication with MCU…
Got answer! AutoDetect firmware…
Communication with MCU established.
Can’t autodetect firmware, because proper answer not received (may be unknown firmware).
Please, reset module or continue.
Ê$NX¸,dCYø4xCÀdà file.remove(“init.lua”);
stdin:1: attempt to index global ‘file’ (a nil value)
stack traceback:
stdin:1: in main chunkfile.open(“init.lua”,”w+”);
stdin:1: attempt to index global ‘file’ (a nil value)
stack traceback:
stdin:1: in main chunkw = file.writeline
stdin:1: attempt to index global ‘file’ (a nil value)
stack traceback:
stdin:1: in main chunkw([==[– Blink using timer alarm –]==]);
stdin:1: attempt to call global ‘w’ (a nil value)
stack traceback:
stdin:1: in main chunkw([==[timerId = 0]==]);
stdin:1: attempt to call global ‘w’ (a nil value)
stack traceback:
stdin:1: in main chunkw([==[dly = 1000]==]);
stdin:1: attempt to call global ‘w’ (a nil value)
stack traceback:
stdin:1: in main chunkw([==[– use D4]==]);
stdin:1: attempt to call global ‘w’ (a nil value)
stack traceback:
stdin:1: in main chunkw([==[ledPin = 4]==]);
stdin:1: attempt to call global ‘w’ (a nil value)
stack traceback:
stdin:1: in main chunkw([==[– set mode to output]==]);
stdin:1: attempt to call global ‘w’ (a nil value)
stack traceback:
stdin:1: in main chunkw([==[gpio.mode(ledPin,gpio.OUTPUT)]==]);
stdin:1: attempt to call global ‘w’ (a nil value)
stack traceback:
stdin:1: in main chunkw([==[ledState = 0]==]);
stdin:1: attempt to call global ‘w’ (a nil value)
stack traceback:
stdin:1: in main chunkw([==[– timer loop]==]);
stdin:1: attempt to call global ‘w’ (a nil value)
stack traceback:
stdin:1: in main chunkw([==[tmr.alarm( timerId, dly, 1, function()]==]);
stdin:1: attempt to call global ‘w’ (a nil value)
stack traceback:
stdin:1: in main chunkw([==[ ledState = 1 - ledState;]==]);
stdin:1: attempt to call global ‘w’ (a nil value)
stack traceback:
stdin:1: in main chunkw([==[ – write state to D4]==]);
stdin:1: attempt to call global ‘w’ (a nil value)
stack traceback:
stdin:1: in main chunkw([==[ gpio.write(ledPin, ledState)]==]);
stdin:1: attempt to call global ‘w’ (a nil value)
stack traceback:
stdin:1: in main chunkw([==[end) ]==]);
stdin:1: attempt to call global ‘w’ (a nil value)
stack traceback:
stdin:1: in main chunkfile.close();
stdin:1: attempt to index global ‘file’ (a nil value)
stack traceback:
stdin:1: in main chunkdofile(“init.lua”);
cannot open init.lua
stack traceback:
[C]: in function ‘dofile’
stdin:1: in main chunk

Poul Serek

Hi Ender

I think you need to try to re-flash the firmware, it does look like it is flashed correctly or the firmware might be broken. From the error message it cannot even find the “file” library. Try another branch and make sure you check the options in my guide. You need to see the correct boot screen before even attempting to get the blink demo working.

/Poul

ender

I have tried several combinations of modules and finally it worked with combinations of modules: adc,bit,crypto,dht,enduser_setup,file,gpio,http,i2c,mdns,mqtt,net,node,ow,pwm,sntp,spi,tmr,uart,wifi.

Thanks for your reply.

Poul Serek

Hi Seb

Yes, I use it all the time with my ESP-12. You could try removing some unneeded modules or try the integer version.

/Poul

Leave a reply