UNO Speicher problem??

hallo miteinander,

habe seit neusten ein UNO :grin:

wenn ich dort meine Firmware für die Tropfenbox aufspiele
bekomme ich entweder keine Rückmeldung oder Falsche Rückmeldungen vom UNO.

Kann das an einem Speicher Problem Ligen?

wenn ich die ziele:

    hardware_t hardware[60]=

von 60 auf 70 erhöhe habe ich die Probleme.
mit 60 habe ich die Probleme nicht.

wie kann ich raus finden ob ich ein Speicher Problem habe auf dem UNO oder nicht?

Firmware aufspielen, Seriellen Monitor Starten und den Befehl eingeben "print_config" dann müsste eine Liste aller Daten in dem Array kommen, wie gesagt wenn ich die Zahl auf 70 erhöhe bekomme ich Falsche antworten oder es reagiert nicht mehr.
aus dem Grund dachte ich an ein Speicherproblem.

das ist die vollständige Firmware:

// *****************************************************************
// *****************************************************************
// *****************************************************************

// Befehl         Ausgabe 

// get_name      = Es antwortet mit seinem Namen
// get_firmware  = Es Antwortet mit der Versionsnummer 
// configure     = Format: configure,pin,vorlaufzeit,dauer
// print_config  = Es antwortet mit einer Tabelle aller Hardware Zeiten 
// *print_steps* = Es antwortet mit einer Tabelle aller Schaltzeiten 
// reset         = Es setzt alle Hardware Schaltzeiten wider auf 0 zurück 

//   * nicht inplementirt

// *****************************************************************
// *****************************************************************
// *****************************************************************



        #define ZEILENTRENNZEICHEN 10
    int startPin           = A4;
   char Firmware_Nr[]      = "2.0-MG";
   char Name[]             = "Tropfen Box";
    int Baudrate           = 9600;
    int Lauf               = 0;
    int Zeile              = 4;
    
    
    struct hardware_t{int pin;long vorlaufzeit; long dauer;};              // Struktur einer einzelnen Schaltzeit
    struct schaltzeit_t{int pin;long zeit; boolean geschaltet;};           // Struktur einer einzelnen Schaltzeit

    hardware_t hardware[60]=
{                                              // Vorlaufzeit und Dauer für die Hardware
//  {2, 0000,     500000},              // Musterdaten
//  {3, 500000,   500000},              // Musterdaten
//  {4, 1000000,  500000},              // Musterdaten
//  {5, 1500000,  500000},              // Musterdaten
//  {6, 0,        2000000},             // Musterdaten
};

    #define schritte sizeof(hardware)/sizeof(hardware[0])


    schaltzeit_t schaltzeiten[2*schritte];
    int anzahlSchaltzeiten;
    long geschalteteZeit[2*schritte];
    void sortSchaltzeiten(int n) 
    {
      schaltzeit_t temp;
      for(int x=0; x<n; x++) 
      {
        for(int y=0; y<n-1; y++) 
        {
          if (schaltzeiten[y].zeit>schaltzeiten[y+1].zeit) 
          {
            temp=schaltzeiten[y+1];
            schaltzeiten[y+1]=schaltzeiten[y];
            schaltzeiten[y]=temp;
          }
        }
      }
    }


    // Funktion - Serielle Schnittstelle auslesen -
      char* receiveBuffer() {
      static char lineBuffer[100];
      static byte counter=0;
      char c;
      if (Serial.available()==0) return NULL;
      if (counter==0) memset(lineBuffer,0,sizeof(lineBuffer));
      c=Serial.read();
      if (c==ZEILENTRENNZEICHEN){
      counter=0;
      return lineBuffer; }
      else if (c>=32) {
      lineBuffer[counter]=c;
      if (counter<sizeof(lineBuffer)-2) counter++; }
      return NULL; }
    // Funktion - Serielle Schnittstelle auslesen -


void setup() 
  {
    pinMode(startPin, INPUT);
    Serial.begin(Baudrate);
  }  

