Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

NMEA: come memorizzare i dati

47 views
Skip to first unread message

Marco Trapanese

unread,
May 31, 2009, 7:13:49 AM5/31/09
to

Ciao,

domanda forse ingenua. Sto scrivendo una libreria per gli AVR per
decodificare i pacchetti NMEA (non solo GPS). A differenza di quanto si
fa su macchine piᅵ performanti o addirittura su un PC c'ᅵ da tenere in
considerazione lo spazio occupato in memoria.

Prendiamo per esempio una classica stringa:

$--RMC,hhmmss.ss,A,llll.ll,a,yyyyy.yy,a,x.x,x.x,xxxx,x.x,a*hh

1) Time (UTC)
2) Status, V = Navigation receiver warning
3) Latitude
4) N or S
5) Longitude
6) E or W
7) Speed over ground, knots
8) Track made good, degrees true
9) Date, ddmmyy
10) Magnetic Variation, degrees
11) E or W
12) Checksum

Quale modo furbo conviene utilizzare per memorizzare i dati ricevuti?

Potrei semplicemente memorizzare i campi in stringhe, ma poi quando
dovrᅵ utilizzarli dovrᅵ convertirli ogni volta in numeri.

L'ideale sarebbe memorizzarli nel formato corretto, ad esempio:

* time e date in una struct che contenga i campi hour, minute, second ecc...
* coordinate e velocitᅵ in float

Non mi piace perᅵ usare la virgola mobile. Volendo evitarla dovrei usare
un intero a 32 bit per la longitudine e longitudine e a 16 per gli altri
rendendo poco uniformi i vari dati.

Ultima perplessitᅵ: visto che i vari progetti faranno uso di stringhe
NMEA diverse e quindi difficilmente saranno usate tutte assieme vorrei
evitare di allocare lo spazio per poi lasciare i campi inutilizzati.

Perᅵ, viceversa, la routine di decodifica vorrebbe avere il puntatore
alla struttura ricevente.

Mi ᅵ venuto in mente di utilizzare una serie di #define e successivi
#ifdef per escludere a livello di compilazione la dichiarazione dei
campi stringa e il blocco di decodifica relativo ma mi sembra poco elegante.

Suggerimenti? :)

Marco

Francesco Sacchi

unread,
May 31, 2009, 7:33:53 AM5/31/09
to

Mi sembra una buona idea, i dati non devono per forza essere tutti
dello stesso tipo, devono essere del tipo giusto per la grandezza che
devono contenere. Ti sconsiglio di usare la virgola mobile, secondo me
riesci a fare tutto con dati a virgola fissa.

> Ultima perplessitᅵ: visto che i vari progetti faranno uso di stringhe
> NMEA diverse e quindi difficilmente saranno usate tutte assieme vorrei
> evitare di allocare lo spazio per poi lasciare i campi inutilizzati.
>
> Perᅵ, viceversa, la routine di decodifica vorrebbe avere il puntatore
> alla struttura ricevente.
>
> Mi ᅵ venuto in mente di utilizzare una serie di #define e successivi
> #ifdef per escludere a livello di compilazione la dichiarazione dei
> campi stringa e il blocco di decodifica relativo ma mi sembra poco
> elegante.

Al contrario io credo che sia un'idea molto buona, ᅵ l'approccio
standard che si usa quando si vuole supportare diverse modalitᅵ di
funzionamento senza appesantire troppo il codice compilato: a compile
time configuri il modulo per come ti serve e quando generi il codice
le strutture e il codice contengono solo il necessario. Questo
approccio va bene fintanto che non devi far interagire codice
configurato in maniera diversa, ma non mi sembra questo il caso.

> Suggerimenti? :)

Ti sei giᅵ suggerito tutto da solo :-)

P.S.
Fra un po' anche io dovrᅵ parsare dati NMEA su un AVR!

--
_|/ Francesco Sacchi - Develer S.r.l., R&D dept.
|\ http://www.develer.com/ - http://www.bertos.org

Marco Trapanese

unread,
May 31, 2009, 8:14:59 AM5/31/09
to
Francesco Sacchi ha scritto:

>> Suggerimenti? :)
>
> Ti sei giᅵ suggerito tutto da solo :-)


Bene! Allora vuol dire che qualcosa sto imparando :)


