[erledigt] ausführliches Debugging möglich?

Moin,

ich hab hier 2 Wemos D1 Minis. Diese laufen mit gleichem Grundgerüst im Sketch; der eine hat eine Dallas Temp.-Sensor und steuert einen Lüfter; der andere hat einen Taster und steuert via 433Mhz (Lib: rc-switch) das Licht im Flur.

Der eine läuft seit vielen Tagen 24/7 unfallfrei; der ander stürzt nach ein paar Stunden ab. Ich habe nun versucht via Seriellen Monitor die Ausgaben der Serial.println ausgaben zu loggen. Aber beim Absturz sendet er nur noch blödsinn (s. Anhang).

Wie kann ich mehr Infos im Seriellen Monitor oder sonst wie erhalten? Oder kann ich einen Debug-Level höher einstellen, so dass mehr im Monitor erscheint, als nur das, was Serial.print ausgibt?

Vielen Dank! ~Ralf~

Mqtt verbindung verloren
Prfe WLAN...ok
Verbinde mit MQTT-Server verbunden
und online!
Recieved [bs/flur/sub]: ok
Status Taster hat sich gendert
{"id": "Flur","date": "30.10.2019", "time": "22:12:30", "utctimestamp": "1572469950","msg": "Tr auf"}
Recieved [bs/flur/sub]: 1115473
Recieved [bs/flur/sub]: ok
Status Taster hat sich gendert
{"id": "Flur","date": "30.10.2019", "time": "22:12:33", "utctimestamp": "1572469953", "msg": "Tr zu"}
Mqtt verbindung verloren
Prfe WLAN...ok
Verbinde mit MQTT-Server verbunden
und online!
Recieved [bs/flur/sub]: ok
Recieved [bs/flur/sub]: 1115476
Recieved [bs/flur/sub]: ok
Recieved [bs/flur/sub]: 1115476
Recieved [bs/flur/sub]: ok
osn|'|^Cno<o||||||||||<|||||||||||||<<||||||<||||||<|<|||<||<<<<|||||||<<|<|<||||||||||||||||||||||||<
|||<||<|||<<|||||||||||<||<|||||||||||<||<|||<|||<<|<|||<<||||<||||||||||||<|<|||||<|
|||||<||||||<|||
||||<||||||<||<||||||||<|<<|||||||||||||||||||<|||||<||||||||||<|||||||||||<||<|<||||
|||||||||||||||<
||<|<|<<|||||<||||||||<<||<<|||||||||||<<|<<<|||||<|<|||||||||||<||||||||||||||||||||
|||<|<<<|||<||||
||<|||||||||||||||||||||||||||<||||<|||||||<|||<||||<<|||||||<|||<|||<||||<|<|||<||||
|

Um ein ausführliches Debugging einzurichten, musst du an den gewünschten Stellen im jeweiligen Sketch, selber mehr Serial.println(), mit eindeutigen Bezeichnungen, eintragen. Außer deine uns unbekannten Sketches und/oder Libs haben das schon vorgesehen, aber da uns unbekannt, können wir es nur raten.

Schon mal die D1 Minis untereinander getauscht und den jeweils anderen Sketch aufgespielt?

Moin, anbei der Code;

in secrets.h stehen nur Definitionen wie Wlan-SSID, Passwörter Fingerprints etc.

in functions.h steht neben #include <time.h> noch die Zeitfunktion setupTime().

Wenn diese noch benötigt werden, kann ich die auch noch Posten...

#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <MQTT.h>

// https://www.youtube.com/watch?v=ytQUbyab4es
//                   platformio device monitor --baud 115200
//                   platformio run --target upload && platformio device monitor --baud 115200

//enable only one of these below, disabling both is fine too.
//#define CHECK_CA_ROOT // geht nicht!
//#define CHECK_PUB_KEY
#define CHECK_FINGERPRINT
////--------------------------////

#include "secrets.h"
#include "functions.h"


#if (defined(CHECK_PUB_KEY) and defined(CHECK_CA_ROOT)) or (defined(CHECK_PUB_KEY) and defined(CHECK_FINGERPRINT)) or (defined(CHECK_FINGERPRINT) and defined(CHECK_CA_ROOT)) or (defined(CHECK_PUB_KEY) and defined(CHECK_CA_ROOT) and defined(CHECK_FINGERPRINT))
#error "cant have both CHECK_CA_ROOT and CHECK_PUB_KEY enabled"
#endif


#include <RCSwitch.h>
RCSwitch mySwitch = RCSwitch();
int    PIN_EMPFAENGER = 0 ; // D3 = PIN 0          Receiver on interrupt 0 => that is pin D3
int    PIN_SENDER = 5     ; // D1 = PIN 5


BearSSL::WiFiClientSecure net;
MQTTClient client;

