Solved // Falscher Wert in Variable - Arduino reist in die Zukunft

Hallo zusammen!

Ich habe mich nun an ein neues Projekt (für einen Bekannten) gewagt: Eine Datenübertragungseinheit für einen Datalogger. Diese Einheit soll praktisch die Messwerte vom Datalogger über seine serielle Schnittstelle auslesen, danach aufbereiten und via Ethernet auf seinen Webserver (in eine MySQL-Datenbank) übertragen.

Am Mega ist eine DS1307 RTC am I²C-Bus, eine MAX232 Ladungspumpe an Serial1 (Pin 18 & 19) und ein Ethernet-Shield am SPI-Bus angeschlossen. Nun habe ich mal alles so programmiert, wie er sich es gewünscht hat. Das Programm läuft auch ganz zuverlässig.

Nun benötige ich für die Datenabfrage um 24:00 Uhr das gestrige Datum (deshalb auch der Thread "Datum von gestern ohne Library berechnen"). Mir kam jetzt aber die Idee, dass ich es gar nicht berechnen muss, sondern mir einfach um 23 Uhr merken kann. Genau da ist das Problem. Der gestrige Tag und Monat stimmen, aber das Jahr nicht. Als Jahr steht im Befehl nachher 3342 - keine Ahnung warum. Nach dem Senden des Befehls macht der Arduino auch noch einen Reset!?

Das ist die debugging Ausgabe:
(STX)PD(ETX)
Jahr gestern: 14
(XON)
(STX)DS030833422400(ETX)
3342
(STX)DE030833422400(ETX)
-- RESET --

Ich kann mir das komische Verhalten jetzt überhaupt nicht erklären. Beim Speichern im Array yesterday stimmt die Jahreszahl noch. Danach nicht mehr. Tag und Monat stimmen immer überein! Warum funktioniert das so nicht bzw. was ist an meinem Code falsch?

Hier mein Code (gekürzt):

#include <Wire.h>
#include <avr/pgmspace.h>

int Second, Minute, Hour, Day, Month, Year;
int yesterday[3];
int clock[3];
char msg[15];

void setup(){
  Wire.begin();
  Serial.begin(9600);
  Serial1.begin(9600);
  setClock(0);
  setClock(1);
}

void loop(){
  readClock();
  if (Minute % 10 == 0 && Second >= 35 && running == false) sendCommand(0);    // Funktion aufrufen, um Befehl fuer Mittelwerte zu senden
  if (running == true && Minute % 10 == 1) running = false;                   // Variable zuruecksetzen - 15 Sekunden nach Schicken des Befehls. Keine Auswirkung auf das Lesen!
  if (Minute == 3 && running == false) sendCommand(1);                         // Funktion aufrufen, um Befehl fuer Extremwerte zu senden
  if (running == true && Minute == 4) running = false;                        // Variable zuruecksetzen - 60 Sekunden nach Schicken des Befehls. Keine Auswirkung auf das Lesen!
  readString();                                                                // Funktion aufrufen, um Zeichen von Schnittstelle zu speichern
}

// read the rtc clock
void readClock(){
  // ...
}

// set the rtc clock
void setClock(int type) {
 // ...
}

// send command to datalogger
void sendCommand(int type){
  if (Hour == 23 && Minute < 51){ // Datum von gestern speichern -> Logger arbeitet mit 24:00 Uhr
    yesterday[2] = Year;
    Serial.println();
    Serial.print(F("Jahr gestern: "));
    Serial.println(yesterday[2]);
    yesterday[1] = Month;
    yesterday[0] = Day;
  }

  if (type == 0){
    Serial1.write(11);
    Serial.write(11); // DEBUGGING
    delay(4000);
    if (Hour == 0 && Minute < 10) sprintf(msg,"%cDS%02d%02d%02d2400%c", 2, yesterday[0], yesterday[1], yesterday[2], 3); else sprintf(msg,"%cDS%02d%02d%02d%02d%02d%c", 2, Day, Month, Year, Hour, Minute, 3);
  } else {
    if (Hour == 0) sprintf(msg,"%cDE%02d%02d%02d2400%c", 2, yesterday[0], yesterday[1], yesterday[2], 3); else sprintf(msg,"%cDE%02d%02d%02d%02d00%c", 2, Day, Month, Year, Hour, 3);
  }
  Serial1.print(msg);
  Serial.print(msg); // DEBUGGING
  Serial.println(yesterday[2]);
  running = true;
}

