Arduino UNO SRAM zu klein?

Moin,
ich arbeite an einem Projekt mit dem SIM7600CE LTE Shield. Über die Serielle Schnittstelle lasse ich mir Info's zu GNSS und zum Mobilfunknetz ausgeben. Diese Sende ich dann formatiert weiter per HTTP GET an thingspeak. Einzeln funktionieren die Funktionen einwandfrei. Doch wenn ich alles zusammen laufen lasse, fängt irgendwann die Serielle Schnittstelle an faxen zu machen oder das ganze Programm hängt sich irgendwo auf. Ich arbeite viel mit char arrays. Mir ist aufgefallen das beim kompilieren bei 60% Globale Variablen das ganze zum Teil noch klappt, da drüber hinaus ist Feierabend.

Kann ich da einfach drauf schließen dass der UNO mit seinen 2kB SRAM nicht mehr mit macht?

Danke im Voraus!

Hier ist mein gesamter Code:

#include <SoftwareSerial.h>
#include <stdio.h>
#include <string.h>
#include<time.h>
#define BUTTON1 4
//#define PWR 12
//Aufbau 0: Lfd. Nummer | 1: System Mode | 2: Cell ID | 3: RSSI | 4: RSRP | 5: RSRQ | 6: SNR | 7: XXX_Platzhalter_XXX | 8: Lfd. Nummer | 9: Latitude | 10: Longitude | 11: Date | 12: Time | 13: Altitude | 14: Speed | 15: Course |
char globals[1][16][13];
int LfdN =0;
boolean on_off;
SoftwareSerial myserial(7, 8); //Define virtual serial port name as myseria,Rx is port 7, Tx is port 8
uint32_t Timestemp = millis(), Timestemp2 = millis(), Timestemp3 = millis();
int ZeitVar = 1000;
int ZeitVar5s = 5000;
int ZeitVar30s = 30000;
 

boolean checkHTTP_on(void);
boolean checkHTTP_off(void);
boolean checkBoard(void);
void readGNSS(void);
void readPSI(void);
long readBaud(void);
void setCH1(void);
void setCH2(void);
boolean sendHTTP(void);
void clearmySerial(void);
void printGlobals(void);

void setup()
{
  myserial.begin(9600); //Initialize virtual serial port
  Serial.begin(9600); //Initialize Arduino default serial port
  pinMode(BUTTON1, INPUT_PULLUP);
  while(!checkBoard()){
    delay(50);
  }
  checkHTTP_off();
  checkHTTP_on();
/*
  pinMode(PWR, OUTPUT);
  digitalWrite(PWR, LOW);
  delay(500);
  digitalWrite(PWR, HIGH);
*/
  on_off = false;
}

void loop()
{
  while(1){
    if(!digitalRead(BUTTON1)){
      delay(200); //fuer debounce (prellen)
      while(!digitalRead(BUTTON1)) {} //Wartet bis der Button losgelassen wird
      on_off = !on_off;
      if(on_off){
        Serial.println("Started");
      }else{
        Serial.println("Stopped");
      }
      
    }
    if(on_off){
      if((millis()-Timestemp2)>=ZeitVar5s){
        readPSI();
        readGNSS();
        printGlobals();
        Timestemp2=millis();
      }
      if((millis()-Timestemp3)>=ZeitVar30s){
        setCH1();
        while(!sendHTTP()){
          delay(50);
        }
        
        setCH2();
        while(!sendHTTP()){
          delay(50);
        }
        Timestemp3=millis();
      }
    }
  }
}

boolean checkHTTP_on(void){
  int i=0;
  char RecMessage[30]="0";
  bool answer=false;
  clearmySerial();
  myserial.write("AT+HTTPINIT\r");
  myserial.flush();
  Timestemp = millis();
  
  do{
    if(myserial.available() > 0){
      RecMessage[i]=myserial.read();
      i++;
      if (strstr(RecMessage, "OK") != NULL){
        answer = true;
      }else if(strstr(RecMessage, "ERROR") != NULL){
        break;
      }
    }
    if((millis()-Timestemp)>=ZeitVar){
      Serial.println("check HTTP on Timeout");
      break;
    }
  } while (!answer);
  
  if(answer){
    Serial.println("HTTP Service OK");
  }else{
    Serial.println("HTTP Service Error");
  }
  return answer;
}