int timezone = 2;
unsigned long lastMillis_tuer = 0;
unsigned long lastMillis_zeit = 0;
time_t now;
const int TimeSleepS = 1800;   // 900s = 15Min
//const int TimeSleepS = 60;   // 900s = 15Min
int temp = 22;
int hum = 11; 

char actDate[20];
char actTime[20];
 
 
// unsigned long lastMsg_zeit = -333999999; // nicht mehr benötigt.
unsigned long lastMsg_tuer = -333999999;


bool GEAENDERT=false;
bool ALTER_STATUS=false;

int PIN_TASTER=D0; 
bool STATUS_TASTER=false;






void tuer(){    
    now = time(nullptr);
    time_t nowi = time(nullptr);
    struct tm *tmp = localtime(&nowi);
    sprintf (actDate, "%02d.%02d.%04d", tmp->tm_mday , tmp->tm_mon+1, 1900+tmp->tm_year);  
    sprintf (actTime, "%02d:%02d:%02d", tmp->tm_hour , tmp->tm_min, tmp->tm_sec );  

    String payloadT = "{\"id\": \"Flur\",";
    payloadT += "\"date\": \"";
    payloadT += actDate;
    payloadT += "\",";
    
    payloadT += " \"time\": \"";
    payloadT += actTime;
    payloadT += "\",";
    
    payloadT += " \"utctimestamp\": \"";
    payloadT += now;
    payloadT += "\",";

    if(digitalRead(PIN_TASTER))
        {
            payloadT += "\"msg\": \"Tür auf\"}";
        }
    else
        {          
            payloadT += " \"msg\": \"Tür zu\"}";
        }
//    payloadT += "}";
    char attributesT[200];
    payloadT.toCharArray(attributesT, 200 );
    Serial.println(attributesT);
    client.publish(MQTT_PUB_TOPIC, attributesT, true, 1);


    
}




void messung()
{
        STATUS_TASTER=digitalRead(PIN_TASTER);
        if(STATUS_TASTER != ALTER_STATUS)
            {
            ALTER_STATUS=STATUS_TASTER;
            Serial.println(" Status Taster hat sich geändert");
            tuer();
            }
            
}



void mqtt_connect()
{
    Serial.print("Prüfe WLAN...");
    if(WiFi.status() != WL_CONNECTED){
        Serial.print("WiFi verbindung verloren!");
    }else {
        Serial.print("bin noch online");
    }
    while (WiFi.status() != WL_CONNECTED)
    {
        Serial.print(".");
        delay(1000);
    }
    Serial.println("ok");
        client.setWill(MQTT_LWT_TOPIC, "offline", true, 1);
    
    Serial.print("Verbinde mit MQTT-Server  ");
    while (!client.connect(HOSTNAME, MQTT_USER, MQTT_PASS))
    {
        Serial.print(".");
        delay(500);
    }
    Serial.print(" verbunden ");

    client.publish(MQTT_LWT_TOPIC,"online",true, 1);
    Serial.println(" und wieder online!");
    client.subscribe(MQTT_SUB_TOPIC);
}



void messageReceived(String &topic, String &payload)
{
    Serial.println("Recieved [" + topic + "]: " + payload);
    if(payload!="ok")
    {
    int zahl = payload.toInt(); // mach payload zu einer Zahl... 
    mySwitch.send(zahl, 24);    // sende diese Zahl. 
    client.publish(MQTT_SUB_TOPIC, "ok", true, 1);
    }
}


void setup()
{
    Serial.begin(115200);
    Serial.println();
    Serial.print("Attempting to connect to SSID: ");
    Serial.print(ssid);
    Serial.println();
    Serial.println();
    WiFi.hostname(HOSTNAME);
    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, pass);
    while (WiFi.status() != WL_CONNECTED)
    {
        Serial.print(".");
        delay(500);
    }
    Serial.println("connected!");

    Serial.print("Setting time using SNTP");
    configTime(timezone * 3600, 0, "ptbtime1.ptb.de", "ptbtime2.ptb.de");

    #ifdef CHECK_CA_ROOT
        BearSSL::X509List cert(digicert);
        net.setTrustAnchors(&cert);
    #endif
    #ifdef CHECK_PUB_KEY
        BearSSL::PublicKey key(pubkey);
        net.setKnownKey(&key);
    #endif
    #ifdef CHECK_FINGERPRINT
        net.setFingerprint(fp);
    #endif
    #if (!defined(CHECK_PUB_KEY) and !defined(CHECK_CA_ROOT) and !defined(CHECK_FINGERPRINT))
        net.setInsecure();
    #endif

    client.begin(MQTT_HOST, MQTT_PORT, net);
    client.onMessage(messageReceived);

    mqtt_connect();


    Serial.print("Sender und Empfänger vorbereiten..");
    mySwitch.enableReceive(PIN_EMPFAENGER);  // Receiver on interrupt 0 => that is pin D3
    mySwitch.enableTransmit(PIN_SENDER); // D1 PIN Sender  5
    Serial.println(". Fertig!");

    Serial.print("Setup Time ..");
    setupTime();
    Serial.println(". Done!");

}

