giovedì 23 giugno 2016

Flash firmware su Intel Edison

E' passato un paio di settimane che gioco con Intel Edison e sono gia' nella necessita' di flashare il firmware (cercando di installare un dongle USB-Ethernet ho incasinato la connessione WiFi)




Per ripristinare il sistema operativo di Edison si parte scaricando il file
iot-devkit-prof-dev-image-edison-2010606.zip

p
Prima di procedere oltre si deve installare il programma dfu-util.
La sequenza e' la seguente

git clone git://git.code.sf.net/p/dfu-util/dfu-util
cd dfu-util
./autogen.sh
./configure
make
make install

a questo punto si puo' lanciare il file ./flash_all.sh

Si vedono scorrere i seguenti messaggi (il tempo e' di circa 5 minuti)
------------------------------------------------------
[root@localhost immagine]# ./flashall.sh
Using U-Boot target: edison-blankcdc
Now waiting for dfu device 8087:0a99
Please plug and reboot the board
Flashing IFWI
Download    [=========================] 100%      4194304 bytes
Download    [=========================] 100%      4194304 bytes
Flashing U-Boot
Download    [=========================] 100%       237568 bytes
Flashing U-Boot Environment
Download    [=========================] 100%        65536 bytes
Flashing U-Boot Environment Backup
Download    [=========================] 100%        65536 bytes
Rebooting to apply partition changes
Now waiting for dfu device 8087:0a99
Flashing boot partition (kernel)
Download    [=========================] 100%      6144000 bytes
Flashing rootfs, (it can take up to 5 minutes... Please be patient)
Download    [=========================] 100%   1373149184 bytes
Rebooting
U-boot & Kernel System Flash Success...
Your board needs to reboot to complete the flashing procedure, please do not unplug it for 2 minutes.


------------------------------------------------------

Al reboot si collega il cavo USB alla porta seriale per ottenere una consolle

screen /dev/ttyUSB1 115200

(per terminare una connessione screen CTRL+A CTRL+D)

di default l'utente root non ha password. Al login basta digitare root e si entra in shell
Per ottenere la connessione SSH si deve prima configurare la password del dispositivo con

configure-edison --password

a questo punto si configura la connessione WiFi con
configure-edison --wifi

il dispositivo, oltre all'Ip, puo' essere anche richiamato come edison.local

per terminare e' sufficiente installare gli aggiornamenti di sistema

opkg update
opkg upgrade

Facendo cio' si genera il seguente errore
Failed to download http://iotdk.intel.com/repos/3.5/intelgalactic/opkg/i586//Packages

l'errore e' generato dal fatto che la directory non esiste: Guardando al sistema precedente (il 3.0) nella directory http://iotdk.intel.com/repos/3.0/intelgalactic/opkg/i586/ sono contenuti gli aggiornamenti per la libreria mraa e upm ma questi nel sistema 3.5 sono contenuti in http://iotdk.intel.com/repos/3.5/iotdk/edison/core2-32/

Per questo motivo credo si tratti solo di un refuso nel file dei repository nel passaggio da 3.0 a 3.5



mercoledì 22 giugno 2016

Windows 10 Update: Connettivita' limitata su WiFi

Dopo un corposo aggiornamento di Windows 10 (tanto corposo che ho lasciato il calcolatore acceso di notte in attesa del termine) mi sono trovato il giorno successivo con il messaggio di Connettivita' Limitata sulla rete WiFi (il che tradotto vuol dire che il Pc si era collegato all'Access Point ma non era in grado di raggiungere Internet)



L'aggiornamento era stato via WiFi quindi la rete senza fili funzionava. Usando un Surface (hardware Microsoft) mi sono dovuto attrezzare con un dongle Usb-Ethernet per riguadagnare Internet e vedere se c'erano ulteriori aggiornamenti in attesa di installazione. Dopo un altro corposo aggiornamento la situazione e' rimasta identica...niente connessione via WiFi.

Questo problema era segnalato da altri utenti ma erano situazioni legate a upgrade da Windows 8 a Windows 10...quindi non il mio caso

La soluzione e' stata quella di ripristinare il driver della scheda di rete senza fili.
Certo che se Windows non funziona nemmeno su hardware Microsoft......

martedì 21 giugno 2016

Webcam su Intel Edison

Il primo passo per utilizzare una webcam su Intel Edison e' quella di spostare il selettore SW2 dalla parte della porta USB standard. In questo  modo si disattiva la porta microUsb OTG e si attiva la porta USB standard