boolean checkHTTP_off(void){
  int i=0;
  char RecMessage[30]="0";
  bool answer=false;
  clearmySerial();
  myserial.write("AT+HTTPTERM\r");
  myserial.flush();
  Timestemp = millis();
  do{
    if(myserial.available() > 0){
      RecMessage[i]=myserial.read();
      i++;
      if (strstr(RecMessage, "OK") != NULL){
        answer = true;
      }else if(strstr(RecMessage, "ERROR") != NULL){
        break;
      }
    }
    if((millis()-Timestemp)>=ZeitVar){
      Serial.println("check HTTP off Timeout");
      break;
    }
  } while (!answer);
  
  if(answer){
    Serial.println("HTTP Service offline OK");
  }else{
    Serial.println("HTTP Service offline Error");
  }
  return answer;
}


boolean checkBoard(void){
  bool answer=false;
  char RecMessage[20]="0";
  int i=0;
  clearmySerial();
  myserial.write("AT\r");
  myserial.flush();
  Timestemp = millis();
  do{
    if(myserial.available() > 0){
      RecMessage[i]=myserial.read();
      i++;
      if (strstr(RecMessage, "OK") != NULL){
        answer = true;
      }
    }
    if((millis()-Timestemp)>=ZeitVar){
      Serial.println("check Board Timeout");
      break;
    }
  } while (!answer);
  
  if(answer){
    Serial.println("Board rdy!");
  }else{
    Serial.println("Board not rdy!");
  }
  return answer;
}


void readPSI(void){
  int trace=0;
  char RecMessage[100]="0";
  char CutMessage[100]="0";
  char CutMessage2[20]="0";
  int i=0, j=0;
  char * pch;
  bool answer=false;
  
  clearmySerial();
  trace=myserial.write("AT+cpsi?\r");
  myserial.flush();
  Serial.print("PSI myserial bytes: ");
  Serial.println(trace);
  Timestemp = millis();

  do{
    if(myserial.available() > 0){
      RecMessage[i]=myserial.read();
      i++;
      if (strstr(RecMessage, "OK") != NULL){
        answer = true;
        RecMessage[i]='\0';
      }
    }
    if((millis()-Timestemp)>=ZeitVar){
      Serial.println("Read PSI Timeout");
      break;
    }
  } while (!answer);
  if(answer){
    pch = strstr(RecMessage,":");
    int posi = pch - RecMessage;
    posi+=2;
    i=0;
    while(RecMessage[posi+i]!='\n'){
      CutMessage[i]=RecMessage[posi+i];
      i++;
    }
    CutMessage[i]='\0';
    i=0;
    j=0;
    while(CutMessage[i]!=','){
      CutMessage2[j]=CutMessage[i];
      j++;
      i++;
    }
    CutMessage2[j]='\0';
    
    if(!strcmp(CutMessage2,"LTE")){
      strcpy(globals[LfdN][1],CutMessage2);
      strcpy(CutMessage2,"");
      j=0;
      i++;
      int z[5]={4,10,11,12,13};
      int x=0, y=0;
      
      for(i=0;i<=(strlen(CutMessage));i++){
        j=0;
        while(CutMessage[i]!=',' and CutMessage[i]!='\0'){
          CutMessage2[j]=CutMessage[i];
          j++;
          i++;
        }
        CutMessage2[j]='\0';
        
        if(z[y]==x){
          y++;
          strcpy(globals[LfdN][y+1],CutMessage2);
        }
        x++;
        //Serial.println(CutMessage2);
        //Serial.flush();
        strcpy(CutMessage2,"");
      }
    }
  globals[LfdN][6][2]='\0';
  }
  return;
}

