Hardware Schaltzeiten stimmen nicht

Hallo miteinander,

ich habe ja eine TropfenBox (TaT Bilder) als Projekt seit geraumer zeit,
dank dem Forum hier bin ich auch schon sehr weit gekommen, danke dafür.

Jedoch ist mir in der Firmware ein Fehler aufgefallen bei dem ich nicht weiter komme:-(

wenn ich die Konfiguration: (als Start Config hinterlegt) auf dem Bord habe.
Configure,23,0,500
Configure,25,500,500
Configure,27,1000,500
Configure,29,1500,500
Configure,31,0, 2000

Dann sollte eigentlich meine Digitalen Pins nach einander angehen bis auf Pin Nr. 31 der sollte von Anfang bis Ende an sein.
Jedoch ist das nicht der Fall :frowning: die LED`s laufen euch und Pin Nr. 31 wird ignoriert :frowning:

an was kann das Ligen?

Kurze Beschreibung der Firmware:
Man kann Schaltzeiten für die Pin`s auf dem Arduino hinterlegen mit Startzeitpunkt und Dauer wie lange so ein Pin anessen soll.
wenn man Seine Daten hinterlegt hat kann man die gespeicherte Konfiguration der Pins Starten in dem man einen Taster Drückt der sich an Pin 2 befindet.

Befehle die das Bord mit der Firmware kennt.
// 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
// reset = Es setzt alle Hardware Schaltzeiten wider auf 0 zurück

Das ist die 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 13
    int startPin           = 2;
   char Firmware_Nr[]      = "1.2.0.1";
   char Name[]             = "Tropfen Box";
    int Baudrate           = 9600;
    int Lauf               = 0;
    int Zeile              = 5;
    
    
    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[10]=
{                                              // Vorlaufzeit und Dauer für die Hardware
  {23, 0000,     500000},
  {25, 500000,   500000},
  {27, 1000000,  500000},
  {29, 1500000,  500000},
  {31, 0,        2000000},
};

    #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.println(Name);}
           else if (strcmp(text,"get_firmware")==0)   {Serial.println(Firmware_Nr);}
           else if (strcmp(text,"reset")==0)          {memset(hardware, 0, sizeof(hardware)); Zeile = -1; Serial.println("Ok");}
           else if (strcmp(text,"print_config")==0)
             {
               for (int i=0;i<schritte;i++) 
                { 
                  Serial.print(hardware[i].pin);
                  Serial.print("\t");
                  Serial.print(hardware[i].vorlaufzeit/1000);
                  Serial.print("\t");
                  Serial.println(hardware[i].dauer/1000);
                }
             } // Print
           else if (strncmp(text,"configure",9)==0)
             {
                   text = text + strlen_P(PSTR("configure")) ;
                   int pin         = atoi(strtok(text, ","));
                   int vorlaufzeit = atoi(strtok(NULL, ","));
                   int dauer       = atoi(strtok(NULL, ","));
                       Zeile       = Zeile + 1;
      
                if (pin > startPin && pin < 54 && Zeile > -1 && Zeile < 11) 
                  {   
                    hardware[Zeile].pin         = pin;
                    hardware[Zeile].vorlaufzeit = vorlaufzeit;
                    hardware[Zeile].dauer       = dauer;
      
                    hardware[Zeile].vorlaufzeit*=1000;
                    hardware[Zeile].dauer*=1000;
      
                    // Serial.print(pin); Serial.print(",");
                    // Serial.print(vorlaufzeit); Serial.print(",");
                    // Serial.println(dauer);
                   Serial.println("Ok");  
                 }
                 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."); }
             } // Config                                 
          else { Serial.println("Fehler: Befehl nicht bekannt"); }
          
         } // 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++;
            }
          }
            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;}
  }
for (int i=0;i<anzahlSchaltzeiten;i++)
{
    while ((looptime=micros()-starttime)<schaltzeiten[i].zeit);
    digitalWrite(schaltzeiten[i].pin,schaltzeiten[i].geschaltet);
}

