Gps heading convertire gradi in lettere?

Guarda che nessuno ti sta dando dell’ignorante in senso dispregiativo, ci mancherebbe ! :open_mouth:

Ti si sta solo dicendo che … ti mancano le basi di un dato linguaggio, tu vuoi usare quel linguaggio per sviluppare tue applicazioni … il minimo è che ti STUDI approfonditamente il linguaggio che vuoi usare non ti pare ?

Guglielmo

penso di si perchè la nano è già piena al 95% e per quanto abbia scritto le stringhe in modo che credo (forse) corretto non posso caricare salvo non cancellare metà di quello che c’è già.
o almeno così è uscito dalle prove che ho fatto prima che potesse compliare correttamente ho dovuto eliminare // non poche delle parti che adesso sarebbero in uso.
questo è il codice che sto usando e funziona perfettamente ma non ci posso aggiungere un singolo carattere di testo, posso solo limare dalla presentazione"logger gps"

#include <SPI.h>
#include <SD.h>
#include <Wire.h>
#include "SSD1306Ascii.h"
#include "SSD1306AsciiWire.h"
#include <NMEAGPS.h>
#include <NeoSWSerial.h>
const int cs_sd = 2;
#define I2C_ADDRESS 0x3C
#define RST_PIN -1
SSD1306AsciiWire oled;
NMEAGPS gps;
gps_fix fix;
File myFile;
float odo;
float Speed;
float alt;
float Dist;
float maxs = 0;
float Am = 0;
float head;
unsigned int Sat = 0;
NeoGPS::Location_t    lastLoc, base;
bool stScan = true;
bool                  lastLocOK = false;
static const int RXPin = 5, TXPin = 4;
static const uint32_t GPSBaud = 9600;
NeoSWSerial gpsPort(RXPin, TXPin);
const int SHOW_INTERVAL = 1;
const int INITIAL_SHOW  = (2 * SHOW_INTERVAL) - 1;
int show          = INITIAL_SHOW;
const int   LED_PIN  = 3;
const float SPEED_LIMIT = 0.1; // speed limit value
void setup() {
  pinMode (LED_PIN, OUTPUT);
  Serial.begin(9600);
  gpsPort.begin(GPSBaud);
  Wire.begin();
  oled.begin(&SH1106_128x64, I2C_ADDRESS);
  oled.setFont(ZevvPeep8x16);
  oled.clear();
  oled.setCursor(23, 2);
  oled.println("LOGGER GPS");
  delay(2000);
  oled.clear();
  if (!SD.begin(cs_sd)) {
    oled.clear();
    oled.setCursor(60, 2);
    oled.print("SD");
    delay(10000);
    oled.clear();
    return;
  }
  oled.setCursor(60, 2);
  oled.print("OK");
  delay(2000);
  oled.clear();
  File data = SD.open("log.csv", FILE_WRITE);
  data.println("");
  data.println("D  H  La  Lo  A  Am  Km  D  V" );
  data.close();
}
void loop() {
  if (gps.available( gpsPort )) {
    gps_fix fix = gps.read();
    show = (show + 1) % SHOW_INTERVAL;
    if ( Speed > maxs)
      maxs = Speed;
    if (fix.valid.heading )
      head = (fix.heading() );
    if (fix.valid.satellites )
      Sat = (fix.satellites );
    if (fix.valid.altitude)
      alt = (fix.altitude ());
    if ( alt > Am)
      Am = alt;
    if (fix.valid.speed && (fix.speed_kph() > SPEED_LIMIT)) {
      digitalWrite( LED_PIN, HIGH );
    } else {
      digitalWrite( LED_PIN, LOW );
    }
    if (fix.valid.location) {
      if (lastLocOK) {
        odo += fix.location.DistanceKm( lastLoc );
        Speed = (fix.speed_kph());
      }
      lastLoc   = fix.location;
      lastLocOK = true;
      if (stScan) {
        stScan = false;
        base   = fix.location;
      } else {
        Dist = ( fix.location.DistanceKm( base ) );
      }
    }
    if (show == 0) {
#define MAX_CHARS 24
      char displayBufffer[MAX_CHARS];
      oled.setCursor(0, 0);
      snprintf(displayBufffer, MAX_CHARS, "Km:%2d.%1d",  (int)odo, (int)(odo * 100) % 100);
      oled.println(displayBufffer);
      oled.setCursor(65, 0);
      snprintf(displayBufffer, MAX_CHARS, "Di:%2d.%1d",  (int)Dist, (int)(Dist * 100) % 100);
      oled.println(displayBufffer);
      snprintf(displayBufffer, MAX_CHARS, "Ve:%2d.%1d", (int)Speed, (int)(Speed * 100) % 100);
      oled.println(displayBufffer);
      oled.setCursor(65, 2);
      snprintf(displayBufffer, MAX_CHARS, "Vm:%2d.%1d", (int)maxs, (int)(maxs * 100) % 100);
      oled.println(displayBufffer);
      snprintf(displayBufffer, MAX_CHARS, "Al:%2d.%1d", (int)alt, (int)(alt * 100) % 100);
      oled.println(displayBufffer);
      oled.setCursor(65, 4);
      snprintf(displayBufffer, MAX_CHARS, "Am:%2d.%1d", (int)Am, (int)(Am * 100) % 100);
      oled.println(displayBufffer);
      snprintf(displayBufffer, MAX_CHARS, "Sa:%2d", (int)Sat, (int)(Sat * 1) % 1);
      oled.println(displayBufffer);
      oled.setCursor(65, 6);
      snprintf(displayBufffer, MAX_CHARS, "He:%2d.%1d", (int)head, (int)(head * 100) % 100);
      oled.println(displayBufffer);
    }
    if (fix.dateTime);
    String Temps = String(fix.dateTime.hours + 2 ) + (":") + (fix.dateTime.minutes);
    String Date = String(fix.dateTime.day ) + ("/") + (fix.dateTime.month);
    File data = SD.open("log.csv", FILE_WRITE);
    data.println(Date + ("  ") + Temps + ("  ") + String(fix.latitude(), 6) + ("  ") + String(fix.longitude(), 6) + ("  ") + (alt) + ("  ") + (Am) + ("  ") + (odo) + ("  ") + (Dist) + ("  ") + (Speed));
    data.close();
  }
}

