Problemi con ESP8266 su Logger

Buongiorno a tutti,
spero possiate aiutarmi e spero di non aver sbagliato a postare.

Ho assemblato un logger per controllare le temperature di una cella frigorifera con un Arduino Uno R3, una Shield Data Logger, un monitor LCD non I2C, due led, una sonda di temperatura Dallas DS18B20 e una ESP8266 connessa tramite un adattatore ESP-01.

Tramite chiamata http interrogo il logger ogni 5’ e faccio tornare indietro un json in questo modo:
{“idCella”:“1”,“data”:“2020-06-21 10:11:19”,“temperatura”:“3.69”}

Il dato viene poi registrato su una tabella in un DB e riproposto in un grafico su un’applicazione web.

Ho testato il tutto per qualche giorno e sembrava funzionare senza problemi, ma poi pare che la esp8266 si sia bloccata e finché non ho resettato l’Arduino non è ripartita.

Dal momento in cui va in blocco non riesco più ad effettuare chiamate http.
La vedo connessa sul router all’indirizzo 192.168.1.20 (assegnato fisso), faccio partire la chiamata (ho provato da browser) ma non torna mai la risposta.
Sta lì finché non va in timeout la chiamata e non ritorna indietro niente.
Se poi resetto il tutto riparte regolarmente ma non so capire quando poi si bloccherà di nuovo.

Le chiamate non mi sembrano troppo fitte come tempo (5 minuti) e il curl contenuto nella pagina php che uso per interrogare il dispositivo ha un timeout impostato a 5 secondi.

Lo sketch caricato su Arduino è questo:

#include <SoftwareSerial.h>
#include <Wire.h>
#include "RTClib.h"
//#include <SD.h>
#include <LiquidCrystal.h>
#include <OneWire.h>
#include <ArduinoJson.h>

//#define CS 10
#define DEBUG true
#define LCD_LIGHT_PIN A0
#define LED_YELLOW_PIN 13
#define LED_RED_PIN 6

SoftwareSerial esp8266(8, 9);

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
char lcdBuffer[16];

int DS18B20_Pin = 7;
OneWire ds(DS18B20_Pin);

RTC_DS1307 RTC;
char buffer[40];

//File dataFile;
//const char filename[] = "fermlog.CSV";

int lastTime = -1;

void setup() {
  Serial.print(F("Setting pin mode..."));
  //pinMode(CS, OUTPUT);
  pinMode(LED_YELLOW_PIN, OUTPUT);
  pinMode(LED_RED_PIN, OUTPUT);
  Serial.println(F("done."));

  delay(1000);

  flashLED(LED_YELLOW_PIN);

  delay(1000);

  Serial.print(F("Starting LCD..."));
  lcd.begin(16, 2);
  lcd.setCursor(0, 0);
  lcd.print("Fermentation    ");
  lcd.setCursor(0, 1);
  lcd.print("Logger v2.0     ");

  pinMode(LCD_LIGHT_PIN, OUTPUT);
  digitalWrite(LCD_LIGHT_PIN, HIGH);
  Serial.println(F("done."));

  delay(3000);

  Serial.begin(9600);
  esp8266.begin(9600);

  sendData("AT+RST\r\n", 2000, DEBUG);          // command to reset the module
  sendData("AT+CWMODE=3\r\n", 1000, DEBUG);     // This will configure the mode as access point
  sendData("AT+CWJAP=\"TIM-17576626\",\"5zgfCHtUL7ctPGbU\"\r\n", 20000, DEBUG);
  sendData("AT+CIFSR\r\n", 1000, DEBUG);        // This command will get the ip address
  sendData("AT+CIPMUX=1\r\n", 1000, DEBUG);     // This will configure the esp for multiple connections
  sendData("AT+CIPSERVER=1,80\r\n", 1000, DEBUG); // This command will turn on the server on port 80

  delay(2000);

  flashLED(LED_RED_PIN);

  /*
    Serial.println(F("Init SD card..."));
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Init SD Card...");
    lcd.setCursor(0,1);

    if (!SD.begin(CS)) {
    Serial.println(F("initialization failed!"));
    lcd.print("... Failed   ");
    return;
    }
    Serial.println(F("initialization done."));
    lcd.print("... Ready    ");

    delay(2000);
  */

  Serial.print(F("Starting Tiny RTC..."));
  Wire.begin();
  RTC.begin();
  //RTC.sqw(0);        //0 Led off - 1 Freq 1Hz - 2 Freq 4096kHz - 3 Freq 8192kHz - 4 Freq 32768kHz

  if (! RTC.isrunning()) {
    Serial.println(F("RTC is NOT running!"));
    //sets the RTC to the date & time this sketch was compiled
    RTC.adjust(DateTime(__DATE__, __TIME__));
  }
  Serial.println(F("done."));

  /*
    delay(2000);

    // Scrittura riga di accensione logger
    dataFile = SD.open(filename, FILE_WRITE);
    if (dataFile) {
    dataFile.println("*****Accensione Logger*****");
    dataFile.close();
    }
  */

  // Testo se c'è connessione
  String response = sendData("AT+CWJAP?\r\n", 500, DEBUG);
  if(response.indexOf("TIM-17576626") > 0) {
    digitalWrite(LED_RED_PIN, HIGH);
  } else {
    digitalWrite(LED_RED_PIN, LOW);
  }
}

