Help: Saturazione della flash

Ciao ragazzi, ho notato che dopo circa 100 volte che mi ripete questo “ciclo”

void APN() {
  gprsSerial.println("AT+CMGF=1\r\n");
  delay(50);
  pulserial();
  gprsSerial.println("AT+CMGL=\"REC UNREAD\"\r\n");
  delay(50);
  byte puntatore = 0;
  char convalpar = "";
  String valpar = "";
  String apn = "";
  char apn2[20];
  boolean uscciclo = 0;
  boolean carerr = 0;
  char svubuffer = "";
  while (uscciclo < 1 ) {
    if (gprsSerial.available() > 0 and uscciclo < 1) {
      if (puntatore == 24 or puntatore >= 89) {
        convalpar = gprsSerial.read();
        valpar = convalpar;
        Serial.println("valpar:  " + valpar);
        if (valpar == "E" or valpar == "O") {
          uscciclo = 1;
        }
        if (valpar == "<" or puntatore >= 90) {
          apn = apn + valpar;
          if (valpar == ">") {
            apn.replace("<apn<", "");
            uscciclo = 1 ;
          }
        }
        if (valpar != "<" and puntatore == 89) {
          uscciclo = 1;
          carerr = 1;
        }
      } else {
        svubuffer = gprsSerial.read();
      }
      puntatore++;
    }
  }

  if (valpar == "E" or valpar == "O" or carerr == 1) {
    allapn();
    pulserial();
    gprsSerial.println("AT+CMGDA=\"DEL READ\"\r\n");
    delay(2000);
    pulserial();
    APN();
  }

  apn.toCharArray(apn2, 20);
  Serial.println(apn2);
  for (int i = 0; i <= 20 - 1; i++) {
    EEPROM.write(i, apn2[i]);
    if (apn2[i] == ">") {
      i = 20;
    }
    delay(100);
  }
  delay(15000);
}

il programma si blocca.

La seriale dopo che mi ripete in modo corretto lo stesso valore " valpar: O" finisce di stamparmi una riga vuota (non corretto) e si pianta.
In allegato potete trovare la foto di cosa mi spunta nella seriale.
Arduino utilizzato: Arduino Mega 2560

Ho fatto altre prove, si blocca nel momento in cui dichiaro le variabili. Mi conviene dichiarli all’inizio del programma ?

Aggiornamento codice programma:

void APN() {
  gprsSerial.println("AT+CMGF=1\r\n");
  delay(50);
  pulserial();
  gprsSerial.println("AT+CMGL=\"REC UNREAD\"\r\n");
  delay(50);
  Serial.println("inizio");
  puntatore = 0;
  convalpar = "";
  valpar = "";
  apn = "";
  apn2[20];
  uscciclo = 0;
  carerr = 0;
  svubuffer = "";
  while (uscciclo < 1 ) {
    if (gprsSerial.available() > 0 and uscciclo < 1) {
      if (puntatore == 24 or puntatore >= 89) {
        convalpar = gprsSerial.read();
        valpar = convalpar;
        Serial.println("valpar:  " + valpar);
        if (valpar == "E" or valpar == "O") {
          uscciclo = 1;
        }
        if (valpar == "<" or puntatore >= 90) {
          apn = apn + valpar;
          if (valpar == ">") {
            apn.replace("<apn<", "");
            uscciclo = 1 ;
          }
        }
        if (valpar != "<" and puntatore == 89) {
          uscciclo = 1;
          carerr = 1;
        }
      } else {
        svubuffer = gprsSerial.read();
      }
      puntatore++;
    }
  }

  if (valpar == "E" or valpar == "O" or carerr == 1) {
    allapn();
    pulserial();
    gprsSerial.println("AT+CMGDA=\"DEL READ\"\r\n");
    delay(2000);
    pulserial();
    APN();
  }

  apn.toCharArray(apn2, 20);
  Serial.println(apn2);
  for (int i = 0; i <= 20 - 1; i++) {
    EEPROM.write(i, apn2[i]);
    if (apn2[i] == ">") {
      i = 20;
    }
    delay(100);
  }
  delay(15000);
}

Grazie.

Così di primo occhio l'unico consiglio che ti do é, per tutte le print e println di stringhe fisse scrivere prima della '(' una 'F', così da farle scrivere nella memoria di programma, in modo tale che la flash sia usata meno (sempre ammesso che il problema sia quello dato che, essendo una funzione, resetta le sue variabili ogni ciclo)

Dentro APN() c'è una chiamata ad APN(), se stai facendo chiamate ricorsive per forza che si blocca...

Ciao docdoc, lui mi deve ripetere quella funzione fina a quando non riceve l’apn:

if (valpar == "<" or puntatore >= 90) {
          apn = apn + valpar;
          if (valpar == ">") {
            apn.replace("<apn<", "");
            uscciclo = 1 ;
          }

fabio22:
Ciao docdoc, lui mi deve ripetere quella funzione fina a quando non riceve l’apn:

Ho capito, ma QUELLA che fai lì è una chiamata RICORSIVA e con piccoli MCU è una cosa che VA EVITATA.

Non avendo il contesto (né lo sketch completo né conoscendo l’esigenza), non so dirti come, ma devi trasformarla in un ciclo, o, meglio, implementarla come macchina a stati finiti. Ma non puoi fare chiamate ricorsive.

Ragazzi, smettiamola di dire cose senza senso:

  1. La ricorsione INDETERMINATA è sempre sbagliata.
  2. D'accordo che su una MCU con RAM limitata (e dunque con stack molto limitato) la ricorsione non è una tattica particolarmente furba da usare, ma entro certi limiti si potrebbe pure fare, magari per eseguire alcuni algoritmi che in versione ricorsiva sono decisamente più semplici che in verione iterativa.
  3. Lasciando comunque un attimo da parte le seghe mentali, nel caso esposto dall'OP non c'è alcun motivo per dovere ricorrere alla ricorsione, va eliminata, punto e basta.

Posso fare che il tutto l’ho metto all’interno di un ciclo while.

void APN(){
   while (x<1) {

    tutto il codice pubblicato prima.


   }
}

Così va bene ?

fabio22:
Posso fare che il tutto l’ho metto all’interno di un ciclo while.
Così va bene ?

Se in “tutto il codice pubblicato prima” c’è anche questa if():

  if (valpar == "E" or valpar == "O" or carerr == 1) {
    allapn();
    pulserial();
    gprsSerial.println("AT+CMGDA=\"DEL READ\"\r\n");
    delay(2000);
    pulserial();
    APN();  // <===QUESTO E' IL PROBLEMA!
  }

ossia la chiamata ad APN() all’interno della stessa funzione, no che non va bene.

Se ho capito bene l’esigenza, se vuoi fare una cosa del genere o sei SICURO che la chiamata ricorsiva non viene invocata più di qualche (2 o 3) volte in cascata, oppure DEVI per forza cambiare la logica e implementare una macchina a stati finiti (che è la cosa che ti consiglio).

SukkoPera:
Ragazzi, smettiamola di dire cose senza senso:

  1. La ricorsione INDETERMINATA è sempre sbagliata.
  2. D’accordo che su una MCU con RAM limitata (e dunque con stack molto limitato) la ricorsione non è una tattica particolarmente furba da usare, ma entro certi limiti si potrebbe pure fare, magari per eseguire alcuni algoritmi che in versione ricorsiva sono decisamente più semplici che in verione iterativa.
  3. Lasciando comunque un attimo da parte le seghe mentali, nel caso esposto dall’OP non c’è alcun motivo per dovere ricorrere alla ricorsione, va eliminata, punto e basta.

Scusa, chi avrebbe detto “cose senza senso”, e io che ho detto nei miei precedenti post (e in questo)? :slight_smile:

docdoc:
Scusa, chi avrebbe detto "cose senza senso", e io che ho detto nei miei precedenti post (e in questo)? :slight_smile:

Un altro utente, il cui post è stato cancellato e, vista la recidività, l'utente bannato.

Guglielmo

Giuro che prima c'era almeno un altro post oltre al tuo, che suggeriva un metodo per fare una ricorsione "mascherata"!

Il suggerimento poteva anche avere il suo perché, ma il punto principale è quello che dici giustamente anche tu, ovvero che non ha senso ricorrere alla ricorsione in un caso come quello in esame.

EDIT: Ah ecco gpb, allora non me lo sono sognato :D.

SukkoPera:
... che suggeriva un metodo per fare una ricorsione "mascherata"!

Più che altro ad un qualche cosa che tutto era meno che ricorsione ... dato che ad ogni chiamata distruggeva il valore delle variabili precedente (... usava variabili "globali") :smiling_imp:

Guglielmo

Ecco il codice aggiornato:

  if (verapn != 1) {
    while (regavv < 1) {
      Serial.println("APN");
      gprsSerial.println("AT+CMGF=1\r\n");
      delay(50);
      pulserial();
      gprsSerial.println("AT+CMGL=\"REC UNREAD\"\r\n");
      delay(50);
      //Serial.println("inizio");
      puntatore = 0;
      convalpar = "";
      valpar = "";
      apn = "";
      apn2[20];
      uscciclo = 0;
      carerr = 0;
      svubuffer = "";
      while (uscciclo < 1 ) {
        if (gprsSerial.available() > 0 and uscciclo < 1) {
          if (puntatore == 24 or puntatore >= 89) {
            convalpar = gprsSerial.read();
            valpar = convalpar;
            //Serial.println("valpar:  " + valpar);
            if (valpar == "E" or valpar == "O") {
              uscciclo = 1;
            }
            if (valpar == "<" or puntatore >= 90) {
              apn = apn + valpar;
              if (valpar == ">") {
                apn.replace("<apn<", "");
                uscciclo = 1 ;
                regavv = 1; //registazione apn avvenuta con successo
              }
            }
            if (valpar != "<" and puntatore == 89) {
              uscciclo = 1;
              carerr = 1;
            }
          } else {
            svubuffer = gprsSerial.read();
          }
          puntatore++;
        }
      }

      if (valpar == "E" or valpar == "O" or carerr == 1) {
        allapn();
        pulserial();
        gprsSerial.println("AT+CMGDA=\"DEL READ\"\r\n");
        delay(2000);
        pulserial();
      }
    }

    apn.toCharArray(apn2, 20);
    Serial.println(apn2);
    for (int i = 0; i <= 20 - 1; i++) {
      EEPROM.write(i, apn2[i]);
      if (apn2[i] == ">") {
        i = 20;
      }
      delay(100);
    }
    EEPROM.write(20, "1");
    delay(15);
  }
}

Avete suggerimenti o migliorie da propormi.