ESP8266 NodeMcu firmware and some heap issues

Well it’s a fact that programming the ESP8266 in Lua and using the ESPlorer IDE makes a suitable environment for hacking around. But what about stability? We are dealing to some early age firmware, and so lot’s of improvements are down the road, but I’ve hit one issue that most people that is using this firmware are talking about: Heap exhaustion and random reboots.

If we start out our code running some file and not init.lua, what happens is when esp8266 reboots, it just sits idle waiting. To recover from reboots or random reboots you just need a init.lua file.

As I’ve talked in my previous post: developing at the beginning using the init.lua file is a bad idea. Just move your code to init.lua file when it is ready and you are (almost) sure that it won’t make the esp8266 enter a reboot loop.

So from the above post, my init.lua file after making sure that a Wifi connection is established, it launches periodically the following ping.lua file:

heapsize = node.heap()
conn=net.createConnection(net.TCP, false)
conn:on("receive", function(conn, payload) print("Get done.", payload) end )
conn:send("GET /esp8266.html?Heap=" .. heapsize .." HTTP/1.1\r\nHost: xx.xx.xx.xx\r\n"
.."Connection: keep-alive\r\nAccept: */*\r\n\r\n")

So I’m sending the current heap size as a query parameter to my web server, where with tail – F access.log I can see the Heap usage.

So what I’ve found out is that heap usage remains constant during several interactions (the ping.lua file is called every minute), then the heap usage drops and remains constant more or less, for some time, then drops again, and so on until it reboots around 2500/3000 level mark. This process takes around 16 hours.

I’ve tried to add some kind of log file logging on init.lua file, but for being useful it needed to also have the current time logged, which means that I needed to call some web page to provide me the current time. It is far easier to copy the ping.lua file to just a new file called initlog.lua file passing Init as the query parameter:

conn=net.createConnection(net.TCP, false)
conn:on("receive", function(conn, payload) print("Get done.", payload) end )
conn:send("GET /esp8266.html?Init HTTP/1.1\r\nHost:\r\n"
.."Connection: keep-alive\r\nAccept: */*\r\n\r\n")

So by filtering only the Init parameter I can count and find out the reboots.

So now on my init.lua file, the lauch function has the following code:

-- Change the code of this function that it calls your code.
function launch()
  print("Connected to WIFI!")
  print("IP Address: " .. wifi.sta.getip())
  --  New code to log the reboot.
  tmr.alarm(1, 1000, 0 , function() dofile("initlog.lua") end )
  -- Call our command file every minute.
  tmr.alarm(0, 60000, 1, function() dofile(CMDFILE) end )

It uses timer 1 to call the Get request to my server with Init as the query parameter, but only once, and then periodically calls the ping.lua file each minute.

Also there is a new version of the NodeMcu firmware, that on the change log refers to some heap changes/optimizations. I’ll need to flash this new version to see if stability is improved.

8 thoughts on “ESP8266 NodeMcu firmware and some heap issues

  1. Hi, I think u must add conn = nil before creating new connection

    conn = nil
    conn=net.createConnection(net.TCP, false)


    See if it makes diference in ur first example that was eating heap
    And you dont need to create variable heapsize = node.heap() because this variable eats around 55bytes in heap, u can run the node.heap() direct instead of heapsize

    Best regards,

    1. Thanks for the input, but it seems that Lua doesn’t do any kind of garbage collection, so after using a variable, even if you set it to nil, the previous allocated space remains there. For example, in one of my posts, when using MQTT and an unbound array to publish events, even if I set nil to previous used entries after a while it bombs out without memory.

      Also this posts was done with a older NodeMcu versions. Things might be better now, but in reality NodeMcu is great for quick development times at the cost of some stability and the impossibility of doing certain things possible in the native SDK.

  2. Hi, I have done some experiment with very good results, here is code:

    conn=net.createConnection(net.TCP, false)
    i = 0
    conn:on(“receive”, function(conn, pl) i = i+1 conn:send(“POST /dweet/for/espwireless?temperature=” .. i .. “&solar=” .. ..”&heap=”.. node.heap() .. ” HTTP/1.1\r\nHost:\r\n”..”Connection: keep-alive\r\nAccept: */*\r\n\r\n”) print(i) end)
    conn:send(“POST /dweet/for/espwireless?temperature=10&solar=800 HTTP/1.1\r\nHost:\r\n”..”Connection: keep-alive\r\nAccept: */*\r\n\r\n”)

    First if u dont know is a cloud for data form sensors, u can post data and that data is stored in server, and can be acessed in real time anywhere. Also u can link it to to have gauge to read sensors and more
    My gauge test board is that one is linked to dweet espwireless object that contains those two variables.

    But about the code, this make a loop on connections, when receive payload it starts another connection to web site, persistence.
    This can query site real fast, for example i was using 3g acess point and get about 30 updates per second on the gauge meters, thats amazing refresh rate. And heap remains stable at about 19000k
    If connected to wireless router the ping is less than 3g mobile I think u can get much much more update rate.
    To see how much fast is refresh rate u can see is publishing useconds running time to web site

    But u can limit updates per second by adding some delay between receive function and conn:send
    conn:on(“receive”, function(conn, pl) i = i+1 DELAY conn:send(…

    Best regards,Vito

    1. Correction: not 30updates per second but arround 7.25updates/second (tested in a 1Mbps upload link).
      Each time i variable increment is one post request and back response, I archived a rate of 300updates in 41seconds meaning that each update will take aprox. 137ms

    2. Thanks for the input. I do know that existed, but never used it. I’ll have a go with it. Regarding the post, and the heap issues, the post was done with an older (for now, that is) NodeMcu version, so it might be very different now. Things are getting better as newer versions of NodeMcu are released.

  3. Heap shown in web site is more 1500k than real, because after node.heap() are stored more variables. But remains constant
    As I said heap remains about 19000k in real

    1. Thanks for the info!

      I’ll have a look at the thread, but as things are going they only can improve 🙂
      This post is rather old and refers to an obsolete NodeMcu firmware version.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.