Problem an OpenSenseMap Daten mit Wemos D1 zu senden


#1

Hallo,
ich hab versucht mit einem ESP 8266 Wemos D1 Daten an die OpenSenseMap zu sendnen, hierzu hab ich den Quellcode von hier als Basis genommen. Da ich erstmal die Funktionalität testen wollte habe ich die Sensoren weggelassen und hab erstmal fixe Werte versucht zu senden:

#include <SPI.h>
#include <ESP8266WiFi.h>

// Wifi Configuration
const char* server = "ingress.opensensemap.org";
WiFiClient client;
const char* ssid = "***";
const char* password = "****";

typedef struct sensor {
    const uint8_t ID[12];
} sensor;

uint8_t sensorsIndex = 0;

// Number of sensors
static const uint8_t NUM_SENSORS = 1;

// senseBox ID : ***
const uint8_t SENSEBOX_ID[12] = { 0x**, 0x**, 0x**, 0x**, 0x**, 0x**, 0x**, 0x**, 0x**, 0x**, 0x**, 0x**};

// sensor IDs
const sensor sensors[NUM_SENSORS] = {
  // Windspeed: 5cb87bc1c9e9ab001a0a6fdf
  {0x**, 0x**, 0x**, 0x**, 0x**, 0x**, 0x**, 0x**, 0x**, 0x**, 0x**, 0x**},
};

uint8_t contentLength = 0;
float values[NUM_SENSORS];

const unsigned int postingInterval = 60000;

void setup() {
  sleep(2000);
  Serial.begin(9600);
  // start the Wifi connection:
  Serial.println("SenseBox Home software version 2.1");
  Serial.println();
  Serial.print("Starting wifi connection...");
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("done!");
  sleep(1000);
  Serial.print("Initializing sensors...");
  //###
  Serial.println("done!");
  Serial.println("Starting loop.\n");
}

void loop() {
  addValue(1.0);
  sleep(200);
  
  submitValues();

  sleep(postingInterval);
}

void addValue(const float& value) {
  values[sensorsIndex] = value;
  sensorsIndex = sensorsIndex + 1;
}

int printHexToStream(const uint8_t* data,
                     uint8_t length,
                     Print& stream)  // prints 8-bit data in hex
{
  byte first;
  int j = 0;
  for (uint8_t i = 0; i < length; i++) {
    first = (data[i] >> 4) | 48;
    if (first > 57) {
      stream.write(first + (byte)39);
    } else {
      stream.write(first);
    }
    j++;

    first = (data[i] & 0x0F) | 48;
    if (first > 57) {
      stream.write(first + (byte)39);
    } else {
      stream.write(first);
    }
    j++;
  }
  return j;
}

int printCsvToStream(Print& stream) {
  int len = 0;
  for (uint8_t i = 0; i < sensorsIndex; i++) {
    if (!isnan(values[i])) {
      len = len + printHexToStream(sensors[i].ID, 12, stream);
      len = len + stream.print(",");
      // do not print digits for illuminance und uv-intensity
      if (i < 3)
        len = len + stream.println(values[i]);
      else
        len = len + stream.println(values[i], 0);
    }
  }
  return len;
}

// millis() rollover fix -
// http://arduino.stackexchange.com/questions/12587/how-can-i-handle-the-millis-rollover
void sleep(unsigned long ms) {     // ms: duration
  unsigned long start = millis();  // start: timestamp
  for (;;) {
    unsigned long now = millis();         // now: timestamp
    unsigned long elapsed = now - start;  // elapsed: duration
    if (elapsed >= ms)                    // comparing durations: OK
      return;
  }
}

void waitForResponse() {
  // if there are incoming bytes from the server, read and print them
  sleep(100);
  String response = "";
  char c;
  boolean repeat = true;
  do {
    if (client.available())
      c = client.read();
    else
      repeat = false;
    response += c;
    if (response == "HTTP/1.1 ")
      response = "";
    if (c == '\n')
      repeat = false;
  } while (repeat);

  Serial.print("Server Response: ");
  Serial.print(response);

  client.flush();
  client.stop();
}

