Problema lettura seriale ed esecuzione loop

Ciao a tutti sono nuovo del forum.
Sto sviluppando una scheda che va a leggere dei dati tramite seriale e li trasmette tramite un modulo SIM800L ad un server via HTTP POST.
Nello stesso tempo ogni x secondi fa una verifica sul server se ci sono comandi da eseguire.

Ora vi pongo il mio problema (ASSURDO)

Progetto realizzato con ESP-01 Standalone (Ovviamente non comunica in GPRS) nessun problema.
Setup() -> Loop(){leggo da server (eseguo da server e stampo su seriale se c'è da eseguire); leggo seriale; (eseguo seriale se c'è da eseguire e aggiorno su server ) ........ e così via}

Stessa cosa l'ho realizzata con Mega2560 e SIM800L ed ecco il blocco

Se sto leggendo da server e mi arriva qualcosa su seriale si mangia parte dei pacchetti :o

Leggo questo:
AT+SD=2|4|0|0|0|0|0|1|1|100|0|0|0|0|0|1|0|0|0|0|0|0|0|0|0|0|0|0AT+SC=1|0|0|0|0|0|0|0|5.03|11011711010711911100014010|

Ma ho inviato questo:
AT+SD=2|4|0|0|0|0|0|1|1|100|0|0|0|0|0|1|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|1|50|0|0|0|0|0|0|0|1|20|0|0|0|0|0|0|0|1|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|||||||||||||||||||1|0000|0|0|0|0|0|5.03|0.00|0.00|-3875.00|1|

AT+SC=1|0|0|0|0|0|0|0|5.03|11011711010711911100014010|

Buonasera e benvenuto, :slight_smile:
essendo il tuo primo post, nel rispetto del regolamento della sezione Italiana del forum (… punto 13, primo capoverso), ti chiedo cortesemente di presentarti IN QUESTO THREAD (spiegando bene quali conoscenze hai di elettronica e di programmazione ... possibilmente evitando di scrivere solo una riga di saluto) e di leggere con molta attenzione tutto il su citato REGOLAMENTO ... Grazie. :slight_smile:

Guglielmo

P.S.: Ti ricordo che, purtroppo, fino a quando non sarà fatta la presentazione nell’apposito thread, nessuno ti potrà rispondere, quindi ti consiglio di farla al più presto. :wink:

Il fatto che per programmere i due oggetti usi l’IDE di Arduino con lo stesso codice, NON significa che i due oggetti siano paragonabili …

Il ESP8266 montato su ESP-01 è comunque un chip che viaggia ad una frequenza (80 MHz) parecchie volte superiore a quella di un ATmega2560 che va a 16 MHz e NON so neanche se la classe Serial è implementata allo stesso modo o se il buffer circolare di ricezione è più grande su ESP che non su AVR … ::slight_smile:

Quello che riscontri è semplicemente che NON riesci a leggere a sufficiente velocità i dati che arrivano, il buffer si riempie e tu perdi quelli che arrivano dopo …

O rallenti la velocità di trasmissione della seriale o metti le mani nel “core” Arduino (ma te lo sconsiglio) e modifichi la dimensione del buffer usato in ricezione.

Guglielmo

Allora vi aggiorno…
Ho provato ad abbassare la velocità della seriale da 115200 a 9600 (ovviamente gradualmente) e la situazione è migliorata un pò ma il pacchetto mi arrivava sempre troncato. Ne arrivavano due ma sempre troncati quasi a metà.

Ho provato ad alzare la dimensione del buffer del core ed a quanto pare la comunicazione tra scheda1 e scheda2 funzioni perfettamente. Ora mi è sorto il problema che il SIM800L mi restituisce dei codici HTTP strani quando invio i dati al server.

di seguito posto la modifica al file HardwareSerial.h

#if !defined(SERIAL_TX_BUFFER_SIZE)
#if ((RAMEND - RAMSTART) < 1023)
#define SERIAL_TX_BUFFER_SIZE 256
#else
#define SERIAL_TX_BUFFER_SIZE 256
#endif
#endif
#if !defined(SERIAL_RX_BUFFER_SIZE)
#if ((RAMEND - RAMSTART) < 1023)
#define SERIAL_RX_BUFFER_SIZE 256
#else
#define SERIAL_RX_BUFFER_SIZE 256
#endif
#endif

Non so se il problema dei codici HTTP derivi dalla modifica al buffer… anche perchè il modulo si registra tranquillamente al provider e risponde normalmente ai comandi AT.

