2017-03-05 4 views
1

이 문제는 나를 괴롭 히고 있습니다. 그것의 소비 된 방법은 너무 많은 시간과 나는 약간의 도움으로 할 수 있었다, 제발! 기본적으로 Get()을 사용하여 내 서버에서 날씨 데이터를 다운로드하고 있습니다. 이것은 잘 작동합니다. 내가하고 싶은 일은 16x2 i2c LCD 화면에 표시하는 것 뿐이지 만 '메모리 부족'문제로 어려움을 겪고 있습니다. 커뮤니티에서 제공하는 여러 모듈을 사용해 보았는데 모두 똑같은 문제를 겪고있는 것 같습니다. 그래서이 코드는 내 코드/호출 규칙에 문제가 있음을 확신합니다. Im은 현재 lcd.lua 모듈을 사용하고 있습니다. 이는 블라디미르 드로 니 코프의 제안에 약간의 변형이 있습니다. 및 호출 루아 스크립트가 자유롭게 print 문에 뿌려 규정 된 영지또 다른 모듈 메모리 손실 문제

<pre> 
    i2c.setup(0, 3, 4, i2c.SLOW) 
    lcd = dofile("lcd.lua")() 
</pre> 

에 전화 :

wifiConnect이 dofile 호출하면 내 파일 구조는이

<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> 

과 같은

<pre> 
    lcd.put(lcd:locate(0, 0),"Mast Temp: ") 
</pre> 

GetServerData에 대해 보통 '메모리 부족'으로 넘어지기 가끔 스크립트가 2 ~ 3 회 실행됩니다. befo 메모리 부족 오류가 발생했습니다. 그러나 나는 넘어지기 전에 8000-9000 번 뛰었습니다. 내가 wifiConnect 그것이

<pre> 
    PANIC: unprotected error in call to Lua API (not enough memory) 
</pre> 

이 GetServerData로드와 중지됩니다 GetFileData을 실행할 수 있도록 허용 할 경우 (하나 또는 두 번.) 반드시 충분히 실행하려면 18800.를 떠나 .. 힙에 13,816 바이트를 소비 할 것으로 보인다. 나는 require (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) 

을 다음과 esplorer 윈도우의 화면 잡아가 GetServerData을로드하고 수 때

<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> 

어떤 도움을 기꺼이받을 것입니다 및 기타를 실행하려면이 모양으로

GetServerData입니다 행복하게 도울 수있는 정보

많은 감사합니다 필립

+0

지금 해결 되었습니까? –

답변

1

빗 맞을 코드가 상당히 많습니다. 문제를 재현 할 Minimal, Complete, and Verifiable example을 제공하면 도움이 될 것입니다 (->최소).

간략히 살펴보면 2.5 개의 이슈가 있지만 그보다 더 많은 가능성이 있습니다.

청산 upvalues ​​

conn:on("receive",function(conn,payload) 누출 콜백 매개 변수는 conn하지만 뭔가 다른 대신하지 않아야하기 때문이다. https://github.com/nodemcu/nodemcu-firmware/issues/194#issuecomment-184817667 또는 https://stackoverflow.com/a/37379426/131929

가 보내기 참조 이러한 호출의 각 비동기 따라서 호출 순서가 보장되지 않기 때문에

conn:send가 빠르게 연속으로 호출 할 수 없습니다 비동기입니다.자세한 내용과 좋은 예는 net.socket:send 설명서를 참조하십시오.

HTTP 모듈 http.get이 코드에서 복잡성을 줄일 수 있습니다 사용

을 고려하십시오.