void submitValues() {
  // close any connection before send a new request.
  // This will free the socket on the WiFi shield
  Serial.println("__________________________\n");
  if (client.connected()) {
    client.stop();
    sleep(1000);
  }
  // if there's a successful connection:
  if (client.connect(server, 80)) {
    Serial.println("connecting...");
    // send the HTTP POST request:

    client.print(F("POST /boxes/"));
    printHexToStream(SENSEBOX_ID, 12, client);
    client.println(F("/data HTTP/1.1"));

    // !!!!! DO NOT REMOVE !!!!!
    // !!!!! NICHT LÖSCHEN !!!!!
    // print once to Serial to get the content-length
    int contentLen = printCsvToStream(Serial);
    // !!!!! DO NOT REMOVE !!!!!
    // !!!!! NICHT LÖSCHEN !!!!!

    // Send the required header parameters
    client.print(F("Host: "));
    client.println(server);
    client.print(
        F("Content-Type: text/csv\nConnection: close\nContent-Length: "));
    client.println(contentLen);
    client.println();
    printCsvToStream(client);
    client.println();
    Serial.println("done!");

    waitForResponse();

    // reset index
    sensorsIndex = 0;
  } else {
    // if you couldn't make a connection:
    Serial.println("connection failed. Restarting System.");
    sleep(5000);
    ESP.restart();
  }
}

Bis zum erzeugen der “Nachricht” hat das auch geklappt, aber beim Aufruf der Methode “waitForResponse()” kam dann folgende ESP Exception:

Server Response: 
Soft WDT reset

>>>stack>>>

ctx: cont
sp: 3ffffd50 end: 3fffffc0 offset: 01b0
3fffff00:  00000000 3ffee630 3fffff40 40100a04  
3fffff10:  00c41b4e 00418937 00c41b4e 00000000  
3fffff20:  00c41b4e 00000000 00418937 00000000  
3fffff30:  3ffe88c5 3ffee630 401001a5 4bc6a7f0  
3fffff40:  00000000 00000000 00000000 40203bc0  
3fffff50:  003a0c2d 3ffee680 3ffee680 0000001f  
3fffff60:  3ffe84e4 3ffee680 3ffee630 3ffee78c  
3fffff70:  3fffdad0 00002835 0000ea60 40202572  
3fffff80:  3fffdad0 00000000 3ffee75c 40202814  
3fffff90:  3f800000 3ffe85bd 3ffee680 40202644  
3fffffa0:  feefeffe 00000000 3ffee75c 40204460  
3fffffb0:  feefeffe feefeffe 3ffe8514 40100a61  
<<<stack<<<

Kennt jemand das Problem und weiß wie man es löst?
Ich würde micht freuen, weil ich bin langsam mit meinen Kenntnissen am Ende.


#2

Hi @Herocraft_HD,

habe neuerdings auch einen Wemos D1 zuhause und könnte deinen Sketch die Tage mal testen.

Kannst du mir vielleicht noch kurz sagen, welche Arduino Version du im Einsatz hast und welche ESP8266 Version installiert ist? Dann kann ich es direkt mit den richtigen Versionen versuchen nachzustellen.


#3

Hi @matthias,
vielen Dank erstmal für deine Antwort.
Ich benutze die neuste Version der Arduino IDE (1.8.9). Um den ESP zu programmieren hab ich das esp8266 by ESP8266 Community Paket in der Version 2.5.0 verwendet und das Board WeMos D1 R1 ausgewählt.

Wäre cool wenn du mir da weiterhelfen könntest, wenn es so um Internet geht kommt ich an meine momentane Kenntnis-Grenze.


#4

Hallo *

Ich hab zwar nur das Wemos D1 Mini, aber ich konnte nur noch Downgrade auf Version 2.4.2 weiterarbeiten. Finger weg von der v2.5.0

Grüße von
Boris


#5