Dal punto di vista dei moduli del kernel la mia Logitech C310 e' stata vista senza troppi problemi e montata in /dev/video0



Partendo dai repositori dai repository di AlexT (vedi qui) e' banale installare motion 

motion in azione

Piu' problematico invece far funzionare mjpeg-streamer. Scaricando via opkg da AlexT il pacchetto risulta andare in segmentation fault. Ho provato a ricompilare quindi dai sorgenti (l'ultima versione disponibile e' la r63) risolvendo le dipendenze e quindi installando anche v4l-utils.


In fase di compilazione pero' mjpeg-streamer si e' rifiutato per un errore piuttosto criptico su un plugin, penso dovuto al fatto che io ho installato v4l2 mentre mpjeg-streamer usa v4l.

Frugando su github ho trovato v4l2_mjpeg_streamer, una versione alleggerita di mjpeg_streamer basata su v4l2 che permette una trasmissione a 5 fotogrammi per secondo alla massima risoluzione della camera (al contrario di mjpeg_streamer la porta TCP e' la 8081)








venerdì 17 giugno 2016

Accuratezza di sensore ultrasonico SR-04

Per un lavoro di laboratorio e' necessario misurare la distanza di un campione senza toccarlo con un comparatore. Per questo motivo e' stata provato ad usare il sensore ultrasonico SR-04 come misuratore di distanza
La precisione richiesta era di 1 mm mentre le schede tecniche che si trovano su Internet parlano di un valore minimo di risoluzione di 3 mm..in ogni caso e' stata fatta una prova



Il bersaglio era costituito da una lamina di alluminio e il sensore e' stato collegato ad una Arduino Uno. Purtroppo non e' stato possibile mettere su un sistema che permetteva la perfetta ortogonalita' della sensore emittente con la superficie riflettente (questo e' un limite della presente misura)

Visto che il sensore non misura direttamente la distanza ma il tempo di volo di un impulso (la distanza si calcola a ritroso conoscendo la velocita' del suono nell'aria) e visto che la velocita' del suono nell'aria e' funzione della temperatura (e non della pressione) secondo un legge del tipo

velocita'_suono=331.4+0.62*temperatura (m/sec)

ho misurato il tempo di volo tramite la libreria NewPing spostando il bersaglio posto a distanza variabile intorno ai 20 cm, Per ogni posizione sono state effettuate 500 acquisizione che poi sono state mediate mediante la libreria Statistics di Arduino

(di seguito si usa il simbolo ms per indicare i microsecondi)

Lo sketch impiegato e' stato il seguente
------------------------------------------------
#include <NewPing.h>
#include "Statistic.h" 

#define TRIGGER_PIN  12  // Arduino pin tied to trigger pin on the ultrasonic sensor.
#define ECHO_PIN     11  // Arduino pin tied to echo pin on the ultrasonic sensor.
#define MAX_DISTANCE 50 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.

NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.

Statistic myStats; 

void setup() {
  Serial.begin(115200); 
  myStats.clear();
}

void loop() {
  delay(50);                     
  myStats.add(sonar.ping());
  if (myStats.count() == 500)
        {
        Serial.print("  Average: ");
        Serial.print(myStats.average(), 2);
        Serial.print("  Std deviation: ");
        Serial.print(myStats.pop_stdev(), 2);
        Serial.println();
        }
}
------------------------------------------------

I dati, di una prova sicuramente parziale ma comunque indicativa della fattibilita', e' riportata nella figura successiva
Attenzione: si parla di tempi di andata e ritorno dell'impulso.



Molto indicativamente si ha che un centimetro di distanza corrisponde, nelle condizioni di misura, a circa 60 ms quindi se si vuole cerca di misurare una variazione di 1mm si deve riuscire a separare almeno 6 ms. Considerando che l'errore medio di deviazione standard e' di circa 3 ms usare l'SR-04 per misurare con la precisione del millimetro e' decisamente al limite delle proprie possibilita' (si comincia a ragionare se la risoluzione e' un decimo della grandezza che si vuole misurare)


secondo i dati teorici con  temperatura di 20°C la velocita' del suono in aria e' di 0.0343 cm/ms (343 m/s) il tempo di volo e' di 6 ms per mm (andata e ritorno 2 mm) il che ritorna abbastanza bene con quanto misurato

mercoledì 15 giugno 2016

Amplificatore invertente AC con LM358

