A cosa può servire un modulo GPS su ESP32?
Io ho comprato il NEO-6M (vero o falso cmq funziona) con antenna attiva sul sito:
https://it.aliexpress.com/item/1005004841512460.html?spm=a2g0o.order_list.order_list_main.23.ed733696n9BE98&gatewayAdapt=glo2ita
(7€ con la spedizione)
per avere un aggiornamento di data e ora sulla macchina senza avere una connessione wifi o schede con orologio interno che in genere richiedono poi un'aggiornamento (sempre wifi) perchè col passare delle ore/giorni tendono a scostarsi dall'ora precisa e che cmq devono avere una batteria di alimentazione costante per funzionare.
Il mio ESP32 prende l'alimentazione dall'accendisigari della macchina, per cui quando tolgo la chiave della macchina non assorbe corrente.
Consiglio a questo punto, se volete utilizzarlo(e se avete un modulo GPS con chip Ublox), di installare il programma U-CENTER dal sito ufficiale:
perchè con questo programma potete modificare parecchi parametri del GPS e salvarli nella sua memoria interna
e installare anche il programma Google Earth se non lo avete ancora :
per vedere la posizione del GPS sulla mappa 3D che vengono trasmesse automaticamente dal programma U-Center nel primo menù Database export/Google Earth server
COLLGAMENTI PC-GPS
Per collegarmi al modulo GPS (piazzato in balcone con case di fronte per cui non nella posizione ottimale che sarebbe in campo aperto senza neanche alberi o nuvole) dal PC ho utilizzato una prolunga di 5 metri USB e un modulo USB-TTL
L'uscita TX del modulo TTL và collegata alla porta RX del modulo GPS e RX del modulo TTL alla TX del modulo GPS.
RICORDO CHE IL MODULO NEO-6M VÀ ALIMENTATO A 3.3 VOLT
PER CUI PRENDETE L'ALIMENTAZIONE DALL'USCITA 3.3V DEL MODULO TTL o da ESP32
Se non avete un modulo USB-TTL potete utlizzare anche ESP32 con una routine simile a questa:
// In questo esempio sto utilizzando un ESP32-2432S028 Yellow in cui i pin di default (16 e 17) per la Uart 2 sono stati
// utilizzati per il led posteriore...a cosa serve?...un pò di fuochi d'artificio?...visto che non è neanche sul frontale ma sul retro
//Per cui sto utilizzando i pin 21 e 22 disponibili su una porta di espansione + GND e prendo i 3.3 Volt dalla porta accanto
// ma se state usando un ESP32 tradizionale potete usare i pin 16 e 17
#include <HardwareSerial.h>
#define RX 21 // Connesso al modulo GPS TX pin per ESP32 normale è il pin 16
#define TX 22 // Connesso al modulo GPS RX pin per ESP32 normale è il pin 17
HardwareSerial GPS(1); // Usiamo UART1 mentre UART0/Seriale è usato per ricevere/inviare i messaggi da USB
void setup() {
Serial.begin(9600);
delay(500);
while (Serial.available() > 0) {// elimino buffer
Serial.read();
}
GPS.begin(9600, SERIAL_8N1, RX, TX); // Serial GPS
delay(500);
while (GPS.available() > 0) {
GPS.read();
}
}
void loop() {
int len = GPS.available();
while (len > 0) { // Do blocks of bytes for efficiency
uint8_t buffer[128];
int xferlen = len;
if (len > sizeof(buffer)) xferlen = sizeof(buffer);
GPS.readBytes(buffer, xferlen);
Serial.write(buffer, xferlen);
len -= xferlen;
}
int len2 = Serial.available();
while (len2 > 0) { // Do blocks of bytes for efficiency
uint8_t buffer2[128];
int xferlen2 = len2;
if (len2 > sizeof(buffer2)) xferlen2 = sizeof(buffer2);
Serial.readBytes(buffer2, xferlen2);
GPS.write(buffer2, xferlen2);
len2 -= xferlen2;
}
}
Con questo sketch di base possiamo aprire Ucenter e visualizzare o modificare le impostazioni del nostro modulo GPS-
Per cui andiamo nel menù View/Messages (F9) e scorrendo in basso nella finestra apriamo UBX che presenta tutta una serie di parametri modificabili e ci visualizza il comando in esadecimale che possiamo utilizzare poi nel nostro sketch per modificare il dato parametro.
Ad esempio in UBX/CFG/RATE UTC Time 500 ms 2Hz (max per Neo-6M è 5Hz) possiamo impostare un rateo di aggiornamento più veloce nell'aggiornare i dati provenienti dal modulo GPS (che di default è 1000 ms) e questo permette una maggiore risoluzione e quindi cambiamenti più discreti tra una lettura e la successiva.
Questo di 500ms è il limite massimo che il programma Ucenter supporta per un aggiornamento delle varie finestre, perchè se impostate un rateo maggiore (max per Neo-6M è 5Hz) le finestre del programma non riescono più ad aggiornarsi, ma se invece leggete i dati sul serial monitor di arduino (spegnendo Ucenter) io ho provato sino a 5Hz e arrivano tranquillamente anche con la seriale impostata a 9600 Baud.
Ora vediamo quali messaggi NMEA escludere dalla trasmissione tra il GPS e ESP32
Un elenco di messaggi lo trovate all'indirizzo:
https://aprs.gids.nl/nmea/#gga
Come potete vedere parecchi dati contenuti nei messaggi si ripetono anche in altri messaggi, per cui è inutile riempire la seriale di messaggi che non ci servono perchè i dati sono contenuti già in altri messaggi.
In particolare a me interessava la data e l'ora per cui ho escluso gli altri messaggi e selezionato solo F0-00 NMEA GxGGA e F0-04 NMEA GxRMC (e in essi sono contenute anche la latitudine/longitudine/altezza, numero di satelliti, validità dei dati ricevuti)
Però se volete continuare a vedere i risultati in Ucenter NON dovete disabilitare UBX/CFG/MSG (Messages GPS Satellites in view) F0-03 NMEA GxGSV perchè lo usa nella visualizzazione delle finestre.
Altri mesaggi possono risultare utili per muoversi da un waipoint ad un altro, indicandovi la direzione e la velocità di spostamento, dipende dalla vostra applicazione di quali dati avete bisogno.
COME MIGLIORARE LA QUALITÀ DEL SEGNALE
Come riportato da Wiki: "Satellite-based augmentation system - SBAS Questi sistemi supportano vaste regioni anche su scala continentale, attraverso l'utilizzo di satelliti geo-stazionari, equipaggiati con apparati in grado di trasmettere segnali simili a quelli emessi da un satellite GNSS, che diffondono l'informazione incrementata. Uno SBAS accresce la costellazione primaria di GNSS fornendo l'allineamento dei satelliti geo-stazionari, l'integrità del segnale e l'informazione di correzione. Sebbene lo scopo principale dello SBAS sia quello di assicurare l'integrità del segnale, questo in effetti ne aumenta anche l'accuratezza con errori di posizione inferiori al metro."
E' già attivato nella configurazione di default, però và attivato anche in UBX/CFG/GNSS (Config) GPS+SBAS Configure+Enable per dire al GPS di considerare anche i messaggi SBAS e settare Auto set nel umero di canali.
Questa è stata la configurazione che mi ha dato minori spostamenti in velocità (sotto lo zero) e in altezza (+- 5 metri).
Ma ripeto, la posizione dell'antenna sul balcone con case di fronte non è nelle condizioni ottimali (che sono in campo aperto, niente alberi, nessuna nuvola).
C'è poi il sistema RTK, ovvero (Real Time Kinematic). è una tecnica GNSS differenziale che fornisce elevate prestazioni di posizionamento nelle vicinanze di una stazione base. La tecnica si basa sull'uso di misurazioni portanti e sulla trasmissione di correzioni dalla stazione base, la cui posizione è ben nota, al rover, in modo che gli errori principali che guidano il posizionamento autonomo si annullino.
L‟utilizzo di questa tecnica di misura è però limitato dagli effetti generati da ionosfera e troposfera sul segnale che le attraversa.
Possiamo selezionare la voce nel menù UBX/CFG/DGNSS e selezionare l'opzione Differential mode 3 che la utilizza se c'è un segnale disponibile.
C'è poi un filtro anti-jamming sull'antenna che si può selezionare e modificare alla voce UBX/CFG/ITFM
Esistono poi altri filtri tipo il Extended Kalman Filter (EKF) che però funzionano in abbinamento a dati provenienti da giroscopio e odometro utili per la navigazione e bussola.
CONFIGURAZIONE
E quà veniamo alla parte dolente, perchè in teoria il mio modulo ha una batteria tampone per cui la configurazione dovrebbe venire salvata in memoria ma purtroppo allo spegnimento del modulo si perdono tutti i settaggi e si torna alla configurazione di default, per cui con ESP32 nel Setup dobbiamo reinviare i comandi che ci interessano (e non sono pochi) con tanto di checksum alla fine.
Per creare questi comandi ci viene in aiuto Ucenter perchè abilitando la finestra esadecimale avremo la stringa con il checksum già calcolato ad esempio B5 62 06 39 08 00 F3 AC 62 AD 1E 63 00 00 76 A5 e con Notepad++ possiamo fare una sostituzione degli spazi con la stringa ", 0x" per ottenere una stringa 0xB5, 0x62, 0x06, 0x39, 0x08, 0x00, 0xF3, 0xAC, 0x62, 0xAD, 0x1E, 0x63, 0x00, 0x00, 0x76, 0xA5 che verrà messa in un array ed inviata al modulo GPS con il comando GPS.write(byteread); (ovvero in esadecimale)
Un esempio di come inviarli lo riporto quà sotto:
// nella dichiarazione delle variabili mettere:
#include <HardwareSerial.h>
#define RX 21 // Connesso al modulo GPS TX pin per ESP32 normale è il pin 16
#define TX 22 // Connesso al modulo GPS RX pin per ESP32 normale è il pin 17
HardwareSerial GPS(1); // Usiamo UART1 mentre UART0/Seriale è usato per ricevere/inviare i messaggi da USB
const PROGMEM uint8_t GpsRate[] = { 0xB5, 0x62, 0x06, 0x08, 0x06, 0x00, 0xF4, 0x01, 0x01, 0x00, 0x01, 0x00, 0x0B, 0x77 }; // 500ms rispetto ai 1000ms di default
// in SETUP dopo aver aperto le 2 seriali mettere:
GPS_SendConfig(GpsRate, 14); //500 ms Dove GpsRate è l'array e 14 è il numero di dati presente nell'array
// fine Setup
// e poi utilizzare questa subroutine:
void GPS_SendConfig(const uint8_t *Progmem_ptr, uint8_t arraysize) {
uint8_t byteread, index;
Serial.print(F("GPSSend "));
for (index = 0; index < arraysize; index++) {
byteread = pgm_read_byte_near(Progmem_ptr++);
if (byteread < 0x10) {
Serial.print(F("0"));
}
Serial.print(byteread, HEX);
Serial.print(F(" "));
}
Serial.println();
Progmem_ptr = Progmem_ptr - arraysize; //set Progmem_ptr back to start
for (index = 0; index < arraysize; index++) {
byteread = pgm_read_byte_near(Progmem_ptr++);
GPS.write(byteread);
}
delay(100);
}
***************** COMANDI *************
FACCIO PRESENTE che questi comandi sono stati ottenuti settando UART1 come porta di collegamento col modulo GPS, se voi utilizzate un'altra porta vanno ricalcolati con il programma Ucenter.
Ora metto una serie di comandi che ho utilizzato in parte, stà a voi quale intendete utilizzare:
UBX/CFG/CFG (Configuration) Revert to default configuration
21 Data
0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x03, 0x1B, 0x9A
UBX/CFG/CFG (Configuration) Revert to last saved configuration SUL MIO MODULO GPS NON FUNZIONA
21 Data
0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x03, 0x1D, 0xB3
UBX/CFG/CFG (Configuration) Save current configuration
21 Data
0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x1D, 0xAB
UBX/CFG/RST Forced Reset (watchdog) User Defined (all)
12 Data
0xB5, 0x62, 0x06, 0x04, 0x04, 0x00, 0xFF, 0xB9, 0x00, 0x00, 0xC6, 0x8B
***************************** GNSS ************************************
UBX/CFG/GNSS (config) GPS(10) + Galileo (10) + Glonass (10)
36 Data
0xB5, 0x62, 0x06, 0x3E, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x0A, 0x00, 0x01, 0x00, 0x01, 0x01, 0x02, 0x01, 0x0A, 0x00, 0x01, 0x00, 0x01, 0x01, 0x06, 0x01, 0x0A, 0x00, 0x01, 0x00, 0x01, 0x01, 0x95, 0x53
UBX/CFG/GNSS (Config) GPS+SBAS Configure+Enable + Auto Set channels --- USARE QUESTA PER SBAS
28 Data
0xB5, 0x62, 0x06, 0x3E, 0x14, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x5F, 0x1E
UBX/CFG/SBAS gli SBAS correggono gli effetti dei ritardi atmosferici sui segnali trasmessi dai satelliti
Ranging(use SBAS in NAV) Apply SBAS correction data Apply integrity information Channel 3 Auto-scan
16 Data
0xB5, 0x62, 0x06, 0x16, 0x08, 0x00, 0x01, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2F, 0xD5
UBX/CFG/GEOFENCE (config) Confidence level 0 (no confidence required)
16 Data
0xB5, 0x62, 0x06, 0x69, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x1B
****************************** RATE **********************************
UBX/CFG/RATE UTC Time 500 ms 2Hz (max per Neo-6M è 5Hz)
14 Data
0xB5, 0x62, 0x06, 0x08, 0x06, 0x00, 0xF4, 0x01, 0x01, 0x00, 0x00, 0x00, 0x0A, 0x75
UBX/CFG/RATE UTC Time 200 ms 5Hz (max per Neo-6M è 5Hz)
14 Data
0xB5, 0x62, 0x06, 0x08, 0x06, 0x00, 0xC8, 0x00, 0x01, 0x00, 0x00, 0x00, 0xDD, 0x68
UBX/CFG/ITFM (Jamming/interferences of antenna) Broadband 3dB CW 15dB Antenna type Active Enable Jamming monitor
16 Data
0xB5, 0x62, 0x06, 0x39, 0x08, 0x00, 0xF3, 0xAC, 0x62, 0xAD, 0x1E, 0x63, 0x00, 0x00, 0x76, 0xA5
+++++++++++++++++++++++++++ MESSAGGI OFF +++++++++++++++++++++++
UBX/CFG/MSG (Messages Global Positioning System Fix Data) F0-00 NMEA GxGGA all off ---------------- NO
16 Data
0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x24
UBX/CFG/MSG (Messages Global Positioning System Fix Data) F0-00 NMEA GxGGA ON UART 1
16 Data
0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x29
UBX/CFG/MSG (Messages Geographic Position, Latitude / Longitude and time.) F0-01 NMEA GxLL all off
16 Data
0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x2B
UBX/CFG/MSG (Messages GPS DOP and active satellites ) F0-02 NMEA GxGSA all off
16 Data
0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x32
UBX/CFG/MSG (Messages GPS Satellites in view) F0-03 NMEA GxGSV all off ------- NO per Ucenter
16 Data
0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x39
UBX/CFG/MSG (Messages Recommended minimum specific GPS/Transit data) F0-04 NMEA GxRMC all off -------------- NO
16 Data
0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x40
UBX/CFG/MSG (Messages Recommended minimum specific GPS/Transit data) F0-04 NMEA GxRMC ON Uart 1
16 Data
0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x05, 0x45
UBX/CFG/MSG (Messages Track Made Good and Ground Speed.) F0-05 NMEA GxVTG all off
16 Data
0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x05, 0x47
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
La velocità di trasmissione del modulo Neo-6M è settata a 9600 Baud e questo viene resettato quando si toglie l'alimentazione, ma se vogliamo possiamo anche settarla a 115200 Baud, ma solo dopo aver aperto la porta UART1 a 9600 Baud, altrimenti il comando non verrà riconosciuto.
UBX/CFG/PRT ( Ports ) Target UART1 Protocol IN UBX+NMEA Protocol OUT UBX+NMEA Baudrate 115200
28 Data
0xB5, 0x62, 0x06, 0x00, 0x14, 0x00, 0x01, 0x00, 0x00, 0x00, 0xD0, 0x08, 0x00, 0x00, 0x00, 0xC2, 0x01, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBC, 0x5E
inserendo questi comandi :
// nella dichiarazione delle variabili mettiamo questo array
const PROGMEM uint8_t GpsBaud[] = { 0xB5, 0x62, 0x06, 0x00, 0x14, 0x00, 0x01, 0x00, 0x00, 0x00, 0xD0, 0x08, 0x00, 0x00, 0x00, 0xC2, 0x01, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBC, 0x5E};
#define RX 21 // Connesso al modulo GPS TX pin per ESP32 normale è il pin 16
#define TX 22 // Connesso al modulo GPS RX pin per ESP32 normale è il pin 17
//in SETUP mettiamo:
Serial.begin(115200);
delay(500);
while (Serial.available() > 0) {// elimino buffer
Serial.read();
}
GPS.begin (9600, SERIAL_8N1, RX, TX); //modalità predefinita
// mettere prima gli altri comandi che ci interessano a 9600 Baud e alla fine cambiamo la velocità della porta
GPS_SendConfig(GpsBaud, 28); // prima viene cambiata la velocità nel modulo GPS e poi nella UART1
GPS.begin (115200, SERIAL_8N1, RX, TX); //nuova modalità boost 115200 Baud
// fine Setup
void GPS_SendConfig(const uint8_t *Progmem_ptr, uint8_t arraysize) {
uint8_t byteread, index;
for (index = 0; index < arraysize; index++) {
byteread = pgm_read_byte_near(Progmem_ptr++);
GPS.write(byteread);
}
delay(100);
}
Prossimamente metterò anche la routine che legge i comandi in arrivo, li mette in un'array e così possiamo prendere il dato che ci interessa all'interno del messaggio inviato dal gps, il tutto senza utilizzare librerie esterne (tipo TinyGps o simli) che occupano parecchia memoria.