La mia calcolatrice HP 48GX ha trovato la sua sorellina, la stampante termica ad infrarossi HP 82240B, perfettamente funzionante
giovedì 28 marzo 2019
Occupazione memoria Arduino Uno
Frugando il lavoro di altri programmatori ho trovato la seguente funzione per Arduino Uno
---------------------------------------------------------
int freeRam () {
extern int __heap_start, *__brkval;
int v;
return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}
---------------------------------------------------------
Da questo link si puo' leggere che la funzione riporta lo spazio di memoria Ram del Atmega328 libero.
Usando questa funzione si puo' osservare come il compilatore ottimizzi il codice. Se per esempio viene dichiarata una stringa ma non viene utilizzata, il compilatore non alloca spazio di memoria per la stringa
Un altro trucco e' il seguente
Serial.print("luca");
occupa 5 byte (4 caratteri + null) mentre
Serial.print(F("luca"));
non occupa spazio in RAM perche' la stringa viene spostata nella flash memory e non nella ram. Questo trucco funziona per le stringhe statiche .. Serial.print(F(variabile_stringa)) usa lo spazio Ram
Lo sketch di seguito riportato indica uno spazio libero di 1819 bytes.
----------------------------------------------------------------------
//char str[] = "Hello, world!";
void setup() {
Serial.begin(115200);
}
void loop() {
//Serial.println(str);
Serial.println(freeRam());
delay(10000);
}
int freeRam () {
extern int __heap_start, *__brkval;
int v;
return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}
---------------------------------------------------------
int freeRam () {
extern int __heap_start, *__brkval;
int v;
return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}
---------------------------------------------------------
Da questo link si puo' leggere che la funzione riporta lo spazio di memoria Ram del Atmega328 libero.
Usando questa funzione si puo' osservare come il compilatore ottimizzi il codice. Se per esempio viene dichiarata una stringa ma non viene utilizzata, il compilatore non alloca spazio di memoria per la stringa
Un altro trucco e' il seguente
Serial.print("luca");
occupa 5 byte (4 caratteri + null) mentre
Serial.print(F("luca"));
non occupa spazio in RAM perche' la stringa viene spostata nella flash memory e non nella ram. Questo trucco funziona per le stringhe statiche .. Serial.print(F(variabile_stringa)) usa lo spazio Ram
Lo sketch di seguito riportato indica uno spazio libero di 1819 bytes.
----------------------------------------------------------------------
//char str[] = "Hello, world!";
void setup() {
Serial.begin(115200);
}
void loop() {
//Serial.println(str);
Serial.println(freeRam());
delay(10000);
}
int freeRam () {
extern int __heap_start, *__brkval;
int v;
return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}
mercoledì 27 marzo 2019
Gps Kalman Filter con Arduino Uno
Partendo da questo link volevo provare a testare il filtro Kalman sui dati di un GPS ma privo della contributo di una IMU (come fatto qui)
La libreria Arduino utilizzata (questo il link) e' una conversione di un codice in C originario
Mettendo a confronto la linea blu dei dati non filtrati con quella rossa dei dati filtrati e lasciando ferma l'antenna GPS si osserva che il filtro funziona ma non limita le tipiche fluttuazioni (anche molto significative) del segnale GPS
Questo test e' stato effettuato con due antenne a basso costo: un primo modulo senza marca di derivazione cinese ed una antenna con predisposizione per PixHawk denominata gygpsv5 con a bordo un Ublox NEO6M-V2
Utilizzando il codice scaricato da Internet senza particolari modifiche tutto funzionava con il modulo cinese ma non con Ublox nonostante i messaggi NMEA fossero correttamente ricevuti da Arduino.
Salvando i dati si capisce il motivo
Neo 6P
$GLGSV,3,3,09,88,20,181,*56
$GNGLL,4347.03855,N,01113.80955,E,132645.00,A,A*7C
$GNRMC,132646.00,A,4347.03855,N,01113.80955,E,0.030,,270319,,,A*6B
$GNVTG,,T,,M,0.030,N,0.055,K,A*3E
$GNGGA,132646.00,4347.03855,N,01113.80955,E,1,08,1.35,42.1,M,45.5,M,,*76
$GNGSA,A,3,12,24,25,32,,,,,,,,,2.61,1.35,2.23*1E
$GNGSA,A,3,68,86,77,87,,,,,,,,,2.61,1.35,2.23*12
GPS
$GPGSV,2,2,08,32,33,290,40,14,26,308,23,31,04,310,,34,,,*47
$GPRMC,133332.000,A,4347.0429,N,01113.8140,E,0.21,175.07,270319,,,A*60
$GPGGA,133333.000,4347.0428,N,01113.8140,E,1,5,1.55,36.1,M,47.6,M,,*6E
$GPGSA,A,3,12,25,24,29,32,,,,,,,,1.83,1.55,0.98*00
$GPGSV,2,133,37,25,58,293,33,24,46,141,33,29,37,207,25*75
$GPGSV,2,2,08,32,33,290,39,14,26,308,22,31,04,310,,34,,,*48
$GPRMC,133333.000,A,4347.0428,N,01113.8140,E,0.35,175.07,270319,,,A*65
$GPGGA,133334.000,4347.0427,N,01113.8141,E,1,5,1.55,36.1,M,47.6,M,,*67
$GPGSA,A,3,12,25,24,29,32,,,,,,,,1.83,1.55,0.98*00
Il modulo cinese usa delle frasi NMEA che iniziano per GP***** mentre Ublox usa frasi che usaon un prefisso GN****. La libreria TinyGPS riconosce solo il primo prefisso e quindi non sa come trattare i dati dell'Ublox ...e' stato sufficiente editare la libreria sostituendo le stringhe per rendere compatibile TinyGPS con UBlox.....ma come mai questa differenza
GN e' un prefisso generico che si usa per qualunque sorgenti date (Gps americano, Beidu, Glonass etc) mentre il prefisso GP e' relativo solo al GPS americano. (Glonass per esempio ha il prefisso GL).
-----------------------------------------------------------------
#include <SoftwareSerial.h>
#include <TinyGPS.h>
#include <GPSFilter.h>
#define RXPIN 2
#define TXPIN 3
#define GPSBAUD 9600
TinyGPS gps;
SoftwareSerial uart_gps(RXPIN, TXPIN);
GPSFilter f(2.5);
unsigned long lastUpdate;
unsigned long lastSentence;
float c;
void setup()
{
Serial.begin(9600);
uart_gps.begin(GPSBAUD);
lastSentence = millis();
lastUpdate = millis();
}
void loop()
{
while(uart_gps.available()) {
char c = uart_gps.read();
if(gps.encode(c)) {
int year;
byte month, day, hour, minute, second, hundredths;
unsigned long age;
gps.crack_datetime(&year,&month,&day,&hour,&minute,&second,&hundredths,&age); //Get the date from the GPS
unsigned long date;
gps.get_datetime(&date,0,0);
if(date == TinyGPS::GPS_INVALID_DATE){
Serial.println(F("Invalid Age"));
continue;
}
if(age == TinyGPS::GPS_INVALID_AGE) {
Serial.println(F("Waiting for more valid data"));
continue;
}
float latitude, longitude;
double dlat,dlong;
gps.f_get_position(&latitude, &longitude);
double ulat,ulong;
ulat = (double)latitude;
ulong = (double)longitude;
c = (millis() - lastSentence)/1000;
f.update_velocity2d(ulat,ulong,c);
lastSentence = millis();
if((millis() - lastUpdate) >= 500 || lastUpdate == NULL){
f.get_lat_long(&dlat,&dlong);
Serial.print(latitude,8);
Serial.print(";");
Serial.print(longitude,8);
Serial.print(";");
Serial.print(dlat,8);
Serial.print(";");
Serial.println(dlong,8);
}
lastUpdate = millis();
}
}
}
La libreria Arduino utilizzata (questo il link) e' una conversione di un codice in C originario
Mettendo a confronto la linea blu dei dati non filtrati con quella rossa dei dati filtrati e lasciando ferma l'antenna GPS si osserva che il filtro funziona ma non limita le tipiche fluttuazioni (anche molto significative) del segnale GPS
Questo test e' stato effettuato con due antenne a basso costo: un primo modulo senza marca di derivazione cinese ed una antenna con predisposizione per PixHawk denominata gygpsv5 con a bordo un Ublox NEO6M-V2
Utilizzando il codice scaricato da Internet senza particolari modifiche tutto funzionava con il modulo cinese ma non con Ublox nonostante i messaggi NMEA fossero correttamente ricevuti da Arduino.
Salvando i dati si capisce il motivo
Neo 6P
$GLGSV,3,3,09,88,20,181,*56
$GNGLL,4347.03855,N,01113.80955,E,132645.00,A,A*7C
$GNRMC,132646.00,A,4347.03855,N,01113.80955,E,0.030,,270319,,,A*6B
$GNVTG,,T,,M,0.030,N,0.055,K,A*3E
$GNGGA,132646.00,4347.03855,N,01113.80955,E,1,08,1.35,42.1,M,45.5,M,,*76
$GNGSA,A,3,12,24,25,32,,,,,,,,,2.61,1.35,2.23*1E
$GNGSA,A,3,68,86,77,87,,,,,,,,,2.61,1.35,2.23*12
$GPGSV,2,2,08,32,33,290,40,14,26,308,23,31,04,310,,34,,,*47
$GPRMC,133332.000,A,4347.0429,N,01113.8140,E,0.21,175.07,270319,,,A*60
$GPGGA,133333.000,4347.0428,N,01113.8140,E,1,5,1.55,36.1,M,47.6,M,,*6E
$GPGSA,A,3,12,25,24,29,32,,,,,,,,1.83,1.55,0.98*00
$GPGSV,2,133,37,25,58,293,33,24,46,141,33,29,37,207,25*75
$GPGSV,2,2,08,32,33,290,39,14,26,308,22,31,04,310,,34,,,*48
$GPRMC,133333.000,A,4347.0428,N,01113.8140,E,0.35,175.07,270319,,,A*65
$GPGGA,133334.000,4347.0427,N,01113.8141,E,1,5,1.55,36.1,M,47.6,M,,*67
$GPGSA,A,3,12,25,24,29,32,,,,,,,,1.83,1.55,0.98*00
Il modulo cinese usa delle frasi NMEA che iniziano per GP***** mentre Ublox usa frasi che usaon un prefisso GN****. La libreria TinyGPS riconosce solo il primo prefisso e quindi non sa come trattare i dati dell'Ublox ...e' stato sufficiente editare la libreria sostituendo le stringhe per rendere compatibile TinyGPS con UBlox.....ma come mai questa differenza
GN e' un prefisso generico che si usa per qualunque sorgenti date (Gps americano, Beidu, Glonass etc) mentre il prefisso GP e' relativo solo al GPS americano. (Glonass per esempio ha il prefisso GL).
-----------------------------------------------------------------
#include <SoftwareSerial.h>
#include <TinyGPS.h>
#include <GPSFilter.h>
#define RXPIN 2
#define TXPIN 3
#define GPSBAUD 9600
TinyGPS gps;
SoftwareSerial uart_gps(RXPIN, TXPIN);
GPSFilter f(2.5);
unsigned long lastUpdate;
unsigned long lastSentence;
float c;
void setup()
{
Serial.begin(9600);
uart_gps.begin(GPSBAUD);
lastSentence = millis();
lastUpdate = millis();
}
void loop()
{
while(uart_gps.available()) {
char c = uart_gps.read();
if(gps.encode(c)) {
int year;
byte month, day, hour, minute, second, hundredths;
unsigned long age;
gps.crack_datetime(&year,&month,&day,&hour,&minute,&second,&hundredths,&age); //Get the date from the GPS
unsigned long date;
gps.get_datetime(&date,0,0);
if(date == TinyGPS::GPS_INVALID_DATE){
Serial.println(F("Invalid Age"));
continue;
}
if(age == TinyGPS::GPS_INVALID_AGE) {
Serial.println(F("Waiting for more valid data"));
continue;
}
float latitude, longitude;
double dlat,dlong;
gps.f_get_position(&latitude, &longitude);
double ulat,ulong;
ulat = (double)latitude;
ulong = (double)longitude;
c = (millis() - lastSentence)/1000;
f.update_velocity2d(ulat,ulong,c);
lastSentence = millis();
if((millis() - lastUpdate) >= 500 || lastUpdate == NULL){
f.get_lat_long(&dlat,&dlong);
Serial.print(latitude,8);
Serial.print(";");
Serial.print(longitude,8);
Serial.print(";");
Serial.print(dlat,8);
Serial.print(";");
Serial.println(dlong,8);
}
lastUpdate = millis();
}
}
}
Digispark ATTIny85 con Arduino IDE
Per un progettino a basso costo ed in cui necessita una sola porta digitale ho voluto provare qualcosa di differente dalla solita Arduino Uno ovvero il modulo Digispark ATTiny85
Il modulo, che costa circa 1 euro, presenta oltre al microcontrollore anche un regolatore di tensione 78M05 e la possibilita' di programmarezione via USB con Arduino IDE
Il consumo e' attestato intorno ai 20 mA
Sono disponibili 8K di memoria, I2C. SPI, ADC su 4 pin, tutti i pin possono essere usati come pin digitali
Per settare la Arduino IDE si inserisce questo link nelle additional boards
http://digistump.com/package_digistump_index.json
Il modulo, che costa circa 1 euro, presenta oltre al microcontrollore anche un regolatore di tensione 78M05 e la possibilita' di programmarezione via USB con Arduino IDE
Il consumo e' attestato intorno ai 20 mA
Sono disponibili 8K di memoria, I2C. SPI, ADC su 4 pin, tutti i pin possono essere usati come pin digitali
- Pin 0 → I2C SDA, PWM (LED on Model B)
- Pin 1 → PWM (LED on Model A)
- Pin 2 → I2C SCK, Analog In
- Pin 3 → Analog In (also used for USB+ when USB is in use)
- Pin 4 → PWM, Analog (also used for USB- when USB is in use)
- Pin 5 → Analog In
Per settare la Arduino IDE si inserisce questo link nelle additional boards
http://digistump.com/package_digistump_index.json
e dal Boards Manager si installa Digistump AVR Boards
Tra gli sketch di esempio vi sono molte proposte.
La cosa importante da ricordare e' si deve premere il pulsante di Upload dello sketch con la scheda rimossa dalla porta USB. Questa deve essere inserita solo quando viene richiesto dalla IDE
martedì 26 marzo 2019
Frugando nei cassetti dell'ufficio.....
Cosa farsene ai nostri giorni?? Leggendo ho scoperto che questo dispositivo, insieme a molti altri della stessa epoca, erano dotati di Windows CE ma effettuavano direttamente il boot nella applicazione navigatore. Tramite l'applicazione MioPocket si puo' riprendere il controllo della macchina semplicemnente utilizzando una scheda SD da inserire nello slot di espansione
Desktop Windows CE |
Proprieta' |
La cosa interessante e' che basta rimuovere la scheda SD e riavviare il sistema per ripristinare le funzioni di fabbrica
Una nota conclusiva....sono passati meno di 10 anni da quando questo navigatore e; stato messo in disparte da modelli piu' performanti e gia' in rete e' difficile trovare il software
lunedì 25 marzo 2019
Confronto consumi tra Arduino Uno ed Arduino Zero
domenica 24 marzo 2019
Filtro EKF con GPS ed IMU su Android
Per continuare la sperimentazione sui filtri applicati ai sensori ho provato ad usare l' Extended Kalman Filter, un metodo matematico che permette la fusione di dati GPS e derivanti da IMU (per una descrizione abbastanza semplice del metodo si puo' andare qui,
Visto che la matematica non e' banale ho usato un progetto gia' fatto basato su Android. A questo link si trova la descrizione che usa la fusione di velocita' e dati geografici per ridurre le fluttuazioni del segnale GPS. Una libreria EKF per Arduino si trova a questo link basato su questo codice Matlab (l'esempio che usa EKF per GPS si trova nella sottodirectory /extras/c/ con dati di pseudorange, non direttamente lat/lon). Per una breve trattazione matematica invece qui
Un altro sito con una trattazione matematica semplice si trova qui
E' disponibile una app per Android a questo indirizzo GitHub
La prova e' stata effettuata mantenendo il sensore fermo e leggendo ad intervalli di tempo la distanza cumulata (ovvero la somma degli errori dei falsi movimenti registrati dal sensore).
Si evidenzia che il tempo di campionamento del GPS e del'accelerometro sono molto differenti e gli aggiornamento del filtro sono scalati sul sensore piu' lento
Come si vede il filtro impiega circa 100 secondi per stabilizzzarsi
Eliminando i primi due punti si ha una deriva media di 0.0015 m/sec, un dato incredibile considerando che con il solo GPS per ogni secondo la distanza e' di oltre 1 m
La scheda PixHawk contiene all'interno un algoritmo di fusione dei sensori per GPS ed IMU basato su EKF
Visto che la matematica non e' banale ho usato un progetto gia' fatto basato su Android. A questo link si trova la descrizione che usa la fusione di velocita' e dati geografici per ridurre le fluttuazioni del segnale GPS. Una libreria EKF per Arduino si trova a questo link basato su questo codice Matlab (l'esempio che usa EKF per GPS si trova nella sottodirectory /extras/c/ con dati di pseudorange, non direttamente lat/lon). Per una breve trattazione matematica invece qui
Un altro sito con una trattazione matematica semplice si trova qui
E' disponibile una app per Android a questo indirizzo GitHub
La prova e' stata effettuata mantenendo il sensore fermo e leggendo ad intervalli di tempo la distanza cumulata (ovvero la somma degli errori dei falsi movimenti registrati dal sensore).
Si evidenzia che il tempo di campionamento del GPS e del'accelerometro sono molto differenti e gli aggiornamento del filtro sono scalati sul sensore piu' lento
Distanza cumulata in metri |
Eliminando i primi due punti si ha una deriva media di 0.0015 m/sec, un dato incredibile considerando che con il solo GPS per ogni secondo la distanza e' di oltre 1 m
La scheda PixHawk contiene all'interno un algoritmo di fusione dei sensori per GPS ed IMU basato su EKF
Iscriviti a:
Post (Atom)
Debugger integrato ESP32S3
Aggiornamento In realta' il Jtag USB funziona anche sui moduli cinesi Il problema risiede nell'ID USB della porta Jtag. Nel modulo...
-
In questo post viene indicato come creare uno scatterplot dinamico basato da dati ripresi da un file csv (nel dettaglio il file csv e' c...
-
Questo post e' a seguito di quanto gia' visto nella precedente prova Lo scopo e' sempre il solito: creare un sistema che permet...
-
La scheda ESP32-2432S028R monta un Esp Dev Module con uno schermo TFT a driver ILI9341 di 320x240 pixels 16 bit colore.Il sito di riferiment...