Ist der Strichpunkt hinter dem while Absicht? Der sorgt nämlich dafür dass da solange die Bedinung wahr ist nichts gemacht wird. Danach wird einmal kurz digitalWrite() gemacht.

Vielleicht meinst du eher das:

for (int i=0;i<anzahlSchaltzeiten;i++)
{
    while ((looptime=micros()-starttime)<schaltzeiten[i].zeit)
         digitalWrite(schaltzeiten[i].pin,schaltzeiten[i].geschaltet);
}

Neben dem Einrücken wird das auch deutlicher wenn man nochmal einen Block in {} setzt

Noch ne Kleinigkeit. Deine Plausibilitätsüberprüfung stimmt nicht ganz:

if (pin > startPin && pin < 54 && Zeile > -1 && Zeile < 11)

Du hast ein Array der Größe 10. Die Indizes gehen als nur von 0 bis 9. Du solltest die “11” durch “schritte - 1” ersetzen

Muecke: an was kann das Ligen?

Die Schaltzeiten im schaltzeiten-Array werden von Dir nicht sortiert, bevor Du mit dem Schaltdurchlauf beginnst.

Nur wenn das schaltzeiten-Array in sortierter Form vorliegt, kannst Du die Schaltzeiten chronologisch in einer Schleife von vorne nach hinten erfolgreich abarbeiten.

Meine Sortierfunktion dafür ist offenbar in dem Sketch immer noch drin, aber im Gegensatz zu meinem Demo-Code wird die Sortierfunktion in dem modifizierten Sketch nicht mehr aufgerufen.

@Plausibilitätsüberprüfung: oh ja, da ist was durcheinander gekommen, ... :-( stimmt.

@jurs: oh das hört sich plausibel an, das ist wahrscheinlich passiert da ich zwei Codes zusammen gefügt habe, (Befehle erhalten und Das Schalten), wenn ich jetzt nur wüste was der Teil mit dem Sortieren wäre ... muss ehrlich gestehen das ich in dem Code recht wenig verstehe :-(.

Mhh, wenn ich mir noch mal überlege was ich oben geschrieben habe, merke ich eigentlich, dass das keinen Unterschied macht. Kommt in diesem Fall auf das Gleiche raus.

Da würde es auch helfen wenn ich den Teil des Codes genau verstehen würde :stuck_out_tongue: :slight_smile:

Muecke: wenn ich jetzt nur wüste was der Teil mit dem Sortieren wäre ... muss ehrlich gestehen das ich in dem Code recht wenig verstehe

Das Demoprogramm hatte ich Dir hier gepostet: http://forum.arduino.cc/index.php?topic=223038.msg1636451#msg1636451

Der Aufruf zum Sortieren des schaltzeiten-Arrays lautet:

 sortSchaltzeiten(anzahlSchaltzeiten);

In meinem Demoprogramm war der Aufruf im "setup" enthalten. Da sich die Zeiten innerhalb des laufenden Programms nicht ändern konnten, reichte ein einmaliges Sortieren beim Programmstart.

Mit Deiner flexiblen Bearbeitung der Schaltzeiten im Programm muss das Array mindestens dann sortiert werden, wenn es Änderungen bei den Schaltzeiten gegeben hat. Aber im Zweifelsfall sortierst Du einfach jedesmal vor dem Abarbeiten der Schaltfolge, unmittelbar bevor die Startzeit in Microsekunden festgelegt wird. Also vor der Festlegung von "starttime" einfügen:

  sortSchaltzeiten(anzahlSchaltzeiten);
  starttime=micros();

@jurs Danke genau das war es, perfekt

da ich festgestellt habe da an meinem Projekt ein Reges Interesse ist Stelle ich hier die Firmware noch mal vollständig zu Verfügung. und möchte so auch meinen Dank an euch alle ausdrücken ohne euch hätte ich das nie hin bekommen. Danke.

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

// 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 13
    int startPin           = 2;
   char Firmware_Nr[]      = "1.2.0.1";
   char Name[]             = "Tropfen Box";
    int Baudrate           = 9600;
    int Lauf               = 0;
    int Zeile              = 5;
    
    
    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[10]=
{                                              // Vorlaufzeit und Dauer für die Hardware
  {23, 0000,     500000},
  {25, 500000,   500000},
  {27, 1000000,  500000},
  {29, 1500000,  500000},
  {31, 0,        2000000},
};

    #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.println(Name);}
           else if (strcmp(text,"get_firmware")==0)   {Serial.println(Firmware_Nr);}
           else if (strcmp(text,"reset")==0)          {memset(hardware, 0, sizeof(hardware)); Zeile = -1; Serial.println("Ok");}
           else if (strcmp(text,"print_config")==0)
             {
               for (int i=0;i<schritte;i++) 
                { 
                  Serial.print(hardware[i].pin);
                  Serial.print("\t");
                  Serial.print(hardware[i].vorlaufzeit/1000);
                  Serial.print("\t");
                  Serial.println(hardware[i].dauer/1000);
                }
             } // Print
           else if (strncmp(text,"configure",9)==0)
             {
                   text = text + strlen_P(PSTR("configure")) ;
                   int pin         = atoi(strtok(text, ","));
                   int vorlaufzeit = atoi(strtok(NULL, ","));
                   int dauer       = atoi(strtok(NULL, ","));
                       Zeile       = Zeile + 1;
      
                if (pin > startPin && pin < 54 && Zeile > -1 && Zeile < 11) 
                  {   
                    hardware[Zeile].pin         = pin;
                    hardware[Zeile].vorlaufzeit = vorlaufzeit;
                    hardware[Zeile].dauer       = dauer;
      
                    hardware[Zeile].vorlaufzeit*=1000;
                    hardware[Zeile].dauer*=1000;
      
                    // Serial.print(pin); Serial.print(",");
                    // Serial.print(vorlaufzeit); Serial.print(",");
                    // Serial.println(dauer);
                   Serial.println("Ok");  
                 }
                 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."); }
             } // Config                                 
          else { Serial.println("Fehler: Befehl nicht bekannt"); }
          
         } // 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;}
  }