void loop() {  
  unsigned long starttime;
  unsigned long looptime;


   char* text=receiveBuffer();
     if(text != NULL)
        {
           if (strcmp(text,"get_name")==0)            {Serial.print("OK,"); Serial.println(Name); Serial.println("\n");}
           else if (strcmp(text,"get_firmware")==0)   {Serial.print("OK,"); Serial.println(Firmware_Nr); Serial.println("\n");}
           else if (strcmp(text,"reset")==0)          {memset(hardware, 0, sizeof(hardware)); Zeile = -1; Serial.println("OK\n");}
           else if (strcmp(text,"print_config")==0)
             {
                  Serial.print("Zeile");
                  Serial.print("\t");
                  Serial.print("PIN");
                  Serial.print("\t");
                  Serial.print("Start");
                  Serial.print("\t");
                  Serial.println("Dauer");
               for (int i=0;i<schritte;i++) 
                { 
                  Serial.print(i);
                  Serial.print("\t");
                  Serial.print(hardware[i].pin);
                  Serial.print("\t");
                  Serial.print(hardware[i].vorlaufzeit/1000);
                  Serial.print("\t");
                  Serial.println(hardware[i].dauer/1000);
                }
             Serial.print("OK"); 
             } // Print
           else if (strncmp(text,"configure",9)==0)
             {
                   text = text + strlen_P(PSTR("configure")) + 1;

                   int pin;
                    strtok(text, ",");
                     if(text[0] == 'A')
                      {
                        #if defined (__AVR_ATmega328P__)    
                          pin = atoi(text + 1) + 14;  // Arduino UNO
                        #elif defined (__AVR_ATmega2560__)
                          pin = atoi(text + 1) + 54;  // Arduino Mega
                        #endif
                     }
                      else
                       {
                         pin = atoi(text);
                       }

                   int vorlaufzeit = atoi(strtok(NULL, ","));
                   int dauer       = atoi(strtok(NULL, ","));
                       Zeile       = Zeile + 1;
      
                if (Zeile > -1 && Zeile < 11)   // Hier muss noch die Neue Pin abfrage hinein
                  {   
                    hardware[Zeile].pin         = pin;
                    hardware[Zeile].vorlaufzeit = vorlaufzeit;
                    hardware[Zeile].dauer       = dauer;
      
                    hardware[Zeile].vorlaufzeit*=1000;
                    hardware[Zeile].dauer*=1000;
 
 // ***************** muss wider auskommentirt werden  *****************     
                     // Serial.print(pin); Serial.print(",");                          // muss wider raus genommen werden
                     // Serial.print(vorlaufzeit); Serial.print(",");                  // muss wider raus genommen werden 
                     // Serial.println(dauer);                                         // muss wider raus genommen werden 
 // ***************** muss wider auskommentirt werden  *****************   
                   Serial.println("OK\n");  
                 }
                 else 
                   { Serial.print("Pin");
                     Serial.print("\t");
                     Serial.println("Zeile");
                   
                   
                     Serial.print(pin);
                     Serial.print("\t");
                     Serial.print(Zeile);
                     Serial.print("\t");
                     Serial.println("Fehler: Werte komnten nicht eingetragen werden.\n"); }
             } // Config                                 
          else { Serial.println("NOK, Unknown command:\n");}
          
         } // if(text != NULL)
  
     if(digitalRead(startPin)== HIGH && Lauf == 0)
        {
          Lauf = 1;
          anzahlSchaltzeiten=0;
          for (int i=0;i<schritte;i++)
          {
            pinMode(hardware[i].pin,OUTPUT);
            if (hardware[i].dauer>0)
            {
              schaltzeiten[anzahlSchaltzeiten].pin=hardware[i].pin;
              schaltzeiten[anzahlSchaltzeiten].zeit=hardware[i].vorlaufzeit;
              schaltzeiten[anzahlSchaltzeiten].geschaltet=true;
              anzahlSchaltzeiten++;
              schaltzeiten[anzahlSchaltzeiten].pin=hardware[i].pin;
              schaltzeiten[anzahlSchaltzeiten].zeit=hardware[i].vorlaufzeit+hardware[i].dauer;
              schaltzeiten[anzahlSchaltzeiten].geschaltet=false;
              anzahlSchaltzeiten++;
            }
          }
            
            sortSchaltzeiten(anzahlSchaltzeiten);
            starttime=micros();
            for (int i=0;i<anzahlSchaltzeiten;i++)
            {
              while ((looptime=micros()-starttime)<schaltzeiten[i].zeit);
              digitalWrite(schaltzeiten[i].pin,schaltzeiten[i].geschaltet);
            }
        }
     else if (digitalRead(startPin)== LOW) {Lauf = 0; delay(10);}
  }

Gruß Mücke

Jetzt kommt vielleicht zum Tragen, dass du die ganze Zeit ignoriert hast, was ich dir aber schon lange gesagt habe:
Geh sparsamer mit den String Konstanten um

1.) Verwende überall wo du print()/println() hast das F() Makro:

Serial.print(F("String im Flash"));

Dann belegt der String kein RAM mehr

2.) Verwende bei den String Funktionen die _P Versionen und das PSTR() Makro:

if (strcmp_P(text, (PSTR("get_name"))==0)

Das gleiche bei den andere Verwendungen von strmcmp!! Nicht nur da.

strncmp() geht genauso:

else if (strncmp_P(text, PSTR("configure"),9)==0)

3.) Mach den Serial Puffer kleiner wenn möglich

static char lineBuffer[100];

Überträgst du wirklich 100 Zeichen in einem Rutsch?

Den freien Speicher kannst du hiermit berechnen (wenn noch was frei ist):

int freeRam () 
{
  extern int __heap_start, *__brkval; 
  int v; 
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 
}

Ok das werde ich alles Umsätzen,
und ja das wurde mir schon ich wies nicht wie oft gesagt.

demnach kann es wirklich daran liegen das der Speicher voll ist und daher die merkwürdigen Regionen her kommen.

EDIT:

wie muss ich den Code:

Den freien Speicher kannst du hiermit berechnen (wenn noch was frei ist):

verstehen?
für mich sind da ein Haufen Striche und Bahnhof ohne Züge :wink:

Macht genau was der Name sagt und gibt dir den freien Speicher in Bytes zurück.

Das kannst du dir z.B. am Ende von setup() ausgeben lassen:

Serial.print(F("Free RAM: "));
Serial.println(freeRam());

Bezüglich des F()-Makros. Das geht natürlich nur mit String Konstanten. Nicht mit Variablen. Nicht dass du auf die Idee kommst sowas zu machen:

Serial.print(F(Zeile));

Das habe ich hier auch schon von jemandem gesehen :slight_smile:

Serenifly:
Macht genau was der Name sagt und gibt dir den freien Speicher in Bytes zurück.

Das kannst du dir z.B. am Ende von setup() ausgeben lassen:

Serial.print(F("Free RAM: "));

Serial.println(freeRam());

ok das muss ich mal testen.
und den andern teil des Codes packe ich oben über das "void setup()"?

Serenifly:
Bezüglich des F()-Makros. Das geht natürlich nur mit String Konstanten. Nicht mit Variablen. Nicht dass du auf die Idee kommst sowas zu machen:

Serial.print(F(Zeile));

Das habe ich hier auch schon von jemandem gesehen :slight_smile:

ja aber hallo wie kommst du nur auf die Idee,
gut das du es sagst denn ich habe das natürlich gemacht und prompt einen Fehler bekommen den ich schon Posten wollte
dank dir kommt die Meldung aber jetzt nicht hier rein ,-)

dafür habe ich eine andere Meldung:

Binäre Sketchgröße: 5.446 Bytes (von einem Maximum von 14.336 Bytes)
avrdude: stk500_getsync(): not in sync: resp=0xf8

die untere ziele ist Orange also nicht gut?

verändert habe ich bisher nur Punkt 1 und Punkt 3 habe ich auf 25 gesätzt

Schrecklich wie lahm die website ist....

Seit wann hat der/das/die UNO 14.336 Bytes???

Muecke:
und den andern teil des Codes packe ich oben über das "void setup()"?

Das ist eine Funktion wie jede andere auch

Vielleicht noch das Leerzeichen vor dem () entfernen. Das ist beim Kopieren reingerutscht.

dafür habe ich eine andere Meldung:
Binäre Sketchgröße: 5.446 Bytes (von einem Maximum von 14.336 Bytes)
avrdude: stk500_getsync(): not in sync: resp=0xf8

Das hat nichts mit dem Code an sich zu tun. Das heißt mit der Upload klappt was nicht.

Und ja: 14.336 Byte? O_o

skorpi08:
Schrecklich wie lahm die website ist....

Seit wann hat der/das/die UNO 14.336 Bytes???

gute Frage, ich wies zwar nicht wie das passiert ist doch bei Bords war das Falsche eingestellt.
merkwürdig, ja ja vielleicht auf eine tasten Kürzel gekommen mit dem ich das umgestellt habe versehentlich.

wenn ich jetzt mit den zwei Änderungen als Befehl Free eingebe kommt als Antwort:

Free RAM: 273

das muss ich mal in der Alten Version machen um zu sehen was da Free war.

3.) Mach den Serial Puffer kleiner wenn möglich
Code:
static char lineBuffer[100];
Überträgst du wirklich 100 Zeichen in einem Rutsch?

Würd mich auch brennend interessieren aber wie ichs hier lesen konnte, hast du nicht mal Ahnung wofür die Zahlen da sind?!

Ohh, das ist knapp. Und mit Strings ist das gleich weg.

z.B. das:

Serial.println("Fehler: Werte komnten nicht eingetragen werden.\n");

Damit sind ca. 50 Byte fort!

Liegt daran das die ganzen Strings am Anfang vom Flash ins RAM kopiert werden. Mit Sachen wie F() und PSTR() bleiben die Strings im Flash. Man muss aber Funktionen und Konstrukte verwenden die Strings auch direkt im Flash verarbeiten können.

Wo halt am meisten Speicher draufgeht ist die Arrays aus structs. hardware_t hat 10 Bytes und du hast 60 Stück davon. Und dann wenn ich das richtig sehe nochmal 120 * 7 Byte für das Schaltzeiten Array. Damit ist schon das meiste RAM voll.
Das lässt sich allerdings nicht vermeiden, es sei denn du kannst mit weniger Zeiten leben.

Und dann ist hier nochmal ein Array mit 120 * 4 Bytes:

long geschalteteZeit[2*schritte];

das sind meine Aktuellen Speicher Status:

Ohne Veränderung:

Free RAM: 86

Bearbeitet: Punkt 1 und 3 (Punkt drei ist auf 25 gesetzt worden.)

Free RAM: 273

Serenifly:

Serial.println("Fehler: Werte komnten nicht eingetragen werden.\n");