adesso però ho da STUDIARE il linguaggio e vediamo se poi avrò voglia di continuare visto che dalle prove che ho fatto per tutto il pomeriggio con strcpy mi restituisce sempre che non c’è abbastanza memoria a disposizione.
non ho idea se dipende da strcpy oppure da qualcos’altro ma alla fine la bussola in gradi mi va benissimo, so leggerla.
mi spiace se non conosco il linguaggio ma sono un modellista, arduino non è il mio hobby anche se per alcune cose è dovuto diventarlo.
mettermi a studiare il C++ per lavoro non ci potrei mai riuscire, farlo per passione non potrebbe mai essere la mia passione, io maneggio il legno e il metallo.
studiarlo perchè ne ho necessità per costruire qualcosa mi può capitare, ci perdo tutto il tempo necessario leggendomi paginate del forum inglese, sperimentando, sbagliando, ma oltre questo non vado, mi spiace.
per adesso va bene così, grazie a tutti.

Secondo me i problemi derivano piuttosto dalla sprintf() che è abbastanza pesante piuttosto che dalla strcpy() e da tutte quelle maledette classi String che abbiamo detto e ripetuto un’infinità di volte di NON USARE !!!

Guglielmo

Le direzioni sono classificate diversamente, avanti indietro destra sinistra ma sono sempre 8.
Ma questa mi sembra ancora più elegante

e cosa dovei usare invece delle classi String per ottenere il medesimo risultato?

Le stringhe classiche del ‘C’ (array di char) e, come già detto, tutte le funzioni di <string.h>, oppure, “volendo vincere facile”, almeno usare la libreria SafeString che è descritta nella sezione software.

Guglielmo

ho installato la libreria e fatto 1 ora di prove senza venirne a capo (me lo aspettavo? un pochino si) ma quello che non capisco è il fine. cosa cambierebbe? quali vantaggi rispetto a come lo sketch è scritto adesso? non sono non capisco cosa dovrei fare ma soprattutto perchè lo dovrei fare. uso questo sketch da circa 1 anno, funziona bene, posso migliorarlo? ok, in quali termini il miglioramento sarebbe apprezzabile rispetto ad adesso? è chiaro che vorrei rendere il gps (che uso e mi serve) il più efficiente possibile anche perchè adesso ha 2 difetti (il giorno della data è sempre 7, l’altitudine si aggiorna di rado e spesso con valori errati, idem il conteggio dei satelliti che a volte spara numeri a 3 cifre) ma non riesco davvero a mettermi a studiare il C da un giorno all’altro per arrivare a ottenere dei risultati che non so determinare neanche quali potrebbero essere. avrei bisogno di una spiegazione per favore.

Quello che può succedere con l’uso della classe String è che venga consumata la RAM della MCU che ad esempio nel caso della UNO è di soli 2k.
Questo effetto c’è anche sui PC ma siccome di RAM ce n’è una quantità maggiore di diversi ordini di grandezza non te ne accorgi.
Se hai un po’ di basi di C non c’è bisogno che ti fai un corso completo, anche se aiuta.
In questo caso il tuo problema è la gestione di stringhe in C, se cerchi con Google trovi parecchia documentazione.
Per esempio questa

Io neppure ho fatto un corso di C ma piano piano, cercando in rete opportunamente, ho sempre trovato la soluzione e ormai, avendo un po’ di conoscenza, sono in grado di valutare se va bene per me o è una soluzione da Ufficio Complicazione Affari Semplici.
Una miniera è Stackoverflow e tutti quelli derivati in quanto alle soluzioni si da un punteggio e di solito quelle con il punteggio più alto te le trovi in cima.

Evidentemente non hai letto il primo post del link che ti ho dato perché … c’è ben spiegato quale è il problema.

Guglielmo

Un anno è molto tempo :wink:

Battute a parte, è evidente che lo sketch è frutto di un “assemblaggio” delle diverse funzionalità fatto un po’ alla cieca.
Ad esempio per stampare a display i messaggi usi l’istruzione snprintf() / print() con il “trucchetto” per i float mentre per salvare le stesse informazioni sulla SD usi le String di Arduino quindi un metodo completamente diverso.
Ad esempio “riciclando” lo stesso approccio che usi per l’OLED con la parte SD puoi ridurre lo spazio occupato dal firmware dal 97% al 90% (c’è anche un errore sull’if credo).

 if (fix.dateTime) { 
      File data = SD.open("log.csv", FILE_WRITE);      
      snprintf(displayBufffer, MAX_CHARS, "%02d:%02d %02d/%02d ", fix.dateTime.day, fix.dateTime.month, fix.dateTime.hours, fix.dateTime.minutes);
      data.print(displayBufffer);
      snprintf(displayBufffer, MAX_CHARS, "%d.%d %d.%d ", (int)fix.latitude(), (int)(fix.latitude()*1000)%1000, (int)fix.longitude(), (int)(fix.longitude()*1000)%1000) ;
      data.print(displayBufffer);
      snprintf(displayBufffer, MAX_CHARS, "%d.%d %d.%d %d.%d ", (int)alt, (int)(alt*1000)%1000, (int)Am, (int)(Am*1000)%1000, (int)odo, (int)(odo*1000)%1000) ;
      data.print(displayBufffer);
      snprintf(displayBufffer, MAX_CHARS, "%d.%d %d.%d\n", (int)Dist, (int)(Dist*1000)%1000, (int)Speed, (int)(Speed*1000)%1000)  ;
      data.print(displayBufffer);      
      data.close();
    }

Per quanto riguarda l’aggiunta che vuoi fare, se continui ad usare lo stesso metodo non dovrebbero esserci problemi.

grazie! per favore mi puoi spiegare che senso hanno i numeri moltiplicati e divisi alla fine delle stringhe *1000)%1000 ??
perchè non 100 o 10 ?
poi, come mai nell’ultima hai aggiunto \n?
cosa cambia? giusto per dare un senso che possa capire.
ti ringrazio.