void readGNSS(void){
  char RecMessage[100]="0";
  char CutMessage[100]="0";
  char CutMessage2[20]="0";
  char GNSS[9][20]; //0: lat | 1: N/S | 2: log | 3: E/W | 4: date | 5: UTC-Time | 6: alt | 7: speed | 8: course
  char g_d_lat[3];
  char g_m_lat[10];
  char g_d_log[4];
  char g_m_log[10];
  char cd_lat[20];
  char cd_log[20];
  int trace =0;
  int i=0, j=0;
  int i_d_lat=0, i_d_log=0;
  int i_d_NS=0, i_d_EW=0;
  float i_m_lat=0, i_m_log=0;
  float c_lat=0, c_log=0;
  
  char * pch;
  bool answer=false;
  clearmySerial();
  trace=myserial.write("AT+CGPSINFO\r");
  myserial.flush();
  Serial.print("GNSS myserial bytes: ");
  Serial.println(trace);
  Timestemp = millis();
  do{
    if(myserial.available() > 0){
      RecMessage[i]=myserial.read();
      i++;
      RecMessage[i]='\0';
      if (strstr(RecMessage, "OK") != NULL){
        answer = true;
      }
    }
    if((millis()-Timestemp)>=ZeitVar){
      Serial.println("read GNSS Timeout");
      break;
    }
  } while (!answer);
  Serial.println(RecMessage);
  Serial.flush();
      if(answer){
        pch = strstr(RecMessage,":");
        int posi = pch - RecMessage;
        posi+=2;
        i=0;
        while(RecMessage[posi+i]!='\n'){
          CutMessage[i]=RecMessage[posi+i];
          i++;
        }
        
        CutMessage[i]='\0';
        strcpy(CutMessage2,"");
        int z[5]={0,2,11,12,13};
        int y=0;
        
        for(i=0;i<strlen(CutMessage);i++){
          j=0;
          while(CutMessage[i]!=',' and CutMessage[i]!='\0'){
            CutMessage2[j]=CutMessage[i];
            j++;
            i++;
          }
          CutMessage2[j]='\0';
          strcpy(GNSS[y],CutMessage2);
          //Serial.println(CutMessage2);
          //Serial.flush();
          y++;
          strcpy(CutMessage2,"");
        }

        if(strlen(GNSS[0])>=1){
          for(i=0;i<9;i++){
            g_m_lat[i]=GNSS[0][2+i];
            g_m_log[i]=GNSS[2][3+i];
          }
          g_m_lat[9]='\0';
          g_m_log[9]='\0';
          g_d_lat[0]=GNSS[0][0];
          g_d_lat[1]=GNSS[0][1];
          g_d_lat[2]='\0';
          g_d_log[0]=GNSS[2][0];
          g_d_log[1]=GNSS[2][1];
          g_d_log[2]=GNSS[2][2];
          g_d_log[3]='\0';
          
          i_d_lat=atoi(g_d_lat); 
          i_d_log=atoi(g_d_log); 
          i_m_lat=atof(g_m_lat)/60; 
          i_m_log=atof(g_m_log)/60; 

          if(!strcmp(GNSS[1],"N")){
            i_d_NS=1;
          }else if(!strcmp(GNSS[1],"S")){
            i_d_NS=-1;
          }

          if(!strcmp(GNSS[3],"E")){
            i_d_EW=1;
          }else if(!strcmp(GNSS[3],"W")){
            i_d_EW=-1;
          }
          c_lat=(i_m_lat+i_d_lat)*i_d_NS;
          c_log=(i_m_log+i_d_log)*i_d_EW;
          
          sprintf(cd_lat, "%d.%i%i",i_d_lat, (int)(i_m_lat*pow(10,4)), (int)(((i_m_lat*pow(10,4))-(int)(i_m_lat*pow(10,4)))*pow(10,4)));
          sprintf(cd_log, "%d.%i%i",i_d_log, (int)(i_m_log*pow(10,4)), (int)(((i_m_log*pow(10,4))-(int)(i_m_log*pow(10,4)))*pow(10,4)));

          strcpy(globals[LfdN][9],cd_lat);
          strcpy(globals[LfdN][10],cd_log);
          strcpy(globals[LfdN][11],GNSS[4]);
          strcpy(globals[LfdN][12],GNSS[5]);
          strcpy(globals[LfdN][13],GNSS[6]);
          strcpy(globals[LfdN][14],GNSS[7]);
          strcpy(globals[LfdN][15],GNSS[8]);

          globals[LfdN][15][5]='\0';
        }

      }
      Serial.println("");
      Serial.println("GNSS Info:");
      Serial.println("");
      if(strlen(GNSS[0])>=1){
        /*
        Serial.print("Latitude: ");
        Serial.print(i_d_lat);
        Serial.print("° ");
        Serial.print(g_m_lat);
        Serial.println(" min");
        Serial.print("Longitude: ");
        Serial.print(i_d_log);
        Serial.print("° ");
        Serial.print(g_m_log);
        Serial.println(" min");
        Serial.print("Date: ");
        Serial.println(g_date);
        Serial.print("Time: ");
        Serial.println(g_time);
        Serial.print("Altitude: ");
        Serial.println(g_alt);
        Serial.print("Speed: ");
        Serial.println(g_speed);
        Serial.print("Course: ");
        Serial.println(g_course);
        Serial.print("GMaps Link: ");
        Serial.println(g_link);
        */
      }else{
        Serial.println("Keine GNSS Daten Vorhanden..");
        Serial.println(CutMessage);
      }
      return;
}