Damit sind ca. 50 Byte fort!

wenn ich das mit dem F(...) nehmen dann müsste das keine 50 Byte mehr verbrauchen?

skorpi08:

3.) Mach den Serial Puffer kleiner wenn möglich
Code:
static char lineBuffer[100];
Überträgst du wirklich 100 Zeichen in einem Rutsch?

Würd mich auch brennend interessieren aber wie ichs hier lesen konnte, hast du nicht mal Ahnung wofür die Zahlen da sind?!

ich glaube das das für die Anzahl der zeichne steht die ich bei einem Befehl an das Arduino sende. "immer zeilenweise"

Muecke:
wenn ich das mit dem F(...) nehmen dann müsste das keine 50 Byte mehr verbrauchen?

Nur 50 Bytes Flash. Aber kein RAM.

ich glaube das das für die Anzahl der zeichne steht die ich bei einem Befehl an das Arduino sende. "immer zeilenweise"

Ja und wenn du wirklich viele Daten überträgst kann es auch sein dass du das brauchst. Kommst darauf an.

Im Gegensatz zu den anderen Arrays fällt das aber kaum ins Gewicht. Schon nur 50 statt 60 Zeiten würde dir einiges einsparen.

Es kann aber auch sein dass du erst mal mit 270 Bytes leben kannst, solange innerhalb der Funktionen nicht viel Speicher gebraucht wird, wonach es nicht aussieht.

jetzt möchte ich die Optimierung weiter machen :slight_smile:
mal schauen was ich noch raus bekomme, irgend wie bekomme ich immer Fehler muss da noch mal drüber schauen.

ich wollte noch Punkt zwei machen bekomme aber immer egal was ich mache Fehlermeldungen:

das ist die original ziele:

           if (strcmp(text,"get_name")==0)            {Serial.print("OK,"); Serial.println(Name); Serial.println("\n");}

so habe ich sie abgeändert:

        if (strcmp_P(text, (PSTR("get_name"))==0)     {Serial.print(F("OK,")); Serial.println(Name); Serial.println(F("\n"));}

jetzt bekomme ich die Fehler hier:

Firmware_2_0-MG-Speicher.ino: In function 'void loop()':
Firmware_2_0-MG-Speicher.ino:109: error: cannot convert 'bool' to 'const prog_char*' for argument '2' to 'int strcmp_P(const char*, const prog_char*)'
Firmware_2_0-MG-Speicher.ino:109: error: expected )' before '{' token Firmware_2_0-MG-Speicher.ino:192: error: expected primary-expression before '}' token Firmware_2_0-MG-Speicher.ino:192: error: expected ;' before '}' token

das ist der vollständige Code, darf nicht so viele Zeichen in eine Beitrag packen :frowning:
sollte eigentlich zum vorherigen Beitrag dazu.

// *****************************************************************
// *****************************************************************
// *****************************************************************

// Befehl         Ausgabe 

// get_name      = Es antwortet mit seinem Namen
// get_firmware  = Es Antwortet mit der Versionsnummer 
// configure     = Format: configure,pin,vorlaufzeit,dauer
// print_config  = Es antwortet mit einer Tabelle aller Hardware Zeiten 
// *print_steps* = Es antwortet mit einer Tabelle aller Schaltzeiten 
// reset         = Es setzt alle Hardware Schaltzeiten wider auf 0 zurück 

//   * nicht inplementirt

// *****************************************************************
// *****************************************************************
// *****************************************************************



        #define ZEILENTRENNZEICHEN 10
    int startPin           = A4;
   char Firmware_Nr[]      = "2.0-MG";
   char Name[]             = "Tropfen Box";
    int Baudrate           = 9600;
    int Lauf               = 0;
    int Zeile              = 4;
    
    
    struct hardware_t{int pin;long vorlaufzeit; long dauer;};              // Struktur einer einzelnen Schaltzeit
    struct schaltzeit_t{int pin;long zeit; boolean geschaltet;};           // Struktur einer einzelnen Schaltzeit

    hardware_t hardware[60]=
{                                              // Vorlaufzeit und Dauer für die Hardware
//  {2, 0000,     500000},              // Musterdaten
//  {3, 500000,   500000},              // Musterdaten
//  {4, 1000000,  500000},              // Musterdaten
//  {5, 1500000,  500000},              // Musterdaten
//  {6, 0,        2000000},             // Musterdaten
};

    #define schritte sizeof(hardware)/sizeof(hardware[0])


    schaltzeit_t schaltzeiten[2*schritte];
    int anzahlSchaltzeiten;
    long geschalteteZeit[2*schritte];
    void sortSchaltzeiten(int n) 
    {
      schaltzeit_t temp;
      for(int x=0; x<n; x++) 
      {
        for(int y=0; y<n-1; y++) 
        {
          if (schaltzeiten[y].zeit>schaltzeiten[y+1].zeit) 
          {
            temp=schaltzeiten[y+1];
            schaltzeiten[y+1]=schaltzeiten[y];
            schaltzeiten[y]=temp;
          }
        }
      }
    }


    // Funktion - Serielle Schnittstelle auslesen -
      char* receiveBuffer() {
      static char lineBuffer[25];
      static byte counter=0;
      char c;
      if (Serial.available()==0) return NULL;
      if (counter==0) memset(lineBuffer,0,sizeof(lineBuffer));
      c=Serial.read();
      if (c==ZEILENTRENNZEICHEN){
      counter=0;
      return lineBuffer; }
      else if (c>=32) {
      lineBuffer[counter]=c;
      if (counter<sizeof(lineBuffer)-2) counter++; }
      return NULL; }
    // Funktion - Serielle Schnittstelle auslesen -