Puoi salvare ulteriori bytes di ram usando sprintf_P al posto della sprintf() e usando la macro PSTR() per la stringa di formato, esempio:

snprintf_P(displayBufffer, MAX_CHARS, PSTR("%02d:%02d %02d/%02d "), fix.dateTime.day, fix.dateTime.month, fix.dateTime.hours, fix.dateTime.minutes);

Ciao, Ale.

ho fatto questa prova: ho cambiato displayBufffer con SDbufffer e ho sistemato l’esempio di Cotestatnt in questo modo

 File data = SD.open("L.csv", FILE_WRITE);

#define MAX_CHARS 24
    char SDBufffer[MAX_CHARS];
    if (fix.dateTime) {
      snprintf(SDBufffer, MAX_CHARS, "%02d:%02d %02d/%02d ", fix.dateTime.day, fix.dateTime.month, fix.dateTime.hours, fix.dateTime.minutes);
      data.print(SDBufffer);
    }
    snprintf(SDBufffer, MAX_CHARS, "%d.%d %d.%d ", (int)fix.latitude(), (int)(fix.latitude() * 1000) % 1000, (int)fix.longitude(), (int)(fix.longitude() * 1000) % 1000) ;
    data.print(SDBufffer);
    snprintf(SDBufffer, MAX_CHARS, "%d.%d %d.%d %d.%d ", (int)alt, (int)(alt * 1000) % 1000, (int)Am, (int)(Am * 1000) % 1000, (int)odo, (int)(odo * 1000) % 1000) ;
    data.print(SDBufffer);
    snprintf(SDBufffer, MAX_CHARS, "%d.%d %d.%d\n", (int)Dist, (int)(Dist * 1000) % 1000, (int)Speed, (int)(Speed * 1000) % 1000)  ;
    data.print(SDBufffer);
    data.close();
  }
}

però adesso mi dice che c’è poca memoria 27.866 (90%) per i programmi. 1587 (77%) variabili globali, 461 byte per le variabili locali.
non posso provarlo ma adesso vedo di ridurlo giusto per capire come appare scritto su SD perchè con le String di prima era tutto in fila e tutto in colonna.

si capisco ma in questo anno ho preso il covid, mi ritrovo un uovo di gallina da 7cm in un rene e ho perso il lavoro, tutte le aziende del mio settore hanno chiuso… nel frattempo prendo 2 nuovi farmaci giornalieri per tutta la vita e ogni giorno dovrei fare una decina di km a piedi, non ti dico i piedi. il C è l’ultimo dei miei problemi e se posso svagarmi lo faccio con le cose che mi appassionano.
sistemare il gps al suo meglio è qualcosa che per la maggior parte vorrei regalare a chi lo costruirà dopo di me, un copiaincollaro che non sa fare nulla mi va benissimo se lo posso rendere felice con un giochino nuovo che gli interessa.
come è adesso si trova su project hub, se in futuro migliorerà editerò lasciando una versione migliore e sinceramente non mi importa molto se è frutto di anni di studi o dell’aiuto di qualcuno studiato che ha voluto partecipare per semplice passione.

Il suo skecth però è al limite soprattutto con la dimensione della flash (infatti la soluzione proposta dal punto di vista della RAM è leggermente peggiorativa).

Non sono moltiplicati e divisi, sono moltiplicati e poi c’è l’operazione modulo, ovvero l’operazione che restituisce il resto intero della divisione.
Questo è necessario perché le istruzioni tipo snprintf, printf, snprintf_P ovvero tutte quelle che prevedono una stringa di formattazione riempita poi con una serie di variabili, non supportano il tipo dati float proprio perché troppo “oneroso” per piccoli microcontrollori come quello del Nano (ATMega328).
Questo è un modo per visualizzare/printare i float senza “spendere” troppe risorse forzando il casting ad intero con l’istruzione (int) messa prima.
Se ad esempio hai un valore tipo 2.795 ottieni che (int) 2 => diventa 2, questo risultato viene messo dall’istruzione snprintf() al posto del primo format specifiers %d presente nella stringa di formattazione.
La parte decimale la ottieni facendo (int) (2.795*1000) % 1000 => 2795 % 1000 => ovvero prendo 2795 divido per 1000 e tengo il resto == 795 che viene messo al posto del secondo %d e cosi via.

10, 100, 1000, 100000 dipende dal numero dei decimali che vuoi ottenere nella stringa formattata.

1 Like

Ops…

Ciao, Ale.

ah… quindi vediamo se ho capito… non avendo bisogno di decimali eccetto uno (n,n) invece di *1000)%1000 potrei mettere tutto a 10? tutti i dati mi vanno bene con un solo decimale anche l’altitudine potrebbe essere 250,2 giusto per fare un esempio.
i satelliti poi non hanno decimali, a volte riscontro l’errore di numeri assurdi per il conteggio dei satelliti tipo 622 nel caso non desideri decimali doveri mettere *1)%1 ?

Si, ma l’espediente con l’operazione modulo % è necessario solo con i float. Se i valori sono degli interi basta usare un solo specificatore %d

int var = 150;
snprintf(buffer, sizeof(buffer), "Io sono un intero %d",  var);

Ti rimando a questo link per tutti i tipi di specifiers disponibili (eccezione il float) e come si possono combinare.
Ad esempio

int var = 150;
snprintf(buffer, sizeof(buffer), "Io sono un intero %06d",  var);

produrrà un output del tipo “Io sono un intero 000150”,
Al posto dello 0 puoi usare anche uno spazio volendo… etc etc. Ci sono molte possibili combinazioni.

P.S.
Se i valori che sono in ballo sono dei decimali, perché li memorizzi come float?
Anche questo potrebbe (in minima parte a dire il vero) contribuire ad ottimizzare il codice.

Questo link… non c’è! :wink:
O è più su?

Azz… m’hanno fregato il link :rofl::grin:

P.S.
Corretto messaggio originario

grazie, ho provato a definire le stringhe "ora data " nella prima parte del codice, non cambia nulla e funziona in modo identico.
ho sistemato secondo la mia logica gli spazi e i decimali.
il giorno rimane sempre 7 il mese va bene… non so perchè, se dipende dal setup del modulo, dalla libreria, non ho idea.
il meglio che riesco a fare è questo

#include <SPI.h>
#include <SD.h>
#include <Wire.h>
#include "SSD1306Ascii.h"
#include "SSD1306AsciiWire.h"
#include <NMEAGPS.h>
#include <NeoSWSerial.h>
const int cs_sd = 2;
#define I2C_ADDRESS 0x3C
#define RST_PIN -1
SSD1306AsciiWire oled;
NMEAGPS gps;
gps_fix fix;
File myFile;
float odo;
float Speed;
float alt;
float Dist;
float maxs = 0;
float Am = 0;
float head;
unsigned int Sat = 0;
String oStr, dStr;
NeoGPS::Location_t    lastLoc, base;
bool stScan = true;
bool                  lastLocOK = false;
static const int RXPin = 5, TXPin = 4;
static const uint32_t GPSBaud = 9600;
NeoSWSerial gpsPort(RXPin, TXPin);
const int SHOW_INTERVAL = 1;
const int INITIAL_SHOW  = (2 * SHOW_INTERVAL) - 1;
int show          = INITIAL_SHOW;
const int   LED_PIN  = 3;
const float SPEED_LIMIT = 0.1; // speed limit value
void setup() {
  pinMode (LED_PIN, OUTPUT);
  Serial.begin(9600);
  gpsPort.begin(GPSBaud);
  Wire.begin();
  oled.begin(&SH1106_128x64, I2C_ADDRESS);
  oled.setFont(ZevvPeep8x16);
  oled.clear();
  oled.setCursor(55, 2);
  oled.println("GPS");
  delay(2000);
  oled.clear();
  if (!SD.begin(cs_sd)) {
    oled.clear();
    oled.setCursor(60, 2);
    oled.print("SD");
    delay(10000);
    oled.clear();
    return;
  }
  oled.setCursor(60, 2);
  oled.print("OK");
  delay(2000);
  oled.clear();
  File data = SD.open("L.csv", FILE_WRITE);
  data.println("");
  data.println("D  H  La  Lo  A  Km  D  V  H" );
  data.close();
}
void loop() {
  if (gps.available( gpsPort )) {
    gps_fix fix = gps.read();
    show = (show + 1) % SHOW_INTERVAL;

    if (fix.valid.speed && (fix.speed_kph() > SPEED_LIMIT)) {
      digitalWrite( LED_PIN, HIGH );
    } else {
      digitalWrite( LED_PIN, LOW );
    }
    if (fix.valid.location) {
      if (lastLocOK) {
        odo += fix.location.DistanceKm( lastLoc );
        Speed = (fix.speed_kph());
      }
      lastLoc   = fix.location;
      lastLocOK = true;
      if (stScan) {
        stScan = false;
        base   = fix.location;
      } else {
        Dist = ( fix.location.DistanceKm( base ) );
      }
    }
    if ( Speed > maxs)
      maxs = Speed;
    if (fix.valid.heading )
      head = (fix.heading() );
    if (fix.valid.satellites )
      Sat = (fix.satellites );
    if (fix.valid.altitude)
      alt = (fix.altitude ());
    if ( alt > Am)
      Am = alt;

    if (show == 0) {
#define MAX_CHARS 24
      char displayBufffer[MAX_CHARS];
      oled.setCursor(0, 0);
      snprintf(displayBufffer, MAX_CHARS, "Km:%2d.%1d",  (int)odo, (int)(odo * 100) % 100);
      oled.println(displayBufffer);
      oled.setCursor(65, 0);
      snprintf(displayBufffer, MAX_CHARS, "Di:%2d.%1d",  (int)Dist, (int)(Dist * 100) % 100);
      oled.println(displayBufffer);
      snprintf(displayBufffer, MAX_CHARS, "Ve:%2d.%1d", (int)Speed, (int)(Speed * 10) % 10);
      oled.println(displayBufffer);
      oled.setCursor(65, 2);
      snprintf(displayBufffer, MAX_CHARS, "Vm:%2d.%1d", (int)maxs, (int)(maxs * 10) % 10);
      oled.println(displayBufffer);
      snprintf(displayBufffer, MAX_CHARS, "Al:%2d", (int)alt, (int)(alt * 100) % 100);
      oled.println(displayBufffer);
      oled.setCursor(65, 4);
      snprintf(displayBufffer, MAX_CHARS, "Am:%2d", (int)Am, (int)(Am * 100) % 100);
      oled.println(displayBufffer);
      snprintf(displayBufffer, MAX_CHARS, "Sa: %1d", (int)Sat);
      oled.println(displayBufffer);
      oled.setCursor(65, 6);
      snprintf(displayBufffer, MAX_CHARS, "He:%2d", (int)head, (int)(head * 100) % 100);
      oled.println(displayBufffer);
    }

    if (fix.dateTime);
    oStr = String(fix.dateTime.hours + 2) + (":") + (fix.dateTime.minutes);
    dStr = String(fix.dateTime.day) + ("/") + (fix.dateTime.month);
    File data = SD.open("L.csv", FILE_WRITE);
    data.println(dStr + ("  ") + oStr + ("  ") + String(fix.latitude(), 6) + ("  ") + String(fix.longitude(), 6) + ("  ") + (alt) +  ("  ") + (odo) + ("  ") + (Dist) + ("  ") + (Speed) + ("  ") + (head));
    data.close();
  }
}

sono riuscito a far funzionare la colonna di lettere al posto dei gradi sfruttando l’esempio delle direzioni(che è il soggetto del post) ma ho capito che fa schifo, non è per niente pratico e preferisco lasciare i gradi numerici perché diventa tutto troppo approssimativo.
possono esserci miglioramenti possibili eliminando String e usando Le stringhe classiche del ‘C’ ma non so farlo, non posso perdermi oltre per capire qualcosa che ha talmente tante istruzioni da non sapere poi dove mettere mano.
ho provato anche a caricare Safestring ma poi non sono stato capace di mettere in pratica quello che ho letto.
va bene così, per uno come me con la terza media e un’esperienza su metalli e legname posso accettare i miei limiti e anche le critiche di chi giustamente mi dice che sono troppo ignorante.
grazie a tutti.