Zu wenig dynamic memory

Ich hab plötzlich zu wenig dynamic memory bei meinem sketch. Das angeblich aufgrund zu vielen globalen Variablen. Doch ich hab gar nicht viele? Weiss wer warum?

Sketch uses 18942 bytes (58%) of program storage space. Maximum is 32256 bytes.
Global variables use 2015 bytes (98%) of dynamic memory, leaving 33 bytes for local variables. Maximum is 2048 bytes.
Low memory available, stability problems may occur.

Hier der Code:

#include <SoftwareSerial.h>
#include <Arduino.h>
#include <U8g2lib.h>

#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif

U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);

SoftwareSerial HC12(2, 3);


int SwitchPos1 = 8;
int SwitchPos2 = 9;
int SwitchPos3 = 10;


int lastSwitch = 0;


const byte numChars = 32;
char messageReceived[numChars];
char keyWord1[] = "Relais1ON!";
char keyWord2[] = "Relais2ON!";
char keyWord3[] = "Relais3ON!";
char Status1[] = "Relais1isON!";
char Status3[] = "Relais2isON!";
char Status5[] = "Relais3isON!";

char Antenna;


unsigned long last = millis();  // set timer
const unsigned long INTERVAL = 1000L*60*0.5; // Intervall 20 Sec.
unsigned long lastRun = 0 - INTERVAL; //



void setup() {

  u8g2.begin();
  HC12.begin(9600);
  Serial.begin(9600);

  pinMode(SwitchPos1, INPUT);
  pinMode(SwitchPos2, INPUT);
  pinMode(SwitchPos3, INPUT);

  
}

void loop() {

int SwitchPos1State = digitalRead(SwitchPos1);
int SwitchPos2State = digitalRead(SwitchPos2);
int SwitchPos3State = digitalRead(SwitchPos3);



if(millis() - last > 500){


if(SwitchPos1State == HIGH && lastSwitch != 1) {
  Serial.println("1st if condition true!");
  HC12.print(keyWord1);
  lastSwitch = 1;
}
else if(SwitchPos2State == HIGH && lastSwitch != 2) {
  HC12.print(keyWord2);
  lastSwitch = 2;
}
else if(SwitchPos3State == HIGH && lastSwitch != 3) {
  HC12.print(keyWord3);
  lastSwitch = 3;
}
last = millis();
Serial.println("lastSwitch:");
Serial.println(lastSwitch);


  static byte ndx = 0;
  char charReceived;
  char endMarker = '!';
  while (HC12.available() > 0) {
    charReceived = HC12.read();
    if (charReceived != endMarker) {
      messageReceived[ndx] = charReceived;
      ndx++;
      if (ndx >= numChars) {
        ndx = numChars - 1;
      }
    }
    else {
      messageReceived[ndx] = '\0';
      ndx = 0;
      delay(100);
      
      while (HC12.available() > 0) HC12.read();
      
      if(millis() - last > 500){
      
      if(strcmp(messageReceived, Status1) == 0) {
        Antenna = "VHF/UHF"; 
      }
        
      else if(strcmp(messageReceived, Status3) == 0) {
        Antenna = "HF";
        
      }
        else if(strcmp(messageReceived, Status5) == 0) {
        Antenna = "NONE";

      }
      }
    }
  }
  
if(millis() - lastRun >= INTERVAL){ // Check states of relays every 20 seconds and transmit
  

SwitchPos1State = digitalRead(SwitchPos1);
SwitchPos2State = digitalRead(SwitchPos2);
SwitchPos3State = digitalRead(SwitchPos3);

  if(SwitchPos1 == HIGH) {
  HC12.print(keyWord1);
}
else if(SwitchPos2 == HIGH) {
  HC12.print(keyWord2);
}
else if(SwitchPos3 == HIGH) {
  HC12.print(keyWord3);
}


      }
    
  
  u8g2.clearDisplay();
  u8g2.setFont(u8g2_font_profont12_tf);
  u8g2.drawStr(0,15, "ANTENNA STATUS:");
  u8g2.setFont(u8g2_font_profont29_tf);
  u8g2.setCursor(0,30);
  u8g2.println(Antenna);
  u8g2.setFont(u8g2_font_profont12_tf);
  u8g2.drawStr(0, 60, "active");

  u8g2.sendBuffer();
  delay(1000);
  u8g2.clearBuffer();

}

}