int freeRam () 
{
  extern int __heap_start, *__brkval; 
  int v; 
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 
}




void setup() 
  {
    pinMode(startPin, INPUT);
    Serial.begin(Baudrate);
  }  

void loop() {  
  unsigned long starttime;
  unsigned long looptime;


   char* text=receiveBuffer();
     if(text != NULL)
        { 
        if (strcmp_P(text, (PSTR("get_name"))==0)     {Serial.print(F("OK,")); Serial.println(Name); Serial.println(F("\n"));}
           else if (strcmp(text,"get_firmware")==0)   {Serial.print(F("OK,")); Serial.println(Firmware_Nr); Serial.println(F("\n"));}
           else if (strcmp(text,"reset")==0)          {memset(hardware, 0, sizeof(hardware)); Zeile = -1; Serial.println(F("OK\n"));}
           
           else if (strcmp(text,"free")==0)
             {
                Serial.print(F("Free RAM: "));
                Serial.println(freeRam());             
             }
           else if (strcmp(text,"print_config")==0)
             {
                  Serial.print(F("Zeile"));
                  Serial.print(F("\t"));
                  Serial.print(F("PIN"));
                  Serial.print(F("\t"));
                  Serial.print(F("Start"));
                  Serial.print(F("\t"));
                  Serial.println(F("Dauer"));
               for (int i=0;i<schritte;i++) 
                { 
                  Serial.print(i);
                  Serial.print(F("\t"));
                  Serial.print(hardware[i].pin);
                  Serial.print(F("\t"));
                  Serial.print(hardware[i].vorlaufzeit/1000);
                  Serial.print(F("\t"));
                  Serial.println(hardware[i].dauer/1000);
                }
             Serial.print(F("OK")); 
             } // Print
           else if (strncmp(text,"configure",9)==0)
             {
                   text = text + strlen_P(PSTR("configure")) + 1;

                   int pin;
                    strtok(text, ",");
                     if(text[0] == 'A')
                      {
                        #if defined (__AVR_ATmega328P__)    
                          pin = atoi(text + 1) + 14;  // Arduino UNO
                        #elif defined (__AVR_ATmega2560__)
                          pin = atoi(text + 1) + 54;  // Arduino Mega
                        #endif
                     }
                      else
                       {
                         pin = atoi(text);
                       }

                   int vorlaufzeit = atoi(strtok(NULL, ","));
                   int dauer       = atoi(strtok(NULL, ","));
                       Zeile       = Zeile + 1;
      
                if (Zeile > -1 && Zeile < 11)   // Hier muss noch die Neue Pin abfrage hinein
                  {   
                    hardware[Zeile].pin         = pin;
                    hardware[Zeile].vorlaufzeit = vorlaufzeit;
                    hardware[Zeile].dauer       = dauer;
      
                    hardware[Zeile].vorlaufzeit*=1000;
                    hardware[Zeile].dauer*=1000;
 
 // ***************** muss wider auskommentirt werden  *****************     
                     // Serial.print(pin); Serial.print(",");                          // muss wider raus genommen werden
                     // Serial.print(vorlaufzeit); Serial.print(",");                  // muss wider raus genommen werden 
                     // Serial.println(dauer);                                         // muss wider raus genommen werden 
 // ***************** muss wider auskommentirt werden  *****************   
                   Serial.println(F("OK\n"));  
                 }
                 else 
                   { Serial.print(F("Pin"));
                     Serial.print(F("\t"));
                     Serial.println(F("Zeile"));
                   
                   
                     Serial.print(pin);
                     Serial.print(F("\t"));
                     Serial.print(Zeile);
                     Serial.print(F("\t"));
                     Serial.println(F("Fehler: Werte komnten nicht eingetragen werden.\n")); }
             } // Config                                 
          else { Serial.println(F("NOK, Unknown command:\n"));}
          
         } // if(text != NULL)
  
     if(digitalRead(startPin)== HIGH && Lauf == 0)
        {
          Lauf = 1;
          anzahlSchaltzeiten=0;
          for (int i=0;i<schritte;i++)
          {
            pinMode(hardware[i].pin,OUTPUT);
            if (hardware[i].dauer>0)
            {
              schaltzeiten[anzahlSchaltzeiten].pin=hardware[i].pin;
              schaltzeiten[anzahlSchaltzeiten].zeit=hardware[i].vorlaufzeit;
              schaltzeiten[anzahlSchaltzeiten].geschaltet=true;
              anzahlSchaltzeiten++;
              schaltzeiten[anzahlSchaltzeiten].pin=hardware[i].pin;
              schaltzeiten[anzahlSchaltzeiten].zeit=hardware[i].vorlaufzeit+hardware[i].dauer;
              schaltzeiten[anzahlSchaltzeiten].geschaltet=false;
              anzahlSchaltzeiten++;
            }
          }
            
            sortSchaltzeiten(anzahlSchaltzeiten);
            starttime=micros();
            for (int i=0;i<anzahlSchaltzeiten;i++)
            {
              while ((looptime=micros()-starttime)<schaltzeiten[i].zeit);
              digitalWrite(schaltzeiten[i].pin,schaltzeiten[i].geschaltet);
            }
        }
     else if (digitalRead(startPin)== LOW) {Lauf = 0; delay(10);}
  }

ARG! Sorry, das war mein Fehler. Keine Ahnung wieso ich da nochmal eine Klammer gesetzt habe. Sollte so sein:

if (strcmp_P(text, PSTR("get_name"))==0)

Bei den String Funktionen hängt man allgemein an den Namen ein _P und setzt ein PSTR() um die Konstante.

Das musst du dann auch noch analog auf die anderen Verwendungen von strcmp() und strncmp() anwenden!! Die eine Zeile war nur zur Demonstration. An den anderen Stellen geht es genauso.

ah ok,

habe es jetzt verändert :slight_smile: und habe einen Freien Speicher von 319

das ist der Aktuelle Code:

// *****************************************************************
// *****************************************************************
// *****************************************************************

// Befehl         Ausgabe 

// get_name      = Es antwortet mit seinem Namen
// get_firmware  = Es Antwortet mit der Versionsnummer 
// configure     = Format: configure,pin,vorlaufzeit,dauer
// print_config  = Es antwortet mit einer Tabelle aller Hardware Zeiten 
// *print_steps* = Es antwortet mit einer Tabelle aller Schaltzeiten 
// reset         = Es setzt alle Hardware Schaltzeiten wider auf 0 zurück 

//   * nicht inplementirt

// *****************************************************************
// *****************************************************************
// *****************************************************************



        #define ZEILENTRENNZEICHEN 10
    int startPin           = A4;
   char Firmware_Nr[]      = "2.0-MG";
   char Name[]             = "Tropfen Box";
    int Baudrate           = 9600;
    int Lauf               = 0;
    int Zeile              = 4;
    
    
    struct hardware_t{int pin;long vorlaufzeit; long dauer;};              // Struktur einer einzelnen Schaltzeit
    struct schaltzeit_t{int pin;long zeit; boolean geschaltet;};           // Struktur einer einzelnen Schaltzeit

    hardware_t hardware[60]=
{                                              // Vorlaufzeit und Dauer für die Hardware
//  {2, 0000,     500000},              // Musterdaten
//  {3, 500000,   500000},              // Musterdaten
//  {4, 1000000,  500000},              // Musterdaten
//  {5, 1500000,  500000},              // Musterdaten
//  {6, 0,        2000000},             // Musterdaten
};

    #define schritte sizeof(hardware)/sizeof(hardware[0])


    schaltzeit_t schaltzeiten[2*schritte];
    int anzahlSchaltzeiten;
    long geschalteteZeit[2*schritte];
    void sortSchaltzeiten(int n) 
    {
      schaltzeit_t temp;
      for(int x=0; x<n; x++) 
      {
        for(int y=0; y<n-1; y++) 
        {
          if (schaltzeiten[y].zeit>schaltzeiten[y+1].zeit) 
          {
            temp=schaltzeiten[y+1];
            schaltzeiten[y+1]=schaltzeiten[y];
            schaltzeiten[y]=temp;
          }
        }
      }
    }


    // Funktion - Serielle Schnittstelle auslesen -
      char* receiveBuffer() {
      static char lineBuffer[25];
      static byte counter=0;
      char c;
      if (Serial.available()==0) return NULL;
      if (counter==0) memset(lineBuffer,0,sizeof(lineBuffer));
      c=Serial.read();
      if (c==ZEILENTRENNZEICHEN){
      counter=0;
      return lineBuffer; }
      else if (c>=32) {
      lineBuffer[counter]=c;
      if (counter<sizeof(lineBuffer)-2) counter++; }
      return NULL; }
    // Funktion - Serielle Schnittstelle auslesen -


int freeRam () 
{
  extern int __heap_start, *__brkval; 
  int v; 
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 
}




void setup() 
  {
    pinMode(startPin, INPUT);
    Serial.begin(Baudrate);
  }  

void loop() {  
  unsigned long starttime;
  unsigned long looptime;


   char* text=receiveBuffer();
     if(text != NULL)
        {

                if (strcmp_P(text, PSTR("get_name"))==0)      {Serial.print(F("OK,")); Serial.println(Name); Serial.println(F("\n"));}
           else if (strcmp_P(text, PSTR("get_firmware"))==0)   {Serial.print(F("OK,")); Serial.println(Firmware_Nr); Serial.println(F("\n"));}
           else if (strcmp_P(text, PSTR("reset"))==0)          {memset(hardware, 0, sizeof(hardware)); Zeile = -1; Serial.println(F("OK\n"));}
           
           else if (strcmp_P(text, PSTR("free"))==0)
             {
                Serial.print(F("Free RAM: "));
                Serial.println(freeRam());             
             }
           else if (strcmp_P(text, PSTR("print_config"))==0)
             {
                  Serial.print(F("Zeile"));
                  Serial.print(F("\t"));
                  Serial.print(F("PIN"));
                  Serial.print(F("\t"));
                  Serial.print(F("Start"));
                  Serial.print(F("\t"));
                  Serial.println(F("Dauer"));
               for (int i=0;i<schritte;i++) 
                { 
                  Serial.print(i);
                  Serial.print(F("\t"));
                  Serial.print(hardware[i].pin);
                  Serial.print(F("\t"));
                  Serial.print(hardware[i].vorlaufzeit/1000);
                  Serial.print(F("\t"));
                  Serial.println(hardware[i].dauer/1000);
                }
             Serial.print(F("OK")); 
             } // Print
           else if (strncmp(text, "configure",9)==0)
             {
                   text = text + strlen_P(PSTR("configure")) + 1;

                   int pin;
                    strtok(text, ",");
                     if(text[0] == 'A')
                      {
                        #if defined (__AVR_ATmega328P__)    
                          pin = atoi(text + 1) + 14;  // Arduino UNO
                        #elif defined (__AVR_ATmega2560__)
                          pin = atoi(text + 1) + 54;  // Arduino Mega
                        #endif
                     }
                      else
                       {
                         pin = atoi(text);
                       }

                   int vorlaufzeit = atoi(strtok(NULL, ","));
                   int dauer       = atoi(strtok(NULL, ","));
                       Zeile       = Zeile + 1;
      
                if (Zeile > -1 && Zeile < 11)   // Hier muss noch die Neue Pin abfrage hinein
                  {   
                    hardware[Zeile].pin         = pin;
                    hardware[Zeile].vorlaufzeit = vorlaufzeit;
                    hardware[Zeile].dauer       = dauer;
      
                    hardware[Zeile].vorlaufzeit*=1000;
                    hardware[Zeile].dauer*=1000;
 
 // ***************** muss wider auskommentirt werden  *****************     
                     // Serial.print(pin); Serial.print(",");                          // muss wider raus genommen werden
                     // Serial.print(vorlaufzeit); Serial.print(",");                  // muss wider raus genommen werden 
                     // Serial.println(dauer);                                         // muss wider raus genommen werden 
 // ***************** muss wider auskommentirt werden  *****************   
                   Serial.println(F("OK\n"));  
                 }
                 else 
                   { Serial.print(F("Pin"));
                     Serial.print(F("\t"));
                     Serial.println(F("Zeile"));
                   
                   
                     Serial.print(pin);
                     Serial.print(F("\t"));
                     Serial.print(Zeile);
                     Serial.print(F("\t"));
                     Serial.println(F("Fehler: Werte komnten nicht eingetragen werden.\n")); }
             } // Config                                 
          else { Serial.println(F("NOK, Unknown command:\n"));}
          
         } // if(text != NULL)
  
     if(digitalRead(startPin)== HIGH && Lauf == 0)
        {
          Lauf = 1;
          anzahlSchaltzeiten=0;
          for (int i=0;i<schritte;i++)
          {
            pinMode(hardware[i].pin,OUTPUT);
            if (hardware[i].dauer>0)
            {
              schaltzeiten[anzahlSchaltzeiten].pin=hardware[i].pin;
              schaltzeiten[anzahlSchaltzeiten].zeit=hardware[i].vorlaufzeit;
              schaltzeiten[anzahlSchaltzeiten].geschaltet=true;
              anzahlSchaltzeiten++;
              schaltzeiten[anzahlSchaltzeiten].pin=hardware[i].pin;
              schaltzeiten[anzahlSchaltzeiten].zeit=hardware[i].vorlaufzeit+hardware[i].dauer;
              schaltzeiten[anzahlSchaltzeiten].geschaltet=false;
              anzahlSchaltzeiten++;
            }
          }
            
            sortSchaltzeiten(anzahlSchaltzeiten);
            starttime=micros();
            for (int i=0;i<anzahlSchaltzeiten;i++)
            {
              while ((looptime=micros()-starttime)<schaltzeiten[i].zeit);
              digitalWrite(schaltzeiten[i].pin,schaltzeiten[i].geschaltet);
            }
        }
     else if (digitalRead(startPin)== LOW) {Lauf = 0; delay(10);}
  }

ich kann mein EDIT nicht einfügen da der Beitrag dann wider zu lang ist.
Wäre echt gut wenn das Forum sagt wie viele Zeichen ich über der max. Länge bin dann könnte man vielleicht etwas Optimieren.
naja egal.

EDIT: habe jetzt die Datei "Funktion.h" hinein gemacht in der ich die Funktion ausgelagert habe,

  • Serielle Schnittstelle auslesen
  • Schaltzeiten Sortieren
  • Freien Speicher auf dem Bord auslesen
    das sind doch alle? hoffe ich. :*

wie kann ich denn jetzt für die Übersicht her bei den Befehlen

                if (strcmp_P(text, PSTR("get_name"))==0)      { Serial.print(F("OK,")); Serial.println(Name); Serial.print(F("\n"));  }

den Teil in den geschweiften klammern an einen andere Stelle Sätzen?

z.B. so

if (strcmp_P(text, PSTR("get_name"))==0) { Befehl_get_name; }

Befehl_get_name:
 { Serial.print(F("OK,")); Serial.println(Name); Serial.print(F("\n")); }

so wie GoTo, der überstrichshalber

so wie GoTo, der überstrichshalber

Du machst dich unbeliebt, wenn du GoTo sagst. Was du meinst ist eine Funktion, kein GoTo.

                if (strcmp_P(text, PSTR("get_name"))==0)    printName(Name);


void printName(char* name)  
{ 
    Serial.print(F("OK,")); Serial.println(name); Serial.print(F("\n"));  
}

Wobei die Art, wie du den Namen ausgibst, schon recht speziell ist, so dass hierfür eine Funktion zu schreiben, es nicht wirklich übersichtlicher macht. Hast du vor, die Funktion printName mehrfach an vewrschiedenen Stellen zu verwenden ?

Wenn es nur drum geht, dass die eine Zeile zu lang ist, das ist kein Problem...

       if (strcmp_P(text, PSTR("get_name"))==0)  
       {
             Serial.print(F("OK,")); Serial.println(name); 
             Serial.write('\n'));  // noch eine Leerzeile    ( für einen Buschstaben lohnt das F-Makro nicht )
       }

