Svuotare variabile

Ciao a tutti, è da settimane che cerco di realizzare un gps con il modulo SIM808 v3.2 shield,ma riscontro sempre problemi e non riesco ad andare avanti.
Vi risparmio tutte le librerie provate che si sono rivelate inadatte o con degli errori..
Ho trovato uno sketch online che mi sembra ottimo come base di partenza ma ho un problema che non so come risolvere.

Sketch:

#include <SoftwareSerial.h>
SoftwareSerial mySerial(10,11);   //software serial instance for GPS/GSM module
String latlongtab[5];  // for the purpose of example let array be global
#define DEBUG true 
String state, timegps, latitude, longitude;
void setup() {
  
  mySerial.begin(9600);
  Serial.begin(9600);           //open serial port
  delay(50);
  
  /*We can use old sendData function to print our commands*/
  sendData("AT+CGNSPWR=1",1000,DEBUG);       //Initialize GPS device
  delay(50);
  sendData("AT+CGNSSEQ=RMC",1000,DEBUG);
  delay(150);
}
void loop() {
   sendTabData("AT+CGNSINF",1000,DEBUG);    //send demand of gps localization
   if(state != 0){
    /*we just dont want to print empty signs so we wait until 
     * gps module will have connection to satelite.
    
     * when whole table returned:
   for(int i = 0; i < (sizeof(latlongtab)/sizeof(int)); i++){
      Serial.println(latlongtab[i]); // print 
    }*/
    Serial.println("State: "+state+" Time: "+timegps+"  Latitude: "+latitude+" Longitude "+longitude);
   }else{
    Serial.println("GPS initializing");
   }
   
}
void sendTabData(String command, const int timeout, boolean debug){
 
    mySerial.println(command); 
    long int time = millis();
    int i = 0;   
    
    while((time+timeout) > millis()){
      while(mySerial.available()){       
        char c = mySerial.read();
        if(c != ','){ //read characters until you find comma, if found increment
          latlongtab[i]+=c;
          delay(100);
        }else{
          i++;        
        }
        if(i == 5){
          delay(100);
          goto exitL;
        }       
      }    
    }exitL:    
    if(debug){ 
      /*or you just can return whole table,in case if its not global*/ 
      state = latlongtab[1];     //state = recieving data - 1, not recieving - 0
      timegps = latlongtab[2];
      latitude = latlongtab[3];  //latitude
      longitude = latlongtab[4]; //longitude
    }    
}
String sendData(String command, const int timeout, boolean debug){
  
    String response = "";    
    mySerial.println(command); 
    long int time = millis();
    int i = 0;  
     
    while( (time+timeout) > millis()){
      while(mySerial.available()){       
        char c = mySerial.read();
        response+=c;
      }  
    }    
    if(debug){
      Serial.print(response);
    }    
    return response;
}

Problema: Ogni volta che stampa il nuovo stato nella seriale, aggiunge sempre i nuovi valori a seguire(come potete vedere nello stato 11).

Come faccio a svuotare la variabile e ottenere gli stati 'puliti' come lo stato1?

Sulla seriale ho questo:

AT

OK
AT+CGNSPWR=1

OK
AT+CGNSSEQ=RMC

OK

State: 1
Time: 20180519173709.000
,
Latitude: 38.124132
Longitude: 13.35088
Substringa: 13.35088

State: 11
Time: 20180519173709.00020180519173719.000
Latitude: 38.12413238.124132
Longitude: 13.3508813.350881
Substringa: 13.35088

Vi prego, aiutatemi! :sob: :sob:

Serial.println("State: "+state+" Time: "+timegps+" Latitude: "+latitude+" Longitude "+longitude);

come fa a funzionare?

Eppure funziona!
In realtà la seriale l'ho copiata da uno sketch un pelo diverso, infatti ho aggiunto la substringa come puoi notare.

Comunque l'ho cambiato così ma a me compilo lo stesso in entrambi i modi:

Serial.println("State: "+state);
Serial.println("Time: "+timegps);
Serial.println(" Latitude: "+latitude);
Serial.println(+ Longitude "+longitude);

Patrick_M:
come fa a funzionare?

... funziona perché usa l'istanza per un oggetto di tipo String() e, come già abbiamo discusso, quella sintassi è perfettamente legale per un oggetto String().

Che poi l'uso della classe String() su un Arduino UNO sia fonte di innumerevoli possibili problemi ... è un altro conto :smiley:

Guglielmo

si è vero essendo tutti string li concatena :slight_smile:

e allora non è che devi ripulire tutte le variabili prima di un nuovo dato...

Infatti non azzera mai nessun elemento di latlongtab
latlongtab [ i ] +=c; ma mai un azzeramento

nid69ita:
Infatti non azzera mai nessun elemento di latlongtab
latlongtab [ i ] +=c; ma mai un azzeramento

Si avevo intuito ma se lo uguaglio e basta per sostituire il nuovo valore al vecchio non va proprio

certo perchè non aggiunge il carattere c
ma ti basta azzerarlo prima...

while((time+timeout) > millis()){

 latlongtab[i]=""

 while(mySerial.available()){       
        char c = mySerial.read();
        if(c != ','){ //read characters until you find comma, if found increment
          latlongtab[i]+=c;
          delay(100);
        }else{

scusa ma se già legge con un while() perché non inserire un semplice for() alla fine del loop per svuotare l'array recuperando la sua lunghezza/dimensione?

era la prima che mi veniva in mente.... :slight_smile:
e tra l'altro così non funziona :slight_smile:
se aggiungi questo alla fine del loop

for (int i = 0; i < 5; i++){
      latlongtab[i]="";
    }

forse si :slight_smile:

... perfetti questi sistemi, che richiedono in continuazione allocazione e riallocazione dinamica della memoria, per far bloccare, a caso, Arduino ! :smiling_imp:

Guglielmo

:smiley: ... non vorrai che mi metta a chiedergli di modificare lo sketch per usare i char...

...

...

...

si ! lo so che lo stai chiedendo :smiley:

Patrick_M:
... chiedergli di modificare lo sketch per usare i char ...

... array di char NULL terminated ... le uniche stringhe che io conosca :stuck_out_tongue_closed_eyes: :stuck_out_tongue_closed_eyes: :stuck_out_tongue_closed_eyes:

Guglielmo

Patrick_M:
era la prima che mi veniva in mente.... :slight_smile:
e tra l'altro così non funziona :slight_smile:
se aggiungi questo alla fine del loop

for (int i = 0; i < 5; i++){

latlongtab[i]="";
   }



forse si :)

Così funziona! Grazie mille!

gpb01:
... perfetti questi sistemi, che richiedono in continuazione allocazione e riallocazione dinamica della memoria, per far bloccare, a caso, Arduino ! :smiling_imp:

Guglielmo

Sono consapevole, ma al momento la mia conoscenza in linguaggio di programmazione è molto limitata! :slightly_frowning_face:
Se qualcuno è disposto ad linkami qualcosa di utile a questo scopo che ben venga, non fraintendetemi ho letto e sto continuando a leggere dei pdf trovati in rete ma ma sono tutti abbastanza superficiali. In caso contrario penso che per il momento mi accontenterò!

Per ammazzare un po il tempo di quest'altra notte in bianco ho provato a cimentarmi con le vere stringhe (ovvero quelle ufficialmente riconosciute da Guglielmo :D)
Non so se è scritto bene, vorrei il parere del re di String.h :smiley: :smiley: (spero di non aver scritto castronate ::slight_smile: )

/*############---Codice rivisitato eliminando STRING---#######
   Codice postato da Manfredk:
   Lo sketch usa 5946 byte (18%) dello spazio disponibile per i programmi.
   Il massimo è 32256 byte.
   Le variabili globali usano 465 byte (22%) di memoria dinamica, lasciando altri
   1583 byte liberi per le variabili locali. Il massimo è 2048 byte.


   Codice rivisitato da me:
   Lo sketch usa 4012 byte (12%) dello spazio disponibile per i programmi.
   Il massimo è 32256 byte.
   Le variabili globali usano 484 byte (23%) di memoria dinamica, lasciando altri
   1564 byte liberi per le variabili locali. Il massimo è 2048 byte.
   COPIALO, GIRALO, MANDALO, MODIFICALO, CONDIVIDILO,
   FANNE QUELLO CHE VUOI ;)
   ###########---by miky_police---#####

   1934 byte di memoria risparmiata (TANTA ROBA) e si evita di allocare e riallocare memoria.
   Compila, ma non so se funziona, non ho quel modulo.
*/

#include <SoftwareSerial.h>
SoftwareSerial mySerial(10, 11);
char latitudine[10];
char longitudine[10];
char statoGps[2];
char timeGps[19];
char inizializzaGps[] = "AT+CGNSPWR=1";
char impostaNMEA[] = "AT+CGNSSEQ=RMC";
char richiediCoordinate[] = "AT+CGNSINF";
char rispostaAt[8];



void setup() {
  mySerial.begin(9600);
  Serial.begin(9600);
}

void loop() {
  while (statoGps[0] == '1') {
    Serial.println("Stato: GPS INIZIALIZZATO");
    Serial.print("Ora GPS: ");
    Serial.println(timeGps);
    Serial.print("Latitudine: ");
    Serial.println(latitudine);
    Serial.print("Longitudine: ");
    Serial.println(longitudine);
    Serial.println();
  }
  atCommand(inizializzaGps, 1000);
  atCommand(impostaNMEA, 1000);
  atCommand(richiediCoordinate, 1000);
  Serial.println("INIZIALIZZAZIONE IN CORSO...");
  Serial.println();
  delay(2000);
}


void atCommand(const char comando[], const int timeout) {
  mySerial.println(comando);
  Serial.println(comando);
  unsigned long inizioRichiesta = millis() + 1000;
  int posArray = 0;
  int numeroStringa = 0;
  if (strcmp(comando, richiediCoordinate) != 0) {
    if (inizioRichiesta >= millis()) {
      while (mySerial.available()) {
        rispostaAt[posArray] = mySerial.read();
        posArray++;
      }
      posArray++;
      rispostaAt[posArray] = '\0';
      Serial.println(rispostaAt);
    }
  }
  else {
    if (inizioRichiesta >= millis()) {
      while (mySerial.available()) {
        char c = mySerial.read();
        if (c != ',') {
          rispostaAt[posArray] = c;
          posArray++;
        }
        else {
          posArray++;
          rispostaAt[posArray] = '\0';
          switch (numeroStringa) {
            case 0:
              strcpy(statoGps, rispostaAt);
              break;
            case 1:
              strcpy(timeGps, rispostaAt);
              break;
            case 2:
              strcpy(latitudine, rispostaAt);
              break;
            case 3:
              strcpy(longitudine, rispostaAt);
              break;
          }
          numeroStringa++;
          posArray = 0;
        }
      }
    }
  }
}

Le mie orecchie sono pronte Guglielmo :smiley: :smiley:
Considera che mi sto cimentando seriamente da appena 2 giorni su string.h
A proposito, avrei una domanda in merito...
Pensando allo svuotamento mi è venuto in mente un'altra possibile soluzione.

char nome[10] = "Michele";
//se la voglio "svuotare" non viene più comodo fare ->
char nome[0] = '\n';

cioè setto il primo byte come carattere terminatore...
oppure gli altri byte, se occupati precedentemente, mantengono il valore assegnatogli?
della serie

char nome[4] = "Mik";
char nome[0] = '\n';
//risultato
char nome[4]= {'\n', 'i', 'k', '\n'};

EDIT: IL CODICE è STATO AGGIORNATO. 21/05/2018 :smiley:

Non ho ovviamnete provato il codice e quindi non so dirti se gira o meno, i concetti sono comunque giusti, salvo l'azzeramento che, come hai immaginato, si fa mettendo 0x00 nel elemento [ 0 ] (e NON \n che corrisponde a 0x0A ovvero LF).

E' ovvio che gli altri bytes rimangono sporchi, ma, utilizzando le funzioni di string.h, la cosa non ha alcuna importanza dato che tutte si fermano appena incontrano il primo 0x00 e quindi, indipendentemnete da quello che segue, viene preso in considerazione quello che c'è dall'elemento [ 0 ] all'elemento che contiene 0x00 (se i due coincidono viene considerata stringa vuota).

Poi, quando fai delle print() o println() NON serve fare il cast (char*) ... il nome di un array di char è già di per sé un char* e quindi il cast è ridondante.

Ancora, come sempre dice Nid, specie se sono le prime volte che usi tali funzioni, una la loro versione con la 'n', ovvero strncpy, strncat, ecc. ecc. che ti controllano la lunghezza massima della stringa destinazione ... così, anche se sbagli i conti, NON rischi sforamenti di memoria.

Altro, al momento, non mi viene in mente ... ::slight_smile:

Guglielmo

oddio, chiedo scusa, ma erano le 3 del mattino... appena ho 2 secondi correggo quell'orrore. era palese che l'intenzione era quella '\0'
Quindi è giusto ripulire array di char settando il primo Byte con '\0', o meglio serve solo per far restituire l'array vuoto fittiziamente. Ricapitolando e Ponendo un esempio con un Array di char di lunghezza 8 riempiendo lo totalmente di caratteri E poi settando il primo Byte a '\0' questo restituisce valore Nullo in caso di sua chiamata. Ma se poi vado a riempire la stessa variabile con soli 3 caratteri e poi la richiamo per vedere il contenuto ovviamente mostrerà i primi tre caratteri settati nell'ultima operazione e i restanti 5 settati inizialmente.

miky_police:
... Ma se poi vado a riempire la stessa variabile con soli 3 caratteri e poi la richiamo per vedere il contenuto ovviamente mostrerà i primi tre caratteri settati nell'ultima operazione e i restanti 5 settati inizialmente.

... solo se la riempi TU male a mano, difatti, come detto, qualsiasi funzione di string.h, termina le sue stringhe con 0x00 e quindi, se usi la strncpy() per mettere i tuoi tre caratteri, nel carattere [ 3 ] la funzione provvederà a mettere 0x00 terminando la stringa.

Guglielmo

miky_police:
Per ammazzare un po il tempo di quest'altra notte in bianco ho provato a cimentarmi con le vere stringhe (ovvero quelle ufficialmente riconosciute da Guglielmo :D)
Non so se è scritto bene, vorrei il parere del re di String.h :smiley: :smiley: (spero di non aver scritto castronate ::slight_smile: )

/*############---Codice rivisitato eliminando STRING---#######

Codice postato da Manfredk:
  Lo sketch usa 5946 byte (18%) dello spazio disponibile per i programmi.
  Il massimo è 32256 byte.
  Le variabili globali usano 465 byte (22%) di memoria dinamica, lasciando altri
  1583 byte liberi per le variabili locali. Il massimo è 2048 byte.

Codice rivisitato da me:
  Lo sketch usa 4012 byte (12%) dello spazio disponibile per i programmi.
  Il massimo è 32256 byte.
  Le variabili globali usano 484 byte (23%) di memoria dinamica, lasciando altri
  1564 byte liberi per le variabili locali. Il massimo è 2048 byte.
  COPIALO, GIRALO, MANDALO, MODIFICALO, CONDIVIDILO,
  FANNE QUELLO CHE VUOI :wink:
  ###########---by miky_police---#####

1934 byte di memoria risparmiata (TANTA ROBA) e si evita di allocare e riallocare memoria.
  Compila, ma non so se funziona, non ho quel modulo.
*/

#include <SoftwareSerial.h>
SoftwareSerial mySerial(10, 11);
char latitudine[10];
char longitudine[10];
char statoGps[2];
char timeGps[19];
char inizializzaGps[] = "AT+CGNSPWR=1";
char impostaNMEA[] = "AT+CGNSSEQ=RMC";
char richiediCoordinate[] = "AT+CGNSINF";
char rispostaAt[8];

void setup() {
 mySerial.begin(9600);
 Serial.begin(9600);
}

void loop() {
 while (statoGps[0] == '1') {
   Serial.println("Stato: GPS INIZIALIZZATO");
   Serial.print("Ora GPS: ");
   Serial.println(timeGps);
   Serial.print("Latitudine: ");
   Serial.println(latitudine);
   Serial.print("Longitudine: ");
   Serial.println(longitudine);
   Serial.println();
 }
 atCommand(inizializzaGps, 1000);
 atCommand(impostaNMEA, 1000);
 atCommand(richiediCoordinate, 1000);
 Serial.println("INIZIALIZZAZIONE IN CORSO...");
 Serial.println();
 delay(2000);
}

void atCommand(const char comando[], const int timeout) {
 mySerial.println(comando);
 Serial.println(comando);
 unsigned long inizioRichiesta = millis() + 1000;
 int posArray = 0;
 int numeroStringa = 0;
 if (strcmp(comando, richiediCoordinate) != 0) {
   if (inizioRichiesta >= millis()) {
     while (mySerial.available()) {
       rispostaAt[posArray] = mySerial.read();
       posArray++;
     }
     posArray++;
     rispostaAt[posArray] = '\0';
     Serial.println(rispostaAt);
   }
 }
 else {
   if (inizioRichiesta >= millis()) {
     while (mySerial.available()) {
       char c = mySerial.read();
       if (c != ',') {
         rispostaAt[posArray] = c;
         posArray++;
       }
       else {
         posArray++;
         rispostaAt[posArray] = '\0';
         switch (numeroStringa) {
           case 0:
             strcpy(statoGps, rispostaAt);
             break;
           case 1:
             strcpy(timeGps, rispostaAt);
             break;
           case 2:
             strcpy(latitudine, rispostaAt);
             break;
           case 3:
             strcpy(longitudine, rispostaAt);
             break;
         }
         numeroStringa++;
         posArray = 0;
       }
     }
   }
 }
}





**EDIT: IL CODICE è STATO AGGIORNATO. 21/05/2018 :D**

Ho caricato il codice, come avete già verificato compila, però non va.

La risposta della seriale è questa in loop:

ATAT+CGNSPWR=1

AT+CGNSSEQ=RMC

AT+CGNSINF
INIZIALIZZAZIONE IN CORSO...

Ho spostato queste righe nel setup, perchè basta scriverle solo una volta

  Serial.println("INIZIALIZZAZIONE IN CORSO...");
  atCommand(inizializzaGps, 1000);
  atCommand(impostaNMEA, 1000);

E la condizione del ciclo while all'inizio del loop l'ho cambiato in "(statoGps[0] != '0')" ma niente coordinate ancora (Sinceramente non so se è corretto, non siate cattivi, ad intuito mi sembrava corretto però).

Comunque, ad ogni comando AT il modulo dovrebbe rispondere, cosa che non succede in questo caso, quindi suppongo per questo non ricevo orario e coordinate.

Ps: Grazie molte per l'aiuto comunque :slight_smile: