这个问题让我疯了 . 它消耗的时间太多了,我可以帮忙,请!基本上,我使用Get()从我的服务器下载天气数据 . 这很好用 . 我想做的就是在16x2 i2c lcd屏幕上显示它,但是我遇到了'out of memory'问题 . 我已经尝试了社区提供的几个模块,所有人似乎都遇到了同样的问题,所以我确信这个问题与我的代码/调用约定有关 . 我目前正在使用模块lcd.lua,这是Vladimir Dronnikov提供的略有变化 . 并在规定的庄园中称呼它
<pre>
i2c.setup(0, 3, 4, i2c.SLOW)
lcd = dofile("lcd.lua")()
</pre>
调用lua脚本充满了印刷语句:
<pre>
lcd.put(lcd:locate(0, 0),"Mast Temp: ")
</pre>
我的文件结构如下所示
<pre>
Init.lua -- opportunity to prevent script execution. Calls wifiConnect
wifiConnect.lua -- connects to wifi and calls dofile(DetServerData())
GetServerData.lua -- Fetches data and displays on lcd module.
</pre>
当wifiConnect对GetServerData调用dofile时,它通常会被'not enough memory'覆盖,有时脚本会在遇到'out of memory'错误之前运行2到3次 . 然而,我有它跑了8000-9000次,然后跌倒 . (只有一两次 . )如果我允许wifiConnect运行GetFileData,它将停止
<pre>
PANIC: unprotected error in call to Lua API (not enough memory)
</pre>
加载GetServerData似乎在堆上消耗13816个字节..离开18800.肯定足以运行 . 我尝试过require(getServerData),数字略有不同,结果相同 .
GetServerData如下
-- 0 DS18B20_temp_C
-- 1 WindSpeed_kmph
-- 2 WindBearing;
-- 3 WindDir
-- 4 BMP_temp
-- 5 BMP_pressure
-- BMP_altitude --------------REMOVED
-- 6 DHT22_temperature
-- 7 DHT22_humidity
-- DH22_dewPoint--------------REMOVED
-- DHT22_heatIndex--------------REMOVED
local WDPin = 1
local LCDscreenPin = 2
local LCDmaxScreen = 4
local cycleCount=0
local WDogLED = false
local dataTable={} ; i=1
local connClosed = true
local LCDpageID = 1
function GetData()
if connClosed == true then
local conn=net.createConnection(net.TCP, 0)
print("Open connection...")
WatchDog()
if conn == nil then
print("Connection error")
else
conn:connect(80,'31.220.16.114')
connClosed = false
tmr.alarm(4,3000,0,ResetConn)
conn:send("GET /test.txt? HTTP/1.1\r\n")
conn:send("Host: theoldschool.esy.es\r\n")
conn:send("Accept: */*\r\n")
conn:send("User-Agent: Mozilla/4.0 (compatible; esp8266 Lua; Windows NT 5.1)\r\n")
conn:send("\r\n")
conn:on("disconnection", function(conn)
connClosed = true
WatchDog()
print("Disconnected...")
end) -- on:"disconection"
conn:on("receive",function(conn,payload)
cleanData = extractWeatherData(payload)
DbugGarbageCollect()
fillDataTable(cleanData,'\r\n')
for k,v in pairs(dataTable) do print(k,v) end
cycleCount = cycleCount +1
print(cycleCount)
end)-- on recieve
end-- if conn == nil
end -- if connClosed
end--GetData
function ResetConn()
print("Stuck")
connClosed = true
end -- ResetConn
function fillDataTable(inputstr, sep)
local i=0
for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
dataTable[i] = str
i = i + 1
end--for
end--splitCmd
function stripMarkers(str, chrs)
local s = str:gsub("["..chrs:gsub("%W","%%%1").."]", '')
return s
end
function extractWeatherData (payload)
local startChar = string.find(payload, '%')
local s = string.sub(payload, startChar,endChar)
s = stripMarkers(s, "")
return s
end -- extractWeatherData
function WatchDog()
if WDogLED == false then
WDogLED = true
gpio.write(WDPin, gpio.HIGH)
else
WDogLED = false
gpio.write(WDPin, gpio.LOW)
end --if
end--WatchDog
function DbugGarbageCollect()
local before = collectgarbage("count")
collectgarbage()
print(before - collectgarbage("count"))
print(node.heap())
end --DbugGarbageCollect
function LCDdisplay()
lcd.clear()
if LCDpageID == 1 then
lcd.put(lcd:locate(0, 0),"Mast Temp: ")
lcd.put(lcd:locate(1, 0),"Shade Tmp: ")
elseif LCDpageID == 2 then
lcd.put(lcd:locate(0, 0),"Wind Dir: ")
lcd.put(lcd:locate(1,0),"Wind Knts: ")
elseif LCDpageID == 3 then
lcd.put(lcd:locate(0, 0),"Pressure: ")
lcd.put(lcd:locate(1, 0),"BMP Temp: ")
elseif LCDpageID == 4 then
lcd.put(lcd:locate(0, 0),"DHT Temp: ")
lcd.put(lcd:locate(1, 0),"Humidity: ")
else
lcd.put(lcd:locate(0, 0),"SCREEN ERROR 1")
end --if
--updateLCDDisplay()
collectgarbage()
end --LCDdisplay
function updateLCDDisplay()
if LCDpageID == 1 then
lcd.put(lcd:locate(0, 11),dataTable[0])
-- LCDScreenOP.lcdprint(dataTable[0],1,11)
-- LCDScreenOP.lcdprint(dataTable[7],2,11)
elseif LCDpageID == 2 then
--LCDScreenOP.lcdprint(dataTable[2],1,10)
-- LCDScreenOP.lcdprint(dataTable[3],1,14)
-- LCDScreenOP.lcdprint(dataTable[1],2,11)
elseif LCDpageID == 3 then
-- LCDScreenOP.lcdprint(dataTable[5],1,10)
-- LCDScreenOP.lcdprint(dataTable[4],2,10)
elseif LCDpageID == 4 then
--LCDScreenOP.lcdprint(dataTable[6],1,10)
-- LCDScreenOP.lcdprint(dataTable[7],2,10)
else
-- LCDScreenOP.cls()
-- LCDScreenOP.cursor(0)
-- LCDScreenOP.lcdprint("U/D ERROR",1,0)
end --if
-- package.loaded.LCDScreenOP = nil
DbugGarbageCollect()
end -- updateDisplay
function LCDScreenChange(level)
LCDpageID = LCDpageID + 1
if LCDpageID == LCDmaxScreen + 1 then LCDpageID = 1 end
LCDdisplay()
end-- buttonpress
--============================ CODE ==============================
i2c.setup(0, 3, 4, i2c.SLOW)
lcd = dofile("lcd.lua")()
print ("here")
gpio.mode(WDPin, gpio.OUTPUT)
gpio.write(WDPin, gpio.HIGH)
gpio.mode(LCDscreenPin, gpio.INPUT, gpio.PULLUP)
DbugGarbageCollect()
gpio.trig(LCDscreenPin, "down",LCDScreenChange)
tmr.alarm(2,1500,1,GetData)
并且在加载GetServerData并允许它运行时,esplorer窗口的屏幕抓取看起来像这样
<pre>
abort = true
startup aborted
=node.heap()
>**32616**
file.remove("GetServerData.lua");
file.open("GetServerData.lua","w+");
w = file.writeline
-- Above code in here !!
file.close();
dofile("GetServerData.lua");
>not enough memory
dofile('GetServerData.lua')
not enough memory
=node.heap()
>**18800**
dofile('GetServerData.lua')
>not enough memory
</pre>
我们将非常感激地提供任何帮助,并且可以提供任何其他可能有用的信息
非常感谢菲利普
1 回答
如果您提供Minimal, Complete, and Verifiable example将重现问题( - >最小),那么's quite a lot of code to comb through. It'会更有帮助 .
快速浏览一下就发现了2.5个问题,但可能会有更多问题 .
Closed upvalues
conn:on("receive",function(conn,payload)
泄漏,因为回调参数不应该是conn
而是其他内容 . 见https://github.com/nodemcu/nodemcu-firmware/issues/194#issuecomment-184817667或https://stackoverflow.com/a/37379426/131929Sending is asynchronous
conn:send
不应该快速连续调用,因为每个调用都是异步的,因此不能保证调用顺序 . 有关详细信息,请参阅net.socket:send文档 .Consider http module
使用http.get可以帮助您降低代码的复杂性 .