// receive data from datalogger
void readString(){
  // ...
}

Gruß

Hallo,

mach mal testweise Dein Array char msg[15] ein paar Byte größer. Ich vermute, Du schreibst hier mehr Zeichen rein, als das Array aufnehmen kann.

Gruß,
Ralf

Schachmann:
[...] mach mal testweise Dein Array char msg[15] ein paar Byte größer. Ich vermute, Du schreibst hier mehr Zeichen rein, als das Array aufnehmen kann. [...]

Ja, sobald die Jahreszahl nicht mehr stimmt schreibe ich 2 Zeichen zu viel ins Array. Wenn die Jahreszahl aber richtig ist, stimmt auch die Größe vom Array msg: (STX)DS0308141210(ETX) + /0 sind genau 15 Zeichen.

Ist zwar nicht die Lösung hier, aber mal zwei allgemeine Tips zu sprintf():

Du machst es im Moment so:

sprintf(msg,"%cDE%02d%02d%02d%02d00%c", 2, Day, Month, Year, Hour, 3);

Besser:

snprintf_P(msg, sizeof(msg), PSTR("%cDE%02d%02d%02d%02d00%c"), 2, Day, Month, Year, Hour, 3);

Das behebt zwei Probleme:
1.) durch die n Version schreibt man nicht über die Array Grenzen hinaus und hat garantiert einen Null-terminierten String. Ist natürlich im Fehlerfall dann hinten nicht korrekt.
2.) durch die _P Version und das PSTR() Makro bleibt der Format String im Flash und belegt kein RAM. Ähnlich wie das Arduino F() Makro bei print()

Statt Arrays, sind structs eine sehr schöne Sache um Daten zu speichern:

struct Date
{
    byte day;
    byte month;
    unsigned int year;
}
Date yesterday;

Dann:

yesterday.day = ...;
yesterday.month = ...;

Dadurch hat man ansprechendere Namen als Array Indizes

Hi Serenifly,

danke für den Tipp! Habe es im Programm schon abgeändert.
Stimmt, structs gibt's ja auch noch. :slight_smile: Einen Test mit einem struct konnten wir noch nicht durchführen.
Das werden wir dann heute noch machen.

Eine andere Lösung habe ich jetzt dennoch. Ich generiere die beiden Befehle bei der Datenabfrage um 23:50 Uhr und kopiere sie mit strcpy() dann ins Array msg[]. So richtig gefällt mir das nicht, aber warum einfach wenn's auch kompliziert geht.

Hi,

Serenifly, Du hast mal wieder genau die Lösung! :slight_smile: Ich habe jetzt ein struct angelegt, indem Tag, Monat und die Jahreszahl gespeichert werden. Heute Nacht konnte sich das Programm beweisen... Siehe da, die Jahreszahl von gestern wird perfekt übernommen und nicht irgendwie überschrieben/ enthält einen falschen Wert.
Wobei in dem Code von Serenifly ein ";" am Ende von der Zuweisung des structs fehlt.

Gruß

-Jan-:
Wobei in dem Code von Serenifly ein ";" am Ende von der Zuweisung des structs fehlt.

Schande über mich :frowning:

Es sei den man macht Murks mit den Array Indizes, ist mir aber nicht so klar wieso das das Problem löst. Ist einfach nur eine andere Art die Daten zu speichern und darzustellen.