ps. die Schaltung für das ganze teil mit Platinen Layout ist hier zu finden.

hallo Miteinander,

vielleicht kann mir jemand von euch helfen.

die Firmware nimmt Config Daten über die Serielle Schnittelle entgegen und verarbeitet die dann. Dabei werden auch PIN Nr. übergeben, jetzt ist es so das ich nicht nur die Digitalen Pin Nr. durchgeben möchte sondern auch die Analogen.

ja die Analogen Pin nr. kann auch Hochgezählt werden nach der Letzten Digitalen Pin Nr. einfach weiter zählen. Würde jedoch gerne die Pin Nr. A0 weiter geben können über die Serielle Schnittelle jedoch wird so was immer als PIN 0 anerkannt :-(

was kann man da machen?

Den Parser umschreiben:

int length = strlen_P(PSTR("configure"));
if (strncmp_P(text, PSTR("configure"), length) == 0)
{
    text = text + length;
    strtok(text, ",")

    int pin = 0;
    if(text[0] == 'A') 
      pin = atoi(text + 1) + 54;
    else
      pin = atoi(text);

    int vorlaufzeit = atoi(strtok(NULL, ","));
    int dauer = atoi(strtok(NULL, ","));
    Zeile = Zeile + 1;
}

Nur in Visual C++ getestet

Du musst halt einfach abfragen ob das Token mit 'A' anfängt. Dann macht atoi() ab +1 und addiert 54 drauf (beim Mega. Beim UNO wären es 14). So dass 0 + 54 = 54

Cool danke, das muss ich mal testen.

es gibt aber keinen Befehl das der Arduino selber die zahl 54 bzw. 14 kennt? ich muss die Firmware dann also immer anpassen von Mega zu Uno? habe gehofft das es da was gibt das es automatisch umgeschlüsselt.

Wenn du statt A0 14/54 schreiben willst, kannst du das ja einfach so eingegeben. Das sollte auch so gehen. Du hast es aber so geschrieben, dass du A0, A1, etc. verarbeiten willst. Vielleicht habe ich das auch nur falsch verstanden.

Um die Prozessoren zu unterscheiden gibt es den Prä-Prozessor. Geht ganz einfach:

  int pin = 0;
  if(text[0] == 'A') 
#if defined (__AVR_ATmega328P__)
    pin = atoi(text + 1) + 14;
#elif defined (__AVR_ATmega2560__)
    pin = atoi(text + 1) + 54;
#endif
  else
    pin = atoi(text);

Das wird dann noch vor dem Kompilieren ausgewertet und je nach eingestelltem Board wird was anderes übersetzt. Wenn sowas nicht ginge würden bräuchte man ja bei allen Libraries unterschiedliche Versionen für jeden Prozessor

Vielleicht hast du hiermit ein Problem:

if (pin > startPin && pin < 54 && Zeile > -1 && Zeile < 11)

Da fragst du ab ob der Pin < 54 ist. Und wenn ja wird nichts gemacht. Das muss natürlich auch angepasst werden. Und am besten auch in zwei Versionen wie oben wenn das auch auf einem UNO laufen soll.

richtig würde gerne A0 eingeben können oder A4.

das mit der abfrage welcher AVR_ATmega328P es ist finde ich gut. das werde ich mal einbauen. Danke

ich habe jetzt ein Update vorgenommen, doch jetzt habe ich ein neues Problem das ich mir nicht erklären kann.
finde den Fehler nicht :frowning:

wenn ich nun über den Befehl “configure, …” den PIN A1 übergebe dann rechnet er richtig und meine Vorlauf zeit etc. werden richtig übernommen.

Wenn ich einen PIN Digitalen PIN also ohne A übergebe dann wird der Richtige PIN erkannt und ausgegeben jedoch ist meine Vorlaufzeit und Dauer immer bei 0 warum das denn?

ich verstehe nicht was da schief geht.
kann mir jemand helfen?

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

// 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 13
    int startPin           = A4;
   char Firmware_Nr[]      = "1.2.0.1";
   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[10]=
{                                              // Vorlaufzeit und Dauer für die Hardware
  {2, 0000,     500000},
  {3, 500000,   500000},
  {4, 1000000,  500000},
  {5, 1500000,  500000},
  {6, 0,        2000000},
};

    #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.println(Name);}
           else if (strcmp(text,"get_firmware")==0)   {Serial.println(Firmware_Nr);}
           else if (strcmp(text,"reset")==0)          {memset(hardware, 0, sizeof(hardware)); Zeile = -1; Serial.println("Ok");}
           else if (strcmp(text,"print_config")==0)
             {
               for (int i=0;i<schritte;i++) 
                { 
                  Serial.print(hardware[i].pin);
                  Serial.print("\t");
                  Serial.print(hardware[i].vorlaufzeit/1000);
                  Serial.print("\t");
                  Serial.println(hardware[i].dauer/1000);
                }
             } // Print
           else if (strncmp(text,"configure",9)==0)
             {
                   text = text + strlen_P(PSTR("configure")) ;

                   int pin;
                    strtok(text, ",");
                     if(text[1] == 'A')
                      {
                        #if defined (__AVR_ATmega328P__)    
                          pin = atoi(text + 2) + 14;  // Arduino UNO
                        #elif defined (__AVR_ATmega2560__)
                          pin = atoi(text + 2) + 54;  // Arduino Mega
                        #endif
                     }
                      else
                       {
                         pin = atoi(strtok(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");  
                 }
                 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."); }
             } // Config                                 
          else { Serial.println("Fehler: Befehl nicht bekannt"); }
          
         } // 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);}
  }

was ich als Update eingefügt habe:

  1. Start Pin
    → ist jetzt FIX auf “A4”
  2. Taster entprellt
    → Puffer damit das Programm nicht versehentlich beim loslassen der taste aktivirt wird.
  3. Test Hadware
    → Schaltzeiten bzw. Pins angepasst
  4. Zeile Nr. angepasst
    → Hat sich ein Fehler eingeschlichen muss 4 nicht 5 sein !
    ist abhängig von der Anzahl der Test Hardware Daten
  5. Analoge PIN Nr Erkennung
    → Serielle Schnittelle erkennt und rechnet richtig Analoge Pins um
  6. Analoge Pins umrechnen
    → Abhängig vom Bord erstellt unterschied UNO / MEGA

jetzt ist nur das Problem das wenn ich einen nicht analogen Pin übergebe meine

  • vorlaufzeit
  • dauer
    immer auf 0 gesetzt werden :frowning:
    das versteh ich nicht, arrrrr, … wie ich das hasse …
    kann mir da mal jemand drüber schauen und mir sagen was ich falsch gemacht habe.

Gruß

ARG! Da ist ein Fehler drin. Das hätte dir aber auch auffallen können
~~</strike> <strike>~~ else {   pin = atoi(strtok(text, ",")); }~~</strike> <strike>~~
Hier muss man NULL übergeben, statt text. strtok() wurde ja weiter oben schon initialisiert.
Dann nochwas das eventuell einen Fehler verursacht aber generell nicht schön ist. Den String den den du eingibst ist so:
> “configure,A1”
Also ein zusätzliches Komma dass ich nicht berücksichtigt habe. Dann mach es besser so:
~~</strike> <strike>~~text = text + strlen_P(PSTR("configure")) + 1 ;~~</strike> <strike>~~
Also hier den Text nicht auf das Komma zu setzen, sondern eins danach
Dann kannst du unten text[0] und atoi(text + 1) machen. Das ist logischer und beißt sich nicht mit dem strtok() das danach kommt! So findet strtok() gleich ein Komma am Anfang. Das ist wahrscheinlich auch nicht gut.

oh wie peinlich, du hast recht hier ist der Fehler gewesen in Zeile: 128

sie muss lauten:

                      else
                       {
                         pin = atoi(text + 1);
                       }

Danke, ich dachte ich werde noch verrückt.

so habe das von dir angedeutete noch mit umgesetzt.

Jetzt haben wir eine Neue Firmware :slight_smile:
Version: 2.0.0.0

was wurde gemacht:

  • Start Pin Anpassung
  • Taster entprellt
  • Test Hardware Anpassung
  • Zeile Nr. Anpassung
  • Analoge PIN Nr Erkennung
  • Analoge Pins umrechnen für die Bords UNO und MEGA

Es können nun über die Serielle Schnittelle auch Analoge Pins übergeben werden z.B. A1

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

// 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 13
    int startPin           = A4;
   char Firmware_Nr[]      = "2.0.0.0";
   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[10]=
{                                              // Vorlaufzeit und Dauer für die Hardware
  {2, 0000,     500000},
  {3, 500000,   500000},
  {4, 1000000,  500000},
  {5, 1500000,  500000},
  {6, 0,        2000000},
};

    #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.println(Name);}
           else if (strcmp(text,"get_firmware")==0)   {Serial.println(Firmware_Nr);}
           else if (strcmp(text,"reset")==0)          {memset(hardware, 0, sizeof(hardware)); Zeile = -1; Serial.println("Ok");}
           else if (strcmp(text,"print_config")==0)
             {
               for (int i=0;i<schritte;i++) 
                { 
                  Serial.print(hardware[i].pin);
                  Serial.print("\t");
                  Serial.print(hardware[i].vorlaufzeit/1000);
                  Serial.print("\t");
                  Serial.println(hardware[i].dauer/1000);
                }
             } // 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");  
                 }
                 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."); }
             } // Config                                 
          else { Serial.println("Fehler: Befehl nicht bekannt"); }
          
         } // 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);}
  }