void loop() 
{
    now = time(nullptr);
    if (WiFi.status() != WL_CONNECTED)
    {
        Serial.print("Wlan verloren ");
        while (WiFi.waitForConnectResult() != WL_CONNECTED)
        {
            WiFi.begin(ssid, pass);
            Serial.print(".");
            delay(10);
        }
        Serial.println("connected");
    }
    else
    {
        if (!client.connected())
        {
        Serial.println("Mqtt verbindung verloren");
            mqtt_connect();
        }
        else
        {
            client.loop();
        }
    }

    unsigned long  jetzt = millis(); 
    if (jetzt - lastMsg_tuer > 500) {
            lastMsg_tuer = jetzt;   
            messung();
    }

   delay(100);
}

Warum gehst Du den Umweg über String, wenn Du dann doch wieder ein Char-Array draus baust? Das kannst Du doch gleich im sprintf komplett machen.

Auch der RAM eines ESP8266 ist endlich und kann fragmentiert werden. Es dauert nur etwas länger.

Gruß Tommy

Tommy56:
Warum gehst Du den Umweg über String, wenn Du dann doch wieder ein Char-Array draus baust? Das kannst Du doch gleich im sprintf komplett machen.

Ok- kann ich noch mal ändern; noch gar nicht drüber nachgedacht. Ich war nur froh, dass ich das mit meinem begrenzten Wissen überhaupt hinbekommen habe...

Tommy56:
Auch der RAM eines ESP8266 ist endlich und kann fragmentiert werden. Es dauert nur etwas länger.

Einfach mal den ESP wechseln gegen einen neuen? Aber so alt ist der noch nicht!?!? Ich probiere es aus.

Wie kann ich denn den RAM fragmentieren?

Gruß Ralf

BastelRalf:
Wie kann ich denn den RAM fragmentieren?

Fragmentieren ist kein Alterungsprozess, sondern ungünstige dynamische Verwendung von Speicher, wie es die Klasse String macht. Irgendwann hast Du kein zusammenhängendes Stück RAM von der benötigten Größe mehr, sondern nur noch viele kleine Stückchen.

Nicht nur die eine Stelle, sondern String komplett raus werfen ist mein Vorschlag.

Gruß Tommy

Die folgende Variblenzuweisung im Header ist zwar nicht der Grund für die Fehlfunktion, aber vollkommen unnötig:

unsigned long lastMsg_tuer = -333999999;

unsigned beinhaltet keine Vorzeichen und der Wert wird m.E. als 0 zugewiesen.

Befolg mal den Hinweis von Tommy56 mit den Strings, wenn es dann immer noch Probleme macht, teste einfach mal einen anderen Wemos D1 Mini mit dem Sketch und der Schaltung.

Vielen Dank für die Anregung. Ich habe jetzt den Payload-String-Blösinn rausgeschmissen und dafür sprintf benutzt:

und

unsigned long lastMillis_tuer = 0;
unsigned long lastMillis_zeit = 0;

Hier noch die Änderungen... oder noch mal den gesamten Code posten?

char auf_strg[200];
char zu_strg[200];

und

    if(digitalRead(PIN_TASTER))
        {
            sprintf(auf_strg, "{\"id\": \"Flur\", \"date\": \"%s\", \"time\": \"%s\", \"utctimestamp\":\"%i\",\"msg\":\"Tür auf\"}", actDate, actTime, now );
            Serial.println(auf_strg);
            client.publish(MQTT_PUB_TOPIC, auf_strg, true, 1);
        }
    else
        {          
            sprintf(zu_strg, "{\"id\": \"Flur\", \"date\": \"%s\", \"time\": \"%s\", \"utctimestamp\":\"%i\",\"msg\":\"Tür zu\"}", actDate, actTime, now );
            Serial.println(zu_strg);
            client.publish(MQTT_PUB_TOPIC, zu_strg, true, 1);
        }

wapjoe:

unsigned long lastMsg_tuer = -333999999;

unsigned beinhaltet keine Vorzeichen und der Wert wird m.E. als 0 zugewiesen.

Das ist falsch. Probiere mal aus, was da drin steht.

Gruß Tommy

Tommy56:
Das ist falsch. Probiere mal aus, was da drin steht.

Gruß Tommy

Kann ich grad leider nicht, bin im Urlaub bei der Family und hab nur mein Laptop mit :wink:

Also nach meinem Verständnis wird lastMsg_tuer = 0 - 333.999.999 gerechnet und das ergibt einen negativen Wert, der durch unsigned = 0 ist. Wenn ich da einen Verständnisfehler habe, klär mich bitte auf.

Schönen Urlaub.

Da steht drin:

unsigned long 0xEC179081 oder 3960967297
long 0xEC179081 oder -333999999

Der Unterschied ist nur die Interpretation des höchstwertigen Bits. Die Bits selbst sind in beiden Fällen gleich.
Bei unsigned gehört es zur Zahl, bei signed bestimmt es ob negativ (1) oder positiv (0) und der Rest an Bits ist dann der Zahlenwert.

Gruß Tommy

Tommy56:
Schönen Urlaub.

Danke, das nächste mal nehme ich ein Arduino Notfallpack mit :smiley:

Da steht drin:

unsigned long 0xEC179081 oder 3960967297

long 0xEC179081 oder -333999999




Der Unterschied ist nur die Interpretation des höchstwertigen Bits. Die Bits selbst sind in beiden Fällen gleich. 
Bei unsigned gehört es zur Zahl, bei signed bestimmt es ob negativ (1) oder positiv (0) und der Rest an Bits ist dann der Zahlenwert.

Gruß Tommy

Also wenn ich das jetzt richtig verstehe, wird das Vorzeichen ignoriert? Wie auch immer, wird in dem Sketch vom TO, der Wert im ersten Loopdurchlauf überschrieben, daher mein Hinweis dass die Zuweisung unnötig sei.

wapjoe:
Also wenn ich das jetzt richtig verstehe, wird das Vorzeichen ignoriert?

nein, das Vorzeichen wird nicht ignoriert. Der Compiler macht aus der vorzeichenbehafteten Konstante eine entsprechende Binärzahl, und die wird in der Variable gespeichert. Da die Variable aber als unsigned deklariert ist, wird dann im Programm diese Binärzahl bei Berechnungen und Vergleichen eben anders interpretiert.
Würdest Du da z.B. bei der Ausgabe wieder auf signed casten, käme wieder die ursprüngliche negative Zahl raus. Alles nur eine Frage der Interpretation des Variableninhalts.

Edit: Übrigens ist bei negativen Zahlen nicht einfach nur das höchstwertige Bit gesetzt, die werden anders dargestellt. Z.B. sind bei -1 grundsätzlich immer alle Bits gesetzt. Schau mal nach Zweierkomplement. So werden negative Zahlen in Computern dargestellt.

Gut, dass Du da nochmal darauf hin weist. Das hatte ich unterschlagen.

Gruß Tommy

Ihr Lieben,

noch mal zurück zum String-Problem: Wie kann den Code hier umgehen? Node-Red wertet den Status der Tür aus, guckt, ob es Tag oder Nacht (Sunset und Sunrise) ist und sendet dann den RF-Code via mqtt an ein bestimmtes Topic. Entweder wird eine Zahl gesendet oder selber wird "ok" gesendet, damit Node-red weiß, dass die Nachricht angekommen ist... Es wird also im Topic ein "ok" oder eine Zahl gesendet..

void messageReceived(String &topic, String &payload)
{
    Serial.println("Recieved [" + topic + "]: " + payload);
    if(payload!="ok")
    {
    int zahl = payload.toInt(); // mach payload zu einer Zahl... 
    mySwitch.send(zahl, 24);    // sende diese Zahl. 
    client.publish(MQTT_SUB_TOPIC, "ok", true, 1);
    }
}

oder ist das alles zu kompliziert (gedacht)?

Was ich möchte ist, dass im Flur das Licht für 10 Minuten angeht, wenn die Haustür geöffnet wird. Geht das nicht einfacher?

Gruß Ralf

Nochmal kurz OT: @Tommy56 und @MicroBahner Danke für die Info, ich muss noch viel lernen! :slight_smile:

Moin Liebes Forum,

ALSO ich denke die ,,Abstürze'' lagen nicht (nur) am Sketch. Ich habe zwei weitere Wemos mit dem Code gefüttert (nur kleinigkeiten wie ID o.ä. geändert) und parallel zum ersten angeschlossen: Alle drei laufen seit mehreren Tagen problemlos durch!

Dh. Es lag wohl an der Spannungs-/Stromversorgung.

Nun muss ich mal nach einer guten Energiequelle für die Dinger suchen.

Vielen Dank - für die Mühen und zahlreichen Tipps.

Ralf

~closed~

BastelRalf:
~closed~

Hallo Ralf,
wenn Du das Thema als erledigt ansiehst, dann editiere deinen 1. Post und füge im Titel '[erledigt]' hinzu. Dann erkennt man das gleich.