void loop() {
  DateTime now = RTC.now();
  float temperature = getTemp();

  lcd.clear();

  sprintf(lcdBuffer, "%02d/%02d/%04d %02d:%02d", now.day(), now.month(), now.year(), now.hour(), now.minute());
  lcd.setCursor(0, 0);
  lcd.print(lcdBuffer);
  //Serial.print(F("Date: "));
  //Serial.println(lcdBuffer);

  lcd.setCursor(0, 1);
  lcd.print(temperature);
  lcd.setCursor(6, 1);
  lcd.print((char)223);
  lcd.print("C");
  //Serial.print(F("Temperature: "));
  //Serial.println(temperature);

  delay(1000);

  //String response = sendData("AT+CIPSTATUS\r\n", 500, DEBUG);
  /*
  // Testo se c'è connessione
  String response = sendData("AT+CWJAP?\r\n", 500, DEBUG);
  if(response.indexOf("TIM-17576626") > 0) {
    digitalWrite(LED_RED_PIN, HIGH);
  } else {
    digitalWrite(LED_RED_PIN, LOW);
  }

  delay(1000);
  */
  
  // This command will that check if the esp is sending a message
  if (esp8266.available()) {
    if (esp8266.find("+IPD,")) {

      flashLED(LED_YELLOW_PIN);
      
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Invio dati      ");
      lcd.setCursor(0, 1);
      lcd.print("in corso...     ");

      sprintf(buffer, "%d-%02d-%02d %02d:%02d:%02d", now.year(), now.month(), now.day(), now.hour(), now.minute(), now.second());
      //Serial.println(buffer);
      
      StaticJsonDocument<256> doc;
      JsonObject root = doc.to<JsonObject>();
      root["idCella"] = "1";
      root["data"] = buffer;
      root["temperatura"] = String(temperature);

      /*dataFile = SD.open(filename, FILE_WRITE);
        if (dataFile) {
        dataFile.println(buffer);
        dataFile.close();
        } else {
        Serial.print(F("error opening "));
        Serial.println(filename);
        }*/

      delay(1000);
      int connectionId = esp8266.read() - 48; /* We are subtracting 48 from the output because the read() function returns
                                            the ASCII decimal value and the first decimal number which is 0 starts at 48*/
      String webpage = "";
      serializeJson(doc, webpage);
      
      serializeJson(doc, Serial);
      
      String cipSend = "AT+CIPSEND=";
      cipSend += connectionId;
      cipSend += ",";
      cipSend += webpage.length();
      cipSend += "\r\n";

      sendData(cipSend, 1000, DEBUG);
      sendData(webpage, 1000, DEBUG);
      String closeCommand = "AT+CIPCLOSE=";
      closeCommand += connectionId;
      closeCommand += "\r\n";
      sendData(closeCommand, 3000, DEBUG);
    }
  }
}

