ESP32....problema con millis()

ciao a Tutti,

come da titolo sto avendo delle dificoltà a capire cosa c’è di sbagliato in una funzione che ho creato per inviare richieste modbus.
cerco di spiegarmi…in allegato il pezzo della funzione incriminato; se nella funzione includo il “Serial.print(’.’)” evidenziato tutto va come deve…se invece metto qualsiasi altra cosa (tipio delay()) o niente il ciclo si blocca e non fa nulla…sembra che millis() non si aggiorni.
il pezzo di codice incriminato è:

              if (!Seriale) {
                Seriale = true;
                ESP_Easy.begin(_myBaud, SERIAL_8N1 + (32 * i) + j, ESP_Easy_RX, ESP_Easy_TX, false, 10000UL);
                ESP_SVS.begin(_myBaud, SERIAL_8N1 + (32 * i) + j, ESP_SVS_RX, ESP_SVS_TX, false, 10000UL);
                node.begin(_ID, ESP_Easy);
              }
              for (byte g = 0; g < 8; g++) {
                ESP_Easy.write(mb_data[g]);
                bittes++;
              }
              if (bittes == 8) {
                ESP_Easy.flush();
                delay(5);
                invio = true;
                Dev_Finder_Time_Out = millis();
                Serial.print('.'); // senza questa si blocca!
              }
            }
            if (invio) {
              bittes = 0;
              if (millis() - Dev_Finder_Time_Out > TIME_OUT) {
                bittes = 0;
                pos = 0;
                invio = false;
                ricerca = false;
                ESP_Easy.end();
                ESP_SVS.end();
                Seriale = false;
                Serial.println("Time out");
              }
              if (ESP_Easy.available() && invio) {
                pos = ESP_Easy.readBytes(mb_answer, 7);
                Dev_Finder_Time_Out = millis();
              }

preciso che il blocco NON attiva nessun WD e NON resetta la ESP32…semplicemente rimane li.
prima di scrivere qui ho fatto tutta una serie di test (con Serial.print() sparse ovunque) e ripeto tutto viene eseguito secondo aspettative…ma arrivato li non prosegue…ed ovviamente non ci sono byte che entrano dalla HS chiamata ESP_Easy!
qui du seguito tutta a funzione:

bool ricercaTST() {
  uint32_t myBaud = 9600;
  uint32_t myConfig = SERIAL_8N1;
  char serialFormat[][14] = {"SERIAL_8N1...", "SERIAL_8E1...", "SERIAL_8O1...", "SERIAL_8N2...", "SERIAL_8E2...", "SERIAL_8O2..."};
  byte mb_data[] = {1, 3, 0, 0, 0, 1, 0, 0};
  byte mb_answer[45];
  bool trovato = false;
  bool ricerca = false;
  bool invio = false;
  uint16_t pos = 0;

  bool Seriale = false;
  uint16_t bittes = 0;

  uint32_t Dev_Finder_Time_Out = 0;
  uint32_t myMillis = millis();

  for (byte _ID = 1; _ID <= 31; _ID++) {
    //node.setID(_ID);
    mb_data[0] = _ID;
    ModRTU_CRC(mb_data, 8);
    for (byte _baud = 1; _baud < 3; _baud++) {
      uint32_t _myBaud = myBaud ;
      _myBaud *= _baud;
      char y = -1;
      for (byte i = 0; i < 2; i++) {
        for (byte j = 0, z = 0; j <= 3; j == 0 ? j += 2 : j++, z++) {
          ricerca = true;
          while (!trovato && ricerca) {
            if (millis() - myMillis > BLINK_SLOW) {
              digitalWrite(LED_BLU, !digitalRead(LED_BLU));
              myMillis = millis();
            }

            if (!invio) {
              y++;
              Serial.print(_ID);
              Serial.print('\t');
              Serial.print(_myBaud);
              Serial.print('\t');
              Serial.print(serialFormat[y]);
              delay(5);

              if (!Seriale) {
                Seriale = true;
                ESP_Easy.begin(_myBaud, SERIAL_8N1 + (32 * i) + j, ESP_Easy_RX, ESP_Easy_TX, false, 10000UL);
                ESP_SVS.begin(_myBaud, SERIAL_8N1 + (32 * i) + j, ESP_SVS_RX, ESP_SVS_TX, false, 10000UL);
                node.begin(_ID, ESP_Easy);
              }
              for (byte g = 0; g < 8; g++) {
                ESP_Easy.write(mb_data[g]);
                bittes++;
              }
              if (bittes == 8) {
                ESP_Easy.flush();
                delay(5);
                invio = true;
                Dev_Finder_Time_Out = millis();
                Serial.print('.'); // senza questa si blocca!
              }
            }
            if (invio) {
              bittes = 0;
              if (millis() - Dev_Finder_Time_Out > TIME_OUT) {
                bittes = 0;
                pos = 0;
                invio = false;
                ricerca = false;
                ESP_Easy.end();
                ESP_SVS.end();
                Seriale = false;
                Serial.println("Time out");
              }
              if (ESP_Easy.available() && invio) {
                pos = ESP_Easy.readBytes(mb_answer, 7);
                Dev_Finder_Time_Out = millis();
              }
              if ( pos == 7) {
                bittes = 0;
                pos = 0;
                invio = false;
                trovato = ModRTU_CRC(mb_answer, 7, true);
                ricerca = false;
                if (!trovato) {
                  ESP_Easy.end();
                  ESP_SVS.end();
                  Seriale = false;
                }
                if (trovato) {
                  break;
                }
              }
            }
          }
          if (trovato) {
            break;
          }
        }
        if (trovato) {
          break;
        }
      }
    }
  }
  if (trovato) {
    Serial.println("TROVATO ");
  }
  if (!trovato) {
    Serial.println("NON TROVATO ");
  }
  return trovato;
}

ho rimosso le “info” in merito a cosa fanno i vari for ed if…alla fine devo verificare con che impostazioni di seriale (baud, parity, stop bit) mi risponde uno slave che può avere ID da 1 a 31…
se guardate c’è un piccolo for per far lampeggiare il LED blu della ESP…senza quel Serial.print(’.’) nemmeno quello funziona più…con la Serial.print()…va alla grande. ::slight_smile:

a dirla tutta ho avuto anche problemi con la serialFormat[y] che ho risolto con quella char y messa così…se provavo a fare una cosa del tipo:

serialFormat[((i*3)+z)]

che dovrebbe ritornare valori da 0 a 5…si bloccava tutto al primo risultato utile cioè (0*3)+0 = 0…ma forse era sempre dovuto alla mancanza di quella Serial.print(’.’) che ho aggiunto dopo…

grazie

Serial.print('\t');

Serial.print('\t');

Prova...

Scusa ma mi renderizzava uno dei caratteri ' in modo anomalo è ho voluto provare se per caso c'era qualche carattere spurio nel codice, invece sembra tutto ok, anzi no vedo ancora carattere strano al posto di ', bo nel mio post non c'è.

Allora il problema odora di stack corruption ma su ESP questo dovrebbe sollevare una eccezione e dovresti vedere dei messaggi di log sempre che li hai abilitati.

Alcune cose che mi fanno storcere il naso sono:
Il for e if e while innestati sono troppo lunghi.
Troppe variabili sparse locali rendono complicato seguire il codice.
Questa la preferisco così.

const char *serialFormat[] = {"SERIAL_8N1...", "SERIAL_8E1..."
                                   , "SERIAL_8O1...", "SERIAL_8N2..."
                                   , "SERIAL_8E2...", "SERIAL_8O2..."};

Per prova puoi provare a ridimenzionare l'impegno di stack riducendo la dimensione della funzione, ma devi procedere a tentativi.

Ciao.

ciao Maurotec,

grazie per la risposta...quello che posso dire per l'ipiego di memoria è che al momento il programma compila ritornando:

Lo sketch usa 260749 byte (19%) dello spazio disponibile per i programmi. Il massimo è 1310720 byte.
Le variabili globali usano 15780 byte (4%) di memoria dinamica, lasciando altri 311900 byte liberi per le variabili locali. Il massimo è 327680 byte.

quindi di memoria disponibile penso ce ne sia.

per quanto riguarda le eccezioni di solito l'ESP32, quando faccio le mie solite 'zzatine, mi ritorna l'eccezione che poi ricerco (mi sono anche installato il tool per rederle più leggibili)...o ci sono altre opzioni da selezionare per avere più info (quelle della compilazione sono già al massimo)!?...
In questo caso semplicemente si mette in pausa!...come se ci fosse un delay() infinito...per curiosità l'ho lasciato li mezz'ora e non è cambiato nulla...se invece aggiungo quella Serial.print('.') va tutto bene.

modificando questo if:

if (millis() - Dev_Finder_Time_Out > TIME_OUT) {
                bittes = 0;
                pos = 0;
                invio = false;
                ricerca = false;
                ESP_Easy.end();
                ESP_SVS.end();
                Seriale = false;
                Serial.println("Time out");
              }

in questo modo funziona anche senza la Serial.print(’.’):

if (millis() - Dev_Finder_Time_Out > TIME_OUT) {
                bittes = 0;
                pos = 0;
                Serial.println("Time out");
                invio = false;
                ricerca = false;
                Seriale = false;
                ESP_Easy.end();
                ESP_SVS.end();
              }

Piccola domanda (forse off topic): come mai è così complicato e nidificato quel programma?
Le mie richieste al Modbus sono di una o due righe...

ciao Steve,

perchè la richiesta modbus la faccio in hardcode...cioè byte a byte...non uso librerie modbus (per il momento)...questo perchè non conosco a priori l'impostazione seriale dello slave...devo trovarle e poi creo il nodo modbus.

Io ho capito che provi due baudrate: 9600 e 19200 allora visto che sai di questi due valori perché non usare un array anziché calcolare con questo for:

for (byte _baud = 1; _baud < 3; _baud++) {
      uint32_t _myBaud = myBaud ;
      _myBaud *= _baud;

quando basterebbe:

for (byte baudIdx=0; baudIdx<2; baudIdx++) {
    chekBaud = baudList[baudIdx];

Anche il for seguente è davvero difficile da comprendere e infatti ancora non mi pare chiaro:

for (byte j = 0, z = 0; j <= 3; j == 0 ? j += 2 : j++, z++) {

Capisci che la mia è solo una critica costruttiva al fine di rendere più comprensibile il codice e fare emergere gli errori che si possono commettere facilmente quando i cilci sono così ampi.

Ciao.

Capisci che la mia è solo una critica costruttiva al fine di rendere più comprensibile il codice e fare emergere gli errori che si possono commettere facilmente quando i cilci sono così ampi.

assolutamente si…altrimenti mica venivo a chiedere qui :wink:

per i cicli…quello con l’operatore ternario deriva dal fatto che:

/*in ESP32 le define per il tipo di comunicazione hanno valori diversi da arduino; in BIT sono:
  1000000000000000000000011100 -> SERIAL_8N1
  1000000000000000000000011110 -> SERIAL_8E1
  1000000000000000000000011111 -> SERIAL_8O1

  1000000000000000000000111100 -> SERIAL_8N2
  1000000000000000000000111110 -> SERIAL_8E2
  1000000000000000000000111111 -> SERIAL_8O2
  quindi, per configurare la porta HS si essguira il ciclo
  for (byte i = 0; i < 2; i++) {
    for (byte j = 0; j <= 3; j == 0 ? j += 2 : j++) {
      Serial.println((SERIAL_8N1 + (32 * i)) + j, BIN);
    }
  }
  questo ciclo va ripetuto per 2 volte alla ricerca del baud rate (9600 o 19200)
*/

quindi (solo per dire)…al valore di base dato dalla #define SERIAL_8N1 si devono aggiungere 32 per passare da 1 a 2 bit di stop e fare salti a 0,2,3 (1 mancante) per selezionare la parità.
E tu penserai…si poteva fare anche questo con un array!?..sicuramente si come per i baud…ma nella mia testa ero partito con i for…e mi è venuto naturale continuare in questo modo…quando questa parte del progetto, che include altre azioni/funzioni, sarà completata vedrò di migliorare, spero, il tutto.