Arduino--Debug aus der Ferne

Hallo, mir wurde hier schon oft ganz toll geholfen, evtl. klappt es jetzt wieder.

Projekt: ein Arduino Mini mit Lan angeschlossen an einem UMTS Router, sendet regelmäßig Wetterdaten per “GET” an einen Webserver wo dann die entsprechende php Datei die Daten in eine DB einträgt. Alles Gut alles geht “irgendwie”.
Das “Ding” steht 25KM von mir entfernt auf einem Feld ohne Strom (ausser 12V Solar), daher wenn etwas nicht geht, hinfahren, ca. 1,5Std Zeit dann Laptop Akku leer und zurück == Nervt.
Bisher ging ja alles recht gut 1,5Jahre, jetzt spinnt das Teil, warum auch immer.

Zum Problem bzw. zur Frage, ich hab im Sketch einige Debug Sachen zur Fehleranalyse

Beispiel

#ifdef DEBUG    
    Serial.print("header: ");
    for (byte j = 5; j > 0; j--) {            
      if (header & (1 << (j - 1))) {
        Serial.print("1");
      } else {
        Serial.print("0");
      }
    }
    Serial.print("\tdir: ");
    for (byte j = 4; j > 0; j--) {           
      if (richtung & (1 << (j - 1))) {
        Serial.print("1");
      } else {
        Serial.print("0");
      }
    }
    Serial.print("\tDEC: ");
    Serial.print(richtung);
    Serial.print("\tspeed: ");
    for (byte j = 12; j > 0; j--) {           
      if (windspeed & (1 << (j - 1))) {
        Serial.print("1");
      } else {
        Serial.print("0");
      }
    }
    Serial.print("\tDEC: ");
    Serial.print(windspeed);
    Serial.print("  ");
    Serial.print(" m/s\tcheck: ");
    for (byte j = 4; j > 0; j--) {           
      if (checksum & (1 << (j - 1))) {
        Serial.print("1");
      } else {
        Serial.print("0");
      }
    }
    Serial.println();
#endif

könnte man jetzt nicht die ganzen “Inhalte” des serialprint irgendwie sammeln und auch an den Webserver senden, das dort dann in eine txt Datei schreiben?
Da könnte man bei Bedarf schon von zuhause debuggen…

Idee…bei jedem Durchlauf des Arduino die SerialPrints irgendwie sammeln, und dann per GET an den Webserver. Natürlich müsste das irgendwie auch leserlich Formatiert werden.

Oder 2. Idee…eine SD Karte einbauen, die Debugs darauf speichern? Kommt man von aussen dann an die SD Karte des Arduino? KLAR IP muss man wissen und Ports müssen frei sein…

Irgendwie hab ich gerade null Ansatz dazu…mir fehlen die Ideen.

Ich hoffe ihr könnt mir folgen und versteht was/wie ich das meine…

Grüße Heiko

hmmm...

Suche mal nach "Openlog Serial Data Logger" Vielleicht ist es ja das, was du suchst....

Vorsicht! Rx und Tx arbeiten mit 3,3V

kannst dir strommäßig einen zweiten Mini+LAN leisten? Wenn ja könntest die Serielle Ausgabe über diesen separat senden lassen. Evtl. noch über den Zweit-MINI ersteren resetbar machen.

P.S.: wegen der Laptop-Akkulaufzeit: es gäbe auch 12V Laptop-Netzteile ;-)

Man könnte auch einen ESP8266 per I2C anbinden und den die Meldungen schicken lassen.
Oder das Ganze gleich auf einen WMOS D1 mini pro laufen lassen. Da habe ich Ferndebugvarianten über WLAN hier und hier beschrieben.

Gruß Tommy

OK, Danke für die Vorschläge erstmal, 2. Mini + Lan würde aus Platzmangel schwer zu realisieren sein Wemos bzw. irgendwas mit WLAN geht nicht da kein Wlan vorhanden. Reset brauch ich eigentlich nicht, da intern ein "Fehlerzähler" läuft und wenn Fehler > XXX macht er eh Neustart.

merkwürdig, was ich aus der Ferne jetzt schon sehe, ich hab ja diesen "Fehlerzähler", der wird an 2 Stellen aufgerufen, könnte sich also im Fehlerfall maximal um 2 erhöhen pro Durchlauf, er erhöht sich aber teilweise um 7 ?????? Das ist ja schon sehr merkwürdig.

