Skip to content
  • MySensors
  • OpenHardware.io
  • Categories
  • Recent
  • Tags
  • Popular
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo
  1. Home
  2. Troubleshooting
  3. How to optimise a code (95% memory used)

How to optimise a code (95% memory used)

Scheduled Pinned Locked Moved Troubleshooting
7 Posts 4 Posters 82 Views 5 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • C Offline
    C Offline
    cwiekol
    wrote on last edited by
    #1

    Hi,
    i'm not a programmer almost at all, but i've managed to use some examples shared by a community to make a client that is receiveng from domoticz 3 variables (temperatures and status of one switch) and displaying it on 128x64px I2C v2 OLED display together with current time.

    Compilation and uploading of the sketch is being done correctly, however the following error is being displayed:

    Sketch uses 15906 bytes (51%) of program storage space. Maximum is 30720 bytes.
    Global variables use 1959 bytes (95%) of dynamic memory, leaving 89 bytes for local variables. Maximum is 2048 bytes.
    Low memory available, stability problems may occur.
    Invalid version '1.04' for library in: C:\Users\amc002c\Documents\Arduino\libraries\UIPEthernet
    
    

    The sketch usually is not working as should, but when i finally starts it is working correctly for even few hours. and then it is not refreshing values anymore, even though the clock is still working.

    I'm getting the following loop on DEBUG:
    Debug info - not possible to copy paste

    My first guess is that it is a memory issue. I've tried to optimise it by deleting splash screen from GFX library, but what else can i do? how to optimise further or what might be the other reason of such behaviour?

    Please support.

    /*
     * V_TEXT example with Domoticz (c) 2018 GizMoCuz
     * 
     * Note this is some quick code to demonstrate the workings
     * 
     * When the node has started and correctly been found by the controller,
     * you should have two new text sensors in Domoticz (if not, enable accept new hardware!)
     * Those two sensors have an IDX, for example 1063 and 1063
     * To update the first line call something line http://127.0.0.1:8080/json.htm?type=command&param=udevice&idx=1063&nvalue=0&svalue=Hello%20Line%201
     */
     
    // Enable debug prints to serial monitor
    //#define MY_DEBUG
     
    // Enable and select radio type attached
    #define MY_RADIO_NRF24
    //#define MY_RADIO_NRF5_ESB
    //#define MY_RADIO_RFM69
    //#define MY_RADIO_RFM95
     
    #define MY_NODE_ID 253
     
    #include <SPI.h>
    #include <MySensors.h>
    #include <Adafruit_GFX.h>
    #include <Adafruit_SSD1306.h>
    #include <Wire.h>
    #include <TimeLib.h>
    #define UV_SENSOR_ANALOG_PIN 0
     
     
    const byte LCD1_CHILD_ID = 8 ;         // LCD line 1
    const byte LCD2_CHILD_ID = 9 ;         // LCD line 2
    const byte LCD3_CHILD_ID = 7 ;         // LCD line 3
    
    char lastLCD1[7] = "Line1";   // define & init before first receive
    char lastLCD2[7] = "Line2";
    char lastLCD3[7] = "Line3";
    
    uint32_t ActTime = 0, DispTime=0;
    // timers for loop delays
    unsigned long lastUpdate=0, lastRequest=0;
     
    // Initialize messages for sensor network
    MyMessage textMsg(0, V_TEXT);
     
    #define OLED_RESET 4
    Adafruit_SSD1306 display(OLED_RESET);
    
    #define NUMFLAKES 10
    #define XPOS 0
    #define YPOS 1
    #define DELTAY 2
    
    #if (SSD1306_LCDHEIGHT != 64)
    #error("Height incorrect, please fix Adafruit_SSD1306.h!");
    #endif
    
     
    void setup(void){
      // ** LCD display **
      Serial.begin(9600);
      display.clearDisplay();
      display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // 0x3C = 0x78 >> 1 (Arduino's )
      // init done
      
      display.display(); // show splashscreen
      delay(2000);
      display.clearDisplay();   // clears the screen and buffer
    
      // draw a single pixel
      display.drawPixel(20, 20, WHITE);
      display.println("script starting......");
      display.display();
      delay(2000);
      display.clearDisplay();
      Serial.println("end setup");
      Serial.println("Sensor Started");
    }
     
    void presentation()
    {
        // Send the sketch version information to the gateway and Controller
        sendSketchInfo("V_TEXT LCD Sensor", "1.1");
      Serial.println("presentantion");
      present(LCD1_CHILD_ID, S_INFO, "Text Line 1");
      present(LCD2_CHILD_ID, S_INFO, "Text Line 2");
      present(LCD3_CHILD_ID, S_INFO, "Text_Line_3"); 
      // Initializations
      requestTime();            // get the time from controller (handled by receiveTime)
      request(LCD1_CHILD_ID, V_TEXT, 0);           // request latest value from controller
      request(LCD2_CHILD_ID, V_TEXT, 0);          // request latest value from controller
      request(LCD3_CHILD_ID, V_TEXT, 0);          // request latest value from controller
    }
     
    void loop()
    {
      // timer for loop delays
    
      unsigned long now = millis();
    
    //  }// request time and latest value every 15 minutes from controller
      if (now-lastRequest > 15*60000)
      {
        requestTime();  
        lastRequest = now;
        Serial.println("request time from controler");
        request(LCD1_CHILD_ID, V_TEXT, 0);           // request latest value from controller
        request(LCD2_CHILD_ID, V_TEXT, 0);          // request latest value from controller
        request(LCD3_CHILD_ID, V_TEXT, 0);          // request latest value from controller
      
      }
      // Update display every second
      if (now-lastUpdate > 1000) {
        LCD_local_display();
        lastUpdate = now;
      }
    }
     
    // This is called when a new time value was received
    void receiveTime(uint32_t controllerTime)
    {
      Serial.print("Time value received: ");
      Serial.println(controllerTime);
      ActTime = controllerTime;
    } 
     
    void LCD_local_display()
    {
      // take care of LCD display information
     char buf[20]; 
      display.clearDisplay();
      DispTime=ActTime + (millis()-lastRequest)/1000;
      if (ActTime!=0) {
        // start with location & time on first line
        snprintf(buf, sizeof buf, "%02d:%02d:%02d %02d-%02d-%04d", hour(DispTime), minute(DispTime), second(DispTime), day(DispTime), month(DispTime),year(DispTime));
      }
       display.setTextSize(1);
       display.setTextColor(WHITE);
       display.setCursor(0,0);
       display.println("Termometry");
       display.setCursor(0,12);
       display.print("Dom: ");
       display.setTextSize(2);
       display.setCursor(50,12);
       display.println(lastLCD1);
       display.setCursor(0,32);
       display.setTextSize(1);
       display.print("Zewn: ");
       display.setCursor(0,42);   
       display.print(lastLCD3);
       display.setTextSize(2);
       display.setCursor(50,32);
       display.println(lastLCD2);
       display.setTextSize(1);
       display.setCursor(0,55);
       display.println(buf); 
       display.display();
    }
     
    void receive(const MyMessage &message)
    {
      if (message.type!=V_TEXT) // Text messages only
        return;
     
      // Write some debug info
      Serial.print("Message: ");
      Serial.print(message.sensor);
      Serial.print(", Message: ");
      Serial.println(message.getString());
      
      if (message.sensor == LCD1_CHILD_ID ) {
        snprintf(lastLCD1, sizeof(lastLCD1), "%5s", message.getString());  // load text into LCD string
      }
      else if (message.sensor == LCD2_CHILD_ID) {
        snprintf(lastLCD2, sizeof(lastLCD2), "%5s", message.getString());
      }
      else if (message.sensor == LCD3_CHILD_ID) {
        snprintf(lastLCD3, sizeof(lastLCD3), "%5s", message.getString());
      }
    }
    
    1 Reply Last reply
    0
    • electrikE Offline
      electrikE Offline
      electrik
      wrote on last edited by
      #2

      A good start would be to move all the print strings to flash memory, and remove the debug prints as much as possible.
      To move strings, change:

      display.println("script starting......");
      

      to:

      display.println(F("script starting......"));
      

      and do this for all prints. You should try not to exceed 70% memory usage.

      1 Reply Last reply
      0
      • mfalkviddM Offline
        mfalkviddM Offline
        mfalkvidd
        Mod
        wrote on last edited by mfalkvidd
        #3

        Here is how to disable the MySensors splash screen: https://www.mysensors.org/apidocs/group__SerialDebugGrpPub.html#gaf8039ebf2b71a3fd005ddd02b47721f3

        The next step would be to change the text strings to use the F macro. Guide: https://techexplorations.com/guides/arduino/programming/f-macro/ This works for all Serial.print and should also work for all display.print

        1 Reply Last reply
        0
        • C Offline
          C Offline
          cwiekol
          wrote on last edited by
          #4

          hello, i'm back and finally i can try to apply your advices. Thank you very much for them.
          I will come back later today with results. Hope that it will help.
          thanks.

          1 Reply Last reply
          0
          • C Offline
            C Offline
            cwiekol
            wrote on last edited by
            #5

            Hi,
            i've provide some changes and ended on 88%, however it is still not working.
            To find out what is going on, i've split code for the part related to mySensors and the one with LCD. I spot that there is something wrong with mySensors part.
            The code started two or three times and now it is not working at all.
            There is no prints on serial at all. The debug looks as below.
            Have no clue what is going on:(

            The code looks now as follow:

             
            // Enable debug prints to serial monitor
            #define MY_SPLASH_SCREEN_DISABLED
            #define MY_SERIAL_OUTPUT_SIZE (60u)
            //#define MY_DEBUG
             
            // Enable and select radio type attached
            #define MY_RADIO_NRF24
             
            #define MY_NODE_ID 253
             
            #include <SPI.h>
            #include <MySensors.h>
            
            #include <Wire.h>
            #include <TimeLib.h>
            
             
             
            const byte LCD1_CHILD_ID = 8 ;         // LCD line 1
            const byte LCD2_CHILD_ID = 9 ;         // LCD line 2
            const byte LCD3_CHILD_ID = 7 ;         // LCD line 3
            
            char lastLCD1[7] = "Line1";   // define & init before first receive
            char lastLCD2[7] = "Line2";
            char lastLCD3[7] = "Line3";
            
            uint32_t ActTime = 0, DispTime=0;
            // timers for loop delays
            unsigned long lastUpdate=0, lastRequest=0;
             
            // Initialize messages for sensor network
            MyMessage textMsg(0, V_TEXT);
             
            
             
            void setup(void){
            
              Serial.begin(115200);
             
              Serial.println(F("Sensor Started"));
            }
             
            void presentation()
            {
               
                // Send the sketch version information to the gateway and Controller
                sendSketchInfo("V_TEXT LCD Sensor", "1.1");
              Serial.println(F("presentantion"));
              present(LCD1_CHILD_ID, S_INFO, "Text Line 1");
              present(LCD2_CHILD_ID, S_INFO, "Text Line 2");
              present(LCD3_CHILD_ID, S_INFO, "Text_Line_3"); 
              // Initializations
              requestTime();            // get the time from controller (handled by receiveTime)
              request(LCD1_CHILD_ID, V_TEXT, 0);           // request latest value from controller
              request(LCD2_CHILD_ID, V_TEXT, 0);          // request latest value from controller
              request(LCD3_CHILD_ID, V_TEXT, 0);          // request latest value from controller
            }
             
            void loop()
            {
              // timer for loop delays
            
              unsigned long now = millis();
            
            //  }// request time and latest value every 15 minutes from controller
              if (now-lastRequest > 15*60000)
              {
                requestTime();  
                lastRequest = now;
              //  Serial.println(F("request time from controler"));
                request(LCD1_CHILD_ID, V_TEXT, 0);           // request latest value from controller
                request(LCD2_CHILD_ID, V_TEXT, 0);          // request latest value from controller
                request(LCD3_CHILD_ID, V_TEXT, 0);          // request latest value from controller
              
              }
              // Update display every second
              if (now-lastUpdate > 1000) {
                LCD_local_display();
                lastUpdate = now;
              }
            }
             
            // This is called when a new time value was received
            void receiveTime(uint32_t controllerTime)
            {
            
              ActTime = controllerTime;
            } 
             
            void LCD_local_display()
            {
              // take care of LCD display information
             char buf[20]; 
             // display.clearDisplay();
              DispTime=ActTime + (millis()-lastRequest)/10000;
              if (ActTime!=0) {
                // start with location & time on first line
                snprintf(buf, sizeof buf, "%02d:%02d:%02d %02d-%02d-%04d", hour(DispTime), minute(DispTime), second(DispTime), day(DispTime), month(DispTime),year(DispTime));
              }
              Serial.println(buf);
              Serial.println(F("Dom: "));
              Serial.println(lastLCD1);
              Serial.println(lastLCD3);
              Serial.println(lastLCD2);
            
            }
             
            void receive(const MyMessage &message)
            {
              if (message.type!=V_TEXT) // Text messages only
                return;
              
              if (message.sensor == LCD1_CHILD_ID ) {
                snprintf(lastLCD1, sizeof(lastLCD1), "%5s", message.getString());  // load text into LCD string
              }
              else if (message.sensor == LCD2_CHILD_ID) {
                snprintf(lastLCD2, sizeof(lastLCD2), "%5s", message.getString());
              }
              else if (message.sensor == LCD3_CHILD_ID) {
                snprintf(lastLCD3, sizeof(lastLCD3), "%5s", message.getString());
              }
            }
            

            and debug is repeating all the time like this:

            18:12:27.468 -> 0 MCO:BGN:INIT NODE,CP=RNNNA---,FQ=16,REL=255,VER=2.3.2
            18:12:27.468 -> 4 TSM:INIT
            18:12:27.468 -> 5 TSF:WUR:MS=0
            18:12:27.468 -> 12 TSM:INIT:TSP OK
            18:12:27.468 -> 13 TSM:INIT:STATID=253
            18:12:27.468 -> 16 TSF:SID:OK,ID=253
            18:12:27.468 -> 17 TSM:FPAR
            18:12:29.274 -> 1832 ?TSF:MSG:SEND,253-253-255-255,s=255,c=3,t=7,pt=0,l=0,sg=0,f3840 !TSM:FPAR:NO REPLY
            18:12:31.292 -> 3842 TSM:FPAR
            18:12:33.098 -> 5657 ?TSF:MSG:SEND,253-253-255-255,s=255,c=3,t=7,pt=0,l=0,sg=0,f7664 !TSM:FPAR:NO REPLY
            18:12:35.115 -> 7666 TSM:FPAR
            18:12:36.923 -> 9482 ?TSF:MSG:SEND,253-253-255-255,s=255,c=3,t=7,pt=0,l=0,sg=0,f11489 !TSM:FPAR:NO REPLY
            18:12:38.938 -> 11491 TSM:FPAR
            18:12:40.746 -> 13307 ?TSF:MSG:SEND,253-253-255-255,s=255,c=3,t=7,pt=0,l=0,sg=0,f15315 !TSM:FPAR:FAIL
            18:12:42.762 -> 15318 TSM:FAIL:CNT=1
            18:12:42.762 -> 15320 TSM:FAIL:DIS
            18:12:42.762 -> 15322 TSF:TDI:TSL
            18:12:52.756 -> 25325 TSM:FAIL:RE-INIT
            18:12:52.756 -> 25327 TSM:INIT
            18:12:52.756 -> 25333 TSM:INIT:TSP OK
            18:12:52.756 -> 25335 TSM:INIT:STATID=253
            18:12:52.756 -> 25338 TSF:SID:OK,ID=253
            18:12:52.756 -> 25340 TSM:FPAR
            
            mfalkviddM 1 Reply Last reply
            0
            • C cwiekol

              Hi,
              i've provide some changes and ended on 88%, however it is still not working.
              To find out what is going on, i've split code for the part related to mySensors and the one with LCD. I spot that there is something wrong with mySensors part.
              The code started two or three times and now it is not working at all.
              There is no prints on serial at all. The debug looks as below.
              Have no clue what is going on:(

              The code looks now as follow:

               
              // Enable debug prints to serial monitor
              #define MY_SPLASH_SCREEN_DISABLED
              #define MY_SERIAL_OUTPUT_SIZE (60u)
              //#define MY_DEBUG
               
              // Enable and select radio type attached
              #define MY_RADIO_NRF24
               
              #define MY_NODE_ID 253
               
              #include <SPI.h>
              #include <MySensors.h>
              
              #include <Wire.h>
              #include <TimeLib.h>
              
               
               
              const byte LCD1_CHILD_ID = 8 ;         // LCD line 1
              const byte LCD2_CHILD_ID = 9 ;         // LCD line 2
              const byte LCD3_CHILD_ID = 7 ;         // LCD line 3
              
              char lastLCD1[7] = "Line1";   // define & init before first receive
              char lastLCD2[7] = "Line2";
              char lastLCD3[7] = "Line3";
              
              uint32_t ActTime = 0, DispTime=0;
              // timers for loop delays
              unsigned long lastUpdate=0, lastRequest=0;
               
              // Initialize messages for sensor network
              MyMessage textMsg(0, V_TEXT);
               
              
               
              void setup(void){
              
                Serial.begin(115200);
               
                Serial.println(F("Sensor Started"));
              }
               
              void presentation()
              {
                 
                  // Send the sketch version information to the gateway and Controller
                  sendSketchInfo("V_TEXT LCD Sensor", "1.1");
                Serial.println(F("presentantion"));
                present(LCD1_CHILD_ID, S_INFO, "Text Line 1");
                present(LCD2_CHILD_ID, S_INFO, "Text Line 2");
                present(LCD3_CHILD_ID, S_INFO, "Text_Line_3"); 
                // Initializations
                requestTime();            // get the time from controller (handled by receiveTime)
                request(LCD1_CHILD_ID, V_TEXT, 0);           // request latest value from controller
                request(LCD2_CHILD_ID, V_TEXT, 0);          // request latest value from controller
                request(LCD3_CHILD_ID, V_TEXT, 0);          // request latest value from controller
              }
               
              void loop()
              {
                // timer for loop delays
              
                unsigned long now = millis();
              
              //  }// request time and latest value every 15 minutes from controller
                if (now-lastRequest > 15*60000)
                {
                  requestTime();  
                  lastRequest = now;
                //  Serial.println(F("request time from controler"));
                  request(LCD1_CHILD_ID, V_TEXT, 0);           // request latest value from controller
                  request(LCD2_CHILD_ID, V_TEXT, 0);          // request latest value from controller
                  request(LCD3_CHILD_ID, V_TEXT, 0);          // request latest value from controller
                
                }
                // Update display every second
                if (now-lastUpdate > 1000) {
                  LCD_local_display();
                  lastUpdate = now;
                }
              }
               
              // This is called when a new time value was received
              void receiveTime(uint32_t controllerTime)
              {
              
                ActTime = controllerTime;
              } 
               
              void LCD_local_display()
              {
                // take care of LCD display information
               char buf[20]; 
               // display.clearDisplay();
                DispTime=ActTime + (millis()-lastRequest)/10000;
                if (ActTime!=0) {
                  // start with location & time on first line
                  snprintf(buf, sizeof buf, "%02d:%02d:%02d %02d-%02d-%04d", hour(DispTime), minute(DispTime), second(DispTime), day(DispTime), month(DispTime),year(DispTime));
                }
                Serial.println(buf);
                Serial.println(F("Dom: "));
                Serial.println(lastLCD1);
                Serial.println(lastLCD3);
                Serial.println(lastLCD2);
              
              }
               
              void receive(const MyMessage &message)
              {
                if (message.type!=V_TEXT) // Text messages only
                  return;
                
                if (message.sensor == LCD1_CHILD_ID ) {
                  snprintf(lastLCD1, sizeof(lastLCD1), "%5s", message.getString());  // load text into LCD string
                }
                else if (message.sensor == LCD2_CHILD_ID) {
                  snprintf(lastLCD2, sizeof(lastLCD2), "%5s", message.getString());
                }
                else if (message.sensor == LCD3_CHILD_ID) {
                  snprintf(lastLCD3, sizeof(lastLCD3), "%5s", message.getString());
                }
              }
              

              and debug is repeating all the time like this:

              18:12:27.468 -> 0 MCO:BGN:INIT NODE,CP=RNNNA---,FQ=16,REL=255,VER=2.3.2
              18:12:27.468 -> 4 TSM:INIT
              18:12:27.468 -> 5 TSF:WUR:MS=0
              18:12:27.468 -> 12 TSM:INIT:TSP OK
              18:12:27.468 -> 13 TSM:INIT:STATID=253
              18:12:27.468 -> 16 TSF:SID:OK,ID=253
              18:12:27.468 -> 17 TSM:FPAR
              18:12:29.274 -> 1832 ?TSF:MSG:SEND,253-253-255-255,s=255,c=3,t=7,pt=0,l=0,sg=0,f3840 !TSM:FPAR:NO REPLY
              18:12:31.292 -> 3842 TSM:FPAR
              18:12:33.098 -> 5657 ?TSF:MSG:SEND,253-253-255-255,s=255,c=3,t=7,pt=0,l=0,sg=0,f7664 !TSM:FPAR:NO REPLY
              18:12:35.115 -> 7666 TSM:FPAR
              18:12:36.923 -> 9482 ?TSF:MSG:SEND,253-253-255-255,s=255,c=3,t=7,pt=0,l=0,sg=0,f11489 !TSM:FPAR:NO REPLY
              18:12:38.938 -> 11491 TSM:FPAR
              18:12:40.746 -> 13307 ?TSF:MSG:SEND,253-253-255-255,s=255,c=3,t=7,pt=0,l=0,sg=0,f15315 !TSM:FPAR:FAIL
              18:12:42.762 -> 15318 TSM:FAIL:CNT=1
              18:12:42.762 -> 15320 TSM:FAIL:DIS
              18:12:42.762 -> 15322 TSF:TDI:TSL
              18:12:52.756 -> 25325 TSM:FAIL:RE-INIT
              18:12:52.756 -> 25327 TSM:INIT
              18:12:52.756 -> 25333 TSM:INIT:TSP OK
              18:12:52.756 -> 25335 TSM:INIT:STATID=253
              18:12:52.756 -> 25338 TSF:SID:OK,ID=253
              18:12:52.756 -> 25340 TSM:FPAR
              
              mfalkviddM Offline
              mfalkviddM Offline
              mfalkvidd
              Mod
              wrote on last edited by
              #6

              Nice work @cwiekol !

              !TSM:FPAR:NO REPLY

              This means that the node is not able to reach the gateway? How far away is your gateway? Could you post the debug logs from your gateway?

              See also section #2:4 I only get Find parent in serial log for node at https://forum.mysensors.org/topic/666/read-this-first-it-could-save-you-a-lot-of-time/2

              1 Reply Last reply
              0
              • OldSurferDudeO Offline
                OldSurferDudeO Offline
                OldSurferDude
                wrote on last edited by
                #7

                I found that timelib.h uses a tremendous amount of memory. You avoid using it by getting time string from the controller.

                I have also found that when you're using that amount of memory that bad things happen, as you noted. I use global variables to avoid the transient nature of function variables.

                I'll be looking forward to other comments as, I, too, do not know all the tricks;)

                OSD

                1 Reply Last reply
                1
                Reply
                • Reply as topic
                Log in to reply
                • Oldest to Newest
                • Newest to Oldest
                • Most Votes


                20

                Online

                11.7k

                Users

                11.2k

                Topics

                113.1k

                Posts


                Copyright 2025 TBD   |   Forum Guidelines   |   Privacy Policy   |   Terms of Service
                • Login

                • Don't have an account? Register

                • Login or register to search.
                • First post
                  Last post
                0
                • MySensors
                • OpenHardware.io
                • Categories
                • Recent
                • Tags
                • Popular