Arduino stellt immer nach einiger Zeit das arbeiten ein

Hallo,
ich habe einen Arduino Nano, mit einem Ethernet Shield und einem DHT22-Sensor.
Nun messe ich die Temperatur und Feuchtigkeit, gebe sie als Debug Meldung aus und versende sie als MQTT Nachricht.

Beim Hochlagen erhalte ich folgende Info:
Der Sketch verwendet 23238 Bytes (75%) des Programmspeicherplatzes. Das Maximum sind 30720 Bytes.
Globale Variablen verwenden 1570 Bytes (76%) des dynamischen Speichers, 478 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.
Wenig Arbeitsspeicher verfügbar, es können Stabilitätsprobleme auftreten.
...den Code kann ich eigentlich kaum noch reduzieren, hab schon allen Luxus rausgeschmissen :wink:

Meine Code sieht so aus, startet wie gewünscht und nach ein paar Minuten erhalte ich keine Ausgabe mehr und es wird auch keine MQTT-Nachricht mehr versendet.

#include <SimpleDHT.h>
#include "PubSubClient.h"
int dataPinSensor1 = 6;
SimpleDHT22 dht1(dataPinSensor1);

int timer = 0; //damit ich die Zeit nicht in der delay-Funktion abwarten muss!
#define CLIENT_ID    "NanoKeller"
#define debug        true
#define sendtimer    1000   //ca. 1.5 gesendete pro Min bei 15.000
// ethernet interface ip address
byte ipfixed[]={192,168,0,180};
uint8_t mac[6] = {0x00,0x01,0x02,0x03,0x04,0x06};

#include <UIPEthernet.h>
EthernetClient ethClient;
PubSubClient mqttClient;

byte temperature1 = 0;
byte humidity1 = 0;

void setup() {
  Serial.begin(115200);
  Ethernet.begin(mac,ipfixed);

  // setup mqtt client
  mqttClient.setClient(ethClient);
  mqttClient.setServer("192.168.0.175",1883); 
  if(debug)
    Serial.println(F("MQTT client configured"));
}

void readDHT22() {  
  int err = SimpleDHTErrSuccess;
    if ((err = dht1.read(&temperature1, &humidity1, NULL)) != SimpleDHTErrSuccess) {
      if(debug)
        Serial.print("Communication error with Sensor 1, err="); Serial.println(err);delay(1000);
      return;
    }
    if(debug)
    {
      Serial.print((int)temperature1); Serial.print(" *C, ");   
      Serial.print((int)humidity1); Serial.println(" % humidity");
    }
}

void sendMQTTData() {
  char msgBuffer[7];
  if(mqttClient.connect(CLIENT_ID)) {
   mqttClient.publish("Keller/temp1", dtostrf(temperature1, 6, 2, msgBuffer));
   mqttClient.publish("Keller/humid1", dtostrf(humidity1, 6, 2, msgBuffer));
  }
}

void loop() {
  timer = timer + 1;
  if(timer >= sendtimer){
    readDHT22();
    sendMQTTData();
    timer = 0;
  }
  delay(1);
}

Wer kann mir hier sagen warum und was ich verbessern könnte?!?!
Eine Fehlermeldung bekomme ich nicht, es läuft einfach gar nichts mehr :frowning: -bis zum Reset.

Up Internet. h deutet auf die Ethernetplatine mit dem hohen Speicherverbauch ENC28J60 hin.
Ob die mqtt-lib String benutzt, musst Du nachschauen.

Gruß Tommy

Danke für die Antworten. Also ohne Debug-Meldungen ist es auch nicht stabiler.

Wie kann ich nachschauen, ob ich mqtt-Nachrichten über mein Arduino Nano Ethernet Shield ENC28J60 versendet werden können?

Wäre hierfür eine andere Bibliothek besser (EtherCard.h)?

Die Lib muss zu Deinem Chip passen und Du hast Dir den schlechtesten Chip ausgesucht. Auf den ersten Blick verwendet pubsubclient keine Strings.

Gruß Tommy

1570 Bytes gebrauchtes RAM sind zuviel. Während des Ausführen des Sketches werden noch weiteres RAM benötigt und auch der Stack braucht RAM.

Du hast zuwenig RAM-Speicher für diesen Sketch.

Wie Tommy schreibt ist diese Ethernetkarte Resourcenfressend weil der Arduino viel machen muß. Eine auf den W5100 basierende Karte wäre besser weil sie selbst viel macht .
Grüße Uwe

Hallo,

habe gerade mal nachgeschaut:
UIPEnternet + PubSubClient und nur MQTT-Test mit publish alle 10 Sekunden: Ram 1417 Bytes (69%)
läuft stabil.
Dazu Adafruit_BME280 und Wire macht Ram 1721 Bytes (84%) und ist kritisch, ich meine aber, das dieser Sketch hier auch über Stunden durchlief.
Mit seinen 1570 Bytes (76%) sollte das eigentlich noch stabil laufen, ich habe keine DHT22 hier im Einsatz und habe mir den Sketch und diese Lib jetzt nicht im Detail angesehen.

