2017-03-05 2 views
1

この問題は私をナットにしています。その消費された方法はあまりにも多くの時間と私はいくつかの助けをすることができますよ! 基本的には、Get()を使ってサーバから気象データをダウンロードしています。これはうまくいく。私がしたいのは、16x2のi2c液晶画面に表示するだけですが、私は「メモリ不足」問題に悩まされています。 私はコミュニティーから提供されたいくつかのモジュールを試しましたが、すべて同じ問題を抱えているようですので、私のコード/呼び出し規約に問題があると確信しました。 Imは現在、lcd.luaというモジュールを使用しています。これは、Vladimir Dronnikovの製品に若干のバリエーションがあります。そして、規定マナーさらに別のモジュールのメモリ損失の問題

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

でそれを呼び出し、呼び出しのluaスクリプトを自由にprint文を振りかけている:wifiConnectはdofileを呼び出すと

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

のように見えますGetServerDataに対してそれは通常フォールオーバー "不十分なメモリ"時にはスクリプトは2または3回実行されますbefoメモリ不足のエラーが発生しました。 しかし私はそれが転倒する前に8000-9000回走っていました。 (1つまたは2回) 私はwifiConnectがGetFileDataを実行できるようにする場合は、

GetServerDataをロード
<pre> 
    PANIC: unprotected error in call to Lua API (not enough memory) 
</pre> 

で停止します実行することが確実に十分18800.を残して...ヒープ上に13816のバイトを消費しているようです。 私は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) 

を次のようにGetServerDataがあると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> 

を実行できるようにするときesplorerウィンドウの画面のグラブは、このようになります。喜んで役立つ情報

多くのありがとう フィリップ

+0

これは解決されましたか? –

答えて

1

これは非常に多くのコードを解決するためのものです。問題を再現するMinimal, Complete, and Verifiable exampleを提供した場合は、もっと便利です( - >最小)。

クイックグランは2.5の問題を明らかにしましたが、もっと可能性があります。

クローズ上位値

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は、あなたのコード内の複雑さを軽減することが使用

に考えてみましょう。