> P.S.
> Fra un po' anche io dovrᅵ parsare dati NMEA su un AVR!


Benvenuto! Io con l'NMEA ci gioco un po' ovunque: PC, Rabbit, ARM e ora AVR.

Marco

dalai lamah

unread,
May 31, 2009, 1:31:48 PM5/31/09
to
Un bel giorno Marco Trapanese digit�:

> * coordinate e velocit� in float
>
> Non mi piace per� usare la virgola mobile. Volendo evitarla dovrei usare

> un intero a 32 bit per la longitudine e longitudine e a 16 per gli altri
> rendendo poco uniformi i vari dati.

Tieni presente che un float a 32 bit non ti fornisce la sufficiente
risoluzione per memorizzare qualsiasi coordinata generata dalle sentenze
NMEA. In alcune condizioni (che ora su due piedi non ricordo) c'� un errore
vicino al mezzo metro; in molte applicazioni pu� essere irrilevante,
comunque � bene tenerlo a mente.

--
emboliaschizoide.splinder.com

Marco Trapanese

unread,
Jun 1, 2009, 3:15:28 AM6/1/09
to
dalai lamah ha scritto:

> Tieni presente che un float a 32 bit non ti fornisce la sufficiente
> risoluzione per memorizzare qualsiasi coordinata generata dalle sentenze
> NMEA. In alcune condizioni (che ora su due piedi non ricordo) c'� un errore
> vicino al mezzo metro; in molte applicazioni pu� essere irrilevante,
> comunque � bene tenerlo a mente.


A parte che lo standard non mi � chiaro: riporta appunto llll.ll per la
latitudine e yyyyy.yy per la longitudine quindi con 2 cifre decimali. Ma
ho qui un log di un GPS che ha 3 cifre decimali...

Comunque nel caso peggiore avrei 18000000 (180� 00.000') che dovrebbe
starci in un float o sbaglio?

Ad ogni modo se anche volessi usare un int32 dovrei sapere se moltiplico
per 100 o per 1000, non voglio mettermi via anche un campo dove inserire
il moltiplicatore! Per� lo standard dice 2 cifre decimali, questo GPS ne
da 3.

Ognuno fa a modo suo?

Marco

dalai lamah

unread,
Jun 1, 2009, 1:33:47 PM6/1/09
to
Un bel giorno Marco Trapanese digit�:

>> Tieni presente che un float a 32 bit non ti fornisce la sufficiente


>> risoluzione per memorizzare qualsiasi coordinata generata dalle sentenze
>> NMEA. In alcune condizioni (che ora su due piedi non ricordo) c'� un errore
>> vicino al mezzo metro; in molte applicazioni pu� essere irrilevante,
>> comunque � bene tenerlo a mente.
>
>
> A parte che lo standard non mi � chiaro: riporta appunto llll.ll per la
> latitudine e yyyyy.yy per la longitudine quindi con 2 cifre decimali. Ma
> ho qui un log di un GPS che ha 3 cifre decimali...

Ovviamente pi� il GPS � preciso, pi� cifre decimali servono. E non farti
ingannare dal fatto che i comuni GPS hanno una precisione CEP assoluta di
2-3 metri; in realt� grazie all'analisi del doppler la precisione relativa
fra un punto e l'altro � molto maggiore (decine di cm, appunto). Per
applicazioni GIS magari non serve, ma se invece hai bisogno di tracciare
una traiettoria � abbastanza utile. :)

> Comunque nel caso peggiore avrei 18000000 (180� 00.000') che dovrebbe
> starci in un float o sbaglio?

Non � una questione di starci, � una questione di risoluzione. Rispetto ai
fixed point, i numeri floating point ovviamente sacrificano risoluzione in
favore di un range estremamente pi� grande. Puoi fare degli esperimenti con
questa calcolatrice online:

http://babbage.cs.qc.cuny.edu/IEEE-754/Decimal.html

Prendiamo ad esempio le coordinate di Roma indicate su Wikipedia: 41.893056
N, 12.483333 E. Con la calcolatrice sopra citata puoi vedere che i punti
(41.893054,12.483333) e (41.893056,12.483333) sono indistinguibili; se li
convertiamo in UTM, ad esempio con questo tool:

http://www.apsalin.com/convert-geodetic-to-universal-transverse-mercator.aspx

Otteniamo le coordinate (291219.612045562,4640965.05372734) e
(291219.618563301,4640965.27580443), cio� due punti che distano
(-0.006517739,-0.22207709), cio� circa 22 cm. E questo a Roma, figurati a
Berlino o a Reykiavik o come diavolo si scrive, da qualche parte
dev'esserci una j. :)

--
emboliaschizoide.splinder.com

Marco Trapanese

unread,
Jun 1, 2009, 2:08:15 PM6/1/09
to
dalai lamah ha scritto:

> Ovviamente pi� il GPS � preciso, pi� cifre decimali servono.

Quindi devo memorizzare per ciascun campo NMEA decimale anche un valore
intero che mi dice quanto cifre ho dopo la virgola? Argh...


> Prendiamo ad esempio le coordinate di Roma indicate su Wikipedia: 41.893056
> N, 12.483333 E. Con la calcolatrice sopra citata puoi vedere che i punti
> (41.893054,12.483333) e (41.893056,12.483333) sono indistinguibili; se li
> convertiamo in UTM, ad esempio con questo tool:

[cut]

Ricevuto!

Marco

Francesco Sacchi

unread,
Jun 1, 2009, 2:48:40 PM6/1/09
to
Marco Trapanese wrote:
> dalai lamah ha scritto:
>
>> Ovviamente pi� il GPS � preciso, pi� cifre decimali servono.
>
> Quindi devo memorizzare per ciascun campo NMEA decimale anche un valore
> intero che mi dice quanto cifre ho dopo la virgola? Argh...

Non � necessario farlo a runtime, anche questo pu� essere
configurabile a compile time con una macro.

Poi ti devi fare anche delle macrettine di accesso ai membri della
struttura che dividono/moltiplicano per il numero giusto ed il gioco �
fatto.

Questa soluzione, come dicevo in un post precedente, funziona finch�
la tua libreria non deve interfacciarsi con il mondo esterno,
altrimenti la precisione con cui fornisci i dati conta e deve essere
nota a priori.

Comunque, anche in questo caso, io stabilirei una precisione che va
bene per la mia applicazione e userei quella.
Se a te bastano 2 cifre e un GPS ne fornisce 3, scarterai la terza;
viceversa se ne gestisci 3 e un GPS ne ha solo 2, la terza sar� sempre
a 0.

In definitiva io non mi complicherei la vita fino a quando non �
necessario.

Marco Trapanese

unread,
Jun 1, 2009, 2:53:44 PM6/1/09
to
Francesco Sacchi ha scritto:

> Non � necessario farlo a runtime, anche questo pu� essere configurabile
> a compile time con una macro.


E come fai a sapere che razza di GPS o altro strumento NMEA ci collega
l'utonto? :)


> Questa soluzione, come dicevo in un post precedente, funziona finch� la
> tua libreria non deve interfacciarsi con il mondo esterno, altrimenti la
> precisione con cui fornisci i dati conta e deve essere nota a priori.


Ecco, appunto!


> Comunque, anche in questo caso, io stabilirei una precisione che va bene
> per la mia applicazione e userei quella.
> Se a te bastano 2 cifre e un GPS ne fornisce 3, scarterai la terza;
> viceversa se ne gestisci 3 e un GPS ne ha solo 2, la terza sar� sempre a 0.


Si, in effetti � forse pi� semplice questa via. Definisco la precisione
e poi nella routine di decodifica agisco di conseguenza.

Marco

Pasu

unread,
Jun 2, 2009, 3:48:57 AM6/2/09
to
Marco Trapanese wrote:
> Francesco Sacchi ha scritto:
>
>> Non � necessario farlo a runtime, anche questo pu� essere
>> configurabile a compile time con una macro.
>
>
> E come fai a sapere che razza di GPS o altro strumento NMEA ci collega
> l'utonto? :)

Mi intrometto come al solito :-p
Ma una volta che hai deciso la lunghezza del tuo dato (16 o 32 bit o
quantaltro), non � pi� semplice usare la massima precisione disponibile
e (come dice Francesco) riempire di zeri le cifre decimali che non
conosci? Il tuo dato varia da -180 a 180 giusto? E allora perch� non ti
riservi i bit necessari per rappresentare il tuo +/-180 ed il resto lo
usi per i decimali? Oppure, per sfruttare appieno tutta la risoluzione
disponibile (e forse anche semplificare i calcoli) trasformi il tuo 360
nella pi� piccola frazione rappresentabile: 2^32/360/60/60, hai che la
risoluzione � di 1/3300 di secondo.
Il parsing della stringa NMEA non dovrebbe essere un problema (mi sembra
di capire che ci sia una virgola tra un dato e l'altro).

F.S.>> Comunque, anche in questo caso, io stabilirei una precisione che va


>> bene per la mia applicazione e userei quella.
>> Se a te bastano 2 cifre e un GPS ne fornisce 3, scarterai la terza;
>> viceversa se ne gestisci 3 e un GPS ne ha solo 2, la terza sar� sempre
>> a 0.
>
>
> Si, in effetti � forse pi� semplice questa via. Definisco la precisione
> e poi nella routine di decodifica agisco di conseguenza.

Forse come prima versione � pi� saggio fare il minimo indispensabile.
Una volta testato il funzionamento si fa sempre in tempo ad espandere.

Marco Trapanese

unread,
Jun 2, 2009, 3:57:32 AM6/2/09
to
Pasu ha scritto:

> Mi intrometto come al solito :-p


Fai bene! :)


> Ma una volta che hai deciso la lunghezza del tuo dato (16 o 32 bit o
> quantaltro), non � pi� semplice usare la massima precisione disponibile
> e (come dice Francesco) riempire di zeri le cifre decimali che non
> conosci?


Certo, ma io davo per scontato che se lo standard mi faceva vedere un
dato come xxx.x mi sarei aspettato 3 cifre intere e 1 decimale.
Invece ho scoperto che tanto standard non � :)

Per cui l'idea iniziale l'ho dovuta abbandonare!


> Il tuo dato varia da -180 a 180 giusto? E allora perch� non ti
> riservi i bit necessari per rappresentare il tuo +/-180 ed il resto lo
> usi per i decimali?


Perch� in alcuni casi non � cos� chiaro il dominio del dato. Prendi ad
esempio il campo profondit� (da DBT, DBS) non sta scritto da nessuna
parte quale potr� essere la massima rilevata :(
Ok, a intuito ci si pu� arrivare basandosi sulla strumentazione
utilizzata ma o si fa una routine di conversione per nulla banale (che
gestisca anche l'overflow) altrimenti si rischia di avere un firmware
che funziona solo con determinata strumentazione...


> Il parsing della stringa NMEA non dovrebbe essere un problema (mi sembra
> di capire che ci sia una virgola tra un dato e l'altro).

La stringa in se � banale: i campi sono separati da virgola e i decimali
da un punto. Per�, ripeto, non sapendo il range di ciascun campo �
difficile scegliere il corretto tipo di dato e la precisione dei decimali.


> Forse come prima versione � pi� saggio fare il minimo indispensabile.
> Una volta testato il funzionamento si fa sempre in tempo ad espandere.


Penso anche io. Per ora mi accontento di definire la precisione con una
define, poi una volta capiti bene i limiti di ciascun campo vedr� di
impostare la migliore possibile!

Ciao!
Marco

Pasu

unread,
Jun 2, 2009, 4:12:00 AM6/2/09
to
Marco Trapanese wrote:

> Perch� in alcuni casi non � cos� chiaro il dominio del dato. Prendi ad
> esempio il campo profondit� (da DBT, DBS) non sta scritto da nessuna
> parte quale potr� essere la massima rilevata :(

Se per profondit� intendi l'asse z (la quota, insomma) se non sbaglio
questa ha precisione minore rispetto alle altre due coordinate. Quindi
anche se fossero date con lo stesso numero di cifre decimali queste non
sarebbero tutte significative. In ogni caso il tuo apparecchio non andr�
nello spazio (o s�? :-o) o nella fossa delle Marianne (nella quale, mi
dicono, la ricezione � un po' scadente:-)
Comunque fino a 12000m (mi sembra sia questo il limite imposto dalla
NASA) con 16bit avresti la precisione del mezzo metro.

Ciao!

Pasu

Marco Trapanese

unread,
Jun 2, 2009, 4:15:51 AM6/2/09
to
Pasu ha scritto:

> Se per profondit� intendi l'asse z (la quota, insomma) se non sbaglio
> questa ha precisione minore rispetto alle altre due coordinate. Quindi
> anche se fossero date con lo stesso numero di cifre decimali queste non
> sarebbero tutte significative. In ogni caso il tuo apparecchio non andr�
> nello spazio (o s�? :-o) o nella fossa delle Marianne (nella quale, mi
> dicono, la ricezione � un po' scadente:-)
> Comunque fino a 12000m (mi sembra sia questo il limite imposto dalla
> NASA) con 16bit avresti la precisione del mezzo metro.


Il DBT o il DBT sono dati che normalmente vengono generati dagli
ecoscandagli quindi misurano la profondit� del fondale dall'imbarcazione
di superficie o immersa.

Normalmente arrivano a 100 m di range utile, con la precisione (o meglio
risoluzione) al decimetro.

Per� il mio era un esempio per dire che bisogna sempre sapere
concretamente che utilizzo si fa del dato e poi ragionarci sopra per
trovare il compromesso migliore. Insomma, lo standard non aiuta!

Ma come fanno gli altri? Meglio che provo a vedere qualche codice gi�
scritto...

Marco

ps. comunque il mio funziona, solo che ha le limitazioni appena esposte!

Pasu

unread,
Jun 2, 2009, 4:26:46 AM6/2/09
to
Marco Trapanese wrote:

> Il DBT o il DBT sono dati che normalmente vengono generati dagli
> ecoscandagli quindi misurano la profondit� del fondale dall'imbarcazione
> di superficie o immersa.

Ah ok scusa, mi ero fissato col GPS...

> Normalmente arrivano a 100 m di range utile, con la precisione (o meglio
> risoluzione) al decimetro.

ok, quindi ampiamente sotto i 16bit

> Per� il mio era un esempio per dire che bisogna sempre sapere
> concretamente che utilizzo si fa del dato e poi ragionarci sopra per
> trovare il compromesso migliore. Insomma, lo standard non aiuta!

Io non la vedo cos� tragica la configurazione con dei #define.
Dovrebbe esserci un modo per far controllare al precompilatore se una
costante (o un prodotto) supera la capacit� di rappresentazione scelta,
cos� da agire di conseguenza.

> Ma come fanno gli altri? Meglio che provo a vedere qualche codice gi�
> scritto...

Ottima idea...Reinventare la ruota non aiuta quasi mai.

Ciao

Pasu

Marco Trapanese

unread,
Jun 2, 2009, 4:35:14 AM6/2/09
to
Pasu ha scritto:

>> Ma come fanno gli altri? Meglio che provo a vedere qualche codice gi�
>> scritto...
>
> Ottima idea...Reinventare la ruota non aiuta quasi mai.


Infatti le persone serie utilizzano float o double :o)
Ho appena trovato 3-4 sorgenti (anche per AVR) in cui utilizzavano
comodamente una scanf e in una riga di codice si mettevano via tutto il
pacchetto :(
Si, per� cos� non vale...

Sgrunt, ma ci vuole un'enormit� di RAM (e anche una discreta velocit� di
calcolo) per fare ci�!

Marco

Pasu

unread,
Jun 3, 2009, 5:06:31 AM6/3/09
to
Marco Trapanese wrote:
> Infatti le persone serie utilizzano float o double :o)

Bisogna vedere se sono "persone serie" informatiche o
elettroniche/firmwariste
Magari il codice � elegante, ordinato, modulare, autoesplicativo... Ma
l'efficienza (in termini di consumo di risorse e di tempo di esecuzione)
di solito non si sposa bene con le qualit� suddette.

> Ho appena trovato 3-4 sorgenti (anche per AVR) in cui utilizzavano
> comodamente una scanf e in una riga di codice si mettevano via tutto il
> pacchetto :(
> Si, per� cos� non vale...

Probabilmente � gente che non si � mai posta il problema di andare a
verificare il codice generato...

> Sgrunt, ma ci vuole un'enormit� di RAM (e anche una discreta velocit� di
> calcolo) per fare ci�!

Infatti, sarebbe interessante confrontare il codice macchina generato
dal tuo metodo ed il loro...

Ciao!

Pasu

0 new messages