AnalogRead e ritardi

ECCOLO

//#include <SdFatUtil.h>
#include <SoftwareSerial.h>
#include "sms.h"

#define BUFFSIZ 70// se troppo grosso 70
#define LED 6
#define DC 5
SoftwareSerial gps(4,5); //Seriale Software Vs GPS(RX,TX)

SMSGSM sms;
boolean lettura=false;
boolean GPRMC=true;
boolean GPGGA=true;
// PArsing GPS variabili Globali
char buffer[BUFFSIZ]; // Buffer dei dati G
char *parseptr; // un puntatore Char per il Parsing
char buffidx; // Indice del Parsing
boolean startup=true;
boolean stato=false; //0 atterrato 1 Volo
char TEXT_SMS[30];

// time, date, location data, etc.
//uint8_t day;
uint32_t day,time,latitude, longitude;
uint8_t groundspeed, trackangle,altitude;
uint8_t latdir, longdir,quality;
int status;
String STR_SMS; //Variabile String per concatenare la stringa SMS
int batt;

void setup()
{
pinMode(LED,OUTPUT);
pinMode(DC,INPUT);
Serial.begin(9600); //Seriale del PC

gps.begin(38400); //Velocità seriale GPS
digitalWrite(LED,LOW);

}

uint32_t parsedecimal(char *str) {
uint32_t d = 0;
while (str[0] != 0) {
if ((str[0] > '9') || (str[0] < '0'))
return d;
d *= 10;
d += str[0] - '0';
str++;
}
return d;
}

void readline(void) {
char c;
buffidx = 0; // start at begninning

Serial.print(batt);
while (1) {
c=gps.read();
if (c == -1)
continue;
//Serial.print(" ");
delay(1);
if (c == '\n')
continue;
if ((buffidx == BUFFSIZ-1) || (c == '\r')) {
buffer[buffidx] = 0;
return;
}
buffer[buffidx++]= c;
}
}

void loop()
{
uint32_t tmp;

readline(); //legge dati da GPS
// se disponibile $GPRMC
batt = analogRead (A0); //QUESTO FA INCHIODARE LO SCHETCH DOPO 2/3 letture

if (startup) { // si attiva solo alla prima accensione del dispositivo
if (groundspeed == 0)Serial.println("DISPOSITIVO ACCESO ");
if (groundspeed == 0) tone (9,700,1000);
if (groundspeed > 0) Serial.println("WARNING WARNING");

//Serial.println(FreeRam());
startup=false;
}

}


GRAZIE SPERIAMO

Parlavi di "blocco".... ma non è che hai esaurito la memoria?
Vorrei provare a compilare lo sketch, da dove hai prelevato le librerie SdFatUtil.h e sms.h (così da usare quelle che hai tu)?

veramente puoi anche eliminare i riferimenti alle librerie, non vengono usate...vai tranquillo

no, la memoria non è esaurita....considera che poi fa molto altro ancora che ho dovuto togliere dallo schetch altrimenti non si capiva nulla...

Ma fa sempre lo stesso problema, questa è la zona problematica. Se metti una Serial.print dopo la AnalogRad ti rendi conto che si inchioda...

....molto gentile....

Ma sei sicuro che si inchiodi all'analogRead e non alla comunicazione col GPS che c'è subito prima?
Potresti provare così:

Serial.println("Sono alla readline...");
readline();   //legge dati da GPS 
Serial.println("Adesso leggo il pin A0...");
  // se disponibile $GPRMC
  batt = analogRead (A0); 
Serial.println("Lettura fatta. Proseguo...");

e la risposta è questa


Sono alla readline...
0Adesso leggo il pin A0...
Lettura fatta. Proseguo...
DISPOSITIVO ACCESO
Sono alla readline...


quindi si ferma dopo la Read...è come se il GPS non passando l'endline ogni tanto prende e si inchioda...che dici?

praticamente si blocca alla readline ma solo se attivi l'analogread....prova a commentare analog read e tutto cammina....(tranne le letture sull'analogico).....

Il problema sembra risiedere in readline().
A me non esce da lì:
ecco l'ouput:

Sono alla readline...
0

Nel senso che se non c'è nulla in arrivo dal gps, il codice ti resta bloccato lì dentro.

si è vero,....ma che c'entra con la AnalogRead....prova a commentare l'analog e vedrai che tutto torna...
metto delle Serial.println nella funzione

void readline(void) {
char c;
buffidx = 0; // start at begninning
unsigned long tempMillis = millis();

Serial.print(batt);
while (millis() - tempMillis < 5000) {
c=gps.read();
if (c == -1)
continue;
//Serial.print(" ");
delay(1);
if (c == '\n')
continue;
if ((buffidx == BUFFSIZ-1) || (c == '\r')) {
buffer[buffidx] = 0;
return;
}
buffer[buffidx++]= c;
}
}

Con questo funziona perfettamente.
E' un timeout di 5 secondi, se non riceve nulla sulla seriale software, esce.

giocastel:
si è vero,....ma che c'entra con la AnalogRead....prova a commentare l'analog e vedrai che tutto torna...
metto delle Serial.println nella funzione

Sarà stato un caso. Anche a te non è uscito dalla funzione readline.

PS:
siccome la SoftwareSerial usa gli interrupt, potresti provare a rendere "atomica" la lettura analogica di A0. Per "atomico" si intende un blocco di codice che non è interrompibile da un interrupt. In questo modo evitiamo che interferenze esterne della libreria diano noia alla funzione di lettura del pin analogico.

cli();
batt = analogRead(A0);
sei();

PS2:
una domanda...

hai per caso intenzione di lanciare un pallone sonda con l'Arduino? ]:smiley:

leo72:
PS:
siccome la SoftwareSerial usa gli interrupt, potresti provare a rendere "atomica" la lettura analogica di A0. Per "atomico" si intende un blocco di codice che non è interrompibile da un interrupt. In questo modo evitiamo che interferenze esterne della libreria diano noia alla funzione di lettura del pin analogico.

cli();

batt = analogRead(A0);
sei();

vero e già provato....ma nulla...stesso problema
come è vero che ho anche provato a Stoppare la seriale prima di leggere il valore analogico per poi farlo ripartire....NULLA....sto impazzendo!

si la sonda è finita da tempo....in primavera lanciamo!

:slight_smile:

Ma hai provato questo codice che ti ho postato?
A me funziona perfettamente, e non si blocca.

leo72:

void readline(void) {
char c;
buffidx = 0; // start at begninning
unsigned long tempMillis = millis();

Serial.print(batt);
while (millis() - tempMillis < 5000) {
c=gps.read();
if (c == -1)
continue;
//Serial.print(" ");
delay(1);
if (c == '\n')
continue;
if ((buffidx == BUFFSIZ-1) || (c == '\r')) {
buffer[buffidx] = 0;
return;
}
buffer[buffidx++]= c;
}
}

Con questo funziona perfettamente.
E' un timeout di 5 secondi, se non riceve nulla sulla seriale software, esce.

purtroppo non funziona ancora neanche così

..

giocastel:
purtroppo non funziona ancora neanche così

A me però funziona.
Domanda: perché usi "continue"? Per uscire dal while? Forse dovresti usare "break", allora.
Mi potresti spiegare anche la logica della funzione readline: che cosa dovrebbe attendersi per uscire? Vediamo cioè se la si può rendere più efficiente.

leo72:

giocastel:
purtroppo non funziona ancora neanche così

A me però funziona.
Domanda: perché usi "continue"? Per uscire dal while? Forse dovresti usare "break", allora.
Mi potresti spiegare anche la logica della funzione readline: che cosa dovrebbe attendersi per uscire? Vediamo cioè se la si può rendere più efficiente.

la readline deve contenere la sentenza disponibile nmea del gps, quindi tutto quello che sente dalla seriale lo butta in buffer. ovviamente fa un controllo che buffer non sia pieno e che ci sia una nuova linea , tutto semplicissimo

Ok, ho capito.

Ecco i risultati del test fatto sullo sketch tuo, commentando analogRead: BLOCCO.

Quindi a me non è l'analogRead che blocca il codice, ma proprio la funzione readline che, senza timeout, si blocca in un loop infinito.
Usando il seguente codice al posto del tuo:

//#include <SdFatUtil.h>
#include <SoftwareSerial.h>
//#include "sms.h"



#define BUFFSIZ 70// se troppo grosso 70
#define LED 6
#define DC 5    
SoftwareSerial gps(4,5); //Seriale Software Vs GPS(RX,TX)


//SMSGSM sms;
boolean lettura=false;
boolean GPRMC=true;
boolean GPGGA=true;
// PArsing GPS variabili Globali
char buffer[BUFFSIZ];        // Buffer dei dati G
char *parseptr;              // un puntatore Char per il Parsing
char buffidx;                // Indice del Parsing
boolean startup=true;
boolean stato=false;              //0 atterrato 1 Volo
char TEXT_SMS[30];




//  time, date, location data, etc.
//uint8_t  day;
uint32_t day,time,latitude, longitude; 
uint8_t groundspeed, trackangle,altitude;
uint8_t latdir, longdir,quality;
int status;
String STR_SMS;         //Variabile String per concatenare la stringa SMS
int batt;


void setup() { 
    pinMode(LED,OUTPUT);
    pinMode(DC,INPUT);
    Serial.begin(9600);   //Seriale del PC    
    delay(2000);

    gps.begin(38400); //Velocità seriale GPS
    digitalWrite(LED,LOW);
}


uint32_t parsedecimal(char *str) {
    uint32_t d = 0;  
    while (str[0] != 0) {
        if ((str[0] > '9') || (str[0] < '0'))
            return d;
        d *= 10;
        d += str[0] - '0';
        str++;
    }
    return d;
}


void readline(void) {
    char c;  
    buffidx = 0; // start at begninning

    Serial.println("Stampo la lettura...");
    Serial.println(batt);
    Serial.println("Entro nel while...");
    while (1) {
        Serial.println("Leggo il GPS...");
        c=gps.read();
        Serial.println("OK. Proseguo");
        if (c == -1)     
            Serial.println("C=-1");
            continue;
        //Serial.print(" ");
        delay(1);
        Serial.println("Delay(1)");
        if (c == '\n')
            Serial.println("c=\n");
            continue;
        if ((buffidx == BUFFSIZ-1) || (c == '\r')) {         
            Serial.println("Buffer pieno o ritorno a capo...");
            buffer[buffidx] = 0;
            Serial.println("Fatto. Esco.");
            return;
        }      
        Serial.println("Inserisco il dato nel buffer...");
        buffer[buffidx++]= c;
    }
}

void loop() {
    uint32_t tmp; 

    readline();   //legge dati da GPS  
    // se disponibile $GPRMC 
    //batt = analogRead (A0);  //QUESTO FA INCHIODARE LO SCHETCH DOPO 2/3 letture

    if (startup) {                                                   // si attiva solo alla prima accensione  del dispositivo
        if (groundspeed == 0)Serial.println("DISPOSITIVO ACCESO ");
        if (groundspeed == 0) tone (9,700,1000);
        if (groundspeed > 0) Serial.println("WARNING WARNING");

        //Serial.println(FreeRam());  
        startup=false;
    }
    delay(1000);
}

ottengo questo (ovviamente all'infinito):

Stampo la lettura...
0
Entro nel while...
Leggo il GPS...
OK. Proseguo
C=-1
Leggo il GPS...
OK. Proseguo
C=-1
Leggo il GPS...
OK. Proseguo
C=-1
Leggo il GPS...
OK. Proseguo
C=-1
Leggo il GPS...
OK. Proseguo
C=-1
Leggo il GPS...
OK. Proseguo
C=-1
Leggo il GPS...
OK. Proseguo
C=-1
Leggo il GPS...
OK. Proseguo
C=-1
Leggo il GPS...
OK. Proseguo
C=-1
Leggo il GPS...
OK. Proseguo
C=-1
Leggo il GPS...
OK. Proseguo
C=-1
Leggo il GPS...
OK. Proseguo
C=-1
Leggo il GPS...
OK. Proseguo

Mentre mettendo il timeout, ottengo questo:

Stampo la lettura...
0
Entro nel while...
Leggo il GPS...
OK. Proseguo
C=-1
Leggo il GPS...
OK. Proseguo
C=-1
Leggo il GPS...
OK. Proseguo
C=-1
Leggo il GPS...
OK. Proseguo
C=-1
Leggo il GPS...
......... (per 5 secondi circa).......
OK. Proseguo
C=-1
DISPOSITIVO ACCESO

Come vedi, esce e ritorna al loop principale. Ciò mi ha fatto pensare sull'uso di "continue". Con "continue" tu esegui l'istruzione successiva, mentre con "break" esci dal ciclo.

Modificando la readline così:

void readline(void) {
    char c;  
    buffidx = 0; // start at begninning
    unsigned long tempMillis = millis();
  
  

    Serial.println("Stampo la lettura...");
    Serial.println(batt);
    Serial.println("Entro nel while...");
    while (millis() - tempMillis < 5000) {
        Serial.println("Leggo il GPS...");
        c=gps.read();
        Serial.println("OK. Proseguo");
        if (c == -1)     
            Serial.println("C=-1");
            break;
        //Serial.print(" ");
        delay(1);
        Serial.println("Delay(1)");
        if (c == '\n')
            Serial.println("c=\n");
            continue;
        if ((buffidx == BUFFSIZ-1) || (c == '\r')) {         
            Serial.println("Buffer pieno o ritorno a capo...");
            buffer[buffidx] = 0;
            Serial.println("Fatto. Esco.");
            return;
        }      
        Serial.println("Inserisco il dato nel buffer...");
        buffer[buffidx++]= c;
    }
}

Ottengo questo:

Stampo la lettura...
0
Entro nel while...
Leggo il GPS...
OK. Proseguo
C=-1
DISPOSITIVO ACCESO 
Stampo la lettura...
0
Entro nel while...
Leggo il GPS...
OK. Proseguo
C=-1
Stampo la lettura...
0
Entro nel while...
Leggo il GPS...
OK. Proseguo
C=-1
Stampo la lettura...
0
Entro nel while...
Leggo il GPS...
OK. Proseguo
C=-1
Stampo la lettura...
0
Entro nel while...
Leggo il GPS...
OK. Proseguo
C=-1

Come vedi, il ciclo termina ben prima del timeout.