Und ich hatte auch noch einen Fehler gemacht. strtok() durfte man da ja gar nicht machen. Oops. :~ Da hatte ich einfach deinen Code übernommen ohne darüber nachzudenken.

Wobei das bei dir noch kein Fehler war, da du strtok() einfach nochmal mit text aufgerufen hast. Das hat nichts geschadet. Meine Variante mit NULL wäre dagegen ein Fehler gewesen. :(

Jedenfalls ist es so besser. Das Komma durch die Indizes zu überlesen ist viel zu fehleranfällig, da du da an mehreren Stellen nachbessern musst. Statt dessen einfach den Anfangszeiger korrekt setzen und man hat diese Probleme nicht.

so geht es mir immer wider, ich über nehme etwas und dann klappt es nicht ;-)

wollte das nicht so drauf eingehen bei dir, da du mich an die Richtige Stelle gebracht hast und dann siehe an es klappt ;-) Also hat alles genau richtig funktioniert. Danke

ich habe eine Speicheroptimierung im Code vorgenommen, OK war ich nicht ganz alleine, danke Forum für die Unterstützung.

des weiteren habe ich,

... neue befehle eingeführt.

  1. free
  2. repetition
  3. break
  4. run

... habe Befehle verändert

  1. reset
  2. print_config

  1. free
  2. Senden "free"
  3. Antwort "Freier RAM Speicher"

  4. repetition

  5. Senden "repetition,3"

  6. Antwort "OK\n"

  7. Bemerkung: hier werden die Anzahl der Wiederholungen definiert (Stück)

  8. break

  9. Senden "break,10"

  10. Antwort "OK\n"

  11. Bemerkung: hier wird die Pause zwischen den Wiederholungen definiert Achtung in Sekunden !!!

  12. run

  13. Senden "run"

  14. Antwort "OK\n"

  15. Bemerkung: das Programm wird gestartet wie wenn man auf den Knopf gedrückt hätte, das OK wird erst gesendet wenn alle Wiederholungen abgeschlossen sind.

  16. reset

  17. Bemerkung: hier wird auch die Wiederholung und die Pause zurückgesetzt

  18. print_config

  19. Bemerkung: es wird nun auch die Wiederholung und die Pause zurück gegeben