Gruß aus Berlin
Michael

Also an der Hardware kann ich nichts mehr ändern. Soll ich seltener senden lassen?

Wäre es ein Unterschied, wenn ich in die Loop-Funktion sleep() schreibe, statt den Zähler hochzuzählen?

Alles was RAM braucht macht die Sache schlimmer.
Grüße Uwe

Was mir ins Auge fällt: ich sehe keine reconnect-Routine. Er stellt die Verbindung her und geht in die loop(). Bricht mal die Verbindung weg, wird nirgends darauf getestet und eine neue Verbindung hergestellt...

@DerLehmi
Danke für die Info! Ich habe es mit reconnect versucht, aber alles klappte leider nicht :frowning:

Im Internet hab ich einen Beitrag gefunden, da hat ein Programmierer alle 8 Sekunden den Watchdog aktiviert und das komplette Board neu gestartet. Aber das kann doch auch keine Lösung sein.

Dummerweise kann ich nicht mehr auf einen anderen Chip umsetzen und muss das nun irgendwie stabil zum Laufen bringen.

Hat hier wer einen Beispielcode, mit dem das Ethernetshield stabil läuft und bei Unterbrechung sich auch wieder verbinden kann??

Dann aber möglichst den W5100.

Gruß Tommy

Danke für die Info! Ich habe es mit reconnect versucht, aber alles klappte leider nicht :frowning:

-->auch eine reconnect-Routine kann man falsch aufbauen :wink:
Prüfe doch erstmal, was genau nicht funktioniert. Liegt das Problem am MQTT-Broker oder -Clienten, liegt es an der Ethernet-Verbindung oder hängt sich der Controller iwie auf?

Im Internet hab ich einen Beitrag gefunden, da hat ein Programmierer alle 8 Sekunden den Watchdog aktiviert und das komplette Board neu gestartet. Aber das kann doch auch keine Lösung sein.

-->So funktioniert ein Watchdog eigentlich nicht. Der Watchdogtimer läuft im Hintergrund und wird regelmäßig zurückgesetzt. Er läuft unabhängig vom Programm, und wenn sich der Controller aufhängt läuft der Watchdog über und löst einen Reset aus. Er ist eine Sicherung, wird er benötigt, stimmt etwas mit dem Controller/ dem Code nicht

Hi

ACHTUNG: Man kann den Watchdog auch so kurz einstellen, daß ein Arduino NICHT MEHR STARTET.
Der Arduino (besser: der Bootloader) wartet bei Spannungswiederkehr 1...2 Sekunden, ob Da Jemand einen neuen Sketch aufspielen will.
In dieser Zeit läuft aber auch (noch) der Wach Hund - und wenn Dessen Wartezeit kürzer ist, gibt's den nächsten Reset.

Nach dem Watchdog-Reset ist der Wachhund mit genau den gleichen Werten immer noch in Betrieb!!

MfG

ACHTUNG: Man kann den Watchdog auch so kurz einstellen, daß ein Arduino NICHT MEHR STARTET.
...
Nach dem Watchdog-Reset ist der Wachhund mit genau den gleichen Werten immer noch in Betrieb!!

Eigentlich ist es noch schlimmer!

Bei einem Reset wird der WDT nicht abgeschaltet, ja.
Die eingestellte Zeit, wird allerdings dabei auf den minimalen Wert gesetzt.

Aber, es gibt auch gutes zu berichten:
Der UNO und der neue Nano Bootloader kann damit umgehen.
Andere fallen in einen Dauer-WDT-Reset-loop

Hallo,

da ich noch einen DHT22 in der Kiste hatte, habe ich das jetzt mal zusammengesteckt und mit Deinem Sketch angeworfen.
Warum schickst Du eigentlich so oft die Daten? So schnell ändert sich doch sowieso nichts?

Zumindest schickt er jetzt erstmal seit 21:46:25 Uhr artig seine Daten.
Mal abwarten...

PS:
Der Sketch verwendet 22698 Bytes (73%) des Programmspeicherplatzes. Das Maximum sind 30720 Bytes.
Globale Variablen verwenden 1535 Bytes (74%) des dynamischen Speichers, 513 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.

und keine Stabilitäts-Warnung, warum auch immer...

23:05 Uhr noch sendet er. Nach dem Foto kamen keine Meldungen mehr, lag darn, daß ich das LAN-Kabel nicht sauber eingerastet hatt. Nochmal sauber gesteckt und er schickt weiter siene Daten.
Ist eigentlich auch logisch, wenn der ENC keinen Link hat gibt es eben keine Daten. Das fängt der UIP-Stack sowieso erstmal ab. Der MQTT-Broker wird auch erst unruhig wennd as keep-alive abgelaufen ist. MQTT ist ja extra für instbille Verbindungen entwicklet worden. Wenn innerhalb keep-alive wieder Daten kommen passiert garnichts weiter.

Nachtrag: heute morgen um gegen 5:00 Uhr lief er noch, jetzt 8:00 Uhr hat er den Betrieb eingestellt.
Ich habe jetzt erstmal den DHT22 komplett rauskommentiert und lasse mir nur Dummy-Daten schicken.
Mal abwarten...

