Pages: [1]   Go Down
Author Topic: Un aiuto con le stringhe............  (Read 772 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Sr. Member
****
Karma: 1
Posts: 443
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ciao a tutti, è da tanto che non programmo seriamente, ma non mi ricordavo che fosse un casino simile manipolare delle stringhe.
Ci ho perso tutta la giornata ma non ne sono venuto a capo.
Sto sviluppando un pde che prende i dati seriali da un GPS e poi se mai dovessi riuscire a manipolare le stringhe, "dovrebbe" compiere determinate azioni in base a quello che gli dice il gps.
Allora, il pde è questo:
Code:
#include <string.h>
#include <ctype.h>
#include <SoftwareSerial.h>

#define  MONITORRXPIN    0
#define  MONITORTXPIN    1
#define  GPSRXPIN        8
#define  GPSTXPIN        9
#define  RXBUFFERLENGHT  500
#define  GPRMCCOMMAND    "$GPRMC"
#define  GPGGACOMMAND    "$GPGGA"
#define  GPGSACOMMAND    "$GPGSA" 
#define  GPGSVCOMMAND    "$GPGSV"

char   byteGPS = -1;
char   RXBuffer[RXBUFFERLENGHT];
int    CharCount=0;

SoftwareSerial GPSSerial =  SoftwareSerial(GPSRXPIN, GPSTXPIN);

void setup()
{
  pinMode(MONITORRXPIN, INPUT);
  pinMode(MONITORTXPIN, OUTPUT);
   
  GPSSerial.begin(4800);
  Serial.begin(9600);
  InitRXBuffer();
}

void loop()
{
   byteGPS=GPSSerial.read();     

   if (byteGPS >= 0)
   {
     RXBuffer[CharCount]=byteGPS;   
     CharCount++;
     Serial.print(byteGPS, BYTE);     
     if (CharCount >= RXBUFFERLENGHT)
     {
       Serial.print("Errore superamento buffer");
       return;
     }       
   
     if (byteGPS==13)
     {
       CharCount=0;
       InitRXBuffer();
     }
   }
}
 
void  InitRXBuffer()
{
  for (int i=0;i < RXBUFFERLENGHT;i++) { RXBuffer[i] = 0; }
}
 

E mi da questo risultato (che è corretto):
Code:
$GPGSA,A,1,,,,,,,,,,,,,,,*1E
$GPRMC,212320.718,V,,,,,,,230911,,*29
$GPGGA,212321.709,,,,,0,00,,,M,0.0,M,,0000*59
$GPGSA,A,1,,,,,,,,,,,,,,,*1E
$GPRMC,212321.709,V,,,,,,,230911,,*28
$GPGGA,212322.709,,,,,0,00,,,M,0.0,M,,0000*5A
$GPGSA,A,1,,,,,,,,,,,,,,,*1E
$GPRMC,212322.709,V,,,,,,,230911,,*2B
$GPGGA,212323.739,,,,,0,00,,,M,0.0,M,,0000*58
$GPGSA,A,1,,,,,,,,,,,,,,,*1E
$GPGSV,3,1,10,20,75,047,,23,65,203,,32,48,072,,24,40,141,*74
$GPGSV,3,2,10,17,34,270,,31,26,056,,11,25,157,,04,20,309,*70
$GPGSV,3,3,10,14,13,044,,10,01,272,*78
$GPRMC,212323.739,V,,,,,,,230911,,*29
$GPGGA,212324.709,,,,,0,00,,,M,0.0,M,,0000*5C
$GPGSA,A,1,,,,,,,,,,,,,,,*1E
$GPRMC,212324.709,V,,,,,,,230911,,*2D
$GPGGA,212325.709,,,,,0,00,,,M,0.0,M,,0000*5D
$GPGSA,A,1,,,,,,,,,,,,,,,*1E
$GPRMC,212325.709,V,,,,,,,230911,,*2C
$GPGGA,212326.718,,,,,0,00,,,M,0.0,M,,0000*5E
$GPGSA,A,1,,,,,,,,,,,,,,,*1E
$GPRMC,212326.718,V,,,,,,,230911,,*2F
$GPGGA,212327.709,,,,,0,00,,,M,0.0,M,,0000*5F
$GPGSA,A,1,,,,,,,,,,,,,,,*1E
$GPRMC,212327.709,V,,,,,,,230911,,*2E
$GPGGA,212328.709,,,,,0,00,,,M,0.0,M,,0000*50
$GPGSA,A,1,,,,,,,,,,,,,,,*1E
$GPGSV,3,1,10,20,75,047,,23,65,203,,32,48,072,,24,40,141,*74
$GPGSV,3,2,10,17,34,270,,31,26,056,,11,25,157,,04,20,309,*70

Il testo viene scritto byte per byte in seriale e sembra funzionare, però se tiro via la riga che scrive
byte per byte e provo a fargli scrivere l'array, il risultato non è lo stesso:
Code:
#include <string.h>
#include <ctype.h>
#include <SoftwareSerial.h>

#define  MONITORRXPIN    0
#define  MONITORTXPIN    1
#define  GPSRXPIN        8
#define  GPSTXPIN        9
#define  RXBUFFERLENGHT  100
#define  GPRMCCOMMAND    "$GPRMC"
#define  GPGGACOMMAND    "$GPGGA"
#define  GPGSACOMMAND    "$GPGSA" 
#define  GPGSVCOMMAND    "$GPGSV"

char   RXBuffer[RXBUFFERLENGHT];
int    CharCount=0;

SoftwareSerial GPSSerial =  SoftwareSerial(GPSRXPIN, GPSTXPIN);

void setup()
{
  pinMode(MONITORRXPIN, INPUT);
  pinMode(MONITORTXPIN, OUTPUT);
   
  GPSSerial.begin(4800);
  Serial.begin(9600);
  InitRXBuffer();
}

void loop()
{
   char   byteGPS = -1;

   byteGPS=GPSSerial.read();       

   if (byteGPS >= 0)
   {
     RXBuffer[CharCount]=byteGPS;
     CharCount++;
//   Serial.print(byteGPS, BYTE);   ************** commentato riga che scrive byte per byte
     if (CharCount >= RXBUFFERLENGHT)
     {
       Serial.print("Errore superamento buffer");
       return;
     }       
   
     if (byteGPS==13)
     {
    // **************** aggiunto ciclo for che scorre l'array e invia alla seriale un carattere per volta
     for (int i=0; i <= strlen(RXBuffer)-1; i++)
      {
         Serial.print(RXBuffer[i], BYTE);
      }       
     Serial.println("");
    //****************************************************************************
       CharCount=0;
       InitRXBuffer();
     }
   }
}
 
void  InitRXBuffer()
{
  for (int i=0;i < RXBUFFERLENGHT;i++) { RXBuffer[i] = 0; }
}
 
Ho evidenziato le righe modificate/aggiunte.

Il risultato è questo:
Code:
,,,*1E

GSV,3,1,11,23,85,194,,20,61,082,,04,36,306,,32,34,085,*7B

f23,148,,31,19,041,,13,14,224,*7A

3f14,282,,11,09,159,,30,00,028,*48

21,V,,,,,,,230911,,*26

$GPGGA,220354.713,,,,,0,00,,,M,0.0,M,,0000*51

,,,,,*1E

RMC,220354.713,V,,,,,,,230911,,*20

$GPGGA,220355.713,,,,,0,00,,,M,0.0,M,,0000*50

,,,,,*1E

RMC,220355.713,V,,,,,,,230911,,*21

$GPGGA,220356.721,,,,,0,00,,,M,0.0,M,,0000*52

,,,,,*1E

RMC,220356.721,V,,,,,,,230911,,*23

$GPGGA,220357.713,,,,,0,00,,,M,0.0,M,,0000*52

,,,,,*1E

RMC,220357.713,V,,,,,,,230911,,*23

$GPGGA,220358.713,,,,,0,00,,,M,0.0,M,,0000*5D

,,,,,*1E

GSV,3,1,11,23,85,194,,20,61,082,,04,36,306,,32,34,085,*7B

f23,148,,31,19,041,,13,14,224,*7A

3f14,282,,11,09,159,,30,00,028,*48

13,V,,,,,,,230911,,*2C

$GPGGA,220359.721,,,,,0,00,,,M,0.0,M,,0000*5D

,,,,,*1E

RMC,220359.721,V,,,,,,,230911,,*2C

$GPGGA,220400.713,,,,,0,00,,,M,0.0,M,,0000*57

,,,,,*1E

RMC,220400.713,V,,,,,,,230911,,*26

$GPGGA,220401.713,,,,,0,00,,,M,0.0,M,,0000*56

cf
$GPRMC,220401.713,V,,,,,,,230911,,*27

$GPGGA,220402.721,,,,,0,00,,,M,0.0,M,,0000*54

,,,,,*1E

RMC,220402.721,V,,,,,,,230911,,*25

$GPGGA,220403.713,,,,,0,00,,,M,0.0,M,,0000*54

,,,,,*1E

GSV,3,1,11,23,85,194,,20,61,082,,04,36,306,,32,34,085,*7B

f23,148,,31,19,041,,13,14,224,*7A

3f14,282,,11,09,159,,30,00,028,*48

13,V,,,,,,,230911,,*25

$GPGGA,220404.713,,,,,0,00,,,M,0.0,M,,0000*53

,,,,,*1E

RMC,220404.713,V,,,,,,,230911,,*22

$GPGGA,220405.724,,,,,0,00,,,M,0.0,M,,0000*56

,,,,,*1E

RMC,220405.724,V,,,,,,,230911,,*27

$GPGGA,220406.715,,,,,0,00,,,M,0.0,M,,0000*57

,,,,,*1E

RMC,220406.715,V,,,,,,,230911,,*26

$GPGGA,220407.715,,,,,0,00,,,M,0.0,M,,0000*56

,,,,,*1E

RMC,220407.715,V,,,,,,,230911,,*27

$GPGGA,220408.723,,,,,0,00,,,M,0.0,M,,0000*5C

,,,,,*1E

GSV,3,1,11,23,85,194,,20,61,082,,04,36,306,,32,34,085,*7B

f23,148,,31,19,041,,13,14,224,*7A

3f14,282,,11,09,159,,30,00,028,*48

23,V,,,,,,,230911,,*2D

$GPGGA,220409.715,,,,,0,00,,,M,0.0,M,,0000*58

,,,,,*1E

RMC,220409.715,V,,,,,,,230911,,*29

$GPGGA,220410.715,,,,,0,00,,,M,0.0,M,,0000*50

,,,,,*1E

RMC,220410.715,V,,,,,,,230911,,*21

$GPGGA,220411.724,,,,,0,00,,,M,0.0,M,,0000*53

,,,,,*1E

RMC,220411.724,V,,,,,,,230911,,*22

$GPGGA,220412.715,,,,,0,00,,,M,0.0,M,,0000*52

,,,,,*1E

RMC,220412.715,V,,,,,,,230911,,*23

$GPGGA,220413.715,,,,,0,00,,,M,0.0,M,,0000*53

,,,,,*1E

GSV,3,1,11,23,85,194,,20,61,082,,04,36,306,,32,34,085,*7B

f23,148,,31,19,041,,13,14,224,*7A

3f14,282,,11,09,159,,30,00,028,*48

15,V,,,,,,,230911,,*22

$GPGGA,220414.724,,,,,0,00,,,M,0.0,M,,0000*56

,,,,,*1E

RMC,220414.724,V,,,,,,,230911,,*27

Mi sono fatto l'idea che nel primo caso, viene scritto byte per byte in tempo reale, mentre nel secondo
il tempo che arduino impiega a scorrere l'array e a printarlo in seriale fa passare dei cicli di cpu in cui
il gps continua ad inivare dati che vanno persi perchè non scaricati dal buffer.
Però, se il problema è veramente questo, come potrei risolverlo?
La prova di scrittura dell'array l'ho fatta non perchè mi serva stamparlo a video tramite seriale, ma perchè
non risuscivo a capire come mai mi era impossibile manipolare le strinche con strcmp e strcpy.
Se qualcuno ha qualche dritta smiley
Grazie.
Ciao.
Logged


Ivrea
Offline Offline
God Member
*****
Karma: 5
Posts: 680
"La teoria è quando si sa tutto ma non funziona niente. La pratica è quando funziona tutto ma non si sa il perché. In ogni caso si finisce sempre con il coniugare la teoria con la pratica: non funziona niente e non si sa il perché." Albert Einstein
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Penso anche io che il tuo problema sia la software serial. Prova ad abbassare il baud rate della software serial e a portare quello della seriale vera a 115200, così hai meno tempi morti.

P.S. L'IDE di arduinio ha messo a disposizione una classe apposita per le stringhe. Se hai da manipolarle pesantemente ti conviene dargli un'occhiata. Il link è questo: http://arduino.cc/en/Reference/StringObject
Logged

Ivrea
Offline Offline
God Member
*****
Karma: 5
Posts: 680
"La teoria è quando si sa tutto ma non funziona niente. La pratica è quando funziona tutto ma non si sa il perché. In ogni caso si finisce sempre con il coniugare la teoria con la pratica: non funziona niente e non si sa il perché." Albert Einstein
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Mi è venuta a mente un'altra cosa (guarda, stavo per andare a letto, sono tornato al pc apposta  smiley-grin ). Se fosse il problema della software serial, la prima stringa in teoria dovrebbe stampartela correttamente... Fammi sapere.
Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 325
Posts: 22498
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Non conosco le librerie in oggetto ma mi pare che ci sia un errore logico di fondo, ossia il tuo codice dovrebbe/vorrebbe fare questo:

1) inizializzo le comunicazioni col GPS e la Seriale->PC
2) mi metto in attesa e ricevo i dati eventualmente spediti dal GPS mettendoli in un array
3) nel momento in cui leggo il byte 13 (carattere invio, presumo), stampo sulla seriale->PC i dati raccolti
4) reinizializzo il buffer di ricezione e mi rimetto in ascolto

