venerdì 29 marzo 2019

Dragino LG01 Lora Gateway su TheThingsNetwork

Un gateway Lora e' un dispositivo che legge il traffico Lora e lo rilancia su Internet e nel caso sul cloud di TheThingsNetwork (abbreviato TTN)
Ci sono molti Gateway Lora compreso quello originale Arduino ma a causa dei costi (Lora Gateway Arduino costa circa 350 euro) ho preso Dragino LG01, a canale singolo 868 MHz (standard Italia) che e' molto simile ad una Arduino Yun (si  programma via Arduino IDE con la libreria Bridge)


Le istruzioni ufficiale si trovano al link seguente
https://wiki.dragino.com/index.php?title=Connect_to_TTN#Create_TTN_account

(il manuale completo si trova qui)

Ma prima di iniziare si deve creare un account se TheThingsNetwork, andare nella console a creare un Gateway


Per il codice identificativo si puo'utilizzare il Mac Address (riempiendo i byte rimanenti per arrivare a 16 con FF) ed impostando Legacy Packet Forwarder

Successivamente ci si collega alla WiFi aperta del Dragino al 10.130.1.1 (od alla porta LAN) con le credenziali root/dragino. Il sistema di base e' OpenWRT per cui e' semplice configurare l'access point in WPA e controllare che il gateway sia connesso ad Internet


Si va poi sul Dragino e si scarica da qui  il file single_pkt_fwd_v004.hex. Attenzione : il file sul server si chiama single_pkt_fwd_v004.ino.hex... ho dovuto rinominare il file
Poi si va Sensor/Flash MCU, si seleziona il file sopra indicato e si aggiorna. Da questa pagina si puo' controllare che il caricamento sia avvenuto in modo corretto



Si imposta la radio sullo standard europeo


Si configura il Lora Gateway per dialogare con TheThingsNetwork indicando l'indirizzo router.eu.thethings.network, ed il Gateway ID che e' riportato nella consolle di TTN (ma senza i primi 4 caratteri ovvero senza eui-)




e si seleziona LorWan come IoT server


Se tutto e' andato bene sulla consolle di TTN il gateway sara' visto come online 

giovedì 28 marzo 2019

MPU9250 9DOF e filtro Madgwick

La MPU9250 e' un dispositivo con accelerometro, giroscopio e magnetometro triassiale


Per interfacciare l'MPU9250 ho usato la libreria https://github.com/sparkfun/MPU-9250_Breakout che funziona solo con schede Arduino con processore SAM (quindi MKR)

Nello sketch degli esempi e' stato aggiunto il filtro Madgwick

5852 dati

Pitch (filtrato)
media 60.475°
std 0.22°
skew -0.597

Roll (filtrato)
media 50.471°
std 0.34°
skew -0.113

Yaw (filtrato)
media 209.56°
std 0.54°
skew 0.2


---------------------------------------------------------------------------
#include <SparkFunMPU9250-DMP.h>
#include  <MadgwickAHRS.h> 



MPU9250_DMP imu;
Madgwick  MadgwickFilter;


void setup() 
{
  Serial.begin(115200);

   MadgwickFilter.begin(100);  // 100 Hz

  if (imu.begin() != INV_SUCCESS)
  {
    while (1)
    {
      Serial.println("Unable to communicate with MPU-9250");
      Serial.println("Check connections, and try again.");
      Serial.println();
      delay(5000);
    }
  }


  imu.setSensors(INV_XYZ_GYRO | INV_XYZ_ACCEL | INV_XYZ_COMPASS);


  imu.setGyroFSR(2000); // Set gyro to 2000 dps
  // Accel options are +/- 2, 4, 8, or 16 g
  imu.setAccelFSR(2); // Set accel to +/-2g
  // Note: the MPU-9250's magnetometer FSR is set at 
  // +/- 4912 uT (micro-tesla's)

  // setLPF() can be used to set the digital low-pass filter
  // of the accelerometer and gyroscope.
  // Can be any of the following: 188, 98, 42, 20, 10, 5
  // (values are in Hz).
  imu.setLPF(5); // Set LPF corner frequency to 5Hz

  // The sample rate of the accel/gyro can be set using
  // setSampleRate. Acceptable values range from 4Hz to 1kHz
  imu.setSampleRate(10); // Set sample rate to 10Hz

  // Likewise, the compass (magnetometer) sample rate can be
  // set using the setCompassSampleRate() function.
  // This value can range between: 1-100Hz
  imu.setCompassSampleRate(10); // Set mag rate to 10Hz

  imu.dmpBegin(DMP_FEATURE_GYRO_CAL |   // Enable gyro cal
              DMP_FEATURE_SEND_CAL_GYRO,// Send cal'd gyro values
              10);         
}

void loop() 
{

  if ( imu.dataReady() )
  {
    
    imu.update(UPDATE_ACCEL | UPDATE_GYRO | UPDATE_COMPASS);
    printIMUData();
  }
}

void printIMUData(void)
{  

  float accelX = imu.calcAccel(imu.ax);
  float accelY = imu.calcAccel(imu.ay);
  float accelZ = imu.calcAccel(imu.az);
  float gyroX = imu.calcGyro(imu.gx);
  float gyroY = imu.calcGyro(imu.gy);
  float gyroZ = imu.calcGyro(imu.gz);
  float magX = imu.calcMag(imu.mx);
  float magY = imu.calcMag(imu.my);
  float magZ = imu.calcMag(imu.mz);

  MadgwickFilter.update(accelX,accelY,accelZ,gyroX,gyroY,gyroZ,magX,magY,magZ) ;

  
  Serial.print(String(accelX) + "," +String(accelY) + "," + String(accelZ));
  Serial.print("," + String(gyroX) + "," + String(gyroY) + "," + String(gyroZ) + ",");
  Serial.print(String(magX) + "," + String(magY) + "," + String(magZ)+ "," );
  Serial.print(String(MadgwickFilter.getPitch())+ "," +String(MadgwickFilter.getRoll())+ "," +String(MadgwickFilter.getYaw()));
  Serial.println();
}

HP 82240B Stampante termica

La mia calcolatrice HP 48GX ha trovato la sua sorellina, la stampante termica ad infrarossi HP 82240B, perfettamente funzionante




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);
}

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();
   }
 }
}

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

  • 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.....

e' saltato fuori un vecchio navigatore da tempo abbandonato a causa della mancanza di aggiornamenti delle mappe (l'ultimo aggiornamento presente e' del 2008)



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
In fondo e' sostanzialmente inutilizzabile. Lo schermo da 5 pollici e l'assenza di una virtual keyboard (io per lo meno non l'ho trovata) rendendo l'interfaccia quasi inutilizzabile

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 

Feature Matching OpenCv

Il problema e' il seguente: trovare le differenze tra le due foto. Le due immagini sono state riprese a distanza di oltre un anno ed il ...