Gruß aus Berlin
Michael

@Michael, wow das ist wirklich nett! Und irgendwie bin ich beruhigt, dass er sich bei dir auch aufhängt.
Siehst du, warum das so is? Was muss ich am Code ändern, damit es dauerhaft läuft bzw. der Arduino Nano wieder neu startet, wenn er nicht wie gewünscht funktioniert.

Einen anderen Ethernetchip kann ich derzeit nicht nehmen, dafür habe ich mehrere ENC28J60 hier :confused:

Du könntest mit dem F Macro noch einige Bytes RAM frei machen.

ENCs hab ich auch noch ein paar rumliegen, nehme sie aber nirgends mehr. Haben sich sogar nach Tagen stabilen Betriebes noch aufgehängt. Es gibt auch Breakouts mit dem W5100 im fast gleichen Format.

Hallo,

sunshineh:
@Michael, wow das ist wirklich nett! Und irgendwie bin ich beruhigt, dass er sich bei dir auch aufhängt.
Siehst du, warum das so is? Was muss ich am Code ändern, damit es dauerhaft läuft bzw. der Arduino Nano wieder neu startet, wenn er nicht wie gewünscht funktioniert.

ich habe aus Bequemlichkeit mal meinen alten BM280-Sketch genommen und nur den BM280 rausgeworfen und den DHT22 reingebaut.

#include <UIPEthernet.h>
#include <PubSubClient.h>
#include <SimpleDHT.h>

#define SENSOR 6
SimpleDHT22 dht1(SENSOR);

byte temperature1 = 0;
byte humidity1 = 0;

char msgBuffer[10];

unsigned long starttime = 0;
unsigned long repeattime = 10000; 
unsigned int reconnecttime = 2000;                 // max. 65535
unsigned long waittime = reconnecttime;

// Update these with values suitable for your network.
byte mac[]    = {  0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED };
byte server[] = { 192, 168, 0, 99 };
byte ip[]     = { 192, 168, 0, 200 };

void callback(char* topic, byte* payload, unsigned int length);

EthernetClient ethClient;
PubSubClient mqttClient(server, 1883, 0, ethClient);

void setup()
{
  waittime = reconnecttime;            // kurze Wartezeit bis Senden oder Connect-Versuch
  starttime = millis();
  
  Ethernet.begin(mac, ip);
  if (mqttClient.connect("ENC-Client"))
  {
    mqttClient.publish("Keller1/Status","online");
  }
}

void loop()
{
 if (millis() > (starttime + waittime))
 {  
   if (mqttClient.connected())
   {  
     int err = dht1.read(&temperature1, &humidity1, NULL);
     if (err == SimpleDHTErrSuccess)
     {  
       mqttClient.publish("Keller1/temp1", dtostrf(temperature1, 6, 2, msgBuffer));
       mqttClient.publish("Keller1/humidity1", dtostrf(humidity1, 6, 2, msgBuffer));
     }
     else
     {
       mqttClient.publish("Keller1/Error", itoa(err,msgBuffer,16));    
     }  
     waittime = repeattime;                // normale Wiederholzeit 
   }
   else                                    // Verbindung verloren
   {
     if (mqttClient.connect("ENC-Client"))
     {
        mqttClient.publish("Keller1/Status","online");
     }
     waittime = reconnecttime;             // kurze Wartezeit bis Senden oder Connect-Versuch   
  }    
  starttime = millis();
}
 mqttClient.loop();
}

Schickt mir seit vorgestern Abend alle 10s artig die Daten.
Vielleicht hilft es ja, Keller heißt jetzt Keller1, ich hatte schon einen "Keller".

Nachtrag 10.11.: schickt immernoch stabil seine Meldungen, die Werte des DHT22 sehen auch recht glaubwürdig aus, hatte die bisher nie verwendet.

Gruß aus Berlin
Michael

Hallo,

ich hole das nochmal nach oben. Daten kommen auch weiterhin stabil alle 10s an.
Das ist weniger eine Empfehlung für die ENC28J60 Module am Mega328, mehr der Hinweis, daß es stabil laufen kann. Ram sparen wo immer es geht. Array global anlegen wenn es mehrfach gebraucht wird hat hier den Vorteil, daß sofort klar ist, ob der Ram reicht. Funktionsaufrufe vermeiden wenn sie nur der Übersicht dienen und man es auch direkt in loop() packen kann usw. Der Funktionsaufruf kostet wie arrays in Funktionen Platz auf dem Heap und da hat man durch die genutzen Sachen der Libs wenig Überblick und kaum Kontrolle.
Da kracht es dann gern, wenn irgendwann eine Lib mal temporär mehr belegt hat und man mit dem eigenen Aufruf das Faß zum Überlaufen bringt.

Ich baue das jetzt trotzdem wieder ab, ich stolpee dauern über das rumliegende LAN-Kabel...

Gruß aus Berlin
Michael

amithlon:
Der Funktionsaufruf kostet wie arrays in Funktionen Platz auf dem Heap

Eher auf dem Stack.

Gruß Tommy