Ecco, il problema sono i puntoi 3 e 4, secondo me.
Col punto 3 tu ti metti ad inviare i dati verso il PC ma il GPS non continua a spedirti i dati verso l'Arduino? A me pare di sì.
Dopo che hai spedito l'array al PC, tu al punto 4 reinizializzi il buffer di ricezione, ma così cancelli i dati che avevi ricevuto dal GPS fino a quel momento. Così poi ti metti in ascolto in un punto imprecisato della comunicazione, per mandare i dati ancora al PC appena arriva un carattere 13.

Logged


BZ (I)
Offline Offline
Brattain Member
*****
Karma: 251
Posts: 21269
+39 349 2158303
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

non usare  la libreria
SoftwareSerial.h
ma la newsoftseria arduiniana.org/libraries/newsoftserial/

poi per leggere un byte usa il controllo se ci sono dati presenti con

Code:
if (device1.available() > 0)
  {
    int c = device1.read();
    ...
  }

Ciao Uwe
Logged

0
Offline Offline
Sr. Member
****
Karma: 1
Posts: 443
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Penso anche io che il tuo problema sia la software serial. Prova ad abbassare il baud rate della software serial e a portare quello della seriale vera a 115200, così hai meno tempi morti.

P.S. L'IDE di arduinio ha messo a disposizione una classe apposita per le stringhe. Se hai da manipolarle pesantemente ti conviene dargli un'occhiata. Il link è questo: http://arduino.cc/en/Reference/StringObject