Hi Boris,
habe ich probiert, es hat aber nichts an dem Problem geändert.
Es funktioniert ja auch, bis zu dem Zeitpunkt wo er auf Server Response wartet.

SenseBox Home software version 2.1

Starting wifi connection....done!
Initializing sensors...done!
Starting loop.

__________________________

connecting...
5cb87bc1c9e9ab001a0a6fdf,1.00
done!
Server Response: 
Soft WDT reset

ctx: cont 
sp: 3ffffd00 end: 3fffffd0 offset: 01b0

>>>stack>>>
3ffffeb0:  00000000 4bc6a7f0 8f1a9fbe 4020f27e  
3ffffec0:  3ffef018 00000010 00000000 40100575  
3ffffed0:  00000860 3ffefe48 0000196f 000000b3  
3ffffee0:  40104b6e 3ffee468 0013414f 0000001f  
3ffffef0:  00000000 00000004 3ffefe44 4020b23d  
3fffff00:  3ffeec14 0000015a 0000015a 4010020c  
3fffff10:  00000000 3ffeea70 3fffff50 401006dc  
3fffff20:  006bd44a 4bc6a7f0 006bd44a 00000000  
3fffff30:  006bd44a 00000000 4bc6a7f0 00000000  
3fffff40:  00000000 3ffeea70 40106614 4bc6a7f0  
3fffff50:  00000000 00000000 00000000 40203aa8  
3fffff60:  001feadd 3ffeeadc 3ffeeadc 0000001f  
3fffff70:  3ffe84e4 3ffeeadc 3ffeea70 3ffeeb9c  
3fffff80:  3fffdad0 00000fe1 0000ea60 402025ba  
3fffff90:  3fffdad0 00000000 3ffeeb94 40202858  
3fffffa0:  3f800000 3ffe88c4 3ffeeadc 4020268c  
3fffffb0:  feefeffe 00000000 3ffeeb94 40204338  
3fffffc0:  feefeffe feefeffe 3ffe8510 40100739  
<<<stack<<<

Das ist das was er seriell ausgibt.

Ich habe bei einem anderen Eintrag gelesen, dass die Server momentan stark ausgelastet sind. Könnte es damit eswas zu tun haben?


#6

Hallo @Herocraft_HD,

die Server sollten wieder normal laufen und daran sollte es nicht mehr liegen.
Irgendwas kann er mit der Response nicht machen und dann schlägt der Watchdog zu und führt einen Soft reset durch.

Beim Suchen ist mir direkt folgendes Issue auf GitHub aufgefallen: https://github.com/esp8266/Arduino/issues/2866

Hab es mri aber noch nicht weiter angeschaut und auch noch nicht getestet. Hab erst heute Abend Zeit mir das genauer anzuschauen.


#7

Hallo @matthias,
vielen Dank, du hast mich auf die richtige Spur gebracht.
Das Problem war die sleep Funktion. Diese hat ohne delay u.a. das Postinginterval umgesetzt.

void sleep(unsigned long ms) {     // ms: duration
  unsigned long start = millis();      // start: timestamp
  for (;;) {
    unsigned long now = millis();         // now: timestamp
    unsigned long elapsed = now - start;  // elapsed: duration
    if (elapsed >= ms)                    // comparing durations: OK
      return;
  }
}

Der ESP Watchdog hat dann verständlicherweise bei einer einminütigen for-Schleife zugeschlagen. Wenn man die sleep mit einem normalen delay ersetzt funktioniert es.
Ich denke ich werden in Zukunft des delay noch mit einem echten sleep ersetzen um etwas Baterie zu sparen.

Vielen Dank für eue Hilfe.


#8

Ah diese sleep funktion ist noch ein Überbleibsel aus dem Originalen senseBox Sketch für den Arduino Uno…

@Herocraft_HD falls du einen GitHub account hast, könntest du die Anleitung verbessern. Schau mal hier. Dort findest du den Quellcode, aus dem die Anleitungen erstellt werden. Du müsstest nur den Sketch dort mit deiner reparierten Version tauschen.