ESP8266 NodeMCU堆内存不足 [英] ESP8266 NodeMCU Running Out of Heap Memory

查看:1362
本文介绍了ESP8266 NodeMCU堆内存不足的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图通过从笔记本电脑发送POST(使用node.js)来使用ESP8266-01切换LED指示灯

I am trying to toggle an LED using ESP8266-01 by sending POST from my laptop (using node.js)

我现在遇到了内存问题,因为每当我发送POST请求时,ESP中使用的内存就会增加,堆内存会减少,并且在没有剩余内存时会崩溃(重新启动).

I now have a memory issue because whenever I send POST request, the memory used in the ESP increases, and heap memory decreases, and it crashes (restart) when theres no memory left.

有什么想法吗?

这是我在ESP端的代码(main.lua):

Here is my code on the ESP side (main.lua):

gpio.mode(3, gpio.OUTPUT)
srv=net.createServer(net.TCP,28800)
print("Server created... \n")
local pinState=0
srv:listen(80,function(conn)
    conn:on("receive", function(conn,request)
        local _, _, method, path, vars = string.find(request, "([A-Z]+) (.+)?(.+) HTTP");
        if(method == nil)then
            _, _, method, path = string.find(request, "([A-Z]+) (.+) HTTP");
        end
        local message={}
        print("Method:"..method);
        if(method == "POST")then
          if(pinState==0)then
              gpio.write(3,gpio.HIGH)
              pinState=1
              print("LED ON")
              message[#message + 1] = "HTTP/1.1 200 OK\r\n"
              message[#message + 1] = "Content-Type: text/html\r\n\r\n"
              message[#message + 1] = "POST request successfully received\r\n"
           elseif(pinState==1)then
              gpio.write(3,gpio.LOW)
              pinState=0
              print("LED OFF")
              message[#message + 1] = "HTTP/1.1 200 OK\r\n"
              message[#message + 1] = "Content-Type: text/html\r\n\r\n"
              message[#message + 1] = "POST request successfully received\r\n"
           end 
        elseif(method == "GET")then
           message[#message + 1] = "HTTP/1.1 200 OK\r\n"
           message[#message + 1] = "Content-Type: text/html\r\n\r\n"
           message[#message + 1] = "LED STATE="..tostring(pinState).."\r\n"
        end
        local function send()
          if #message > 0 then 
             conn:send(table.remove(message, 1))
          else
             conn:close()
          end
        end
        conn:on("sent", send)
        send()
        local message={}
        local _, _, method, path, vars= {}
        local heapSize=node.heap()
        if heapSize<1000 then
           node.restart()
        end
        collectgarbage()
        print("Memory Used:"..collectgarbage("count"))
        print("Heap Available:"..heapSize)
    end)
end)

在node.js上:

var request = require('request');
// Configure request
var options = {
    url: 'http://192.168.1.91',//ESP's IP address
    method: 'POST'
}
// Start the request
request(options, function (error, response, body) 
{
    if(!error) 
    {
        return console.log('Server responded with:',body);
    }
    if(error)
    {
        return console.error('ERROR:', error);
    }
})

我的init.lua刚刚连接到Wifi.

my init.lua is just connecting to Wifi.

感谢您的帮助!

雷伊

推荐答案

There was a problem in the NodeMCU docs with the socket:send example you seem to have based your implementation on. We discussed it and I fixed it.

您的代码的改进版本是这样:

An improved version of your code is this:

gpio.mode(3, gpio.OUTPUT)
srv = net.createServer(net.TCP, 28800)
print("Server created... \n")
local pinState = 0
srv:listen(80, function(conn)
    conn:on("receive", function(sck, request)
        local _, _, method, path, vars = string.find(request, "([A-Z]+) (.+)?(.+) HTTP");
        if (method == nil) then
            _, _, method, path = string.find(request, "([A-Z]+) (.+) HTTP");
        end
        local message = {}
        message[#message + 1] = "HTTP/1.1 200 OK\r\n"
        message[#message + 1] = "Content-Type: text/html\r\n\r\n"
        print("Method:" .. method);
        if (method == "POST") then
            message[#message + 1] = "POST request successfully received\r\n"
            if (pinState == 0) then
                gpio.write(3, gpio.HIGH)
                pinState = 1
                print("LED ON")
            elseif (pinState == 1) then
                gpio.write(3, gpio.LOW)
                pinState = 0
                print("LED OFF")
            end
        elseif (method == "GET") then
            message[#message + 1] = "LED STATE=" .. tostring(pinState) .. "\r\n"
        end
        local function send(sk)
            if #message > 0 then
                sk:send(table.remove(message, 1))
            else
                sk:close()
                message = nil
                print("Heap Available:" .. node.heap())
            end
        end
        sck:on("sent", send)
        send(sck)
    end)
end)

我删除了一些重复的代码,并填充了message,最后我也删除了重置"和GC代码(不再相关).真正的问题是关闭了回调函数中的 upvalues .

I removed some duplicated code wrt populating message and I also remove the "resetting" and GC code at the end (no longer relevant). The real issue though was with closed upvalues in the callback functions.

您的每个回调函数都应使用自己的已传递套接字实例副本,而不是引用包装的回调函数之一.

  • 在第5行srv:listen(80, function(conn)上,回调中的套接字变量为conn.
  • 在第6行上,还有另一个回调函数,该函数接收一个套接字,这次称为sck.在该函数中应将其引用为sck(sck:on()send(sck)).
  • socket:on("sent") 回调本身会收到一个/套接字实例.您原来的send()函数没有使用它,而是使用了conn.因此,我添加了sk并将其专门用于send().
  • On line 5 srv:listen(80, function(conn) the socket variable in the callback is conn.
  • On line 6 there's another callback function which receives a socket, this time called sck. It should be referenced within that function as sck (sck:on() and send(sck)).
  • The socket:on("sent") callback itself receives a/the socket instance. Your original send() function didn't not use that though and used conn instead. So, I added sk and use this one exclusively within send().

这篇关于ESP8266 NodeMCU堆内存不足的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