esp8266 memory problems

Posted on
Page
of 2
/ 2
Next
  • Hi,

    I have some memory problems with a js code.

    I connect to wifi, resolve an ip addr, connect to onewire, get the ds18s20 sensor data, and every minutes it sends the data to thingspeak.

    For a while (what is sometimes 5-10 horus, sometimes less), I got this (it disconnect from espruino ide, and I need to reconnect):

    The response connection closed
    connection close
    { "free": 107, "usage": 916, "total": 1023, "history": 1 }
    >
    Disconnected
    >
    Connected
    >)ü
    =undefined
    >
    =undefined
    current temp:25.5
    sendTsStart
    { "free": 213, "usage": 810, "total": 1023, "history": 17 }
    ERROR: Out of Memory!
    WARNING: Unable to create string as not enough memory
    WARNING: Out of memory while appending to array
    Execution Interrupted
    current temp:25.5
    sendTsStart
    { "free": 212, "usage": 811, "total": 1023, "history": 1 }
    WARNING: Unable to create string as not enough memory
    WARNING: Out of memory while appending to array
    Execution Interrupted
    

    Here is the code:

    require("ESP8266").logDebug(false);
    
    var ssid = "ssid";
    var pass = "pass";
    
    var ApiKey = 'apikey';
    
    
    var peri = 60; //period of reading sensor in sec.
    
    var iotHostName="thingspeak.com";
    var iotIpAddr="";
    
    
    var GPIO0 = new Pin(12); // GPIO0 | ~D3 port
    var ow = new OneWire(GPIO0);
    var sensor = require("DS18S20").connect(ow);
    
    var GPIO2 = new Pin(2); // internal led
    var toggle=1;
    
    var startBlink = function()
    {
      print("startBlink");
      setInterval(function() {
        toggle=!toggle;
          digitalWrite(GPIO2, toggle);
        }, 500);
    };
    
    var connectToWifi = function() {
      console.log('connecting to wifi');
      var GPIO2 = new Pin(2);
    
      digitalWrite(GPIO2, 1);
      ESP8266WiFi.init();
      ESP8266WiFi.connect(ssid, pass, function() {
        digitalWrite(GPIO2, 0);
        console.log('connected to wifi');
        var ipInfo = ESP8266WiFi.getIPInfo();
        print("Current IP address is: " +
          ESP8266WiFi.getAddressAsString(ipInfo.ip­) + ':' +
          ESP8266WiFi.getAddressAsString(ipInfo.ne­tmask));
    
        resolveIotAddress(repeat);
    
      });
    };
    
    var resolveIotAddress= function(callback)
    {
      var ESP8266 = require("ESP8266");
      ESP8266.getHostByName(iotHostName, function(address) {
    
        iotIpAddr = ESP8266.getAddressAsString(address);
        console.log('resolved:' + iotIpAddr);
    
        startBlink();
    
        callback();
    
      });
    
    };
    
    var sendTs = function(temp) {
        console.log('sendTsStart');
        console.log(process.memory());
    
        var http = require("http");
        http.get({
            host: iotIpAddr,
            port: 80,
            headers: {
              'Host': 'tingspeak.com',
            },
            path: '/update?key=' + ApiKey + '&field1=' + temp
          },
          function(response) {
            print("get callback!");
            response.on('data', function(data) {
              console.log('connection getdata:');
              console.log(process.memory());
              print(data);
            });
            response.on('close', function() {
              print("The response connection closed");
              console.log('connection close');
              console.log(process.memory());
    
            });
          }
        );
    
    };
    
    var sendTemperature = function(temp)
    {
      console.log('current temp:' + temp);
    //  var field2 = 1 + Math.floor(Math.random() * 40);
      sendTs(temp);
    };
    
    repeat = function() {
      //var field1 = 1 + Math.floor(Math.random() * 40);
     // var field2 = 1 + Math.floor(Math.random() * 40);
    //  sendTs(field1, field2);
    
      sensor.getTemp(sendTemperature);
    
      setTimeout(repeat, peri * 1000);
    };
    
    
    E.on('init', function() {
      connectToWifi();
    });
    
    

    The smallest value what I get, is the response in the sendTs function in respons.on data part:

    { "free": 17, "usage": 1006, "total": 1023, "history": 1 }
    1331

    I used a changed ds18b20 library to support ds18s20. I send it in the next post.

    thanks,
    HyGy

  • Here is the modified ds18b20 code. It uses a callback when the temperature is ready.

    /* Copyright (c) 2013 Gordon Williams, Pur3 Ltd. See the file LICENSE for copying permission. */
    /* Modified by HyGy */
    /* Module for the DS18B20 temperature sensor */
    
    var C = {
        CONVERT_T: 0x44,
        COPY: 0x48,
        READ: 0xBE,
        WRITE: 0x4E
    };
    
    function DS18B20(oneWire, device) {
        this.bus = oneWire;
        if (device === undefined) {
            this.sCode = this.bus.search()[0];
        } else {
            if (parseInt(device).toString() == device && device >= 0 && device <= 126) {
                this.sCode = this.bus.search()[device];
            } else {
                this.sCode = device;
            }
        }
        this.deviceTypeCode=parseInt(this.sCode[­0]+this.sCode[1]);
    }
    
    /** For internal use - read the scratchpad region */
    DS18B20.prototype._readSpad = function(convert_t) {
    
        var spad = [];
        this.bus.reset();
        this.bus.select(this.sCode);
        convert_t=false;
        if (convert_t) {
    
            this.bus.write(C.CONVERT_T, true);
            this.bus.reset();
            this.bus.select(this.sCode);
        }
        this.bus.write(C.READ);
        for (var i = 0; i < 9; i++) {
            spad.push(this.bus.read());
        }
        return spad;
    };
    
    /** For internal use - write the scratchpad region */
    DS18B20.prototype._writeSpad = function(th, tl, conf) {
        this.bus.reset();
        this.bus.select(this.sCode);
        this.bus.write(C.WRITE);
        this.bus.write(th);
        this.bus.write(tl);
        this.bus.write(conf);
        this.bus.reset();
        this.bus.select(this.sCode);
        this.bus.write(C.COPY);
        this.bus.reset();
    };
    
    /** Set the resolution in bits. From 8 to 12 bits */
    DS18B20.prototype.setRes = function(res) {
        var spad = this._readSpad();
        res = [0x1F, 0x3F, 0x5F, 0x7F][E.clip(res, 9, 12) - 9];
        this._writeSpad(spad[2], spad[3], res);
    };
    
    /** Return the resolution in bits. From 8 to 12 bits */
    DS18B20.prototype.getRes = function() {
        return [0x1F, 0x3F, 0x5F, 0x7F].indexOf(this._readSpad()[4]) + 9;
    };
    
    /** Return true if this device is present */
    DS18B20.prototype.isPresent = function() {
        return this.bus.search().indexOf(this.sCode) !== -1;
    };
    
    /** Get a temperature reading, in degrees C */
    DS18B20.prototype.getTempOld = function(verify) {
    
        var spad = null;
        var temp = null;
        if ((verify && !this.isPresent()) || !this.sCode) {
            return temp;
        }
        spad = this._readSpad(true);
    
        temp = spad[0] + (spad[1] << 8);
        if (temp > 32767) {
            temp -= 65536;
        }
        temp = temp / 16.0;
        return temp;
    };
    
    DS18B20.prototype.getTemp = function(callback) {
    
        var me=this;
        var temp=null;
        var spad=null;
    
      ow.reset();
      ow.select(this.sCode);
      ow.write(C.CONVERT_T, true);
    
      setTimeout(
        function() {
          var s = sensor._readSpad(false);
          var str="";
          s.forEach( function(v) { str+=" 0x"+v.toString(16); } );
          var temp = s[0] + (s[1]<<8);
          if (temp > 32767) temp -= 65536;
    
          switch (me.deviceTypeCode)
          {
            case 10:
               temp = temp/2.0;
                break;
            default:
              temp = temp/16;
              break;
          }
          callback(temp);
        },
        1000);
    }
    
    /** Return a list of all DS18B20 sensors with the alarms set */
    DS18B20.prototype.searchAlarm = function() {
        return this.bus.search(0xEC);
    };
    
    /** Set alarm low and high values in degrees C - see DS18B20.prototype.searchAlarm.
      If the temperature goes below `lo` or above `hi` the alarm will be set. */
    DS18B20.prototype.setAlarm = function(lo, hi) {
        lo--; // DS18B20 alarms if (temp<=lo || temp>hi), but we want (temp<lo || temp>hi)
        if (lo < 0) lo += 256;
        if (hi < 0) hi += 256;
        var spad = this._readSpad();
        this._writeSpad(hi, lo, spad[4]);
    };
    
    /** Initialise a DS18B20 device. Use either as:
      connect(new OneWire(pin)) - use the first found DS18B20 device
      connect(new OneWire(pin), N) - use the Nth DS18B20 device
      connect(new OneWire(pin), ID) - use the DS18B20 device with the given ID
     */
    exports.connect = function(oneWire, device) {
        return new DS18B20(oneWire, device);
    };
    
    
  • As far as I can tell, the out of memory error comes from JsVars:
    https://github.com/espruino/Espruino/blo­b/4f9f8a0bfea3e9fa8c9bffca71eab00f18676d­48/src/jsvar.c#L371
    @Gordon, is there a way to have this print a stack backtrace for where the out of memory failure occurs?

  • @HyGy I've just confirmed on gitter that using IP address in place of hostname allows me to send data to Sparkfun using http.get(...). With hostname I was getting the out of memory issue after about 7 requests similar to what you have been seeing. @kolban gave me the heads up on that last night.

    https://data.sparkfun.com/streams/6JxNaX­7o06S0RxJgvRdD

    Will bet that is your issue? Maybe try divorce your code from the temperature polling as that would appear to be a separate issue - maybe the probe you have? (I was able read temp using the DS18B20 module and a DS18B20 probe on ESP8266 just fine - also posted about that on gitter)

  • @hygy so you're saying it runs fine, but crashes occasionally? Or it never completes successfully?

    If it never completes successfully then it's just likely that what you've written uses up too much memory:

    • Make sure the Web IDE is set to upload minified modules.
    • Delete the setAlarm and other functions you're not using from your DS18B20 module
    • Delete the lines of commented out code you've put in functions in your main file - these will use up memory

    If it is crashing only after some hours, try running E.getSizeOf(global, 1) repeatedly, and see if any one of the variables listed keeps getting bigger. If so, that might give some hint as to where the problem is. You can use E.getSizeOf(global, 2)/etc to drill down more to find the problem.

    The disconnect is worrying too. If you're using something like the NodeMCU board, the USB is handled by a separate chip - about the only thing that could cause the connection to drop if if there was some problem with the power supply.

    @tve I'm afraid there isn't - the usual stack trace stuff runs by storing the stack trace in variables, so it wouldn't work as there's no memory!

    Usually these things aren't caused by the actual function that fails with out of memory though - it'd be something else eating it up slowly and not releasing it.

    As I feel I have to say in these circumstances: if you used an 'official' Espruino board this would work without problems - because I can afford to properly support and test those boards

  • @Ollie thanks - sorry, I missed your post while typing the response here :)

    With hostname I was getting the out of memory issue after about 7 requests

    That sounds like a memory leak in the ESP8266 code then. Probably the callback that's being locked but not unlocked in the C code.

  • Yup ... we need to do better in handling gethostbyname functions on the ESP8266 ... the following Issue will be used to track: #590

    https://github.com/espruino/Espruino/iss­ues/590

  • @Gordon it is running some time, whitout problem, then it dies. When this happens, i reset the board, the problem will be the same exactyl, then I try to plug and unplug the board from the usb port but it is wrong. So I send the saved code to esp8266 again with the espruino ide, then save() it, after that it is working.

    I'll try tu put the given code lines to have more debug messages.

    But I think there is stg wrong with the http get module, maybe the esp8266 implementation is buggy somewhere.

  • Wooo I write this in the console:

    what is that: ----> "ÿ"

    >E.getSizeOf(global, 1)
    =[
      {
        "name": "ÿ",
        "size": 354 },
      {
        "name": "Modules",
        "size": 3 },
      {
        "name": "ssid",
        "size": 3 },
      {
        "name": "pass",
        "size": 3 },
      {
        "name": "ApiKey",
        "size": 5 },
       ...
      {
        "name": "Restart",
        "size": 2 },
      {
        "name": "process",
        "size": 3 },
      {
        "name": "httpCRs",
        "size": 8 },
      {
        "name": "httpCRq",
        "size": 8 },
      {
        "name": "JSON",
        "size": 2 }
     ]
    > 
    
  • I believe that Espruino has a concept called "hidden variables" and these are variables that are rooted from a JavaScript object called "\0xFF" ... i.e. an object name composed of a single character that is unprintable and has the ordinal value of 255 decimal.

  • Yes, it's a bit hacky at the moment, but \xFF contains internal stuff. You could look inside with E.getSizeOf(global["\xFF"], 1) and in even greater depth with E.getSizeOf(global["\xFF"], 2)

  • E.getSizeOf(global["\xFF"]["modules"], 1);
    =[
      {
        "name": "DS18B20",
        "size": 207 },
      {
        "name": "ESP8266",
        "size": 3 }
     ]
    > 
    
  • But... do any of them get bigger after you have done an HTTP request or two?

  • I put this line

    console.log(process.memory());

    in the http response.on('data', function(data) {

    And now it is crashing immediately, when get into this part.

  • Crashing? Or getting out of memory?

    Something sounds pretty broken there then. @Kolban I see you had your windows-based debug build that you put in the repositories. Did you ever finish that? If you could reproduce the issue on there (you might want to make sure build_platform_config builds the image with 1023 vars too) then debugging would be a lot easier.

  • Okay,

    The mean time I connected a second usbttl to UART1:

    @Kolban is it help for you?
    Here is what I get on the debug serial port:

    Restart info:
      reason:   6=reset pin
      exccause: 0
      epc1:     0
      epc2:     0
      epc3:     0
      excvaddr: 0
      depc:     0
    Flash map 512KB:256/256, manuf 0xE0 chip 0x4016
    Heap: 6096
    Variables: 1023 @12ea = 12276bytes
    Time sys=320912 rtc=62118
    mode : null
    > initDone
    > jshInit
    RTC read: 1685498645 1873183604 0xfd538868 (0x9e8d8e81)
    RTC: cannot restore time
    UStimer init
    < jshInit
    > jswrap_ESP8266_init
    > jswrap_ESP8266WiFi_
     ets Jan  8 2013,rst cause:2, boot mode:(3,0)
    
    load 0x40100000, len 30936, room 16 
    tail 8
    chksum 0x75
    load 0x3ffe8000, len 2108, room 0 
    tail 12
    chksum 0x34
    ho 0 tail 12 room 4
    load 0x3ffe8840, len 29476, room 12 
    tail 8
    chksum 0x15
    csum 0x15
    
    
    
    
    Restart info:
      reason:   2=exception
      exccause: 0
      epc1:     40100711
      epc2:     0
      epc3:     0
      excvaddr: 0
      depc:     0
    Flash map 512KB:256/256, manuf 0xE0 chip 0x4016
    Heap: 6096
    Variables: 1023 @12ea = 12276bytes
    Time sys=330807 rtc=944651649
    mode : null
    > initDone
    > jshInit
    RTC read: 5374 933665468 0xa95ea382 (0xdeadbeef)
    RTC: restore sys=340961 rtc=944653293
    RTC: restored time: 5442 (delta=10987825 cal=6174us)
    UStimer init
    < jshInit
    > jswrap_ESP8266_init
    > jswrap_ESP8266WiFi_
    

    And here is what I got from the espruino console:

    sendTsStart
    { "free": 425, "usage": 598, "total": 1023, "history": 20 }
    >
    Disconnected
    >
    Connected
    Interrupted
    Execution Interrupted
    Execution Interrupted
    >
    ASSERT(jsvHasCharacterData(str)) FAILED AT src/jsvariterator.c:144
      #1[r1,l2] Object {
        #2[r1,l2] Name String [1 blocks] ""      #3[r1,l2] Object {
            #6[r1,l2] Name String [1 blocks] ""          #493[r1,l2] String [2 blocks] "\x04\x00\x00\x00\x00ÿÿÿ"
            #9[r1,l2] Name String [2 blocks] ""          #11[r2,l1] Array(177) [
                #513[r1,l2] Name Integer 1              #521[r1,l1] Object {
                    #519[r1,l2] Name String [1 blocks] ""                  undefined
                    #517[r1,l2] Name String [2 blocks] ""                  #518[r1,l1] Integer 500000
                    #515[r1,l2] Name String [2 blocks] ""                  #531[r1,l1] Function {
                        #526[r1,l2] Name String [1 blocks] ""                      #532[r1,l1] String [6 blocks] "{toggle=!toggle;digitalWrite(GPIO2,togg­le)}"
                        #525[r1,l2] Name String [1 blocks] ""                      #201[r1,l1] Function {
                            #509[r1,l2] Name String [2 blocks] ""                          undefined
                          }
                        #523[r1,l2] Name String [1 blocks] ""= int 4
                      }
                  }
                #474[r1,l2] Name Integer 176              #377[r1,l1] Object {
                    #372[r1,l2] Name String [1 blocks] ""                  undefined
                    #462[r1,l2] Name String [2 blocks] ""                  #432[r2,l1] ...
     
                  }
              ]
            #12[r1,l2] Name String [2 blocks] ""          #14[r2,l1] Array(0) [ ]
            #15[r1,l2] Name String [2 blocks] ""          #19[r1,l1] Array(13) [ ]
            #21[r1,l2] Name String [2 blocks] ""          #35[r1,l1] Object {
                #23[r1,l2] Name String [2 blocks] ""              #36[r2,l1] ...
     
                #186[r1,l2] Name String [1 blocks] ""              #185[r2,l1] ...
     
              }
            #641[r1,l2] Name String [2 blocks] ""          #643[r1,l1] Array(175) [
                #719[r1,l2] Name Integer 73              #728[r1,l1] Object {
                    #727[r1,l2] Name String [2 blocks] ""                  #660[r9,l1] ...
     
                    #721[r1,l2] Name String [1 blocks] ""= int 1
                    #722[r1,l2] Name String [2 blocks] ""                  #817[r1,l1] Function {
                        #813[r1,l2] Name Param ""                       undefined
                        #778[r1,l2] Name String [1 blocks] ""                      #814[r1,l1] String [37 blocks] "{print(\"get callback!\");a.on(\"data\",function(a){c­onsole.log(\"connection getdata:\");console.log(process.memory()­);console.log(E.getSizeOf(global,1));pri­nt(a)});a.on(\"close\",function(){print(­\"The response connection closed\");console.log(\"connection close\");console.log(process.memory())})­}"
                        #777[r1,l2] Name String [1 blocks] ""                      #953[r1,l1] Function {
                            #955[r1,l2] Name Param ""                           #488[r176,l1] ...
     
                            #949[r1,l2] Name String [2 blocks] ""                          undefined
                          }
                        #775[r1,l2] Name String [1 blocks] ""= int 6
                      }
                    #718[r1,l2] Name String [1 blocks] ""                  #731[r1,l1] Object {
                        #730[r1,l2] Name String [2 blocks] ""                      #649[r176,l1] ...
     
                      }
                    #713[r1,l2] Name String [1 blocks] ""                  #842[r1,l1] Object {
                        #822[r1,l2] Name String [1 blocks] ""                      #535[r9,l1] ...
     
                        #821[r1,l2] Name String [1 blocks] ""= int 80
                        #825[r1,l2] Name String [2 blocks] ""                      #828[r1,l1] Object {
                            #827[r1,l2] Name String [1 blocks] ""                          #826[r1,l1] String [3 blocks] "tingspeak.com"
                          }
                        #938[r1,l2] Name String [1 blocks] ""                      #863[r1,l1] String [6 blocks] "/update?key=UN3U6J51X72NCG18&field1=28"­
                        #733[r1,l2] Name String [2 blocks] ""                      #776[r1,l1] String [1 blocks] "GET"
                      }
                    #640[r1,l2] Name String [1 blocks] ""                  undefined
                    #637[r1,l2] Name String [1 blocks] ""= int 74
                  }
                #748[r1,l2] Name Integer 120              #762[r1,l1] Object {
                    #759[r1,l2] Name String [2 blocks] ""                  #660[r9,l1] ...
     
                    #750[r1,l2] Name String [1 blocks] ""= int 1
                    #751[r1,l2] Name String [2 blocks] ""                  #927[r1,l1] Function {
                        #923[r1,l2] Name Param ""                       undefined
                        #829[r1,l2] Name String [1 blocks] ""                      #924[r1,l1] String [37 blocks] "{print(\"get callback!\");a.on(\"data\",function(a){c­onsole.log(\"connection getdata:\");console.log(process.memory()­);console.log(E.getSizeOf(global,1));pri­nt(a)});a.on(\"close\",function(){print(­\"The response connection closed\");console.log(\"connection close\");console.log(process.memory())})­}"
                        #774[r1,l2] Name String [1 blocks] ""                      #628[r1,l1] Function {
                            #520[r1,l2] Name Param ""                           #488[r176,l1] ...
     
                            #398[r1,l2] Name String [2 blocks] ""                          undefined
                          }
                        #772[r1,l2] Name String [1 blocks] ""= int 6
                      }
                    #747[r1,l2] Name String [1 blocks] ""                  #765[r1,l1] Object {
                        #764[r1,l2] Name String [2 blocks] ""                      #649[r176,l1] ...
     
                      }
                    #746[r1,l2] Name String [1 blocks] ""                  #967[r1,l1] Object {
                        #943[r1,l2] Name String [1 blocks] ""                      #535[r9,l1] ...
     
                        #942[r1,l2] Name String [1 blocks] ""= int 80
                        #947[r1,l2] Name String [2 blocks] ""                      #952[r1,l1] Object {
                            #951[r1,l2] Name String [1 blocks] ""                          #950[r1,l1] String [3 blocks] "tingspeak.com"
                          }
                        #920[r1,l2] Name String [1 blocks] ""                      #769[r1,l1] String [6 blocks] "/update?key=UN3U6J51X72NCG18&field1=28"­
                        #771[r1,l2] Name String [2 blocks] ""                      #773[r1,l1] String [1 blocks] "GET"
                      }
                    #663[r1,l2] Name String [1 blocks] ""                  undefined
                    #629[r1,l2] Name String [1 blocks] ""= int 121
                  }
                #703[r1,l2] Name Integer 148              #710[r1,l1] Object {
                    #708[r1,l2] Name String [2 blocks] ""                  #660[r9,l1] ...
     
                    #705[r1,l2] Name String [1 blocks] ""= int 1
                    #706[r1,l2] Name String [2 blocks] ""                  #977[r1,l1] Function {
                        #970[r1,l2] Name Param ""                       undefined
                        #897[r1,l2] Name String [1 blocks] ""                      #972[r1,l1] String [37 blocks] "{print(\"get callback!\");a.on(\"data\",function(a){c­onsole.log(\"connection getdata:\");console.log(process.memory()­);console.log(E.getSizeOf(global,1));pri­nt(a)});a.on(\"close\",function(){print(­\"The response connection closed\");console.log(\"connection close\");console.log(process.memory())})­}"
                        #896[r1,l2] Name String [1 blocks] ""                      #568[r1,l1] Function {
                            #329[r1,l2] Name Param ""                           #488[r176,l1] ...
     
                            #308[r1,l2] Name String [2 blocks] ""                          undefined
                          }
                        #893[r1,l2] Name String [1 blocks] ""= int 6
                      }
                    #702[r1,l2] Name String [1 blocks] ""                  #734[r1,l1] Object {
                        #725[r1,l2] Name String [2 blocks] ""                      #649[r176,l1] ...
     
                      }
                    #693[r1,l2] Name String [1 blocks] ""                  #1012[r1,l1] Object {
                        #995[r1,l2] Name String [1 blocks] ""                      #535[r9,l1] ...
     
                        #993[r1,l2] Name String [1 blocks] ""= int 80
                        #998[r1,l2] Name String [2 blocks] ""                      #999[r1,l1] Object {
                            #1004[r1,l2] Name String [1 blocks] ""                          #1002[r1,l1] String [3 blocks] "tingspeak.com"
                          }
                        #903[r1,l2] Name String [1 blocks] ""                      #744[r1,l1] String [6 blocks] "/update?key=UN3U6J51X72NCG18&field1=28"­
                        #855[r1,l2] Name String [2 blocks] ""                      #894[r1,l1] String [1 blocks] "GET"
                      }
                    #524[r1,l2] Name String [1 blocks] ""                  undefined
                    #510[r1,l2] Name String [1 blocks] ""= int 149
                  }
                #633[r1,l2] Name Integer 166              #717[r1,l1] Object {
                    #712[r1,l2] Name String [2 blocks] ""                  #660[r9,l1] ...
     
                    #669[r1,l2] Name String [1 blocks] ""= int 1
                    #698[r1,l2] Name String [2 blocks] ""                  #1003[r1,l1] Function {
                        #989[r1,l2] Name Param ""                       undefined
                        #752[r1,l2] Name String [1 blocks] ""                      #992[r1,l1] String [37 blocks] "{print(\"get callback!\");a.on(\"data\",function(a){c­onsole.log(\"connection getdata:\");console.log(process.memory()­);console.log(E.getSizeOf(global,1));pri­nt(a)});a.on(\"close\",function(){print(­\"The response connection closed\");console.log(\"connection close\");console.log(process.memory())})­}"
                        #743[r1,l2] Name String [1 blocks] ""                      #573[r1,l1] Function {
                            #865[r1,l2] Name Param ""                           #488[r176,l1] ...
     
                            #247[r1,l2] Name String [2 blocks] ""                          undefined
                          }
                        #741[r1,l2] Name String [1 blocks] ""= int 6
                      }
                    #625[r1,l2] Name String [1 blocks] ""                  #737[r1,l1] Object {
                        #735[r1,l2] Name String [2 blocks] ""                      #649[r176,l1] ...
     
                      }
                    #623[r1,l2] Name String [1 blocks] ""                  #1022[r1,l1] Object {
                        #1013[r1,l2] Name String [1 blocks] ""                      #535[r9,l1] ...
     
                        #1011[r1,l2] Name String [1 blocks] ""= int 80
                        #1016[r1,l2] Name String [2 blocks] ""                      #1017[r1,l1] Object {
                            #1019[r1,l2] Name String [1 blocks] ""                          #1018[r1,l1] String [3 blocks] "tingspeak.com"
                          }
                        #355[r1,l2] Name String [1 blocks] ""                      #758[r1,l1] String [6 blocks] "/update?key=UN3U6J51X72NCG18&field1=28"­
                        #740[r1,l2] Name String [2 blocks] ""                      #742[r1,l1] String [1 blocks] "GET"
                      }
                    #397[r1,l2] Name String [1 blocks] ""                  undefined
                    #375[r1,l2] Name String [1 blocks] ""= int 167
                  }
                #229[r1,l2] Name Integer 167              #237[r1,l1] Object {
                    #235[r1,l2] Name String [2 blocks] ""                  #660[r9,l1] ...
     
                    #231[r1,l2] Name String [1 blocks] ""= int 1
                    #233[r1,l2] Name String [2 blocks] ""                  #616[r1,l1] Function {
                        #288[r1,l2] Name Param ""                       undefined
                        #248[r1,l2] Name String [1 blocks] ""                      #394[r1,l1] String [37 blocks] "{print(\"get callback!\");a.on(\"data\",function(a){c­onsole.log(\"connection getdata:\");console.log(process.memory()­);console.log(E.getSizeOf(global,1));pri­nt(a)});a.on(\"close\",function(){print(­\"The response connection closed\");console.log(\"connection close\");console.log(process.memory())})­}"
                        #246[r1,l2] Name String [1 blocks] ""                      #864[r1,l1] Function {
                            #374[r1,l2] Name Param ""                           #488[r176,l1] ...
     
                            #239[r1,l2] Name String [2 blocks] ""                          undefined
                          }
                        #244[r1,l2] Name String [1 blocks] ""= int 6
                      }
                    #226[r1,l2] Name String [1 blocks] ""                  #241[r1,l1] Object {
                        #240[r1,l2] Name String [2 blocks] ""                      #649[r176,l1] ...
     
                      }
                    #225[r1,l2] Name String [1 blocks] ""                  #399[r1,l1] Object {
                        #595[r1,l2] Name String [1 blocks] ""                      #535[r9,l1] ...
     
                        #596[r1,l2] Name String [1 blocks] ""= int 80
                        #579[r1,l2] Name String [2 blocks] ""                      #575[r1,l1] Object {
                            #469[r1,l2] Name String [1 blocks] ""                          #574[r1,l1] String [3 blocks] "tingspeak.com"
                          }
                        #298[r1,l2] Name String [1 blocks] ""                      #401[r1,l1] String [6 blocks] "/update?key=UN3U6J51X72NCG18&field1=28"­
                        #243[r1,l2] Name String [2 blocks] ""                      #245[r1,l1] String [1 blocks] "GET"
                      }
                    #440[r1,l2] Name String [1 blocks] ""                  undefined
                    #463[r1,l2] Name String [1 blocks] ""= int 168
                  }
                #470[r1,l2] Name Integer 172              #522[r1,l1] Object {
                    #511[r1,l2] Name String [2 blocks] ""                  #660[r9,l1] ...
     
                    #485[r1,l2] Name String [1 blocks] ""= int 1
                    #486[r1,l2] Name String [2 blocks] ""                  #736[r1,l1] Function {
                        #682[r1,l2] Name Param ""                       undefined
                        #567[r1,l2] Name String [1 blocks] ""                      #695[r1,l1] String [37 blocks] "{print(\"get callback!\");a.on(\"data\",function(a){c­onsole.log(\"connection getdata:\");console.log(process.memory()­);console.log(E.getSizeOf(global,1));pri­nt(a)});a.on(\"close\",function(){print(­\"The response connection closed\");console.log(\"connection close\");console.log(process.memory())})­}"
                        #566[r1,l2] Name String [1 blocks] ""                      #610[r1,l1] Function {
                            #347[r1,l2] Name Param ""                           #488[r176,l1] ...
     
                            #305[r1,l2] Name String [2 blocks] ""                          undefined
                          }
                        #558[r1,l2] Name String [1 blocks] ""= int 6
                      }
                    #468[r1,l2] Name String [1 blocks] ""                  #554[r1,l1] Object {
                        #553[r1,l2] Name String [2 blocks] ""                      #649[r176,l1] ...
     
                      }
                    #467[r1,l2] Name String [1 blocks] ""                  #1001[r1,l1] Object {
                        #861[r1,l2] Name String [1 blocks] ""                      #535[r9,l1] ...
     
                        #856[r1,l2] Name String [1 blocks] ""= int 80
                        #969[r1,l2] Name String [2 blocks] ""                      #980[r1,l1] Object {
                            #984[r1,l2] Name String [1 blocks] ""                          #982[r1,l1] String [3 blocks] "tingspeak.com"
                          }
                        #380[r1,l2] Name String [1 blocks] ""                      #379[r1,l1] String [6 blocks] "/update?key=UN3U6J51X72NCG18&field1=28"­
                        #557[r1,l2] Name String [2 blocks] ""                      #565[r1,l1] String [1 blocks] "GET"
                      }
                    #361[r1,l2] Name String [1 blocks] ""                  undefined
                    #357[r1,l2] Name String [1 blocks] ""= int 173
                  }
                #453[r1,l2] Name Integer 173              #392[r1,l1] Object {
                    #512[r1,l2] Name String [2 blocks] ""                  #660[r9,l1] ...
     
                    #351[r1,l2] Name String [1 blocks] ""= int 1
                    #405[r1,l2] Name String [2 blocks] ""                  #300[r1,l1] Function {
                        #336[r1,l2] Name Param ""                       undefined
                        #29[r1,l2] Name String [1 blocks] ""                      #337[r1,l1] String [37 blocks] "{print(\"get callback!\");a.on(\"data\",function(a){c­onsole.log(\"connection getdata:\");console.log(process.memory()­);console.log(E.getSizeOf(global,1));pri­nt(a)});a.on(\"close\",function(){print(­\"The response connection closed\");console.log(\"connection close\");console.log(process.memory())})­}"
                        #28[r1,l2] Name String [1 blocks] ""                      #472[r1,l1] Function {
                            #307[r1,l2] Name Param ""                           #488[r176,l1] ...
     
                            #339[r1,l2] Name String [2 blocks] ""                          undefined
                          }
                        #24[r1,l2] Name String [1 blocks] ""= int 6
                      }
                    #402[r1,l2] Name String [1 blocks] ""                  #16[r1,l1] Object {
                        #344[r1,l2] Name String [2 blocks] ""                      #649[r176,l1] ...
     
                      }
                    #299[r1,l2] Name String [1 blocks] ""                  #364[r1,l1] Object {
                        #403[r1,l2] Name String [1 blocks] ""                      #535[r9,l1] ...
     
                        #455[r1,l2] Name String [1 blocks] ""= int 80
                        #389[r1,l2] Name String [2 blocks] ""                      #388[r1,l1] Object {
                            #385[r1,l2] Name String [1 blocks] ""                          #386[r1,l1] String [3 blocks] "tingspeak.com"
                          }
                        #466[r1,l2] Name String [1 blocks] ""                      #362[r1,l1] String [6 blocks] "/update?key=UN3U6J51X72NCG18&field1=28"­
                        #20[r1,l2] Name String [2 blocks] ""                      #27[r1,l1] String [1 blocks] "GET"
                      }
                    #701[r1,l2] Name String [1 blocks] ""                  undefined
                    #699[r1,l2] Name String [1 blocks] ""= int 174
                  }
                #564[r1,l2] Name Integer 174              #691[r1,l1] Object {
                    #692[r1,l2] Name String [2 blocks] ""                  #660[r9,l1] ...
     
                    #689[r1,l2] Name String [1 blocks] ""= int 1
                    #1010[r1,l2] Name String [2 blocks] ""                  #359[r1,l1] Function {
                        #358[r1,l2] Name Param ""                       undefined
                        #674[r1,l2] Name String [1 blocks] ""                      #716[r1,l1] String [37 blocks] "{print(\"get callback!\");a.on(\"data\",function(a){c­onsole.log(\"connection getdata:\");console.log(process.memory()­);console.log(E.getSizeOf(global,1));pri­nt(a)});a.on(\"close\",function(){print(­\"The response connection closed\");console.log(\"connection close\");console.log(process.memory())})­}"
                        #675[r1,l2] Name String [1 blocks] ""                      #384[r1,l1] Function {
                            #396[r1,l2] Name Param ""                           #488[r176,l1] ...
     
                            #346[r1,l2] Name String [2 blocks] ""                          undefined
                          }
                        #680[r1,l2] Name String [1 blocks] ""= int 6
                      }
                    #561[r1,l2] Name String [1 blocks] ""                  #684[r1,l1] Object {
                        #685[r1,l2] Name String [2 blocks] ""                      #649[r176,l1] ...
     
                      }
                    #542[r1,l2] Name String [1 blocks] ""                  #688[r1,l1] Object {
                        #338[r1,l2] Name String [1 blocks] ""                      #535[r9,l1] ...
     
                        #367[r1,l2] Name String [1 blocks] ""= int 80
                        #539[r1,l2] Name String [2 blocks] ""                      #1023[r1,l1] Object {
                            #582[r1,l2] Name String [1 blocks] ""                          #583[r1,l1] String [3 blocks] "tingspeak.com"
                          }
                        #350[r1,l2] Name String [1 blocks] ""                      #349[r1,l1] String [6 blocks] "/update?key=UN3U6J51X72NCG18&field1=28"­
                        #681[r1,l2] Name String [2 blocks] ""                      #679[r1,l1] String [1 blocks] "GET"
                      }
                    #376[r1,l2] Name String [1 blocks] ""                  undefined
                    #287[r1,l2] Name String [1 blocks] ""= int 175
                    #484[r1,l2] Name String [1 blocks] ""                  #387[r1,l1] String [37 blocks] "HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=utf-8\r\nConnection: close\r\nStatus: 200 OK\r\nX-Frame-Options: ALLOWALL\r\nAccess-Control-Allow-Origin:­ *\r\nAccess-Control-Allow-Methods: GET, POST, PUT, OPTIONS, DELETE, PATCH\r\nAccess-Control-Allow-Headers: origin, content-type, X-R\nETag: \"e=0, pri"
                  }
              ]
          }
        #26[r1,l2] Name String [2 blocks] ""      #36[r2,l1] NativeFunction 0x40222ac4 (0) { }
        #220[r1,l2] Name String [1 blocks] ""      #219[r1,l1] String [2 blocks] "hygywlanpbj"
        #217[r1,l2] Name String [1 blocks] ""      #216[r1,l1] String [2 blocks] "nEgrO111"
        #214[r1,l2] Name String [2 blocks] ""      #212[r1,l1] String [3 blocks] "UN3U6J51X72NCG18"
        #209[r1,l2] Name String [1 blocks] ""= int 30
        #208[r1,l2] Name String [2 blocks] ""      #206[r1,l1] String [3 blocks] "thingspeak.com"
        #203[r1,l2] Name String [2 blocks] ""      #535[r9,l1] String [3 blocks] "144.212.80.10"
        #200[r1,l2] Name String [2 blocks] ""      #187[r1,l1] Pin 2
        #197[r1,l2] Name String [1 blocks] ""      #198[r2,l1] NativeFunction 0x402335e0 (9) {
            #195[r1,l2] Name String [2 blocks] ""          #193[r1,l1] Object {
                #192[r1,l2] Name String [2 blocks] ""              #198[r2,l2] ...
     
              }
          }
        #196[r1,l2] Name String [2 blocks] ""      #363[r1,l1] Bool false
        #189[r1,l2] Name String [1 blocks] ""      #185[r2,l1] NativeFunction 0x40222b34 (0) { }
        #188[r1,l2] Name String [2 blocks] ""      #488[r176,l1] Double 28
        #183[r1,l2] Name String [2 blocks] ""      #181[r1,l1] Function {
            #168[r1,l2] Name String [1 blocks] ""          #180[r1,l1] String [12 blocks] "{print(\"startBlink\");setInterval(func­tion(){toggle=!toggle;digitalWrite(GPIO2­,toggle)},500)}"
            #166[r1,l2] Name String [1 blocks] ""= int 4
          }
        #167[r1,l2] Name String [3 blocks] ""      #163[r1,l1] Function {
            #118[r1,l2] Name String [1 blocks] ""          #162[r1,l1] String [44 blocks] "{console.log(\"connecting to wifi\");digitalWrite(GPIO2,1);ESP8266WiF­i.init();ESP8266WiFi.connect(ssid,pass,f­unction(){digitalWrite(GPIO2,0);console.­log(\"connected to wifi\");\nvar a=ESP8266WiFi.getIPInfo();print(\"Curren­t IP address is: \"+ESP8266WiFi.getAddressAsString(a.ip)+­\":\"+ESP8266WiFi.getAddressAsString(a.n­etmask));resolveIotAddress(repeat)})}"
            #116[r1,l2] Name String [1 blocks] ""= int 4
          }
        #117[r1,l2] Name String [3 blocks] ""      #113[r1,l1] Function {
            #112[r1,l2] Name Param ""           undefined
            #92[r1,l2] Name String [1 blocks] ""          #111[r1,l1] String [19 blocks] "{ESP8266.getHostByName(iotHostName,func­tion(b){iotIpAddr=ESP8266.getAddressAsSt­ring(b);console.log(\"resolved:\"+iotIpA­ddr);startBlink();a()})}"
            #90[r1,l2] Name String [1 blocks] ""= int 5
          }
        #91[r1,l2] Name String [2 blocks] ""      #88[r1,l1] Function {
            #87[r1,l2] Name Param ""           undefined
            #415[r1,l2] Name String [1 blocks] ""          #86[r1,l1] String [59 blocks] "{console.log(\"sendTsStart\");console.l­og(process.memory());http.get({host:iotI­pAddr,port:80,headers:{Host:\"tingspeak.­com\"},path:\"/update?key=\"+\nApiKey+\"­&field1=\"+a},function(a){print(\"get callback!\");a.on(\"data\",function(a){c­onsole.log(\"connection getdata:\");console.log(process.memory()­);console.log(E.getSizeOf(global,1));pri­nt(a)});a.on(\"close\",function(){print(­\"The response connection closed\");console.log(\"connection close\");console.log(process.memory())})­})}"
            #417[r1,l2] Name String [1 blocks] ""= int 5
          }
        #416[r1,l2] Name String [3 blocks] ""      #420[r1,l1] Function {
            #421[r1,l2] Name Param ""           undefined
            #428[r1,l2] Name String [1 blocks] ""          #422[r1,l1] String [6 blocks] "{console.log(\"current temp:\"+a);sendTs(a)}"
            #430[r1,l2] Name String [1 blocks] ""= int 6
          }
        #429[r1,l2] Name String [2 blocks] ""      #432[r2,l1] Function {
            #439[r1,l2] Name String [1 blocks] ""          #433[r1,l1] String [6 blocks] "{sendTs(field1);setTimeout(repeat,1E3*p­eri)}"
            #441[r1,l2] Name String [1 blocks] ""= int 6
          }
        #456[r1,l2] Name String [1 blocks] ""      #457[r1,l1] NativeFunction 0x40222c34 (1) {
            #480[r1,l2] Name String [2 blocks] ""          #452[r1,l1] Function {
                #479[r1,l2] Name String [1 blocks] ""              #451[r1,l1] String [14 blocks] "{field1=1+Math.floor(40*Math.random());­console.log(\"created new random number:\"+field1);connectToWifi()}"
              }
          }
        #489[r1,l2] Name String [1 blocks] ""      #490[r1,l1] NativeFunction 0x40222b84 (1) { }
        #491[r1,l2] Name String [2 blocks] ""      #501[r1,l1] NativeFunction 0x40222c14 (1) { }
        #506[r1,l2] Name String [2 blocks] ""      #507[r1,l1] NativeFunction 0x40222aa0 (1) { }
        #502[r1,l2] Name String [2 blocks] ""      undefined
        #559[r1,l2] Name String [2 blocks] ""      #551[r1,l1] NativeFunction 0x40222bb4 (1) { }
        #644[r1,l2] Name String [2 blocks] ""      #646[r2,l1] NativeFunction 0x40222ae4 (1) {
            #647[r1,l2] Name String [2 blocks] ""          #649[r176,l1] Object {
                #650[r1,l2] Name String [2 blocks] ""              #646[r2,l2] ...
     
              }
          }
        #655[r1,l2] Name String [2 blocks] ""      #657[r2,l1] NativeFunction 0x40222af4 (1) {
            #658[r1,l2] Name String [2 blocks] ""          #660[r9,l1] Object {
                #661[r1,l2] Name String [2 blocks] ""              #657[r2,l2] ...
     
              }
          }
        #694[r1,l2] Name String [1 blocks] ""      #321[r1,l1] NativeFunction 0x40222c04 (1) { }
      }
     ets Jan  8 2013,rst cause:2, boot mode:(3,0)
    load 0x40100000, len 30936, room 16
    tail 8
    chksum 0x75
    load 0x3ffe8000, len 2108, room 0
    tail 12
    chksum 0x34
    ho 0 tail 12 room 4
    load 0x3ffe8840, len 29476, room 12
    tail 8
    chksum 0x15
    csum 0x15
    don't use rtc mem data
    Disconnected
    
  • Hmm, the error happens when you call jsvStringIteratorNew on something that's not a string.

    ... but it's possible this could be due to the new memory saving changes I have made? Not sure... it's be worth trying to run some non-network-related code on there and see if everything works ok.

  • If it is of any help, here is the error I get, after running simple http get to thingspeak in approx. 2 hours, whitout ds18b20

    http://ernstc.dk/arduino/esp_error.html

  • @Erni,
    Perfect post and diagnostics ... I for one will start investigating what that means from the very detailed info you have supplied.

    ... later ...
    Am now running the same code using my own API key for ThingSpeak ... am watching to see what happens ....

  • I have found at least two major problems and a mystery :-)

    First problem is related to issue #595 which states that there is no network error handling at the ESP8266 level. In English this means that if the ESP8266 detects a network error, it silently ignores this. When working with Thing Speak, we need to assume that Thing Speak may ignore our HTTP GET request ... when that happens, the lack of the ability to form a connection is not handled by the ESP8266 and it keeps the socket open. This means that we start to leak sockets and quickly die. The solution is to detect the failure to form the connection and shutdown the socket.

    The second problem is related to the logic of the sample application. It's logic says "Every period, make a GET request to thing speak" ... however that logic doesn't say "At the end of the PREVIOUS GET request, schedule another request to Thingspeak". What this means is that if a request to connect to Thingspeak takes a while, more and more parallel requests could be made until we run out of resources. The solution is to change the logic to use setTimeout at the completion of the last GET request instead of setInterval which keeps sending new GET requests irrespective of whether previous ones completed.

    The last note is still a mystery. When we use the Espruino "http.get()" method ... that is an asynchronous call ... it takes a callback function to be invoked when the response from the get request is available ... however ... we have a problem. In ESP8266, all network calls are asynchronous and this includes the formation of the connection request in the first place. What should happen when the "http.get()" request connection fails ... because it will be an asynchronous connection and happen later in the story ... this is going to be tricky.

    Again ... I believe that http.get() assumes a synchronous call while ESP8266 network connections are asynchronous. We may be plain stuck here for a while.

  • It is asyncronous... http.get only calls the callback once the socket is open and it's received the header from the web server. If there's a failure then the connect handler won't be called.

    ... however there is no error handling at the moment. In node.js you'd do:

    http.get("http://www.google.com/index.ht­ml", function(res) {
      console.log("Got response: " + res.statusCode);
    }).on('error', function(e) {
      console.log("Got error: " + e.message);
    });
    

    and we don't do anything like that yet. The code will upload, but the error handler will never get called.

    ... to be honest I'm not sure it's that high priority, as you can work around it with:

    var err = setTimeout(function() {
      err = undefined;
      console.log("Oh No!");
    }, 60*6000);
    http.get("http://www.google.com/index.ht­ml", function(res) {
      if (err) clearTimeout(err);
      console.log("Got response: " + res.statusCode);
    });
    

    Basically if something stalled, the socket would have timed out after 60 seconds anyway and closed.

  • wrt network errors:

    What I do for the other stuff is if there's an error, I clean up everything I can and then just return -1 to and calls to send and recv. Once send or recv return -1, the HTTP client/server automatically shuts everything down.

  • I commented out all the onewire and ds18b20 codes and libs from the code when the test run, as @Kolban asked. :)

  • If I'm understanding properly ... the callback handler on an http.get() will not be invoked if the original connection request times out. I think I am also understanding that there is no on("error") handler in the current implementation for the object returned by http.get().

    If these concepts are true, then we don't have an "elegant" means of detecting that a network request through http.get() has timed out and hence have no way of "handling" such a situation.

    The best notion we have right now is firing a timer to go off some time in the future when we could sensibly assume that the connection should have been made ... and in that timer function, check see if the connection did indeed happen (or assume that since the timer fired ... we weren't cancelled) ... and handle there.

    I suggest that this is a great opportunity to form a group of us to determine if this is the desired final semantics we want ... and, if not ... figure out what the correct semantics should be, start a design and then make progress towards implementation. My opinion is that I really don't like the "timer" solution as a long term solution and believe that I would like the on("error") handler on the "get()" request.

  • Isn't that just what I said in my last post? Maybe we were both writing it at the same time :)

    Given Espruino's networking has been in use for some time now, and nobody has made a great fuss about this before, I'd be tempted to say that on('error' isn't vital.

    The issue @hygy would seem to have is that the ESP8266 code isn't reporting back errors (which it can easily do by returning -1 in recv or send), and so the HTTP client is sitting there with allocated memory.

    Once ESP8266 does that, @hygy's problem will go away - and we can look at on('error' later on - it would be a nice addition for sure.

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

esp8266 memory problems

Posted by Avatar for hygy @hygy

Actions