"werr" ist das um was es geht.....Auszug aus dem Sketch, die .......da ist nix was das Verhalten erklären könnte.

void loop()
{
    //Laufzeit des Boards   
    currentTime = millis();
    //Zeitfunktion aufrufen
    uptime(); 
    //Netzwerk
    
    
    if (secs==00) {                                 // Werte für Cam und Windsensor setzem
    windtimer=windtimer+1;                          // Werte für Cam und Windsensor setzem
    camtimer=camtimer+1;                            // Werte für Cam und Windsensor setzem
                              
       
       if (werr > 20) { wdt_enable(WDTO_2S);        // bei häufig Wind Error neustart
       delay (3000);
       }  
     }
//alle 1 minuten winddaten messen und versenden    
       if (windtimer==1){
        windtimer=0;
        Winddaten();
       }

}

void Winddaten()
   {
   ....
   ....
   ....
  whileTime = millis();
   
while(stat == HIGH){                       // wait for falling edge (sync to startbit)
      stat = digitalRead(senspin); 
      if (millis() > (whileTime) + 4000) {    // wenn nach xxx Zeit nix kommt, aufhören sonst steht ewig hier
        werr = werr + 1;                      // Error setzten
      break;                                  // raus hier
     } 
   }
  .....
  .....
  .....
  .....  
    
    //wenn sinnlose Werte empfangen........
    if ((header != 4) || (richtung > 15) || (windspeed > 500)) {
      werr = werr + 1;
      break;
    } else {
    ......
    ......
    ......
      }
  }
}

void uptime()
    {
    secs = currentTime/1000;   // convect milliseconds to seconds
    mins=secs/60;              // convert seconds to minutes
    hours=mins/60;             // convert minutes to hours
    secs=secs-(mins*60);       // subtract the coverted seconds to minutes in order to display 59 secs max
    mins=mins-(hours*60);      // subtract the coverted minutes to hours in order to display 59 minutes max
    }

Könnte es sein das er so schnell durch "Winddaten" durch rauscht das die 1 Sekunde noch nicht um ist, somit "secs" immernoch 0 ist und er dadurch ein 2.mal direkt wieder da rein rauscht? Das würde evtl. dann das Fehlverhalten erklären?? Könnte durch den UMTS Anbieterwechsel sein das er die Daten jetzt schneller los bekommt als vorher, denn eigentlich lief alles 1,5Jahre so ....

noch ein Screenshot aus der Datenbank

Wenn Dein Zeitverhalten von der Übertragungsgeschwindigkeit abhängig ist, machst Du grundlegende Fehler. Da Du nur ein Fragment des Codes postest, kann man da nichts weiter dazu sagen. Baue doch mal eine ordentliche Zeitsteuerung mit millis() auf, um die 1 Minute sicher zu stellen.

Gruß Tommy

Wenn Dein Zeitverhalten von der Übertragungsgeschwindigkeit abhängig ist

Eigentlich nicht, bzw. es ist mir nicht bewusst......

Baue doch mal eine ordentliche Zeitsteuerung mit millis()

Ich bin der Meinung das hab ich gemacht?

Der "Rest" Code ist alles nur Wetter / Wind Abfrage Kram und Debug Zeug ob die Abfragen der Sensoren sauber waren. Das was passiert hab ich gepostet, da ist es egal ob dazwischen noch for i =.......und so Zeug drin steht.

Aber nach mehrfachen hin und her überlegen ist meine Vermutung Quatsch denk ich.

Du bist aber nur der Meinung eine Zeitsteuerung mit millis gebaut zu haben. Real hast Du ein Durcheinander aus millis und delay, was mit Sicherheit nicht das macht, was Du willst. Schau Dir nochmal BlinkWithoutDelay an und mache es so, wie dort gezeigt. Nicht mit irgendwelchen waghalsigen Konstrukten.

Gruß Tommy

@Tommy56 Leider kann ich deiner Aussage nicht folgen, ich sehe da nichts gemischtes mit Delay und millis()....

Also ich war vor Ort, hab 1 Stunde "Debuggt" und was soll ich sagen, mir ist fast der Kopf geplatzt bei so viel wirrem Zeug was das Ding da gemacht hat, für mich völlig unerklärlich.

Ende vom Lied, Strom weg, Strom ein alles läuft wieder perfekt wie vorher :o :o