Ho fatto qualche esperimento con LM358 in passato (con risultati deludenti..per colpa mia).
Frugando su Internet ho trovato questo link dove viene indicato l'utilizzo di LM358 con un configurazione che non avevo mai usato

Il testo di riferimento citato nel testo del post non e' piu' disponibile ma sono riuscito a trovare una copia di Ops amps for Everyone a questo link


Con la configurazione sotto riportata il fattore di amplificazione e' data dalla tensione di ingresso per il rapporto tra Rf ed Rg piu' la tensione di alimentazione divisa per due (le due resistenze R di uguale entita' funzionano come un divisore di tensione)




Non avendo un microfono audio o un generato di segnale  mi sono adattato a vedere l'amplificazione data da un piezoelettrico. In condizioni non amplificate il segnale massimo registrato e' stato di circa 5/6 unita' sull'ingresso analogico



passandolo per l'amplificatore si vede chiaramente che viene amplificato anche il rumore e l'intesita' del segnale e' passata a qualche centinaio di unita' (ho perso i dettagli delle resistenze che ho usato). Si vede anche che il segnale e' stato spostato al centro dell'asse delle Y (valore di circa 500 con una fondo scale di 1024 a bit 10)








martedì 14 giugno 2016

Crearsi una scatola per GPS Arduino

Quando un progetto di Arduino deve diventare operativo e' necessario costruirsi una scatola che alloggi l'elettronica e gli accessori. In questo post descrivo come ho creato la scatola per il mio GPS Arduino Ublox

Il primo passo fondamentale e' munirsi di distanziali (spacer) per bloccare la scheda elettrica alla scatola


Ne esistono sia in metallo (credo sia ottone) che in nylon. Io ho usato quelli in plastica. Il passo della vite e' da 3 per cui si puo' comprare anche minuteria metallica se la lunghezza delle viti del set non e' idonea

Come scatola ho preso una Gewiss GW 44 007 classificata come IP 55 (ovvero Protezione totale alla penetrazione di corpi solidi.Protezione contro la penetrazione di liquidi da gocce, vapori, spruzzi e getti d'acqua in qualsiasi direzione.)

L'utilizzo di questa scatola ha il vantaggio di avere dei tappi removibili che permettono il passaggio di un cavo USB di programmazione per poi richiudere il tutto senza necessariamente dovere rimuovere il coperchio e le sue viti

Modalita' di programmazione


Il progetto prevede di montare sul coperchio l'antenna GPS (all'interno) ed il pannello solare (all'esterno)


Montati i distanziali sull'antenna si devono fare i fori sul coperchio...ma come farli precisi?? Un piccolo trucco. Si macchia il distanziale con un pennarello, essendo di nylon l'inchiostro non penetra e basta appoggiare il tutto sul coperchio per ottenere l'impronta di dove forare.La punta del trapano da usare e' quella da 3

Il risultato finale e' questo



Per montare il pannello solare si deve praticare un foro per passare i fili all'interno della scatola e dei distanziali per sostenere il pannello. Visto che il pannello solare era privo di prefori ho usato dei gommini di plastica fermati da una vite a ferro (fare prima un preforo prima di avvitare la vite perche' la plastica e' molto scivolosa e ci vuole un foro guida)


Per fissare il pannello al coperchio e' sufficiente usare una abbondante dose di silicone


Si passa all'interno della scatola. Su Arduino Uno sono stati montati gli spacer (in questo caso hanno trovato posto solo tre spacer su quattro fori perche' il dado di serraggio dello spacer e' troppo grande...non un gran male perche' comunque sul fondo della scatola ci sono dei bordi rialzati che si possono utilizzare come appoggio)
Per trovare il punto giusto di realizzazione dei fori si usa lo stesso metodo precedente



La batteria invece e' stata bloccata con del velcro.

A questo punto si devono mettere insieme i  pezzi (scatola e coperchio). Qui l'unica attenzione e' quella di allungare tutti i cavi in modo da rendere agevole. E' anche comodo scegliere un lato di apertura della scatola e di marcarla sulla scatola in modo da aprire sempre dallo stesso verso (questo per non aprire per sbaglio un un lato per cui i cavi vanno in tensione)




lunedì 13 giugno 2016

LCD1602 su PIC DevBoard

Codice, ripreso da un produttore cinese, su come usare LCD1602 con PIC. Compilatore MapLab IDE





Schema elettrico


main.c
---------------------------------------------
#include <pic.h>          
#include "LCD1602.h"         
//---------------------------------------
unsigned char str0[]={"Luca            "};
unsigned char str1[]={"Innocenti       "};
unsigned char str2[]={"debiaonoldcomput"};
unsigned char str3[]={"ers.blogspot.com"};
//---------------------------------------

void main(void)           
{

    LCD1602_GPIO_Init();
    LCD1602_init();      
  

    while(1)              
    {
    DisplayListChar(0,0,str0);   
    DisplayListChar(0,1,str1);
  
    Delay1602_MS(500);
 
    DisplayListChar(0,0,str2);   
    DisplayListChar(0,1,str3);
    Delay1602_MS(500);
    }
}

---------------------------------------------


 LCD1602.H
---------------------------------------------
#ifndef  __LCD1602_H
#define  __LCD1602_H


#define E   RA3           
#define RW  RA2        
#define RS  RA5         
#define busy RD7         
#define busy_init TRISD7  
#define Lcd_Date PORTD    


void Delay1602_US(unsigned int t);
void Delay1602_MS(unsigned int t);
void LCD1602_BusyTest(void);
void LCD1602_Write_Instruction(unsigned char combuf);
void LCD1602_Write_data_busy(unsigned char databuf);
void LCD1602_init(void);
void DisplayOneChar(unsigned char X,unsigned char Y,unsigned char DData);
void DisplayListChar(unsigned char X,unsigned char Y,unsigned char *DData);
void LCD1602_GPIO_Init(void);


#endif

---------------------------------------------


 1602.c
---------------------------------------------
#include <pic.h>        
#include "LCD1602.h"   
__CONFIG(HS&WDTDIS&LVPDIS);




void Delay1602_US(unsigned int t)
{
     unsigned int k;     
     for(k=0;k<t;k++);   
}

void Delay1602_MS(unsigned int t)
{
     while(t--)
     Delay1602_US(200);
}
void LCD1602_BusyTest(void)
{
     busy_init=1;          
     RS=0;               
     RW=1;              
     E=1;                
     asm("NOP");         
     asm("NOP");         
     while(busy==1);      
     E=0;                
     busy_init=0;         
}


void LCD1602_Write_Instruction(unsigned char combuf)
{
     LCD1602_BusyTest();         
     RS=0;              
     RW=0;               
     E=0; 
     asm("NOP");         
     Lcd_Date=combuf;      
     asm("NOP");         
     asm("NOP");         
     E=1;              
     asm("NOP");         
     E=0;                
}


void LCD1602_Write_data_busy(unsigned char databuf)
{
     LCD1602_BusyTest();  
     RS=1;              
     RW=0;               
      E=0; 
     asm("NOP");         
     Lcd_Date=databuf;       
     asm("NOP");         
     asm("NOP");         
     E=1;                
     asm("NOP");        
     E=0;                
}



void LCD1602_init(void)
{
     Delay1602_US(1500);         
     LCD1602_Write_Instruction(0x38);
     Delay1602_US(500);         
     LCD1602_Write_Instruction(0x38);
     Delay1602_US(500);          
     LCD1602_Write_Instruction(0x38); 
     LCD1602_Write_Instruction(0x38); 
     LCD1602_Write_Instruction(0x08); 
     LCD1602_Write_Instruction(0x01); 
     LCD1602_Write_Instruction(0x06); 
     LCD1602_Write_Instruction(0x0C);
}



void DisplayOneChar(unsigned char X,unsigned char Y,unsigned char DData)
{
    Y&=1;
    X&=15;
    if(Y)X|=0x40;             
    X|=0x80;                  
    LCD1602_Write_Instruction(X);
    LCD1602_Write_data_busy(DData);
}

void DisplayListChar(unsigned char X,unsigned char Y,unsigned char *DData)
{
    unsigned char ListLength=0;
    Y&=0x01;
    X&=0x0f;
    while(X<16)
    {
        DisplayOneChar(X,Y,DData[ListLength]);
        ListLength++;
        X++;
    }
}


void LCD1602_GPIO_Init(void)
{
    ADCON1=0X07;
    TRISA=0B11010011;    
    TRISD=0B00000000;    
    PORTA=0B00000000;    
    PORTD=0B00000000;    
}

---------------------------------------------

Aruco Tag e filtri Kalman

Usando gli Aruco tag in ambiente esterno con illuminazione solare a diverse ore e in diversi periodi dell'anno ho trovato un errore nell...