Grazie, non sapevo di questa classe per le stringhe.
Per quanto riguarda la velocità della seriale, posso sicuramente aumentare quella che va vero sil pc a 115200 ma non ho trovato nulla per cambiare la velocità del gps.
Logged


0
Offline Offline
Sr. Member
****
Karma: 1
Posts: 443
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Mi è venuta a mente un'altra cosa (guarda, stavo per andare a letto, sono tornato al pc apposta  smiley-grin ). Se fosse il problema della software serial, la prima stringa in teoria dovrebbe stampartela correttamente... Fammi sapere.

Si, la prima la riceve correttamente a parte un carattere ascii casuale all'inizio dovuto forse a qualche spuria.
Inoltre, se io gli faccio printare via seriale ogni byte che riceve, vedo tutti i dati correttamente.
Logged


0
Offline Offline
Sr. Member
****
Karma: 1
Posts: 443
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Non conosco le librerie in oggetto ma mi pare che ci sia un errore logico di fondo, ossia il tuo codice dovrebbe/vorrebbe fare questo:

1) inizializzo le comunicazioni col GPS e la Seriale->PC
2) mi metto in attesa e ricevo i dati eventualmente spediti dal GPS mettendoli in un array
3) nel momento in cui leggo il byte 13 (carattere invio, presumo), stampo sulla seriale->PC i dati raccolti
4) reinizializzo il buffer di ricezione e mi rimetto in ascolto