Also Neustart über "WDT" hat nix geholfen, Strom weg und Strom ein ---> Problem behoben, wer soll das verstehen? Ich nicht.

Ich kann ja bei Bedarf das geloggte mal posten und nach Erklärungen für das komische Verhalten versuchen zu suchen, aber am Code bzw. Sketch kann es nicht liegen da ja 1,5 Jahre Funktion ohne Probleme und jetzt auch wieder........

Grüße Heiko

Hi

Mir wäre jetzt nicht aufgefallen, wo Du den WDT zurück setzt. Bei Wind-Fehlern löst Du ein Reset per WDT(2s) aus, wo Du eine 3 Sekunden Pause einleitest -> Reset. Nun sehe ich aber nicht, daß der WDT wieder deaktiviert wird - somit müsste, nach dem ersten Auslösen des WTS, Dieser alle 2 Sekunden (kA, ob Der einen Standard-Wert annimmt, wird wohl im DaBla stehen) erneut feuern.

MfG

das mit dem WDT passt schon, daher hab ich das weggelassen

// Setup routine runs once when you press reset:
void setup() { 
wdt_reset();  
wdt_disable();

......
......
      if (millis() > (whileTime) + 4000) {    // wenn nach xxx Zeit nix kommt, aufhören sonst steht ewig hier

Diese Zeile ist anfällig für den Millis-Überlauf alle 49Tage. Hat whileTime + 4000 einen Überlauf, dann steht da eine Zahl zwischen 0 und 3999, wodurch am laufenden Band abgebrochen wird. Noch mehr solche Konstruktionen im Sketch könnte zu seltsamen Effekten führen.

Richtig ist if (millis()-(whileTime) > 4000). Hier funktioniert auch mit Überlauf alles richtig.

:o :o :o :o :o

versteh ich nicht......

:confused:

Methode a:

if (millis() > (whileTime) + 4000)

Hier werden 2 Überläufe stattfinden! Millis wird irgendwann überlaufen und die Addition auch. Ein Überlauf kann kompensiert werden. Der zweite bricht dir das Genick.

Methode b:

if (millis()-whileTime > 4000)

Hier kann nur der Millis Überlauf stattfinden. Und dieser wird vom evtl auftretenden Unterlauf der Subtraktion kompensiert.

Methode a versagt nach ca 49 Tagen. Methode b läuft unbeirrt und fehlerfrei durch, bis zum Weltuntergang.

das Teil läuft max 15 Stunden am Tag, dann schläft es und wenn es aufwacht beginnt alles bei 0

Seit wann geht bei einem sleep der millis() Wert verloren? Der zählt, im Tiefschlaf, einfach nicht weiter, und das wars.... Oder? Sämtliche Daten im Ram bleiben erhalten.

@kollimann:

aber egal wie lange das Ding läuft, deine “Formel” geht aus meiner Sicht immer nach hinten los

Dann hast Du sie nicht verstanden.

Damit das nicht so lange läuft, habe ich den Mechanismus mal im Kleinen abgebildet (mit einer 8 bit Zahl):

unsigned char aktuelleMillis = 0, letzteMillis = 0, dauer = 10;
int cnt = 0;
void setup() {
  Serial.begin(115200);
  Serial.println("Start");
  Serial.println("Initialwerte:");
  Serial.print("Dauer = "); Serial.println(dauer);
  Serial.print("letzte = "); Serial.println(letzteMillis);
  Serial.print("aktuell"); Serial.print('\t'); Serial.print("Diff."); 
  Serial.print('\t'); Serial.println("letze");
}

void loop() {
  if (cnt <= 300) { // Damit das nicht ewig läuft
    if ((unsigned char)(aktuelleMillis - letzteMillis) >= dauer) {
      // tu was
      Serial.print(aktuelleMillis); 
      Serial.print('\t'); Serial.print((unsigned char)(aktuelleMillis - letzteMillis));
      Serial.print('\t'); Serial.print(letzteMillis); Serial.println("\tAktion"); 
      letzteMillis = aktuelleMillis;
    }   
    else {
      Serial.print(aktuelleMillis); Serial.print('\t'); 
      Serial.println((unsigned char)(aktuelleMillis - letzteMillis));
      
    }  
    aktuelleMillis++;
    cnt++;
  }    
}

Lass es mal laufen und schaue Dir die Ausgaben an.

Gruß Tommy