Den größten Teil deines Ram wird die U8g2lib.h verbrauchen.
Du könntest evtl. eine alternative Lib verwenden.

Leider habe ich aktuell für dein Display keinen Tipp.

und wenn du dann eine andere lib verwendest, aktiviere auch die Ausgabe der Warnings in der IDE, denn da hast schon noch einige Schitzer drinnen.

C:\Daten\myrepository\Arduino\forum\sketch_dec20a\sketch_dec20b\sketch_dec20b.ino: In function 'void loop()':
C:\Daten\myrepository\Arduino\forum\sketch_dec20a\sketch_dec20b\sketch_dec20b.ino:107:23: warning: invalid conversion from 'const char*' to 'char' [-fpermissive]
Antenna = "VHF/UHF";
^~~~~~~~~
C:\Daten\myrepository\Arduino\forum\sketch_dec20a\sketch_dec20b\sketch_dec20b.ino:111:23: warning: invalid conversion from 'const char*' to 'char' [-fpermissive]
Antenna = "HF";
^~~~
C:\Daten\myrepository\Arduino\forum\sketch_dec20a\sketch_dec20b\sketch_dec20b.ino:115:23: warning: invalid conversion from 'const char*' to 'char' [-fpermissive]
Antenna = "NONE";
^~~~~~

und kontrolliere jede Variable ob sie die richtige Größe hat, oft hast einfach nur int gemacht, was es sicher nicht immer braucht.

mach Variablen const wenn sie sich nicht ändern (z.B. Pins)

und für die 3 Texte auf die Serielle - lies dich über das F-Makro ein.

Danke euch für die Inputs. Hab den Code soweit es geht optimiert und die von noiasca erwähnten Schnitzer mit strncpy ausgebügelt.

Mein Sketch verbraucht mit den Zeilen für das Display (u8g2) aber immer noch 97% des Ram, was offenbar zu viel ist. Das heisst der Atmega328 arbeitet so nicht richtig.

Ich blicke jedoch noch immer nicht durch, weshalb mein Sketch so viel Ram verbraucht. Ich habe andere Sketches, die mit der u8g2lib laufen und viel mehr globale Variablen und auch viel mehr Zeilen für die Display-Steuerung haben.
Hat jemand eine Idee?

Hier der aktuelle Code:

#include <SoftwareSerial.h>
#include <Arduino.h>
#include <U8g2lib.h>

#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif

U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);

SoftwareSerial HC12(2, 3);


const int SwitchPos1 = 8;
const int SwitchPos2 = 9;
const int SwitchPos3 = 10;


int lastSwitch = 0;


const byte numChars = 32;
char messageReceived[numChars];
char keyWord1[] = "Relais1ON!";
char keyWord2[] = "Relais2ON!";
char keyWord3[] = "Relais3ON!";
char Status1[] = "Relais1isON";
char Status3[] = "Relais2isON";
char Status5[] = "Relais3isON";

char Antenna[] = "NONE SELECTED";


unsigned long last = millis();  // set timer
const unsigned long INTERVAL = 1000L*60*0.5; // Intervall 20 Sec.
unsigned long lastRun; //

void draw(){

  u8g2.clearDisplay();
  u8g2.setFont(u8g2_font_profont12_tf);
  u8g2.drawStr(0,15, "ANTENNA STATUS:");
  u8g2.setFont(u8g2_font_profont29_tf);
  u8g2.setCursor(0,30);
  u8g2.println(Antenna);
  //u8g2.setFont(u8g2_font_profont12_tf);
  //u8g2.drawStr(0, 60, "active");

  u8g2.sendBuffer();
  delay(1000);
  u8g2.clearBuffer();

  delay(10);
}


void setup() {

  u8g2.begin();
  HC12.begin(9600);
  Serial.begin(9600);

  pinMode(SwitchPos1, INPUT);
  pinMode(SwitchPos2, INPUT);
  pinMode(SwitchPos3, INPUT);

  
}

void loop() {



if(millis() - last > 500){


if(digitalRead(SwitchPos1) == HIGH && lastSwitch != 1) {
  HC12.print(keyWord1);
  lastSwitch = 1;
  }
  
  else if(digitalRead(SwitchPos2) == HIGH && lastSwitch != 2) {
  HC12.print(keyWord2);
  lastSwitch = 2;
  }
  
  else if(digitalRead(SwitchPos3) == HIGH && lastSwitch != 3) {
  HC12.print(keyWord3);
  lastSwitch = 3;
}

last = millis();


  static byte ndx = 0;
  char charReceived;
  char endMarker = '!';
  
  while (HC12.available() > 0) {
    charReceived = HC12.read();
    if (charReceived != endMarker) {
      messageReceived[ndx] = charReceived;
      ndx++;
      if (ndx >= numChars) {
        ndx = numChars - 1;
      }
    }
    else {
      messageReceived[ndx] = '\0';
      ndx = 0;
      delay(100);
      
      while (HC12.available() > 0) HC12.read();
      
      if(millis() - last > 500){
      
      if(strcmp(messageReceived, Status1) == 0) {
        strncpy( Antenna, "VHF/UHF", sizeof(Antenna) );
        Antenna[sizeof(Antenna)-6] = 0; 
      }
        
        else if(strcmp(messageReceived, Status3) == 0) {
        strncpy( Antenna, "HF DIPOLE", sizeof(Antenna) );
        Antenna[sizeof(Antenna)-4] = 0;
        
      }
        else if(strcmp(messageReceived, Status5) == 0) {
        strncpy( Antenna, "NONE", sizeof(Antenna) );
        Antenna[sizeof(Antenna)] = 0;

      }
     }
    }
  }

  
if(millis() - lastRun >= INTERVAL){ // Check states of relays every 20 seconds and transmit


  if(digitalRead(SwitchPos1) == HIGH) {
  HC12.print(keyWord1);
  }
    else if(digitalRead(SwitchPos2) == HIGH) {
    HC12.print(keyWord2);
  }
    else if(digitalRead(SwitchPos3) == HIGH) {
    HC12.print(keyWord3);
  }

lastRun = millis();


  }
 }

 u8g2.firstPage();
 do
  {
  draw();
  }
 while( u8g2.nextPage() );
 delay(50);
 }

Den größten Teil deines Ram wird die U8g2lib.h verbrauchen.

sehe ich auch so.

Vieleicht mal ein ein anderes Display probieren? Klassisches LCD?

Du hast jetzt strncpy entdeckt, jetzt googelst mal nach strcpy_P und hältst die Daten im Progmem.
Aber unterm Strich sind das alles nur Peanuts, imho ist das Display dein Hauptverbraucher.

Und deine char-Ausgaben solltest du mal in ein char-array einbauen, das wird übersichtlicher.

Und deine char-Ausgaben solltest du mal in ein char-array einbauen, das wird übersichtlicher.

Das verstehe ich nicht. Ich sehe nur char array Texte... Davon könnten zwar einige ins PROGMEM und man könnte das ganze auch 8-bit Controller - freundlicher gestalten. ( Die Textverarbeitungs-kapazitäten sollte man nicht überstrapazieren. )

Wenn du nur 33 Byte für lokale Variable und Stack übrig hast, kannst du das locker verdoppeln, aber das sind immer noch Peanuts, die vermutlich nicht wirklich helfen.

Ich habe andere Sketches, die mit der u8g2lib laufen und viel mehr globale Variablen und auch viel mehr Zeilen für die Display-Steuerung haben.
Hat jemand eine Idee?

Nutzen die einen anderen Font, und liegt der gar im RAM, bei der u8g2lib?

michael_x:
Ich sehe nur char array Texte.
.....

Ja, genau, die meine ich.

Ein Test hat leider gezeigt, das wandeln in ein char-Array schafft keinen Speicher.
Auch das Ändern der Fonts bringt nix.

Ein kleiner Betrag bringt das auskommentieren der seriellen Schnittstelle. Die brauchst du aktuell ja nicht.

Es bleibt dir nichts anderes, als den Displaytreiber zu wechseln.

Welche IDE-Version nutzt du ?