[RISOLTO] pulizia seriale

Salve, da un po di tempo sto usando un modulo GSM per ricevere e inviare dei messaggi. Ma appena accendo il modulo e invio il messaggio va tutto bene, ma quando invio altri messaggi l’output appare sporco, confuso e tagliato

Mi sapete dire come posso pulire la seriale
Questo è il codice:

#include <SoftwareSerial.h>
#define tx 10
#define rx 6
SoftwareSerial gsm(tx, rx);
char carattere;
int i = 0;

void chiamata() { //creo la funzione per fare le chiamate
  //gsm.println("AT+FCLASS=0");
  gsm.println("atd+393421442116;");
}
void intensita_segnale() { //creo la funzione per sapere l'intensita del segnale
  gsm.println("at+csq");
}
void centro_servizi() {//creo la funzione per sapere se è attivato il centro servizi
  gsm.println("at+csca?");
}
void messaggi () { //creo la funzione per inviare messaggi
  gsm.println("at+cmgf=1");
  delay(500);
  gsm.println("at&w");
  delay(500);
  gsm.println("at+cmgs=+393494409152;");
  gsm.println("ciao by christian");
  delay(100);
  gsm.print((char)26);
  delay(100);
}

void setup() {
  gsm.begin(9600);
  Serial.begin(9600);
  //gsm.println("at");
  //chiamata();
  //centro_servizi();
  //intensita_segnale();
  messaggi();
}

void loop() {

  if (gsm.available() > 0) { //verifico se ci sono dei valori in arrivo
    carattere = gsm.read();
    Serial.print(carattere);
  }
  delay(10);
}

Questo è il mio output:

at+cmgf=1

OK
at&w

OK
at+cmgs=+393494409152; ci by christi
+CMGS: 36

Solitamente non rispondo a studenti,
È inutile e spreco di tempo

Ma tu mi sembri differente, ovvero non domandi per scuola...

Quindi faccio eccezione, però non ti dico il mio pensiero, ti mostro cosa ho pensato
Esiste una non lieve differenza tra le due cose

Primo: il ciclo di loop dura almeno ....

E dove ci sono i puntini scrivi tu, guardando il programma, facendo dei calcoli, leggendo la documentazione

Secondo: a 9600 baud dalla seriale arriva un carattere ogni... ovvero ..... caratteri al secondo

Terzo: leggendo .... caratteri per ogni ciclo leggerò .... al secondo

Quarto: siccome quello che arriva dalla seriale non viene letto subito, ma depositato in una piccola area di memoria chiamata buffer, e per la seriale software questo buffer è grande....

Quinto: devo proprio andare avanti?

PS comunque complimenti

Hai scritto un programma indentato, ordinato e con qualche commento congruo

Non come alcuni che in anni non sono riusciti ne ad indentare decentemente, ma nemmeno a cambiare i commenti sbagliati (e copiati da lingue ostrogote)

Comunque hai ragione, sono uno studente ma non era una domanda a fondo scolastico oltre che quest'anno ho finito le medie e quindi alle medie non si fanno queste materie.
Grazie per le domande poste, perchè mi hai fatto approfondire cose nuove :slight_smile: ;). (non sono riuscito a rispondere alla terza domanda.)

Ecco le risposte:

  1. Il ciclo loop dura almeno 10 ms

2)a 9600 baud dalla seriale arriva un carattere ogni 0.83 ms ovvero 1200 caratteri al secondo
Ragionamento:

1 secondo = 1000 millisecondi

9600baud = 9600bit/s = 1200 byte/s

carattere = 1 byte

1200 caratteri/s

1200:1 = 1:x = (11)/1200 = 0,000831000 = 0.83 ms

3)...

4)siccome quello che arriva dalla seriale non viene letto subito, ma depositato in una piccola area di memoria chiamata buffer, e per la seriale software questo buffer è grande 64byte

Visto che non sono riuscito a rispondere alla terza domanda mi potresti dare tu la risposta??

PS. Allora come posso pulire la seriale. Mi puoi dare dei consigli? :open_mouth:

Un byte è composto da 8 bit ... sulla seriale viene prima inviato un bit di START, poi i tuoi 8 bit e poi un bit di STOP ... quanti bit vengono quindi trasmessi per UN carattere? E quindi, se viaggi a 9600 bsp, quanti caratteri al secondo riesci a trasmettere? Prova a rifare i conti ... ::slight_smile:

Guglielmo

gpb01 hai ragione, non avevo contato il bit di start e il bit di stop

contando il bit di start e il bit di stop, in un carattere ci sono 10bit e viaggiando a una velocita di 9600 bps riesco a trasmettere 960 caratteri/s

Arrivano poco meno di 1000 caratteri al secondo

Facendo il conto della serva 1 al millisecondo

Tu lo leggi e poi per 10 ms non fai nulla
Grosso modo 9 byte vanno nel buffer

Poi ne leggi un altro
E altri 9 vanno nel buffer

E fanno 18

Dopo pochi cicli il buffer è pieno

Siccome non c'è handshaking i successivi caratteri si perdono

Poi ogni 10ms tu leggi il più vecchio nel buffer

E uno di quelli nuovi NON si perde e si mette in coda

Adesso sono in auto

Dopo....

va bene grazie e come posso eliminare i caratteri che sono nel buffer ogni volta che finisce il ciclo

a dopo