long readBaud(void){
  int trace;
  char RecMessage[25]="0";
  char CutMessage[20]="0";
  int i=0;
  long Baud=0;
  char * pch;
  bool answer=false;
  clearmySerial();
  trace=myserial.write("AT+iprex?\r");
  myserial.flush();
  Serial.print("myserial bytes: ");
  Serial.println(trace);
  Timestemp = millis();
  do{
    if(myserial.available() > 0){
      RecMessage[i]=myserial.read();
      i++;
      if (strstr(RecMessage, "OK") != NULL){
        answer = true;
        RecMessage[i]='\0';
      }
    }
    if((millis()-Timestemp)>=ZeitVar){
      Serial.println("read Baud Timeout");
      break;
    }
  } while (!answer);
      if(answer){
        pch = strstr(RecMessage,":");
        int posi = pch - RecMessage;
        posi+=2;
        i=0;
        while(RecMessage[posi+i]!='\n'){
          CutMessage[i]=RecMessage[posi+i];
          i++;
        }
        CutMessage[i]='\0';

        Baud=atol(CutMessage);
      }
      Serial.println("");
      Serial.print("Baud Rate:");
      Serial.println(Baud);
      return Baud;
}
void clearGlobalArrays(void){
  for(int i=0;i>14;i++){
    strcpy(globals[LfdN][i],"");
  }
}

void setCH1(void){
  int trace=0;
  char RecMessage[200]="0";
  char URLMessage[200]="0";
  int i=0;
  bool answer=false;
  sprintf(globals[LfdN][0],"%i",LfdN);
  strcpy(URLMessage,"AT+HTTPPARA=\"URL\",\"https://api.thingspeak.com/update?api_key=");
  strcat(URLMessage,"XXXXXXXXXXXXXXXX");
  strcat(URLMessage,"&field1=");
  strcat(URLMessage,globals[LfdN][0]);
  strcat(URLMessage,"&field2=");
  strcat(URLMessage,globals[LfdN][1]);
  strcat(URLMessage,"&field3=");
  strcat(URLMessage,globals[LfdN][2]);
  strcat(URLMessage,"&field4=");
  strcat(URLMessage,globals[LfdN][3]);
  strcat(URLMessage,"&field5=");
  strcat(URLMessage,globals[LfdN][4]);
  strcat(URLMessage,"&field6=");
  strcat(URLMessage,globals[LfdN][5]);
  strcat(URLMessage,"&field7=");
  strcat(URLMessage,globals[LfdN][6]);
  strcat(URLMessage,"\"");    
  strcat(URLMessage,"\r");
  Serial.println(URLMessage);
  clearmySerial();
  trace=myserial.write(URLMessage);
  myserial.flush();
  Serial.print("myserial bytes: ");
  Serial.println(trace);
  Timestemp = millis();
  do{
    if(myserial.available() > 0){
      RecMessage[i]=myserial.read();
      i++;
      if (strstr(RecMessage, "OK") != NULL){
        answer = true;
        RecMessage[i]='\0';
      }else if(strstr(RecMessage, "ERROR") != NULL){
        break;
      }
    }
    if((millis()-Timestemp)>=(ZeitVar*2)){
        Serial.println("HTTP set Timeout");
        break;
    }
  } while (!answer);
  Serial.println("RecMessage: ");
  Serial.println(RecMessage);
  if(answer){
    Serial.println("HTTP set OK");
  }else{
    Serial.println("HTTP set failed");
  }
  return;
}