Paolo

Ti bastava toccare il RX_BUFFER e non il TX che non ti serve particolarmente grande (almeno credo) ... ::slight_smile:

Comunque occhio che, ad ogni aggiornamento dell'IDE, devi rifare tutto da capo ... :confused:

Guglielmo

Bhe la scheda risponde al master con lo stesso pacchetto che a sua volta gli da un ack* quindi ho pensato di dare le stesse dimensioni.

Es.
Ricevo: AT+SD=1................................X
Reply: AT+SD=OK,1................................X (quando completo la trasmissione al server)
Ricevo: AT+SD=OK ed il master si ferma. in caso contrario il master ritrasmette il pacchetto perchè deduce che per un motivo o per un altro non l'ho percepito o non sono riuscito a trasmetterlo al server.

Comunque ancora il problema dei messaggi HTTP 701 / 705 continua. Mi sa che dovrò fare un altro Thread :frowning:
Grazie 1000 Guglielmo mi sei stato di grande aiuto...

Ma tu quando leggi da server lo fai in un'unica procedura e leggi tutto assieme?
Perchè forse si può scrivere il tutto in modo che sia parallelizzabile dandoti la possibilità di svuotare il buffer della seriale prima che si riempia del tutto andando a sovrascriere/perdere pezzi.

Cioè, hai pezzi di software che monopolizzino la MCU per troppo tempo? Bisognerebbe agire su questi punti per cercare di ridurre il tempo di monopolio al minimo, il trucco, spesso, è parallelizzare.
Cioè ad ogni giro di loop leggo solo un piccolo pezzo così ho il tempo di fare anche altro.

Poi, vabeè, aumentare il buffer mitiga il problema, ma se poi invece di due comandi AT te ne arrivano 5 sei da capo, qualcosa te lo perdi comunque se quello che arriva supera il buffer che hai ridefinito.

Io valuterei la parallelizzazione massima delle operazioni.
Ovvio che per essere più specifici servirebbe vedere il codice.

Maurizio

Ciao Maurizio no non manipolo nulla di quello che ricevo dalla seriale. L’unica cosa che faccio è leggere la seriale estrapolare quello che segue il simbolo = e trasmetterlo al server. Ovviamente in funzione del comando che ricevo AT+… rimando il loop alla funzione di trasmissione dell’evento.

Questo è il loop

void loop() {
  while (Serial1.available()) {
    char inChar = (char)Serial1.read();
    if (inChar == '\n' || inChar == '\r') {
      Serial.println(inputString);
      String data = inputString;
      inputString = "";
      data.replace("\n", "");
      data.replace("\r", "");
      if (data.indexOf("AT+ID=") > -1) {
        String rxData = getValue(data, '=', 1);
        id = rxData;
        Serial.print("AT+ID=OK," + id + '\n');
        return;
      }
      if (data.indexOf("AT+PWROF=1") > -1) {
        Serial.print("AT+PWROF=OK" + '\n');
        return;
      }
      if (data.indexOf("AT+SD=") > -1) {
        String rxData = getValue(data, '=', 1);
        lastMsg[1] = rxData;//{rx, txData, txEvento, txConfig}
        sendDataSRV();
        return;
      }
      if (data.indexOf("AT+SE=") > -1) {
        String rxData = getValue(data, '=', 1);
        lastMsg[2] = rxData;//{rx, txData, txEvento, txConfig}
        sendEventSRV();
        return;
      }
      if (data.indexOf("AT+SC=") > -1) {
        String rxData = getValue(data, '=', 1);
        lastMsg[3] = rxData;//{rx, txData, txEvento, txConfig}
        sendConfigSRV();
        return;
      }
    } else {
      inputString += inChar;
    }
  }
  if (lastMsg[1].length() > 0){sendDataSRV();}
  if (lastMsg[3].length() > 0){sendConfigSRV();}
  if (millis() > nextChk && id != "") {
    nextChk = millis() + 2500;
    String payload = getData();
    String rxData = getValue(payload, '#', 1);
    if (rxData.indexOf("ACK*") > -1) {
      lastMsg[0] = "";
    }
    if (rxData.indexOf("AT+") > -1) {
      if (lastMsg[0] != rxData) {
        lastMsg[0] = rxData;
        String replyMsg = rxData;
        Serial1.print(rxData + '\n');
        sendRXAck();
      } else {
        sendRXAck();
      }
    }
    Serial.println("Get: " + getData());
  }

}

Questa è una delle funzioni di sendData:

void sendEventSRV() {
  digitalWrite(13, !digitalRead(13));
  delay(100);
  digitalWrite(13, !digitalRead(13));
  delay(200);
  digitalWrite(13, !digitalRead(13));
  delay(100);
  digitalWrite(13, !digitalRead(13));
  bool connected = false;
  for (uint8_t i = 0; i < 5 && !connected; i++) {
    delay(1000);
    connected = sim800l->connectGPRS();
  }
  if (!connected) {
    sim800l->reset();
    setupModule();
    return;
  }
  String data = "";
  String evento = getValue(lastMsg[2], '|', 0);
  String uid =  getValue(lastMsg[2], '|', 1);
  String queryString = PATH_NAME;
  queryString += "f=sendEvento&id=" + String(id) + "&evento=" + evento + "&uid=" + uid;
  queryString.replace(" ", "%20");
  String composeURL = "http://xx.xx.xx.xx" + queryString;
  const char getURL[composeURL.length() ];
  composeURL.toCharArray(getURL, composeURL.length() );
  Serial.println(getURL);
  uint16_t rc = sim800l->doGet(getURL, 10000);
  if (rc == 200) {
    Serial.print("AT+SE=OK," + lastMsg[2] + '\n');
    lastMsg[2] = "";
  } else {
    Serial.println(rc);
  }
  bool disconnected = sim800l->disconnectGPRS();
  for (uint8_t i = 0; i < 5 && !connected; i++) {
    delay(1000);
    disconnected = sim800l->disconnectGPRS();
  }
}

Questa invece è la funzione di lettura sul server:

String getData() {
  digitalWrite(13, !digitalRead(13));
  passiveDelay(50);
  digitalWrite(13, !digitalRead(13));
  bool connected = false;
  for (uint8_t i = 0; i < 5 && !connected; i++) {
    delay(1000);
    connected = sim800l->connectGPRS();
  }
  if (!connected) {
    sim800l->reset();
    setupModule();
    return;
  }
  String data = "";
  String composeURL = "http://xx.xx.xx.xx/" + String(id) + ".txt";
  const char getURL[composeURL.length() + 1];
  composeURL.toCharArray(getURL, composeURL.length() + 1);
  //Serial.println(getURL);
  uint16_t rc = sim800l->doGet(getURL, 10000);
  if (rc == 200) {
    data = getValue(sim800l->getDataReceived(), '#', 1);
    data.replace("#", "");
  }
  bool disconnected = sim800l->disconnectGPRS();
  for (uint8_t i = 0; i < 5 && !connected; i++) {
    delay(1000);
    disconnected = sim800l->disconnectGPRS();
  }
  nextChk = millis() + 5000;
  return data;
}

Paolo

Nella getData() hai dei delay(1000) che di sicuro non aiutano.
Parallelizzare, per come la volevo intendere io, significava non usare dei delay ma temporizzare con millis facendo proseguire comunque il loop dove acquisisci da seriale.

Tutte le funzioni che non richiedono tempistiche troppo stringenti e che possono essere concettualente spezzate in pezzi distinti andrebbero gestire con una macchina a stati eseguendo i vari pezzi su più cicli di loop in modo da dar modo al loop di fare altre operazioni.

In altre parole, quando esegui la getData() hai tutto bloccato per parecchio tempo, almeno 2s, e se in questo lasso di tempo sulla seriale ti arrivano più dati di quelli che può contenere il buffer, sei fregato.
E in 2s di dati ne possono arrivare tantini.

Maurizio

Onestamente il delay del getData era già nella libreria del SIM800. E' il timeout per il tentativo successivo di connessione. Non so se posso toglierlo per mettere un millis.

significava non usare dei delay ma temporizzare con millis facendo proseguire comunque il loop dove acquisisci da seriale.

Intendi mettere delle variabili di conteggio e indicare

if(millis() > chk){
 ....codice
}

Si, esatto, anche se il test con millis() non andrebbe fatto così, per evitare i problemi di overflow, ma una cosa del tipo:

  #define INTERVAL 1000
  ...
  unsigned long currentMillis = 0;
  ...
  currentMillis = millis();
  ...
  if(currentMillis - previousMillis > INTERVAL) {
  ...

Maurizio

Proverò... ti faro sapere :wink:

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.