Nachtrag:
Wenn ich mir die Mühe machen würde, den ganzen Code anzusehen ( Lob dafür, dass du den aktuellen Stand postest),
könnte ich sehen, dass

  • die Funktion printName zwei mal verwendet wird
  • sie nur Konstante Texte ausgibt, und du
#define Firmware_Nr      F("2.0-MG")
#define Name                    F("Tropfen Box")

schreiben könntest ( Wieder 18 Byte gespart )

void printName(const __FlashStringHelper* f)  
{ 
    Serial.print(F("OK,")); Serial.println(f); Serial.print(F("\n"));  
}
 
void loop() {
 ...
                if (strcmp_P(text, PSTR("get_name"))==0)     printName (Name);
           else if (strcmp_P(text, PSTR("get_firmware"))==0) printName (Firmware_Nr);
...

}

Falls es KompilierFehler hat, ist die Idee wenigstens verständlich ?

ich wollte auch nicht unbedingt GoTo verwenden, denn wie du schon richtig erkannt hast muss ich ja wider an die Stelle die ich vorher verlassen habe wider zurück kehren.

ich möchte die Funktion nicht öfter aufrufen sondern möchte die Abfrage der befehle Übersichtlicher haben.

z.B.s.

jetzt:

     if (strcmp_P(text, PSTR("get_name"))==0)      { Serial.print(F("OK,")); Serial.println(Name); Serial.print(F("\n"));  }
else if (strcmp_P(text, PSTR("get_firmware"))==0)  { Serial.print(F("OK,")); Serial.println(Firmware_Nr); Serial.print(F("\n")); }
else if (strcmp_P(text, PSTR("reset"))==0)         { memset(hardware, 0, sizeof(hardware)); Zeile = -1; Serial.print(F("OK\n")); }
else if (strcmp_P(text, PSTR("free"))==0)          { Serial.print(F("Free RAM: ")); Serial.println(freeRam()); }
else if (strcmp_P(text, PSTR("print_config"))==0)
        {
          ..... 18 Zeilen ....
        }
else if (strncmp(text, "configure",9)==0)
        {
          ..... 47 Zeilen ....
        }

so wäre schön:

     if (strcmp_P(text, PSTR("get_name"))==0)      { Befehl_get_name(Name); }
else if (strcmp_P(text, PSTR("get_firmware"))==0)  { Befehl_get_Firmware(); }
else if (strcmp_P(text, PSTR("reset"))==0)         { Befehl_reset(); }
else if (strcmp_P(text, PSTR("free"))==0)          { Befehl_free(); }
else if (strcmp_P(text, PSTR("print_config"))==0)  { Befehl_config(); }
else if (strncmp(text, "configure",9)==0)          { Befehl_configure(); }

oder so ähnlich,
denn dann wäre der teil in dem die Befehle ausgewertet werden sauber und man kann dann der Funktion oder dem "geheZU" :wink: folgen.