No

Non sono da eliminare

Sono proprio quelli li quelli che ti mancano

Devi leggerli, in tempo perché siano ancora utili

Ovvero devi leggerli più velocemente di quanto arrivano

Quindi non puoi mettere pause nel ciclo

Al limite l'equilibrio sarebbe che il buffer comincia a riempirsi, ma non di 9 caratteri ogni 10 ms

La pausa ti serve?

Va bene allora dopo provo ad eliminare il modulo gsm.

Pensavo che la pausa fosse necessaria per far funzionare il codice, ma riflettendoci hai ragione tu ecco perchè vedevo i caratteri spezzettati.

Ora devo uscire, quando torno vedo se funziona e ti faccio sapere :slight_smile: :slight_smile:

grazie

Ieri ero in auto e non avevo molto tempo

Quindi te lo dico adesso:

Bravo

Bravo per aver cercato e letto la documentazione
Per aver cercato la soluzione
Bravo per aver cominciato a far dei conti e dei ragionamenti sul programma , invece di copincollare a mezzo e cambiare in maniera incontrollata un programma che non capisci

Bravo, la strada è giusta, magari ancora lunga ma corretta

Grazie, ora provo a vedere se funziona con il tuo suggerimento.
Scusa il ritardo nella risposta

Ho provato ad eliminare il delay, anche inviando un semplice at, sperando di ricevere come risposta ok, il messaggio mi appare sporco:

@`

Ps. ho provato anche con altri comandi ma la risposta risulta sempre sporco

Secondo me alla fine del ciclo loop dovrei resettare il buffer.
Secondo voi è fattibile?? Si puo resettare il buffer??

Quello sembra un problema di velocità. Fai uno sketch piccolo che fa SOLO il primo comando AT e poi mostra cosa riceve dal modulo, quindi posta questo sketch ed esattamente il suo output.

Ho fatto uno sketch dove trasmetto solamente at, e mi dovrei aspettare come risposta ok

Questo è lo sketch:

#include <SoftwareSerial.h>
#define tx 10
#define rx 6
SoftwareSerial gsm(tx, rx);
char carattere;

void setup() {
  gsm.begin(9600);
  Serial.begin(9600);
  gsm.println("at");

}

void loop() {
  if (gsm.available() > 0) {
   carattere = gsm.read();
   Serial.print(carattere);
  }

}

Questa è la risposta:

C]_ߧ⸮⸮

ps. il segno posto tra il trattino basso e i due punti interrogativi è un quadrato

Strano. Ma tu il monitor seriale lo hai impostato a 9600? Controlla bene...

Si, a questo punto, secondo me è qualcosa a livello hardware.

Ora verifico di nuovo tutti i collegamenti e vi faccio sapere :confused: :confused:

Macché hardware

Hai una porta aperta alla velocità sbagliata

Fai qualche stampa di prova anche prima di cercare la comunicazione col modulo e vediamo

Va bene allora faccio molte prove a velocità diverse

Ma se dentro allo sketch hai impostato la seriale a 9600 devi solo, come dicevo, controllare che il tuo monitor seriale sia alla stessa velocità, tutto qui!
Al limite, come dice Standardoil, metti una print dentro al setup:

void setup() {
  gsm.begin(9600);
  Serial.begin(9600);
  Serial.println("SETUP");
  delay(1000);
  gsm.println("at");
}

e vedi se leggi la parola "SETUP". In caso contrario, posta nuovamente sketch e relativo output.

Grazie ora ho risolto riesco a mandare i messaggi e ricevo ok come risposta…
Ma rimane ancora un problema superficiale:
quando provo a mandare dei messaggi, i messaggi arrivano arrivano leggibili al telefono ma l’output seriale risulta sporco.
Questo è il mio output

at+cmgf=1

OK
at&w

OK
⸮i⸮W+33r⸮⸮f⸮h⸮⸮9⸮H⸮
> ⸮.⸮ian

+CMGS: 46

OK

Come gia detto il messaggio arriva pulito

Questo è il codice:

#include <SoftwareSerial.h>
#define tx 10
#define rx 6
SoftwareSerial gsm(tx, rx);
char carattere;
int i = 0;

void chiamata() { //creo la funzione per fare le chiamate
  //gsm.println("AT+FCLASS=0");
  gsm.println("atd+393494409152;");
}
void intensita_segnale() { //creo la funzione per sapere l'intensita del segnale
  gsm.println("at+csq");
}
void centro_servizi() {//creo la funzione per sapere se è attivato il centro servizi
  gsm.println("at+csca?");
}
void messaggi () { //creo la funzione per inviare messaggi
  gsm.println("at+cmgf=1");
  delay(500);
  gsm.println("at&w");
  delay(500);
  gsm.println("at+cmgs=+393494409152;");
  gsm.println("ciao by christian");
  delay(100);
  gsm.print((char)26);
  delay(100);
}

void setup() {
  gsm.begin(2400);
  Serial.begin(9600);
  //gsm.println("at");
  //chiamata();
  //centro_servizi();
  //intensita_segnale();
  messaggi();
}

void loop() {

  if (gsm.available() > 0) { //verifico se ci sono dei valori in arrivo
    carattere = gsm.read();
    Serial.print(carattere);
  }
  //delay(10);
}

Mi sapete dire il perché di questo giusto per curiosità??

Grazie per tutta l’attenzione