giovedì 31 dicembre 2015

Linux in ChormeOS con Crouton

Dopo aver installato ChromeOS su Samsung N150 (ed averne notato i limiti) ho provato ad usare crouton, un metodo per mettere in esecuzione Linux su ChromeOS dentro un chjail

Dato che non si tratta di un vero hardware Chromebook non e' stato necessario entrare in modalita' Developer

Linux in esecuzione su ChromeOS

Per installare crouton si procede scaricando lo script al seguente indirizzo https://goo.gl/fd3zc
Si digita da dentro il browser CTRL+ALT+T che apre una crosh shell. Si digita quindi

shell

e si lancia lo script

sudo sh ~/Downloads/crouton -t xfce -t core -t cli-extra
(la password e' password su ChromiumOs)

in questo modo viene lanciata l'installazione che dura oltre mezz'ora e che installa una Ubuntu Precise Pangoline con XFCE come desktop. Al termine dell'installazione vengono richiesti username e password dell'utente Ubuntu

sudo sh ~/Downloads/crouton -t xfce -t core or -t cli-extra

al termine ho provato a lanciare X con il comando
sudo startxfce4
ma ho ricevuto l'errore di No Screen Found. Questo e' un problema che si riscontra anche sui veri Chromebook. Su Internet ci sono molte soluzioni proposte ma nessuna ha funzionato
Ho quindi digitato
sudo startcli
e mi sono ritrovato nella shell di Ubuntu

Per spostarsi da Linux a ChromeOS si dovrebbe usare la combinazione ctrl+alt+shift+function+f1/f2 ma per me la combinazione non ha funzionato (cui veri Chromebook ci sono due tasti speciali che svolgono questa funzione)

Per montare il solo chroot si puo' digitare
sudo enter-chroot

Debris Flow con OpenPIV

Ogni tanto mi ricordo di aver una laurea (ops..un dottorato) in geologia e cerco di applicare qualche idea piu' strettamente informatica al campo geologico.

Un amico vulcanologo (Sebastien Valade) mi ha mostrato un sistema per calcolare il campo di velocita' di un flusso di lava semplicemente da una immagine ottica di una comune telecamera.Mi si e' accesa una lampadina che la stessa cosa poteva essere applicata anche alle frane ed in particolare ai debris flow

La teoria che sta dietro all'interpretazione delle immagini rientra nella categoria del Particle Image Velocimetry (qui la pagina wikipedia) . In estrema sintesi vengono ricercate le porzioni omologhe di due fotogrammi vicini nel tempo per calcolare il campo del vettore spostamento..detto cosi' e' banale ma la pratica e' decisamente differente

Per prova ho preso da Youtube una decina di fotogrammi di questo filmato che ritrare un debris flow in Cancia il 25 luglio 2015


Debris flow Cancia (Italy) 23/07/2015

I fotogrammi sono stati presi scaricando il video in formato mp4 da Youtube mediante una estensione di Firefox e poi avanzando fotogramma per fotogramma (tasto E)  e salvando il frame (Shif+S) con VLC 

I frame sono distanziati di due secondi 

Ho provato ad elaborare i frame per coppie successive (1-2, 2-3,3-4) con il primo esempio di tutorial in Python di OpenPIV

oppure usando un programma in Matlab (decisamente piu' complesso e completo) chiamato PIVLab


Non e' stata fatta alcuna calibrazione sul valore vero della velocita', si tratta solo di una prova di fattibilita' e, specialmente nel secondo caso, sembra funzionare

So long and thanks for all the fish

Grazie per aver contribuito a creare la "palestra" in cui ho imparato un po' di informatica

Ian Murdock (1973-2015), fondatore di Debian

mercoledì 30 dicembre 2015

OpenPIV su Ubuntu 15.10

OpenPIV e' un sistema di analisi di immagini che permette di calcolare il campo di velocita' di un sistema di particelle




per l'installazione su Ubuntu 15.10 si devono risolvere prima alcune dipendenze

apt-get install python-progressbar
apt-get install python-pip
apt-get install python-scipy
apt-get install python-numpy
apt-get install cython
pip install scikit-image (altrimenti apt-get install python-skimage)

dopo cio' si scarica il sorgente da GitHub  e si lancia l'installazione con il classico

python setup.py install

al momento di lanciare il primo esempio (tutorial-part1.py) sono incorso in un errore in fase di importazione del modulo filters di skimage. La soluzione e' piuttosto semplice: il modulo skimage ha modificato il nome del sottomodulo filters in filter (senza la s finale)


/usr/local/lib/python2.7/dist-packages/OpenPIV-0.20.1-py2.7-linux-x86_64.egg/openpiv/preprocess.py
/usr/local/lib/python2.7/dist-packages/OpenPIV-0.20.1-py2.7-linux-x86_64.egg/openpiv/tools.py

basta andare a modificare i file sotto indicati e modificare togliendo la s finale alla riga dell'import
from skimage.filter import....

e tutto inizia a funzionare

martedì 29 dicembre 2015

Progess bar su dd

Un aspetto noioso del comando dd e' quello di non avere una modalita' verbose e quando si copia una immagine (da 8 Gb per esempio) non si sa mai se il comando sia procedendo o si e' bloccato qualcosa

Una semplice soluzione e' installare pv (non e' presente di default su Debian ed Ubuntu) che permette di creare una progress bar sulla shell. L'uso del comando e' il seguente dove immagine.img e' il file che si deve copiare e /dev/sdb il dispositivo su cui copiarlo (in questo caso una chiavetta USB sul mio sistema)

pv -tpreb immagine.img | dd of=/dev/sdb bs=64M

ChromeOS/ChromiumOS su Samsung N150

Era un po' di tempo che volevo provare ChromeOS ma non conosco nessuno che abbia un ChromeBook e non ho voglia di spendere tra 200-300 euro per un portatile sottodimensionato


Ho quindi tirato fuori dal cassetto il mio vecchio Samsung N150  (un ultraportatile del 2010 piuttosto plasticoso) per installare ChromiumOS, la versione compilata partendo dai sorgenti e che puo' essere scaricata da questo link

Al primo tentativo ho scaricato la piu' recente daily build ma all'avvio del sistema da USB non erano funzionanti ne' il trackpad (poco male) ne' la wifi (molto male). Leggendo nel sito ho scoperto che le build daily e weekly hanno inclusi i driver solo per un limitato numero di dispositivi. Per questo motivo ho scaricato la special build del 31 Ottobre ed il sistema ha iniziato a funzionare (e' necessaria chiave USB da almeno 8 Gb)

Una volta effettuato il login con le credenziali di Google si puo' iniziare con l'installazione su disco fisso entrando nella shell di amministrazione con la combinazione CTRL+ALT+F2

L'username di default e' chronos mentre la password di default e' default. Si cambia mediante
chromeos-setdevpasswd

A questo punto ci si puo' elevare con sudo su (si vede che cambia il prompt della shell)
Come indicato dalle istruzioni a video si deve disabilitare powerd in fase di installazione con
initctl stop powerd

Per copiare l'immagine si deve usare il comando
chromeos-install --dest /dev/sda (attenzione al doppio segno meno)

durante questo fase (piuttosto lunga) mi sono stati generati numerosi errori gpt header is invalid ma cio' non ha impedito il termine dell'operazione (sembra che sia qualcosa relativo alla mancanza della partizione di backup, che e' presente sui veri ChromeBook, ma non posso confermare)

Oltre alcune applicazioni nativi si possono utilizzare applicazioni desktop normali medianti servizi come rollApp che rendono disponibili programmi open come Gimp, OpenOffice, Inkscape)



Il file manager si apre con la combinazione Alt+Shift+M e si possono montare anche chiavette USB

Vantaggi

  • Con mia grande sorpresa mi sono trovato lo spazio Google Drive di 211 Gb. Questo spazio e' disponibile e visibile da ChromeOS ma e' differente da quello di Google Drive (che mi mostra sempre un valore disponibile di 17 Gb). Stando a quanto scritto da Google lo spazio disco dovrebbe essere gratuito per due anni


Svantaggi

  • E' necessario utilizzare il sistema su una macchina recente e ben dotata di RAM. Sul Samsung N150 il sistema e' piuttosto lento
  • Non credo che mi abituero' mai ad avere i dati sul cloud
  • Utilizzando un disco a piatti rotanti e non un SSD, il sistema e' piuttosto lento a partire annullando la comodita' di avere un desktop subito pronto (tanto per dire Windows 10 e Ubuntu 15.10 su SSD sono molto piu' veloci al boot rispetto a ChromeOS su disco fisso classico)
  • Le applicazioni non sono molto interessanti. Se devo usare RollApp per usare Gimp preferisco averlo direttamente installato sulla macchina
  • Non ci sono compilatori disponibili
  • Non esiste di fatto un disco locale. Il disco fisso viene visto come cartella Downloads ma c'e' il problema che viene trattato come una grande cache, il sistema operativo puo' cancellare in qualunque momento e senza preavviso i file se ne ha necessita' 
  • Nel mio sistema non risulta disponibile la connessione via cavo di rete

lunedì 28 dicembre 2015

Compilazione OpenCV3 su Ubuntu

OpenCV3 ha introdotto molte novita' nella libreria OpenCV e vale la pena installare la nuova versione...peccato che le principali distribuzioni non abbiano disponibili i pacchetti precompilati per cui bisogna partire dal codice sorgente

Il primo tentativo che ho effettuato e' stato su Centos 7 ma la cosa era un po' troppo complicata per le troppe dipendenze dalle librerie ed ho preferito ripiegare su una Ubunti 15.10 per cui e' stato reso disponibile il seguente script che promette la compilazione senza troppo sforzo

-----------------------------------------------
version="$(wget -q -O - http://sourceforge.net/projects/opencvlibrary/files/opencv-unix | egrep -m1 -o '\"[0-9](\.[0-9]+)+' | cut -c2-)"
echo "Installing OpenCV" $version
mkdir OpenCV
cd OpenCV
echo "Removing any pre-installed ffmpeg and x264"
sudo apt-get -qq remove ffmpeg x264 libx264-dev
echo "Installing Dependenices"
sudo apt-get -qq install libopencv-dev build-essential checkinstall cmake pkg-config yasm libjpeg-dev libjasper-dev libavcodec-dev libavformat-dev libswscale-dev libdc1394-22-dev libxine2-dev libgstreamer0.10-dev libgstreamer-plugins-base0.10-dev libv4l-dev python-dev python-numpy libtbb-dev libqt4-dev libgtk2.0-dev libfaac-dev libmp3lame-dev libopencore-amrnb-dev libopencore-amrwb-dev libtheora-dev libvorbis-dev libxvidcore-dev x264 v4l-utils ffmpeg cmake qt5-default checkinstall
echo "Downloading OpenCV" $version
wget -O OpenCV-$version.zip http://sourceforge.net/projects/opencvlibrary/files/opencv-unix/$version/opencv-"$version".zip/download
echo "Installing OpenCV" $version
unzip OpenCV-$version.zip
cd opencv-$version
mkdir build
cd build
cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -D WITH_TBB=ON -D BUILD_NEW_PYTHON_SUPPORT=ON -D WITH_V4L=ON -D INSTALL_C_EXAMPLES=ON -D INSTALL_PYTHON_EXAMPLES=ON -D BUILD_EXAMPLES=ON -D WITH_QT=ON -D WITH_OPENGL=ON ..
make -j2
sudo checkinstall
sudo sh -c 'echo "/usr/local/lib" > /etc/ld.so.conf.d/opencv.conf'
sudo ldconfig
echo "OpenCV" $version "ready to be used"
-----------------------------------------------
(attenzione lo script originale e' stato modificato perche' la libreria libxine-dev e' stata sostituita da libxine2-dev

Peccato che, nonostante sia esplicitamente richiesto negli switch di cmake, il supporto di Python non venga compilato per la mancanza di alcune dipendenza delle librerie

Per ottenere PyOpenCV e' necessario aggiungere i seguenti pacchetti (in realta' sono anche piu' del necessario ma cosi' si aggiunge anche il supporto ai formati video)

apt-get install libpython3.4-dev
apt-get install python3-numpy
apt-get install libgphoto2-dev
apt-get install doxygen
apt-get install python-vtk libvtk5-dev

in questo modo saranno eseguibili anche gli esempi nella directory samples/python

mercoledì 9 dicembre 2015

Mysql tunnel over SSH

Alcune volte, un po' per passare dati riservati, un po' per bucare firewall non particolarmente permissivi si puo' creare un tunnel SSH per far passare anche informazioni derivanti da altri server. In questo caso si puo' vedere come interagire direttamente con un database MySql nel caso in cui la porta 3306 del server sia filtrata mentre la porta 22 risulta accessibile

In pratica la connessione funziona in questo modo

server Mysql (3306 remota) <-> SSH remoto (22) <-> Internet <-> client locale ssh <->porta locale del tunnel

Linux
Nel caso Linux la procedura per creare un tunnel Mysql over SSH e' piuttosto banale e veloce
Si crea il tunnel con la seguente riga di comando

ssh login@server -L 3306:127.0.0.1:3306 -N &

login e server sono le credenziali del server SSH
in pratica ci si connette con la porta 3306 remota (passando dal tunnel SSH) ed creando una porta 3306 in ascolto. (Ovviamente sulla macchina client non deve essere presente nessun servizio che occupi la porta ... in caso contrario il numero della porta locale puo' essere modificato a piacere)

(importante la & finale per mandare il processo di tunnel in background...in caso si ometta si deve aprire un'altra shell per gestire il collegamento Mysql)

Fatto cio' ci si connette come se il server fosse installato in localhost

mysql -h 127.0.0.1 -p -u user_mysql
(ovviamente le credenziali di Mysql sono quelle dell'host remoto)

Windows
In questo caso il client SSH e' molto piu' spesso Putty. Per creare un tunnel SSH con Putty, dopo aver creato come di norma una sessione, 


si deve andare in Connection/SSH/Tunnels ed impostare 
Source port : 3306
Destination : 127.0.0.1:3306 
Anche in questo caso non deve esserci un altro servizio che occupa la porta 3306 ed in ogni caso la Destination port puo' essere modificata

Di preme Add e la schermata dovrebbe essere identica a quella sottostante


Fatto cio' si puo' aprire MysqlWorkbench e connettersi in localhost per creare una connessione con Mysql remoto

venerdì 4 dicembre 2015

ADXL335 Accelerometro come tiltmetro

In questo post del 2012  avevo usato il componente CMPS10 per avere le indicazione di Yaw, Pitch e Roll.
Con il solo accelerometro (quindi senza una bussola) e' possibile tuttavia avere le informazioni di inclinazione dell'accelerometro in Pitch e Roll (Yaw non e' possibile perche' il calcolo richiede la scomposizione del vettore di accelerazione di gravita' e quindi la rotazione sul piano ortogonale al vettore gravita' non e' registrabile)



Sfruttando questo post ho provato a fare la stessa cosa con un ADXL335

Nel post e' peraltro interessante l'uso di un filtro passa basso.Agendo  sul parametro alpha si puo' ottenere un filtraggio meno (con numeri vicini a 1) o piu' aggressivi (con numeri dell'ordine di 0.1)
A sensore fermo la misura oscilla con filtro a 0.4 di circa +/- 1°
---------------------------------------------------------------------------
const float alpha = 0.5;

double fXg = 0;
double fYg = 0;
double fZg = 0;

double Xg = 0;
double Yg = 0;
double Zg = 0;


void setup()
{
    Serial.begin(9600);
    delay(100);
}

void loop()
{
    double pitch, roll, Xg, Yg, Zg;
    Xg = (analogRead(A5)*(5.0/1023.0))-1.59;
    Yg = (analogRead(A4)*(5.0/1023.0))-1.60;
    Zg = (analogRead(A3)*(5.0/1023.0))-1.67;

    Xg = 9.8*(Xg/0.33);
    Yg = 9.8*(Yg/0.33);
    Zg = 9.8*(Zg/0.33);
   
  
    //Low Pass Filter
    fXg = Xg * alpha + (fXg * (1.0 - alpha));
    fYg = Yg * alpha + (fYg * (1.0 - alpha));
    fZg = Zg * alpha + (fZg * (1.0 - alpha));

    //Roll & Pitch Equations
    roll  = (atan2(-fYg, fZg)*180.0)/M_PI;
    pitch = (atan2(fXg, sqrt(fYg*fYg + fZg*fZg))*180.0)/M_PI;

    Serial.print(pitch);
    Serial.print(":");
    Serial.println(roll);

    delay(100);
}

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

Pi Zero: ne vale la pena??

Grazie ad un amico che la ha acquistata il giorno di uscita, sono riuscito a mettere le mani su una Raspberry Pi Zero. Ma, a parte il prezzo di 5 dollari (la spedizione costa circa 6 volte di piu' che non l'oggetto) vale veramente la pena usare una Pi Zero al posto di una Raspberry B+ per esempio??


Il consumo del dispositivo e' decisamente inferiore ad un Raspberry B (110 mA contro circa il doppio della B...si e' bruciato il punto decimale del misuratore di corrente..si deve leggere 0.11 A)

Sul prezzo c'e' poco da dire, non esistono confronto se non con il futuro Chip (adesso in preordine).
Il problema che per usare una Pi Zero ci si deve munire di almeno un cavo microUsb-USB possibilmente OTG, un HUB Usb per attaccarci tastiera e mouse e un eventuale dongle Ethernet o Wifi (quindi forse e' meglio prendere un HUB alimentato), un non comunissimo cavo HDMI con un connettore standard ed uno in formato miniHDMI

In conclusione un sacco di cavi e cavetti sul tavolo che rendono inutili le dimensioni estremamente ridotte della Pi Zero (avessero messo almeno un Bluetooth ....). Puo' essere interessante come schedina da saldare in un progetto IOT (Internet of Things)... anche se per queste cose preferisco i microcontrollori al posto dei microprocessori ... ma come computer e' molto meglio la PI B+ (anche se molto piu' costosa)

Io nel frattempo ho fatto un preordine per CHIP..........




lunedì 30 novembre 2015

Maratona di Firenze 2015

6° Maratona....stesso sudicio
Anche quest'anno sono stato ripreso in foto andate su giornali on line (firenze.repubblica.it)




Integrazioni dati da accelerometro ADXL335/GY-61

Ho provato ad usare, su suggerimento di un amico, l'accelerometro come misuratore di spostamento.
In estrema sintesi integrando i dati di accelerazione si puo' avere una stima, seppure un po' grossolana, di quanto e' stato spostato il sensore (ovviamente se il sensore viene spostato con velocita' costante questo sistema non funziona)

Il sistema che ho usato e' una schedina GY-61 su cui e' montato un ADXL335 gia' usato altre volte nella versione Sparkfun


Il problema maggiore e' cercare di gestire il rumore dello strumento e la deriva (su quello orginale Sparkfun il modulo non mostra deriva mentre su questo modello cinese la deriva e' presente)

Questo e' lo script per la gestione del calcolo dello spostamento su due assi (x,y); l'asse z ha una sensibilita' differente a quella su x ed y e diventa difficile fare misure accurate

Per prima cosa viene convertito il valore delle porte analogiche in accelerazione in m/s2 togliendo l'offset per avere una misura piu'possibile vicina a zero in condizioni statiche
Successivamente viene integrata la velocita' ed in seguito lo spostamento (vedi questo link per una spiegazione piu' dettagliata)
L'integrazione avviene mediando il valore della accelerazione tra il valore attuale e quello precedente e moltiplicando per il delta di tempo (qui impostato a 0.05 secondi)
Succesivamente si passa allo spostamento sui due assi e calcolando quindi la risultante dello spostamento sui due assi

Il calcolo viene effettuato solo se viene superato un valore di trigger in modo da evitare di registrare tutto il rumore
ATTENZIONE : questo calcolo funziona solo per moti su superfici orizzontali. In caso contrario viene registrata anche una componente della accelerazione di gravita' per cui i dati sono falsati
--------------------------------------------------------------------------
unsigned long time, old_time;
int x,y,z;
float xx,yy,zz,ax,ay;
float old_ax,old_ay,old_vx,old_vy; //
float vx,vy,av_ax,av_ay,av_vx,av_vy; //valori medi di acc e vel sui due assi
float dx,dy,old_dx,old_dy; //spostamento
float delta_time;
float risultante;

void setup() {
  Serial.begin(115200);
  old_ax=0;
  old_ay=0;
  old_vx=0;
  old_vy=0;
  old_dx=0;
  old_dy=0;
  av_ax=0;
  av_ay=0;
  av_vx=0;
  av_vy=0;
}

void loop() {
  //z = analogRead(A3);
  y = analogRead(A4);
  x = analogRead(A5);
  //zz = z * (5.0 / 1023.0);
  yy = y * (5.0 / 1023.0)-1.67;
  xx = x * (5.0 / 1023.0)-1.61;
 
  ax = 9.8*(xx/0.33);
  ay = 9.8*(yy/0.33);

  //toglie offset
  ax = ax + 0.06;
  ay = ay + 0.68 ;
 
if ((ax-old_ax) > 0.3)
  {
  //time = millis();
  //delta_time = (time - old_time)/1000;
  delta_time = 0.05;
 
  //calcolo dell'accelerazione media
  av_ax = (ax+old_ax)/2;
  av_ay = (ay+old_ay)/2;

  //calcolo della velocita'
  vx = old_vx + (av_ax * delta_time);
  vy = old_vy + (av_ay * delta_time);

  // calcolo della velocita' media
  av_vx = (vx+old_vx)/2;
  av_vy = (vy+old_vy)/2;

  // spostamento
  dx = old_dx + (av_vx * delta_time);
  dy = old_dy + (av_vy * delta_time);

  // risultante
  risultante = sqrt((dx*dx)+(dy*dy));

  Serial.print(ax);
  Serial.print(";");
  Serial.print(ay);
  Serial.print(";");
  Serial.print(vx);
  Serial.print(";");
  Serial.print(vy);
  Serial.print(";");
  Serial.print(dx);
  Serial.print(";");
  Serial.print(dy);
  Serial.print(";");
  Serial.println(risultante);
  }

  delay(50);
  //old_time = time;

  //scambio delle variabili
  old_dx = dx;
  old_dy = dy;
  old_vx = vx;
  old_vy = vy;
  old_ax = ax;
  old_ay = ay;
}

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

giovedì 26 novembre 2015

Primi passi con Octave

Durante il dottorato ho avuto il modo di utilizzare (a livello decisamente base) Matlab apprezzandone la sintassi compatta. Purtroppo non ho piu' disponibilita' della licenza universitaria e quindi ho deciso di provare Octave, una versione open source simile a Matlab (anche se chi lavora in modo serio con Matlab mi dice che Octave e' ancora ad anni luce di distanze per alcune funzionalita')

L'aspetto interessante e' che con la versione 3.8 e' stata implementata una GUI simile a Matlab (prima si lavorava praticamente a linea di comando da shell)

Il programma e' stato compilato da sorgenti su Centos 6
Le dipendenze sono
yum install gcc gcc-c++ kernel-devel make mercurial libtool libtool-ltdl-devel libtool-ltdl autoconf cmake lapack-devel \ lapack pcre-devel readline-devel readline fftw-devel glpk-devel suitesparse suitesparse-devel gnuplot libcurl-devel zlib-devel \ flex texlive gperf fltk-devel qhull-devel hdf5-devel gl2ps-devel qrupdate-devel arpack-devel qscintilla-devel llvm-devel qt-devel \ bison ghostscript-devel librsvg2-tools icoutils readline pcre
Dopo la compilazione (un po' lunghina per la verita' ...ma la mia macchina e' un po' vecchiotta) si lancia il programma con

octave --force-gui



Questo e' uno script base su Octave che dovrebbe funzionare senza troppi problemi su Octave
----------------------------------------------------------------------------
clear all
close all
echo off

function rad = radians(degree)
    rad = degree .* pi / 180;
end;

function [a,c,dlat,dlon]=haversine(lat1,lon1,lat2,lon2)
    dlat = radians(lat2-lat1);
    dlon = radians(lon2-lon1);
    lat1 = radians(lat1);
    lat2 = radians(lat2);
    a = (sin(dlat./2)).^2 + cos(lat1) .* cos(lat2) .* (sin(dlon./2)).^2;
    c = 2 .* asin(sqrt(a));
    #arrayfun(@(x) printf("distance: %.8f m\n",6372800 * x), c);
end;

[volt,lat,lon,quota]=textread("tetto_6_11_ridotto.csv", "%u;%u;%u;%u");
mlat = mean(lat);
mlon = mean(lon);
minlat = min(lat);
maxlat = max(lat);
minlon = min(lon);
maxlon = max(lon);
stdlat = std(lat);
stdlon = std(lon);
[r,c] = size(lat);
fprintf("Media Lat: %d\n",mean(lat));
fprintf("Media Lon: %d\n",mean(lon));
fprintf("Std Lat: %d\n",std(lat));
fprintf("Std Lon: %d\n",std(lon));
fig = figure;
plot(lat,lon);
axis([minlat maxlat minlon maxlon]);
title('Originali')
print(fig,'gps','-dpng');
centro = centroid(lat,lon);
fprintf("Centroide %d %d\n",centro);
#plot(volt)
#print(fig,'volt','-dpng')
disp ("-----------------")
mlat = double(mlat)/10000000.0
mlon = double(mlon)/10000000.0
#fprintf("MLat: %f\n",mlat);

ripuliti = zeros(r,2);
indice = 1;

for n = 1:r
  #fprintf("MLat: %f\n",mlat);
  #fprintf("MLon: %f\n",mlon);
  #fprintf("Lat: %f\n",double(lat(n))/10000000.0);
  #fprintf("Lon: %f\n",double(lon(n))/10000000.0);
  [a,c,dlat,dlon] = haversine(mlat,mlon,double(lat(n))/10000000.0,double(lon(n))/10000000.0);
  #fprintf("Distanza %i :%f\n",n,double(c)*6378160.0);
  if (c*6378160.0) < 5.0
        ripuliti(indice,1) = double(lat(n))/10000000.0;
        ripuliti(indice,2) = double(lon(n))/10000000.0;
        indice = indice + 1;
        end
end

fig2 = figure;
plot(ripuliti(1:indice-1,1),ripuliti(1:indice-1,2))
axis([double(minlat)/10000000.0 double(maxlat)/10000000.0 double(minlon)/10000000.0 double(maxlon)/10000000.0]);
title("Filtrati")
mflat = mean(ripuliti(1:indice-1,1));
mflon = mean(ripuliti(1:indice-1,2));
devflat = std(ripuliti(1:indice-1,1));
devflon = std(ripuliti(1:indice-1,2));

fprintf("Media Filtrata Lat: %.7f\n",mflat);
fprintf("Media Filtrata Lon: %.7f\n",mflon);
fprintf("DevSt Filtrata Lat: %.7f\n",devflat);
fprintf("DevSt Filtrata Lon: %.7f\n",devflon);
----------------------------------------------------------------------------


Octave ha un corrispettivo dei toolbox di Matlab, ovvero di pacchetti di estensioni dei comandi che possono essere scaricati, a seconda delle necessita' da Octave Forge
Se per esempio si vuole leggere/scrivere una porta seriale si deve scaricare il pacchetto instrument control in formato tar.gz e si installa con il comando

pkg install instrument-control-0.2.1.tar.gz

Di seguito un semplice esempio per leggere i dati seriali (da Arduino). Per far utilizzare la porta seriale ad un normale utente, quest'ultimo deve essere aggiunto al gruppo dialout (adduser luca dialout)
----------------------------------------------------------------------------
#! /usr/local/bin/octave -qf
pkg load instrument-control
s1 = serial("/dev/ttyACM0");
srl_flush(s1);
get(s1);
set(s1,"baudrate",9600);
set(s1,"bytesize",8);
set(s1,"parity",'N');
set(s1,"stopbits",1);
get(s1);
while true
   valore = srl_read(s1,6);
   char(valore)
   pause(1);
endwhile
srl_close(s1)



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

Per quanto riguarda la connettivita' con i database la versione attuale si interfaccia solo con PostgreSql mediante il pacchetto database 

pkg install database-2.3.2.tar.gz
(deve essere installato il pacchetto devel di postgresql, esempio ripreso da qui. Prima di arrivare ad una connessioni con Postgres c'e' un post da smanettare con la configurazione del server, in particolare con il file pg_hba.conf)

----------------------------------------------------------------------------
pkg load database
conn = pq_connect (setdbopts ("dbname", "test")); 
pq_exec_params (conn, "create table testtable (t text, i int2, b bytea);") 
pq_exec_params (conn, "insert into testtable values ($1, $2, $3);", {"name1", 1, uint8([2, 4, 5])}) 
 pq_exec_params (conn, "select * from testtable;")
 pq_exec_params (conn, "drop table testtable;")
 pq_close (conn);
----------------------------------------------------------------------------


I programmi in Octave possono essere lanciati anche all'esterno dell'ambiente di sviluppo rendendo eseguibile il file .m ed inserendo il testa al file .m la riga
#!/usr/local/bin/octave -qf


Newrez su Centos 6

Un po' per pigrizia utilizzo lo script newrez (gia' descritto qui) per avere una risoluzione personalizzata su portatili un po' vecchiotti (1024x768 oramai e' un po' troppo riduttiva come risoluzione

Attualmente ho montato una Centos 6 su un ToughBook ed ho scoperto che lo script non funziona.
La cosa e' facilmente risolvibile eseguendo il comando xrandr
Newrez si aspetta di dover gestire LVDS1 e VGA1 mentre su Centos lo schermo del portatile viene chiamato LVDS-0

-------------------------------------------------------------------------
Screen 0: minimum 320 x 200, current 1600 x 1000, maximum 4096 x 4096
LVDS-0 connected 1600x1000+0+0 (normal left inverted right x axis y axis) 0mm x 0mm
   1024x768       60.0*+
   800x600        60.3     56.2 
   640x480        59.9 
VGA-0 disconnected (normal left inverted right x axis y axis)
   1600x1000      59.9 
TV-0 unknown connection (normal left inverted right x axis y axis)
   848x480        59.9 +
   640x480        59.9 +
   1024x768       59.9 
   800x600        59.9 
-----------------------------------------------------------------------------

basta modificare lo script e tutto torna a funzionare (certo che 1600x1000 su uno schermo da 10 pollici e' un po' troppo per gli occhi)
------------------------------------------------------------
#!/bin/bash

# newrez

# Marc Brumlik, Tailored Software Inc, tsi-inc@comcast.net

# up to v 0.8
# use 'xrandr' to scale video output to the display

# v 0.9
# Wed Jan  2 05:23:54 CST 2013
# rewrite to handle mouse boundaries when scaled (mouse confined)
# by setting requested resolution to the unused VGA-0 device
# then scaling that for display on the LVDS-0 device

# v 1.1
# Fri Dec 20 08:28:08 CST 2013
# fixed issue where setting to "default" after some other resulution
# left mouse-area at prior resolution

umask 000

# resolution can optionally be specified on command line
newrez=$1

# we MUST be running xrandr 1.3 or higher
if xrandr -v | grep "RandR version 1.[012]"
    then    zenity --info --title="XRandR version is too old" --text="You must be running Xrandr
version 1.3 or newer!
Time to upgrade your system  :-)"
        exit 0
fi

# find the currently connected devices, make a list
devices=`xrandr -q | grep connected | grep -v disconnected | cut -d"(" -f1`

# there MUST be a "connected" LVDS-0 and a "disconnected" VGA-0
current=`xrandr -q`

if echo "$current" | grep "LVDS-0 connected" >/dev/null
    then    : OK
    else    zenity --info --title="PROBLEM" --text="Current display must be LVDS-0"; exit 0
fi
if echo "$current" | grep "VGA-0 disconnected" >/dev/null
    then    : OK
    else    zenity --info --title="IMPORTANT" --text="The VGA-0 display resolution may be affected by this change"
fi

default=`echo "$current" | grep -A 1 "^LVDS-0" | tail -1 | awk '{print $1}'`
H=`echo $default | cut -d'x' -f1`
V=`echo $default | cut -d'x' -f2`
HZ=`echo $default | awk '{print $2}' | tr -d '[*+]'`

# echo DEFAULT: $default $H $V

if [ -z "$newrez" ]
    then    while true
        do
            newrez=`zenity --entry --title="Set New Resolution" \
                --text="Default Resolution: $default\n\nNew size (eg 1280x750 or 1450x1000)\n   -or- \"default\""` || exit 0
            case $newrez in
                default|[0-9]*x[0-9]*)    break ;;
            esac
        done
fi

case $newrez in
    default)    xrandr --output LVDS-0 --mode $default --scale 1x1
            xrandr --addmode VGA-0 $default
            xrandr --newmode $default $newmode
            xrandr --output VGA-0 --mode $default --scale 1x1
            exit 0 ;;
esac

newH=`echo $newrez | cut -d'x' -f1`
newV=`echo $newrez | cut -d'x' -f2`
modeline=`cvt $newH $newV $HZ | grep Modeline`
newmode=`echo "$modeline" | sed 's/^.*"//'`
cvtrez=`echo "$modeline" | sed -e 's/_.*//' -e 's/^.*"//'`

if [ "$newrez" != "$cvtrez" ]
    then    newrez=$cvtrez
        newH=`echo $newrez | cut -d'x' -f1`
        newV=`echo $newrez | cut -d'x' -f2`
fi

scaleH=`echo -e "scale=10\n$newH / $H\nquit" | bc`
scaleV=`echo -e "scale=10\n$newV / $V\nquit" | bc`

if echo "$current" | grep -A 100 "^VGA-0" | grep $newrez >/dev/null
    then    : already there
    else    xrandr --newmode "$newrez" $newmode
        xrandr --addmode VGA-0 $newrez
fi

if xrandr --output VGA-0 --mode $newrez --output LVDS-0 --fb $newrez --scale $scaleH"x"$scaleV 2>&1 | tee -a /tmp/xrandr.err
    then    : success
    else    zenity --info --title="Xrandr produced this error" --text="`cat /tmp/xrandr.err`"

The problem could be that Your video driver
does not support xrandr version 1.3
        rm -f /tmp/xrandr.err
fi

martedì 17 novembre 2015

Validazione MTK3339 (4)

Usando il punto geodetico visto qui, ho provato a testare l'MTK3339 in precisione (e non in accuratezza come negli esempi precedenti)


Effettuando circa 1100 misure Gps con MTK3339 il valore medio della posizione del ricevitore e' stata di
Lat : 43.833061N
Lon: 11.307075E



Confrontando con la posizione misurata con precisione nettamente superiore da IGM e Regione Toscana la distanza del punto misurato da MTK3339 si trova a circa 1.6 m dalla posizione geografica reale. Questo valore e' assolutamente in linea con le tolleranze del sensore


La nuvola dei punti e' stata estremamente ristretta perche' ciascuna singola coppia Lat/Lon e' ripetuta molte volte nel file di acquisizione

lunedì 16 novembre 2015

In volo verso la Luna

Quando ho scoperto che le missioni Apollo erano equipaggiati con dei regoli calcolatori (nel caso di problemi all'AGC Apollo Guidance Computer) la smania di retrocomputing e collezionismo ha preso il sopravvento


Non e' chiaro se i regoli calcolatori siano mai stati effettivamente usati per le missioni Apollo (anche se esiste una foto di Aldrin che sembra utilizzarlo) e non e' chiaro nemmeno quale fosse il modello preciso (di solito viene riportato un modello Pickett N600-ES giallo (la fornte piu' attendibile e' questa)  mentre lo Slide Rule Museum riporta sia il Pickett N600-ES giallo che il Pickett 600-T bianco (vedi pagina 2) .. forse il secondo era in uso ad Armostrong

I due modelli differiscono per la disposizione delle scale ma sono entrambi Log-Log

I regoli Pickett sono decisamente delle formula 1 rispetto ai regoli calcolatori della mia collezione perche' sono interamente in alluminio (al contrario di quelli "europei" che sono in plastica) e danno una sensazione di robustezza oltre al fatto di essere facili da leggere.

Tramite Ebay (si trovano solo negli USA) e' possibile comprare questi modelli a cifre ragionevoli (escludendo il discorso del trasporto e della dogana che pesano sul prezzo quanto l'oggetto stesso)


Pickett N600-ES

Pickett 600-T





Fauna Caldinese - Geco


Forse questo gechino sta iniziando a sentire freddo ed ha deciso di infilarsi in casa..


Blynk : controllo remoto in 5 minuti

Dopo aver provato (ed apprezzato) il cloud di Photon mi sono chiesto se non esisteva qualcosa di simile anche per Arduino. Su indicazione di un amico sono ricaduto su Blynk, un sistema che non permette di programmare i dispositivi ma pubblica in interagisce in modo molto semplice con una grande quantita' di microcontrollori e non (Arduino, Raspberry, Photon,ESP8266 ed altri) pubblicando i dati direttamente su una applicazione mobile completamente configurabile

La prima prova e' stata effettuata con una Arduino Uno con Ethernet Shield originale Arduino collegata via cavo Ethernet per l'accensione da remoto (da applicazione Android) di un led e la lettura, sempre da remoto del valore di un canale analogico variato mediante un potenziometro



Letteralmente in 5 minuti e' stato possibile, aggiungendo due widget su Android e caricando uno sketch generico su Arduino (quello di esempio controlla in modo automatico tutti input/output analogici e digitali di Arduino) conseguire lo scopo come da video

Vediamo se e' possibile controllare la Photon e l'accelerometro visto in precedenza da Blynk

Per prima cosa sulla applicazione Android si deve creare un nuovo progetto indicando l'hardware (Particle Photon ed annotandosi l'Auth Token od inviandoselo per mail)


In seguito si progetta l'interfaccia.Invece di usare dei Gauge (come nel caso precedente via Web) ho impiegato il Graph che mantiene anche un minimo di storico della misure, un grafico per ogni asse dell'accelerometro


A questo punto si configura ogni grafico. Visto che voglio mostrare dei dati elaborati e non il valore di una porta, e' stato impostato un Virtual Pin con un range tra -3 e + 3 (g) e refresh ogni secondo (non passando via Web il refresh puo' anche essere piu' veloce)



Fatto cio' si passa alla programmazione della Photon che si discosta poco dall'esempio base se non per l'uso di 3 Virtual Pin che sono assocciati all'interfaccia utente. Nello sketch si deve copiare l'access token

----------------------------------------------------------------
#include "blynk/BlynkSimpleParticle.h"

char auth[] = "TOKEN";
int analogPin0 = A0;
int analogPin1 = A1;
int analogPin2 = A2;
double volts_x = 0.0;
double volts_y = 0.0;
double volts_z = 0.0;


void setup()
{
    Serial.begin(9600);
    delay(5000); 
    Blynk.begin(auth);
}

void loop()
{
    Blynk.run();
    volts_x = analogRead(analogPin0);
    volts_y = analogRead(analogPin1);
    volts_z = analogRead(analogPin2);
    volts_x = volts_x*3.3/4096.0;
    volts_y = volts_y*3.3/4096.0;
    volts_z = volts_z*3.3/4096.0;
    volts_x = (volts_x-1.64)/0.33;
    volts_y = (volts_y-1.64)/0.33;
    volts_z = (volts_z-1.64)/0.33;
    Blynk.virtualWrite(0,volts_x);
    Blynk.virtualWrite(1,volts_y);
    Blynk.virtualWrite(2,volts_z);
}
----------------------------------------------------------------

Premendo il pulsante Play in alto a destra si manda in esecuzione l'acquisizione dei dati (il tasto diventa un rettangolo a simboleggiare un comando di stop)



Il progetto puo' essere inviato anche ad altri colleghi con la funzione di share

La cosa interessante e' che non e' necessario legarsi mani e piedi ad un sistema di cui non si ha il controllo (per esempio se metto su una struttura complessa e domani blynk chiude o cambia politica cosa succede??) perche' e' possibile creare il proprio server mediante una applicazione java che puo' essere installata sulla propria macchina

venerdì 13 novembre 2015

ADXL335 su Photon Particle

Ho avuto modo di provare una scheda Particle Photon, un modulo programmabile con WiFi, che ha la caratteristica principale di essere programmabile via Cloud con una interfaccia Web. Il prezzo attuale e' circa sui 19 dollari (spedizione esclusa)


Il processore e' un ARM Cortex M3 con un 1Mb di memoria flash e 128 Kb di ram con sistema operativo FreeRTOS 
La scheda e' estremamente piccola (pesa sui 5 grammi ed ha dimensioni di 36.5x20.3x6.8 mm, vedi per confronto la breadboard) e puo' essere alimentata da Usb oppure da VIN con un intervallo da 3.6 a 5.5 V

Immagine ufficiale dal sito del produttore

Si puo' derivare corrente dal pin 3V3 (3.3 V) oppure dal VIN (4.8 V/1A)
Il consumo dichiarato e' di 80 mA ma nelle mie prove ho visto un valore medio di 40 mA (con trasmittente accesa)

Sono disponibili 7 pin analogici con un ADC a 12 bit (come Arduino Due), una seriale TTL e 7 pin GPIO digitali

La programmazione avviene puntando il browser su https://build.particle.io e selezionando il proprio dispositivo.


Si programma in modo molto simile ad una Arduino e per caricare lo sketch sulla scheda si preme il pulsante del fulmine. Visto che tutto avviene via rete non e' necessario nessun cavo di collegamento dati e non e' nemmeno necessaria la vicinanza fisica (io la prova l'ho effettuato programmando da remoto senza averla nemmeno mai vista direttamente)


L'aspetto forse piu' interessante e' che le variabili (per esempio la lettura di un sensore) si possono effettuare direttamente via cloud. Non e' necessario conoscere l'IP della Photon e non e' necessario smanettare sul router per le regole delle porte del firewall

se nello sketch si inserisce una riga del tipo

Spark.variable("volts_x", &volts_x, DOUBLE);

il valore di questa variabile sara' disponibile all'indirizzo (con servizio REST)

https://api.particle.io/v1/devices/ID_PHOTON/volts_x?access_token=ACCESS_TOKEN

dove si deve sostituire a ID_PHOTON una stringa alfanumerica di 24 caratteri identificativa del dispositivo mentre ACCESS_TOKEN e' una stringa di 40 caratteri (entrambe si recuperano dall'interfaccia web cliccando nella colonna a sinistra in basso sul simbolo del mirino (Devices) per ID_PHOTON e su Settings per l'ACCESS_TOKEN

La risposta del sito e' qualcosa di questo tipo (il valore della variabile nel campo result)
--------------------------------------------------------------------------------
{
  "cmd": "VarReturn",
  "name": "volts_x",
  "result": 2.0012695312499997,
  "coreInfo": {
    "last_app": "",
    "last_heard": "2015-11-13T09:19:34.112Z",
    "connected": true,
    "last_handshake_at": "2015-11-13T09:19:02.262Z",
    "deviceID": "430024000e47343233323032",
    "product_id": 6
  }
}
--------------------------------------------------------------------------------
Un altro vantaggio dell'approccio Cloud e' che si puo' ospitare una pagina Web su un IP pubblico e gestire tutti i sensori con indirizzi su rete privata Dato che le informazioni passano via Cloud non e' possibile avere un refresh estramamente veloce (nelle prove e' stato chiaro che scendere sotto 1Hz di refresh dei dati era molto difficile) Per provare la Photon ho collegato un Breakout ADXL335 di Sparkfun, accelerometro in uscita analogica, che e' settato per avere un passo di campionamento di 50 Hz (sono gia' presenti condensatori da 10 microFarad) con misure +/- 3g. Visto che e' stato alimentato a 3.3V la conversione tra V e g e' pari a 330mV/g. Quindi ad accelerazione zero viene letto un valore in tensione pari 1.65 v (3.3V/2). Effettuando la sottrazione tra il valore letto e 1.65 V ed effettuando la conversione si ha il valore in accelerazione g Il consumo dell'ADXL335 e' di circa 375 microAmpere
Attenzione : la sensibilita' e' differente sui vari assi. Su X e Y sono significative fino al centesimo di g mentre su Z e' significativo il decimo di g
Utilizzando questa pagina (modificata da un esempio trovato in rete) 
-----------------------------------------
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/javascript" charset="utf-8"></script>
<script src="raphael-2.1.4.min.js"></script>
<script src="justgage-1.1.0.min.js"></script>
<script>
var accessToken = "INSERIRE ACCESS TOKEN";
var deviceID = "INSERIRE DEVICE ID"
var url_x = "https://api.spark.io/v1/devices/" + deviceID + "/volts_x";
var url_y = "https://api.spark.io/v1/devices/" + deviceID + "/volts_y";
var url_z = "https://api.spark.io/v1/devices/" + deviceID + "/volts_y";
function callback_x(data, status){
if (status == "success") {
volts_x = parseFloat(data.result);
g.refresh(volts_x);
setTimeout(getReading_x, 50);
} else {
alert("There was a problem");
}
}
function callback_y(data, status){
if (status == "success") {
volts_y = parseFloat(data.result);
g2.refresh(volts_y);
setTimeout(getReading_y, 50);
} else {
alert("There was a problem");
}
}
function callback_z(data, status){
if (status == "success") {
volts_z = parseFloat(data.result);
g3.refresh(volts_z);
setTimeout(getReading_z, 50);
} else {
alert("There was a problem");
}
}
function getReading_x(){
$.get(url_x, {access_token: accessToken}, callback_x);
}
function getReading_y(){
$.get(url_y, {access_token: accessToken}, callback_y);
}
function getReading_z(){
$.get(url_z, {access_token: accessToken}, callback_z);
}
</script>
</head>
<body>
<table><tr>
<td><div id="gauge_x" class="200x1600px"></div></td>
<td><div id="gauge_y" class="200x160px"></div></td>
<td><div id="gauge_z" class="200x160px"></div></td>
</tr></table>
<script>
var g = new JustGage({
id: "gauge_x",
value: 0,
min:-3.0,
max: 3.0,
title: "Acc. Z(g)",
decimals : 2
});
getReading_x();
</script>
<script>
var g2 = new JustGage({
id: "gauge_y",
value: 0,
min: -3.0,
max: 3.0,
title: "Acc. Y(g)",
decimals : 2
});
getReading_y();
</script>
<script>
var g3 = new JustGage({
id: "gauge_z",
value: 0,
min: -3.0,
max: 3.0,
title: "Acc. X(g)",
decimals : 2
});
getReading_z();
</script>
</body>
</html>
-----------------------------------------

Si puo' avere una lettura dei valori di accelerazione mediante Photon su Web


(ovviamente l'asse Z misura l'accelerazione di gravita' e quindi non e' zero, il valore dovrebbe essere piu' vicino ad 1, forse c'e' da rivedere il fattore di conversione)

Essendo una visualizzazione via Web il refresh dei dati e' piuttosto lento e lontano dalla frequenza di 50 Hz. In Javascript ho impostato un valore di lettura ogni 50 millisecondi ma aprendo in Chrome Strumenti per sviluppatori/Network si vede chiaramente che vengono impiegati dai 350 ai 500 ms per ogni transazione web (quindi un campionamento intorno a 2-3 Hz)



Una ultima considerazione : come "brand" scegliere Photon e Particle come nomi non e' che sia proprio un colpo di genio. Cercando sui motori di ricerca "Photon Particle" per ottenere informazioni su questo dispositivo saltano fuori seriosissimi articoli di fisica e non quanto desiderato