das Schönste ist das ich jetzt wider 1.311 byte frei habe :cold_sweat: auf dem UNO und es hier zu keinen Problemen mehr kommen sollte. :blush:

den Code gibt es einen Beitrag weiter unten. der ist etwas lang geworden =( und hier darf man nicht so viel auf einmal rein stellen.

Code gehört zusammen aus #19 und #20

Achtung Code geht in #20 weiter !!!

Firmware_MG_3_0.ino

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

// 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 
// repetition    = Format: repetition,Widerholungen (wie offt die Schaltzeiten widerholt werden sollen) 
// break         = Format: break,Sekunden (wie lange zwischen der lätzen und der nächsten Widerholung Pause gemacht werden soll in Sekunden)

//   * nicht inplementirt

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

        #define ZEILENTRENNZEICHEN 10
        #define Firmware_Nr  F("MG 3.0")
        #define Name         F("Tropfen Box")
      int startPin           = A4;
      int Baudrate           = 9600;
      int Lauf               = 0;
      int Zeile              = -1;
      int W_break            = 0;
      int repetition         = 1;
const int MaxSchritte        = 20;
   
    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[MaxSchritte]=      // Musterdaten 
    {                             
     // {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])

#include "Funktion.h"
#include "Befehl.h"


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)        { Befehl_print(Name); }
           else if (strcmp_P(text, PSTR("get_firmware"))==0)    { Befehl_print(Firmware_Nr); }
           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("run"))==0)             { Befehl_run( starttime, looptime); }
           else if (strcmp_P(text, PSTR("print_config"))==0)    { Befehl_print_config(); }
           else if (strncmp_P(text, PSTR("configure"), 9)==0)   { Befehl_configure(text); }
           else if (strncmp_P(text, PSTR("repetition"), 10)==0) { Befehl_repetition(text); }
           else if (strncmp_P(text, PSTR("break"), 5)==0)       { Befehl_break(text); }
           else                                                 { Serial.print(F("NOK, Unknown command:\n"));}
         }

          if (digitalRead(startPin) == HIGH && Lauf == 0)     { Befehl_run(starttime, looptime); }
     else if (digitalRead(startPin) == LOW)                   { Lauf = 0; delay(10); }
  }