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

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

问题描述

我试图通过从我的笔记本电脑(使用 node.js)发送 POST 来使用 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... 
")
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
"
              message[#message + 1] = "Content-Type: text/html

"
              message[#message + 1] = "POST request successfully received
"
           elseif(pinState==1)then
              gpio.write(3,gpio.LOW)
              pinState=0
              print("LED OFF")
              message[#message + 1] = "HTTP/1.1 200 OK
"
              message[#message + 1] = "Content-Type: text/html

"
              message[#message + 1] = "POST request successfully received
"
           end 
        elseif(method == "GET")then
           message[#message + 1] = "HTTP/1.1 200 OK
"
           message[#message + 1] = "Content-Type: text/html

"
           message[#message + 1] = "LED STATE="..tostring(pinState).."
"
        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 上:

On the 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.

感谢您的帮助!

雷伊

推荐答案

NodeMCU docs with the socket:send example 你似乎已经基于你的实现.我们讨论了它,我修复了它.

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... 
")
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
"
        message[#message + 1] = "Content-Type: text/html

"
        print("Method:" .. method);
        if (method == "POST") then
            message[#message + 1] = "POST request successfully received
"
            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) .. "
"
        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)

我删除了一些重复的代码 wrt 填充 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)回调中的socket变量是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天全站免登陆