void flashLED(int ledPin) {
  Serial.print(F("Flashing LED..."));
  digitalWrite(ledPin, HIGH);
  delay(100);
  digitalWrite(ledPin, LOW);
  delay(100);
  digitalWrite(ledPin, HIGH);
  delay(100);
  digitalWrite(ledPin, LOW);
  delay(100);
  digitalWrite(ledPin, HIGH);
  delay(100);
  digitalWrite(ledPin, LOW);
  Serial.println(F("done."));
}

String sendData(String command, const int timeout, boolean debug) {
  String response = "";
  esp8266.print(command);
  long int time = millis();
  while ( (time + timeout) > millis()) {
    while (esp8266.available()) {
      char c = esp8266.read();
      response += c;
    }
  }
  if (debug) {
    Serial.print(response);
  }
  return response;
}

float getTemp() {
  //returns the temperature from one DS18B20 in DEG Celsius
  byte data[12];
  byte addr[8];

  if (!ds.search(addr)) {
    //no more sensors on chain, reset search
    ds.reset_search();
    return -1000;
  }

  if (OneWire::crc8( addr, 7) != addr[7]) {
    Serial.println("CRC is not valid!");
    return -1000;
  }

  if (addr[0] != 0x10 && addr[0] != 0x28) {
    Serial.print("Device is not recognized");
    return -1000;
  }

  ds.reset();
  ds.select(addr);
  ds.write(0x44, 1);

  byte present = ds.reset();
  ds.select(addr);
  ds.write(0xBE); // Read Scratchpad

  for (int i = 0; i < 9; i++) {
    data[i] = ds.read();
  }

  ds.reset_search();

  byte MSB = data[1];
  byte LSB = data[0];

  float tempRead = ((MSB << 8) | LSB);
  float TemperatureSum = tempRead / 16;

  return TemperatureSum;
}

Per il codice ho preso vari pezzi da sketch trovati su internet e magari c’è qualcosa che non torna.
Come se alle volte non si riuscisse a chiudere la connessione con l’esp8266.

Se qualcuno di voi è così gentile da controllarmi il codice per capire se c’è qualcosa che non va lo ringrazio vivamente.

Tommaso

ma poi pare che la esp8266 si sia bloccata e finché non ho resettato l’Arduino non è ripartita.

Sicuro che si sia bloccata la esp8266 e non l’arduino?
Nel codice vedo che usi molto la String, e questo non va molto bene, specialmodo con scheda come l’arduino uno che ha poca ram. In alternativa prova a riscrivere il tutto usando le funzioni classiche string del C, oppure puoi provare la nuova classe SafeString, che nasce proprio per ovviare a questo.

Edit= Dimenticavo : lcdBuffer dovrebbe essere lunga 17, non 16 (16 caratteri + lo ‘\0’ di terminazione), magari non è quello il problema ma sistemalo, non si sa mai!

Ciao, Ale.

Grazie per la risposta e il suggerimento.
Proverò nei prossimi giorni a modificare lo sketch e a vedere che non si blocchi.

Ciao, Tommaso

ilguargua:
Sicuro che si sia bloccata la esp8266 e non l'arduino? ...

Sembra che funzioni, quindi grazie di nuovo.
Tommaso

Prego, anche se così non è ben chiaro quali passi abbiano portato alla risoluzione del problema...

Ciao, Ale.

ilguargua:
Prego, anche se così non è ben chiaro quali passi abbiano portato alla risoluzione del problema...

Ciao, Ale.

Hai ragione.
Ho sostituito tutte le String usando le funzioni classiche string del C.

Tommaso