[Risolto] neoGPS: la velocità dopo i 64km/h ricomincia da zero!

Ciao a tutti

Pochi giorni fa ho riprogrammato il mio indicatore di limiti di velocità, ma succede una cosa strana che posso solo imputare alla libreria, in quanto prima funzionava benissimo, indicando senza problemi i 130km/h, mentre ora il problema si manifesta anche con le vecchie versioni del programma. Inoltre, se forzo a 80km/h o più la variabile V che legge il valore proveniente dalla libreria, tale valore viene visualizzato regolarmente.

Questo è ciò che accade: da 0 a 5km/h viene visualizzato 0, per evitare instabilità da fermi; accelerando, la velocità indicata aumenta fino a 64km/h; accelerando ulteriormente, torna a 0, ricominciando da 5 a 70km/h (poiché fino a 4 viene visualizzato 0) e aumentando progressivamente: 6, 7, 8, 9, 10 (75km/h)…

La versione installata di neoGPS è la 4.2.9. Da sketch/include/gestione librerie ho provato a installare una versione precedente, ma l’IDE dice:

Trovata libreria non valida in E:\Documenti\Arduino\libraries\NeoGPS: Nessun header file (.h) trovato in E:\Documenti\Arduino\libraries\NeoGPS

Ho scaricato l’IDE 1.8.13 in versione zip e ho copiato la cartella contenuta, ma anche con questa versione ottengo lo stesso risultato. Perché non mi fa installare una versione precedente?

Mi potete aiutare?

Grazie
Gianluca

Limiti_v3.2a.zip (26.8 KB)

Adesso, riavviato il computer, non da più errori, ma se installo una versione precedente (ad es. la 4.2.5) appare la barra di scaricamento e finisce, ma rimane scritto:

NeoGPS by SlashDevin Versione 4.2.9 INSTALLED

Anche se chiudo e riapro l'IDE, risulta installata sempre la 4.2.9! >:(

Ho cancellato la cartella NeoGPS e le altre due arduino_xxxxxx in cui credo avesse messo le versioni che avevo sostituito: finalmente sono riuscito a caricare la 3.1.2. Adesso vediamo che succede a 65km/h... (e, se vogliamo, che succede a 88mph applicando 1,21 Gigowatt! :) )

Se si resetta a 65.535 cè sicuramente un unsigned int da qualche che dovrabbe essere un long int.

Dici che misura in m/h?... Giorni fa ho cercato nel codice, ma non sono riuscito a trovare la funzione della velocità.

Ho trovato

bool NMEAGPS::parseSpeedKph( char chr )
{
  #ifdef GPS_FIX_SPEED
    parseSpeed( chr );

    if ((chr == ',') && m_fix.valid.speed) {
      uint32_t kph    = m_fix.spd.int32_000();
      // Convert to Nautical Miles/Hour
      uint32_t nmiph  = (kph * 1000) / gps_fix::M_PER_NMI;
      m_fix.spd.whole = nmiph / 1000;
      m_fix.spd.frac  = (nmiph - m_fix.spd.whole*1000);
    }
  #endif

  return true;

} // parseSpeedKph

ma la funzione è fix.speed_metersph()

Prova a forzare quei 1000 in 1000UL

Quella è la libreria... Adesso vado a vedere che c'è scritto nella vecchia v3.1.2.

V è int

V = fix.speed_metersph()/1000; // km/h

V deve poter contenere solo il risultato finale, no?... Il punto è che fino a qualche settimana fa funzionava. Il problema si è manifestato quando ho ricaricato il codice. Non c'è se forzo V=80.

v3.1.2: metersph è definito in GPSfix.h:

  #ifdef GPS_FIX_SPEED
    whole_frac    spd; // .001 nautical miles per hour

    uint32_t speed_mkn () const { return spd.int32_000(); };
    float    speed     () const { return spd.float_000(); };

    // Utilities for speed in other units
    CONST_CLASS_DATA float KM_PER_NMI = 1.852;
    float    speed_kph () const { return speed() * KM_PER_NMI; };

    CONST_CLASS_DATA uint16_t M_PER_NMI = 1852;
    uint32_t speed_metersph() const { return (spd.whole * M_PER_NMI) + (spd.frac * M_PER_NMI)/1000; };

    CONST_CLASS_DATA float MI_PER_NMI = 1.150779;
    float  speed_mph() const { return speed() * MI_PER_NMI; };
  #endif

v4.2.9:

#ifdef GPS_FIX_SPEED
    whole_frac    spd; // .001 nautical miles per hour

    uint32_t speed_mkn () const { return spd.int32_000(); };
    float    speed     () const { return spd.float_000(); };

    // Utilities for speed in other units
    CONST_CLASS_DATA float KM_PER_NMI = 1.852;
    float    speed_kph () const { return speed() * KM_PER_NMI; };

    CONST_CLASS_DATA uint32_t M_PER_NMI = 1852;
    uint32_t speed_metersph() const { return (spd.whole * M_PER_NMI) + (spd.frac * M_PER_NMI)/1000; };

    CONST_CLASS_DATA float MI_PER_NMI = 1.150779;
    float  speed_mph() const { return speed() * MI_PER_NMI; };
  #endif

Se forzo V:

V = fix.speed_metersph()/1000; // km/h
V=130000/1000;

tutto funziona regolarmente. Appena prendo la macchina e vado fuori città, dove posso superare i 50km/h, vedo se funziona con NeoGPS v3.1.2.

Nota: già a Luglio avevo ricaricato il programma dopo qualche modifica insignificante (riguardava la visualizzazione su LCD) e il numero di satelliti rimaneva sempre a 0! Ho scoperto che il problema si manifestava con le versioni della libreria dalla 4.1.8 in poi, perciò ho usato la 4.1.7.

Datman: Quella è la libreria... Adesso vado a vedere che c'è scritto nella vecchia v3.1.2.

V è int

V = fix.speed_metersph()/1000; // km/h

V deve poter contenere solo il risultato finale, no?... Il punto è che fino a qualche settimana fa funzionava. Il problema si è manifestato quando ho ricaricato il codice. Non c'è se forzo V=80.

Ma non è che nel frattempo è cambiato nell'IDE la toolchain e il compilatore interpreta in maniera diversa le conversioni tra tipi diversi ? (ma mi parrebbe strano/assurdo) La funzione ritorna un uint32_t cioè un unsigned long. V è int, 1000 è int. In teoria dovrebbe essere una divisione senza problemi (tenendo conto del più grande che è uint32_t int=uint32/int )

Prova banalmente a forzare quel 1000 con 1000UL Ancora meglio, aggiungi un passaggio tramite un uint32:

// V = fix.speed_metersph()/1000;
uint32_t tmp=fix.speed_metersph();
V = tmp/1000UL;

Se scrivo V=130000/1000 viene visualizzato correttamente 130...

Purtroppo non ho modo di fare prove senza muovermi realmente ad almeno 70km/h... Domani vedrò se, compilato adesso con la v3.1.2, funziona.

Sono sempre più convinto che dovrebbero essere salvati progetti completi delle librerie usate al momento della compilazione, in maniera da poter, poi, modificare e ricompilare un programma esattamente nelle stesse condizioni, senza alcun problema. Allo stato attuale, invece, già usando un altro computer, ad esempio condividendo un programma, è necessario avere installate le librerie e non si può essere certi che con la versione installata (che potrebbe essere più recente, oppure potrebbe essere una versione più vecchia che non è stata aggiornata) tutto funzionerà come previsto! Nella cartella dei file del programma, quindi, dovrebbe essere inclusa una copia delle librerie usate, richiamate nel programma con un nome che comprenda la versione, ad esempio NMEAGPS 3.1.2 (perché mai, poi, NeoGPS [come appare nel gestore delle librerie] si chiama NMEAGPS???...), o almeno dovrebbe essere fornita una funzione di esportazione che salvi il programma completo delle librerie necessarie. Al momento dell'apertura di un programma, se nella cartella sono presenti le librerie necessarie, verranno usate quelle anziché quelle installate nel computer.

Datman: Se scrivo V=130000/1000 viene visualizzato correttamente 130...

Così scrivi 2 costanti, e il compilatore secondo me ottimizza e sostituisce il tuo calcolo con già il risultato 130.

Ciao a tutti
Ho fatto molti tentativi mentre mia moglie guidava in autostrada ma non sono riuscito a risolvere il problema, finché mi è venuto in mente di provare a fare io la conversione da miglia/h a km/h: ha funzionato! :slight_smile:
Perciò, anziché V=fix.speed_metersph(); ho scritto V=fix.speed_mph()*1.60934;
Evidentemente nella libreria è sbagliato il formato della variabile nella conversione da miglia/h a km/h…

Datman: Evidentemente nella libreria è sbagliato il formato della variabile nella conversione da miglia/h a km/h...

In effetti --> https://github.com/SlashDevin/NeoGPS/blob/1707c2c462e150fdb367bef6b6df51d14632b9a8/src/GPSfix.h#L154

Hai visto qualcosa che non va? Io leggo solo:

    CONST_CLASS_DATA uint32_t M_PER_NMI = 1852;
    uint32_t speed_metersph() const { return (spd.whole * M_PER_NMI) + (spd.frac * M_PER_NMI)/1000; };

    CONST_CLASS_DATA float MI_PER_NMI = 1.150779;
float speed_mph() const { return speed() * MI_PER_NMI; };

e speed_metersph() è a 32 bit, quindi non è limitata a 65535. Da qualche parte ci deve essere una variabile a 16 bit... Probabilmente ha scelto la variabile pensando ai km/h, mentre poi ha modificato in m/h probabilmente per poter leggere i decimi di km/h alle basse velocità.

Quello che non riesco a capire è che una volta funzionava...