da un po' di tempo non usavo più Arduino e sono un po' arrugginito soprattutto per quanto riguarda le cifre significative dei dati a 16bit...
Ho una coordinata (45.064119349972025) che ottengo sotto forma di stringa e devo trasformare a float. Printando con 8 cifre dopo la virgola (so che sono troppe, ma volevo vedere fino a dove 'rispetta' l'input della stringa) ottengo 45.06411743. Quindi dovrebbe avere come significative 7 cifre.
Siccome devo lavorare sempre a 45°N e 9°E ho deciso di eliminare le cifre intere. In quel caso mi sembra che le cifre significative diventino 8. Dovrebbe c'entrare qualcosa la posizione della virgola, ma non ricordo più nulla. Mi rinfrescate la la teoria dietro questo troncamento?
Stavo pensando addirittura di usare degli unsigned long con le prime 9 cifre dopo la virgola, secondo voi ha controindicazioni? Il valore massimo dovrebbe essere 4294967295, evito la decima cifra significativa perché supererei sicuramente quel valore.
Fa differenza se si usano i tipi "standard" del linguaggio( int ecc che sono diversi su architetture diverse), non ne fa usando i c types specifici (uint16_t uint32_t ecc che sono uguali per tutti).
Con 16 bit si possono rappresentare correttamente i decimali da 0 a 9999. Con 32 bit da 0 a 999999999.
E come fai a definire che lavori a 16bit? NON certo dichiarando 'int' che su AVR è a 16 bit, su SAM e su ESP è a 32 bit ... come ti ha detto Claudio, o usi i tipi definiti in <stdint.h> o sei dipendete dall'architettura.
Scordati tutti quei decimali con il float a 32 bit ... c'è una vecchia discussione in merito che riguarda la precisione dei float ... QUI ... fa capire come funzionano
Ma sicuro che le cifre che hai riportato sono realmente quelle in standfard NMEA fornite dal tuo GPS? Perché non credo che per i GPS standard si vada mai oltre le 7 cifre decimali significative, in genere le vedo tra 5 e 7 (e dipende anche dalla precisione necessaria a seconda dell'applciazione).
E comunque neanche un float a 32 bit in genere ti assicura questa precisione per la mantissa (23 bit significano solo 7 decimali).
Per cui la soluzione di usare solo interi potrebbe funzionare, magari uno per i gradi (basta un int) ed un unsigned long per i decimali, che come sai va da 0 a 4,294,967,295 quindi la mantissa sarà limitata a circa 9 cifre comunque. Tutto dipende poi da cosa dovrai farci.
avevo infatti definito che a 16bit intendevo la variabile. Al di là del controllore.
Un po' alla volta sto recuperando le nozioni che avevo messo da parte per anni:
segno(1)-esponente(8)-mantissa(23) e da qua è 'veloce' ricavarsi i valori massimi e minimi immagazzinabili. Ma il numero di cifre dopo la virgola non ricordo come calcolarlo. Però leggendo vedo che dovrebbero essere 6 o 7, per cui devo fare affidamento massimo su 6 certi. Un GPS ritorna standard ggmm.mmmmm quindi dopo il parsing della NMEA in gradi e decimale di grado avrei 7 cifre decimali di grado. Che però sono le uniche che mi interessano all'atto pratico.
Usando un unsigned long dovrei poter rappresentare al massimo il valore 4294967295, per cui io potrei limitarmi a usare 9 cifre dopo la virgola come intero e copro tranquillamente quelle fornite dal GPS. Se poi riesco ad aggiungere 1/2 cifre al GPS copro anche quelle.
Corretto?
@docdoc No, quelle non sono ottenute da un GPS. Devo fare dei checkpoint usando la massima precisione possibile. O meglio c'è tutto un aspetto che esula dal tema del topic e non divago. In breve ho bisogno di un dato con circa 2m di errore massimo.
Con 23 bit per la mantissa puoi avere valori tra 0 e 2^23 ossia 8,388,608 per cui le cifre sicuramente significative sono (almeno) 6.
Che io sappia, con 6 cifre decimali si arriva benissimo a quella precisione per cui la soluzione dell'unsigned long (per la sola mantissa) è più che sufficiente.
Se vuoi verificarlo, prova a giocare un poco con QUESTO convertitore/mappa...
Per provare a fare due calcoli in modo "scientifico", sapendo che il raggio quadratico medio della Terra (ellissoide che approssima la forma non perfettamente sferica della Terra) è di r=6.372.507 metri, data la una differenza angolare "a" (differenza di una coordinata decimale la lunghezza "d" dell'arco) in gradi, si calcola con:
Con a=±0,000001 metri (differenza tra coordinate decimali con 6 cifre significative) si ha:
d = ±0.11122122875 m = ±11.12 cm
Mi sembra che, almeno in teoria, una precisione di ±11 cm sia più che sufficiente.
Lo so bene, ma ciò che ho descritto è semplicemente la teoria, e limitatamente alla parte decimale di un generico float a 32 bit.
Anche io, il GPS non militare ha generalmente una precisione di circa 5-10 metri, che poi unito ad altri criteri (es. a-GPS, sorgenti WiFi, ecc.) può aumentarne la precisione. Ma l'OP ha detto che non è una coordinata proveniente da un GPS per cui tutti i discorsi correlati a come funzionano i GPS ed il formato NMEA li sto ignorando, restando sulla teoria almeno finché non avremo ulteriori spiegazioni su come ottenga quei valori e perché gli servano 14 decimali...
@docdoc
Gentilissimo. Si come dicevo quel dato non è ricavato da un GPS, non ho ancora il GPS in mano fisicamente ed è in arrivo.
Io avrò dei dati noti come checkpoint (il dato che ho postato) e dei dati GPS. Al momento non avendo ancora molto in mano sto ragionando in termini puramente matematici, poi quando avrò il sistema vediamo a che precisione arrivo.
Per cui banalmente sto dicendo: il GPS mi spara fuori 1-25Hz (immagino di gettarlo a 10). Ho una velocità media di 80km/h. A spanne sono circa un dato ogni 2m. Ho visto che 2m sono circa la quinta cifra decimale per cui vorrei avere almeno la sesta. Questo è stato il ragionamento spannometrico che ho fatto.
@gpb01
Avrei un'ultima domanda per te. La scrivo qui anche se leggermente OT: consigli sempre di gestire le stringhe come char e generalmente seguo questo consiglio.
Se però io dovrò ricevere dei byte dalla seriale, ma non so la lunghezza del messaggio come si può gestire?
Ho necessità che la variabile sia definita globale perché potrei leggerla in più iterazioni del loop.
Definendola della massima lunghezza possibile ... TUTTE le stringhe classiche del 'C hanno comunque un terminatore 0x00 che indica la fine, quindi non c'è rischio d'errore.
Ok, ma se il GPS comunque non arriva oltre le 6 cifre decimali significative, un checkpoint a 14 cifre decimali non è che serva a molto, non trovi?
Qui dipende strettamente dal GPS che userai, per cui penso che sia inutile discuterne ulteriormente, devi vedere le specifiche dell'unità GPS che userai e relativo formato dei dati inviati.
Comunque i calcoli teorici che ti ho descritto ovviamente sono validi se la ricezione GPS è buona e stabile. Poi qui parliamo di GPS, ma è anche possibile che il ricevitore supporti più costellazioni (tipo GLONASS, Galileo...) facendone magari anche interpolazione per migliorare la precisione e stabilità.
Confermo quindi che secondo me ti conviene verificare prima su cosa dovrai lavorare e quali caratteristiche e limitazioni abbia, e solo dopo valutare soluzioni. Come dico sempre (anche ad alcuni clienti..), prima di pensare a soluzioni bisogna avere ben chiaro il problema.
PS: 80 kmh, checkpoint (waypoint?)... Tutta sta cosa mi fa pensare ad un drone...
Pienamente d'accordo. Ma quando ho fatto un software che funziona con 8 cifre decimali sono a posto 'per sempre', quando faccio un software che funziona con 5 o 6 il giorno che per qualche motivo ne ho a disposizione 8 mi tocca rifare da capo.
Nono niente droni, ruote ben ancorate sull'asfalto
Di fatto sto cercando di farmi un 'Mychron' fai da te.
Ma con tutte queste cifre che ci fai, a parte stamparle?
Perché se ci devi fare calcoli di distanze o direzioni senza trigonometria non fai nulla
E trigonometria intera piu che una contraddizione è una barzelletta
Mi immagino quanto valga pigreco...
E quindi o trovi un'intera libreria che gestisca numeri "lunghi e diversamente rappresentati" (nel senso che non possono essere ne float ne double e avrei dubbi con i long troncati)
Oppure cerchi una mcu che abbia dei veri double
Come terza alternativa potresti scriverti da te le funzioni trigonometriche base
Ma ci vuole una certa pazienza
... ormai ce ne sono tante, tutte quelle a 32 bit implementano, via software, i double a 64 bit ... se poi c'è bisogno di velocità e si vuole una FPU a 64 bit, basta passare ad una Teeensy 4.1 e si ha di tutto e di più
A domanda ‘provocatoria’ rispondo in modo ‘piccato’, ma ovviamente senza alcuna cattiveria. Ci mancherebbe.
Ci fai il minimo che puoi farci con un GPS che d’ora dati a 25Hz e quindi con ‘Delta’ tra due posizioni che potrebbero variare di pochi cm.
Tra l’altro tra trigonometria ed elettronica ti assicuro che il mio problema minore è la trigonometria
Comunque, tornando seri, in realtà sto cercando di farmi un Mychron fai da te per avere un data logger-telemetria per kart/moto/auto in pista.
Il progetto, se mai vedrà la luce, prevede in vari step:
GPS
Sensori di Hall per le strisce magnetiche (che non sempre ci sono, e di cui non conosci le caratteristiche)
Accelerometri?
Schermo
Invio dati
…?
In futuro prevedo di usare Rasp. Anche perché le liste di Python permettono di giocare coi dati in modo assai più semplice di C. Soprattutto se hai a che fare con le matrici. Ma comunque qui va a gusti.
Al momento ho ‘fretta’ e poca esperienza con Rasp quindi provo a far funzionare tutto con Arduino.
La questione assetto l’ho già affrontata in passato. Usavo inquaternioni (Magdwick), ma ho paura che su messi non sospesi come i kart gli acc impazziscano, è un problema che ho già visto dove lavoro sulle moto di serie…
Dovrò studiare un sistema con montaggio elastico nel caso.
In più per l’assetto te ne frega il giusto, ma se vuoi usare i dati di accelerazione dovresti conoscere il baricentro che su alcuni mezzi cambia costantemente con il movimento del corpo. Quindi temo che questo sarà un passaggio quasi impossibile…
Confermo quindi che secondo me ti conviene verificare prima su cosa dovrai lavorare e quali caratteristiche e limitazioni abbia, e solo dopo valutare soluzioni.
Quindi PRIMA prendi il GPS che pensi di usare, POI vedi quali caratteristiche ha, e IN BASE A QUESTO poi inizi a fare prove per verificare se riesci a fare quello che hai in mente.
Tutto molto bello ("bella la boiserie", cit.), basta che non sia l'ennesimo caso di "sindrome di Gundam" (aggravato dalla tua "fretta")...
E dato che (quasi) tutto si riduce alle caratteristiche (qualità e precisione) del ricevitore GPS, torniamo al punto di partenza, ossia direi di riparlarne solo quando avrai l'aggeggio ed avrai fatto con questo le tue verifiche e test per verificare i dati che invia e la relativa precisione: farlo ora è perfettamente inutile e direi che l'argomento abbia ormai esaurito spunti utili.
Spesso mi domando perché non ci si limiti a rispondere nel tema della domanda fatta, ma si cominci a pontificare e giudicare senza avere la minima idea di chi sia e cosa faccia l’interlocutore.
Il programma l’ho già fatto in Python a 64 bit e funziona. Son tutte cose che ho già usato e fatto, a meno di gps con aggiornamento a frequenza molto elevata e mezzi che viaggiano a velocità che richiedono quella frequenza.
La mia domanda era un ‘rinfrescarmi’ la memoria perché l’ultimo progetto grosso con Arduino l’ho fatto una decina di anni fa e avendo usato sistemi ‘garbate collector’ per anni sono un po’ arrugginito sull’ ottimizzazione delle risorse di memoria…
Fine del problema
Il gps arriverà i primi di febbraio, ho preso un ublox m9