void setCH2(void){
  int trace=0;
  char RecMessage[200]="0";
  char URLMessage[200]="0";
  int i=0;
  bool answer=false;
  sprintf(globals[LfdN][8],"%i",LfdN);
  strcpy(URLMessage,"AT+HTTPPARA=\"URL\",\"https://api.thingspeak.com/update?api_key=");
  strcat(URLMessage,"XXXXXXXXXXXXXXXX");
  strcat(URLMessage,"&field1=");
  strcat(URLMessage,globals[LfdN][8]);
  strcat(URLMessage,"&field2=");
  //strcat(URLMessage,"&latitude=");
  strcat(URLMessage,globals[LfdN][9]);
  strcat(URLMessage,"&field3=");
  //strcat(URLMessage,"&longitude=");
  strcat(URLMessage,globals[LfdN][10]);
  strcat(URLMessage,"&field4=");
  strcat(URLMessage,globals[LfdN][11]);
  strcat(URLMessage,"&field5=");
  strcat(URLMessage,globals[LfdN][12]);
  strcat(URLMessage,"&field6=");
  //strcat(URLMessage,"&elevation=");
  strcat(URLMessage,globals[LfdN][13]);
  strcat(URLMessage,"&field7=");
  strcat(URLMessage,globals[LfdN][14]);
  strcat(URLMessage,"&field8=");
  strcat(URLMessage,globals[LfdN][15]);
  strcat(URLMessage,"\"");    
  strcat(URLMessage,"\r");
  Serial.println(URLMessage);
  clearmySerial();
  trace=myserial.write(URLMessage);
  Serial.print("myserial bytes: ");
  Serial.println(trace);
  myserial.flush();
  Timestemp = millis();
  do{
    if(myserial.available() > 0){
      RecMessage[i]=myserial.read();
      i++;
      if (strstr(RecMessage, "OK") != NULL){
        answer = true;
        RecMessage[i]='\0';
      }else if(strstr(RecMessage, "ERROR") != NULL){
        break;
      }
    }
    if((millis()-Timestemp)>=(ZeitVar*2)){
        Serial.println("HTTP set Timeout");
        break;
    }
  } while (!answer);
  Serial.println("RecMessage: ");
  Serial.println(RecMessage);
  if(answer){
    Serial.println("HTTP set OK");
  }else{
    Serial.println("HTTP set failed");
  }
  return;
}

boolean sendHTTP(void){
  int trace=0;
  int i=0;
  char RecMessage[30]="0";
  bool answer=false;
  clearmySerial();
  trace=myserial.write("AT+HTTPACTION=1\r");
  myserial.flush();
  Serial.print("myserial bytes: ");
  Serial.println(trace);
  Timestemp = millis();
  do{
    if(myserial.available() > 0){
      RecMessage[i]=myserial.read();
      i++;
      if (strstr(RecMessage, "OK") != NULL){
        answer = true;
        RecMessage[i]='\0';
      }else if(strstr(RecMessage, "ERROR") != NULL){
        break;
      }
    }
    if((millis()-Timestemp)>=ZeitVar){
        Serial.println("HTTP send Timeout");
        break;
    }
  } while (!answer);
  
  Serial.println(RecMessage);
  if(answer){
    Serial.println("HTTP send OK");
  }else{
    Serial.println("HTTP send failed");
  }
  return answer;
}

void clearmySerial(void){
  myserial.flush();
  while(myserial.available()>0){
    myserial.read();
  }
  return;
}

void printGlobals(void){
  Serial.println("Globals: ");
  for (int i=0;i<16;i++){
    Serial.print("Stelle ");
    Serial.print(i);
    Serial.print(".: ");
    Serial.print(globals[LfdN][i]);
    Serial.print(" Zeichen: ");
    Serial.println(strlen(globals[LfdN][i]));

  }
  
}

Könnte sein!

Schon von PROGMEM gehört?
Zumindest die konstanten Dinge kann man dahin verlagern.

Hey, ja habe ich schon gesehen, aber dafür müssen char arrays const sein. Somit wären die nur noch read only. Da sich die Werte aber immer wieder ändern hilft mir das leider nicht so ganz, außer es gibt richtige Funktionen um Werte in den Flash zu laden, zu lesen und zu überschreiben..

Eigentlich ist es ja klar!
Du siehst dein Programm.
Ich sehe nix.

Also kannst du auch keine konkreten Vorschläge erwarten.

Hey,

mein Fehler. Ich habe den Code hochgeladen. Ich werde auch gleich noch die Ausgaben der Funktionen hinzufügen.

Du hast doch da eine kleine Unmenge konstanter Strings!
Siehst du sie nicht?

Nur mal einen für einen Vorschlag herausgegriffen:
Serial.print("myserial bytes: "); // weg damit
Serial.print(F("myserial bytes: ")); // so tun

myserial.write("AT+HTTPINIT\r");
myserial.print(F("AT+HTTPINIT\r"));

1 Like

~ 500 Bytes werden genau dort angefordert ...

void readGNSS(void) {
  char RecMessage[100] = "0";
  char CutMessage[100] = "0";
  char CutMessage2[20] = "0";
  char GNSS[9][20]; //0: lat | 1: N/S | 2: log | 3: E/W | 4: date | 5: UTC-Time | 6: alt | 7: speed | 8: course
  char g_d_lat[3];
  char g_m_lat[10];
  char g_d_log[4];
  char g_m_log[10];
  char cd_lat[20];
  char cd_log[20];
  int trace = 0;
  int i = 0, j = 0;
  int i_d_lat = 0, i_d_log = 0;
  int i_d_NS = 0, i_d_EW = 0;
  float i_m_lat = 0, i_m_log = 0;
  float c_lat = 0, c_log = 0;

  char * pch;
  bool answer = false;

puh, und dann noch mal on top 400 Byte wenn die Funktion aufgerufen wird:

neben dem ersten Schritt (F-Makro!) würde ich dir empfehlen, alle Variablen zu überprüfen: müssen die so groß sei wie sie aktuell sind?
auch mal kritisch alle "int" hinterfragen ob die int sein müssen.

Stell mal auch die Warnungen ein: DATEI - VOREINSTELLUNGEN - Ausführliche Ausgabe während [x] Kompilierung und Compiler-Warnungen alle.

Vielen Dank zunächst an alle. Muss man auch erstmal wissen, das der Serial.print/ln Standard gemäß in den RAM läd. Ich werde eure Tipps mal ausprobieren!

Da steht auch noch eine Überprüfung an.

Ich glaube, dass die ganzen fields da nicht reinpassen:

  0    AT+HTTPPARA=\"URL\",\"https://api.thingspeak.com/update?api_key=
 64    XXXXXXXXXXXXXXXX
       // 8 mal mindestens 8 (Fixtext) + max. 12 (aus dem Array) = 20 Byte
       // char globals[1][16][13];
 80    &field1=  
 88    globals[LfdN][8]
240    \"\r
242

Edit:
Na gut, der erste String ist nur 62 Byte lang und die Nummer im ersten Feld hat nur max. 5 Ziffern.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.