Ecco, il problema sono i puntoi 3 e 4, secondo me.
Col punto 3 tu ti metti ad inviare i dati verso il PC ma il GPS non continua a spedirti i dati verso l'Arduino? A me pare di sì.
Dopo che hai spedito l'array al PC, tu al punto 4 reinizializzi il buffer di ricezione, ma così cancelli i dati che avevi ricevuto dal GPS fino a quel momento. Così poi ti metti in ascolto in un punto imprecisato della comunicazione, per mandare i dati ancora al PC appena arriva un carattere 13.

Ma finchè io non ho printato tramite il ciclo for tutto l'array e non l'ho inizializzato, il ciclo di loop non è finito e qundi le istruzioni che scaricano i dati seriali e li mettono sul buffer non vengono eseguite...................o sbaglio?
Logged


0
Offline Offline
Sr. Member
****
Karma: 1
Posts: 443
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

non usare  la libreria
SoftwareSerial.h
ma la newsoftseria arduiniana.org/libraries/newsoftserial/

poi per leggere un byte usa il controllo se ci sono dati presenti con

Code:
if (device1.available() > 0)
  {
    int c = device1.read();
    ...
  }

Ciao Uwe

Provo a studiarmi newsotseriale e vediamo se risolve.
Grazie smiley
Logged


Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 325
Posts: 22498
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Ma finchè io non ho printato tramite il ciclo for tutto l'array e non l'ho inizializzato, il ciclo di loop non è finito e qundi le istruzioni che scaricano i dati seriali e li mettono sul buffer non vengono eseguite...................o sbaglio?
Ma la seriale implementata nell'Arduino ha un buffer di 128 byte. Se arrivano più dei 128 byte, i vecchi dati vanno persi, sovrascritti dai nuovi. Usare la NewSoftSerial può aiutarti nel senso che la libreria riceve i dati dal buffer di Arduino anche quando il tuo codice non fa una lettura esplicita però devi sempre tenere a mente il limite dei 128 byte. Puoi provare ad alzarlo modificando il file HardwareSerial.cpp nel core di Arduino però poi diminuisci la memoria SRAM a disposizione del programma.
« Last Edit: September 24, 2011, 03:08:18 am by leo72 » Logged


0
Offline Offline
Sr. Member
****
Karma: 1
Posts: 443
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Grazie a tutti dei consigli.
NewSoftSerial ha risolto il problema alla grande smiley
Logged


0
Offline Offline
Shannon Member
****
Karma: 130
Posts: 10449
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

non usare  la libreria
SoftwareSerial.h
ma la newsoftseria arduiniana.org/libraries/newsoftserial/

poi per leggere un byte usa il controllo se ci sono dati presenti con

Code:
if (device1.available() > 0)
  {
    int c = device1.read();
    ...
  }

Ciao Uwe


specifichiamo: la softserial NON usa gli interrupt, quindi se arrivano dati mentre non stai facendo una read(), vengono persi per sempre. Invece sia la seriale harware che la NewSoftSerial parcheggiano i dati in arrivo, anche se stai facendo altro, in un buffer, da cui potrai leggeri con calma.
ovvio rimane il "piccolo" problema dell'overflow del buffer, spiegato da leo72, ma a meno che tu non faccia calcoli pazzesci o uso di delay, non dovrestiincappare nel problema
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Pages: [1]   Go Up
Jump to: