ciao ragazzi,
ho un problema, ed oltre a questo, ho anche il problema di riuscire a descriverlo
ci provo:
ho uno sketch che pilota un cellulare in seriale tramite comandi AT. il suo compito è quello di leggere degli sms ed estrapolare dei valori. inviando un sms ad arduino preceduto da # do dei comandi da eseguire. devo anche poter leggere i messaggi inviati da vodafone con il credito residuo.
questo è ciò che ho scritto:
String inputString = ""; // a string to hold incoming data
boolean stringComplete = false; // whether the string is complete
void setup() {
Serial.begin(9600);
Serial1.begin(9600);
Serial1.println("AT"); // sveglia device
delay(80);
Serial1.println("AT+CMGF=1"); //imposta sms in modalita testo
delay(80);
Serial1.println("AT+CMGR=2"); //legge messaggio
}
void loop() {
readSms();
}
void readSms() {
while (Serial1.available()) {
char inChar = (char)Serial1.read(); // get the new byte:
inputString += inChar; // add it to the inputString:
//Serial.println(inputString);
if (inChar == '\n') { // if the incoming character is a newline, set a flag
stringComplete = true;
if ( inputString.startsWith("Il tuo credito", 0) ){
String credito = inputString.substring( 55, 60);
Serial.print(F("Credito residuo: "));
Serial.println ( credito );
}
if ( inputString.startsWith("#", 0) ){
String comando = inputString.substring( 1, 10);
Serial.print(F("Comando SMS ricevuto: "));
Serial.print ( comando );
}
}
}
if (stringComplete) { // print the string when a newline arrives:
// Serial.println(inputString);
inputString = ""; // clear the string:
stringComplete = false;
}
}
il codice funziona, ma a volte si presentano problemi strani.
ad esempio, se sposto i comandi AT all'interno di readSms(), non va più, ma se resetto arduino più di una volta può capitare che una volta su mille dia il risultato giusto.
la stessa cosa capita se provo a decommentare una delle righe di debug.
idem se inserisco un delay nel loop().
credo che il problema sia legato alla scrittura/lettura del buffer, ma non riesco a trovare una soluzione.
capisco che non sarà facile rispondere, perchè mi rendo conto di non aver spiegato al meglio il problema e non tutti avranno il materiale per fare delle prove, per cui se posso postare qualcosa che aiuti a capire ditemi pure.
grazie
grazie Paolo, ho provato ma il risultato è il medesimo.
è una settimana che ci sto sopra, ho provato mille modi di riscrivere il codice....
quello che più mi preme è di togliere i comandi AT dal setup() e inserirli nella funzione, o al limte in una funzione a parte, perchè poi mi servirà all'interno di un altro progetto.
Crea una funzione initSms() e metti dentro l'inizializzazione e la chiami dal setup.
Controlla semmai cosa deve restituire la periferica quando riceve qui comandi.
AT
OK AT+CMGF=1
OK AT+CMGR=2
+CMGR: "REC READ","404","Tra","13/09/28,22:54:00+08",161,0,0,0,"39404",145,156
Il tuo credito disponibile al 28-09-2013 alle 22:54 e' 15.15 euro.Ultimo addebito 0.30 euro.Per tenere sotto controllo il traffico registrat....
Crea una funzione initSms() e metti dentro l'inizializzazione e la chiami dal setup.
questo non posso farlo, perchè dal setup quei comandi verrebbero eseguiti una sola volta all'avvio di arduino, mentre mi servirebbe poterlo fare in qualsiasi momento.
ho semplificato un po' le cose, ma il risultato sfugge alla mia comprensione....
String inputString = ""; // a string to hold incoming data
char inChar ;
int i=0;
void setup() {
Serial.begin(9600);
Serial1.begin(9600);
}
void loop() {
//primo comando
Serial1.print("AT\r"); // sveglia device
delay(200);
Serial.print ( readSerial() );
Serial.print ( "----------- loop: " ); Serial.println ( i++ );
}
String readSerial() {
while (Serial1.available()) {
inChar = Serial1.read(); // get the new byte:
inputString += inChar; // add it to the inputString:
String serialReply = "";
if (inChar == '\n') { // if the incoming character is a newline, set a flag
serialReply = inputString;
inputString = "";
return (serialReply) ;
}
}
}
sul monitor ottengo:
AT
----------- loop: 0
OK
----------- loop: 1
AT
----------- loop: 2
OK
----------- loop: 3
AT
----------- loop: 4
OK
----------- loop: 5
AT
----------- loop: 6
OK
----------- loop: 7
AT
----------- loop: 8
OK
----------- loop: 9
AT
----------- loop: 10
OK
----------- loop: 11
AT
----------- loop: 12
OK
----------- loop: 13
AT
----------- loop: 14
OK
----------- loop: 15
AT
----------- loop: 16
OK
----------- loop: 17
AT
----------- loop: 18
OK
----------- loop: 19
AT
----------- loop: 20
OK
----------- loop: 21
AT
----------- loop: 22
OK
----------- loop: 23
AT
----------- loop: 24
OK
----------- loop: 25
AT
----------- loop: 26
OK
----------- loop: 27
AT
----------- loop: 28
OKAT
----------- loop: 29
AT
----------- loop: 30
AT
----------- loop: 31
AT
----------- loop: 32
AT
----------- loop: 33
AT
----------- loop: 34
AT
----------- loop: 35
AT
----------- loop: 36
AT
----------- loop: 37
AT
----------- loop: 38
AT
----------- loop: 39
AT
----------- loop: 40
AT
----------- loop: 41
AT
----------- loop: 42
AT
----------- loop: 43
AT
----------- loop: 44
OKAT
----------- loop: 45
AT
----------- loop: 46
AT
----------- loop: 47
AT
----------- loop: 48
AT
----------- loop: 49
AT
----------- loop: 50
AT
----------- loop: 51
AT
----------- loop: 52
AT
----------- loop: 53
AT
----------- loop: 54
AT
----------- loop: 55
AT
----------- loop: 56
AT
----------- loop: 57
AT
----------- loop: 58
AT
----------- loop: 59
AT
----------- loop: 60
OKAT
----------- loop: 61
AT
----------- loop: 62
dal loop 30 in poi inizia ad andare in tilt. cosa ne dovrei dedurre? il buffer è pieno (intorno ai 64byte dovremmo esserci)? ma in teoria la funzione readSerial() dovrebbe leggere e cancellare di conseguenza giusto?
poi, perchè al primo loop mi stampa il comando e al loop successivo la risposta?
leo72:
Nella funzione che chiami la prima istruzione è un while.
Tu gli dici: mentre ci sono dei dati nella seriale, fai questo..
Ma se i dati nel buffer di ricezione della seriale ancora non ci sono, lui esce. E quindi torna al loop dove ti stampa ".........loop xx".
in teoria la tua risposta ha un senso, ma nella pratica non trovo riscontro.
ho provato con un abbondante delay dentro il while e dopo l'invio del comando AT ma non cambia nulla. o forse non ho capito il tuo suggerimento?
c'è da dire che provando il telefono con minicom la risposta è pressochè istantanea.
altra cosa che non capisco è perchè il comando che invio finisce nel buffer... è normale? c'è un buffer anche in trasmissione?
credo di essere giunto ad una soluzione utilizzando il serialEvent().
e dire che avevo guardato più volte quell'esempio, per non dire che l'avevo utilizzato come base di partenza (cambiando il nome alla funzione ) senza averne capito il significato e nel reference mi era proprio sfuggito.
/*
** SerialEvent occurs whenever a new data comes in the** hardware serial RX. This routine is run between each time loop() runs, so using delay inside loop can delay response. Multiple bytes of data may be available. */
E' un metodo non documentato dell'oggetto String.
In pratica, alloca dinamicamente nello stack un blocco di RAM pari al dato che gli passi, in modo da evitare overflow dello stack stesso, che con l'oggetto String sono molto facili dato che la RAM del chip è limitata.