venerdì 2 gennaio 2015

Bridge su Arduino Yun

Sulla YUN vivono in coabitazione due anime, la parte Arduino e la parte Linux.
L'interfaccia naturale per scambiarsi i dati e' un servizio REST
Sullo sketch, mediante la libreria Bridge, si carica una variabile in valore (nell'esempio la variabile e' A3 ed il suo contenuto e' il valore della porta analogica A33)

------------------------------------------------------------
#include <Bridge.h>

void setup() {
  Bridge.begin();
}

void loop() {
  Bridge.put("A3",String(analogRead(A3)));
  delay(2);
   
}
------------------------------------------------------------

Sulla parte Linux il valore puo' essere letto mediante uno scritp in Python come di seguito mediante una get
------------------------------------------------------------
#!/usr/bin/python
import time
import sys

sys.path.insert(0,'/usr/lib/python2.7/bridge/')

from bridgeclient import BridgeClient as bridgeclient

value = bridgeclient()

while True:
    x1 = value.get("A3");
    print x1
    time.sleep(2);
------------------------------------------------------------
tutto molto lineare tranne il fatto e' che disperatamente lento (diciamo un ciclo al secondo)

Installare LAMP su Arduino Yun

Tecnicamente parlando non e' proprio un LAMP (Linux+Apache+Mysql+PHP) ma piuttosto un LUMP (Linux+Uhttpd+Mysql+PHP) ma il concetto e' il medesimo




In aggiunta ho installato anche il sempre utile Midnight Commander per avere un editor un po' piu' umano di Vi

La configurazione parte collegandosi in SSH alla shell della Yun

ssh root@arduino.local

e lanciano prima un aggiornamento dei pacchetti

okpg update

per Midnight Commander ed unzip (che servono sempre)

opkg install mc 
opkg install unzip

per quanto riguarda Uhttpd, questo risulta configurato di default per cui non e' necessario fare niente di speciale. La directory dove devono essere posti i file e' in /www (direttamente nella root). Gli scrpt di amministrazione sono /etc/init.d/uhttpd

Per aggiungere PHP5 si lancia

opkg install php5 php5-cgi

al termine si deve modificare il file di configurazione di Uhttpd (/etc/config/uhttpd) e decommentare la riga dell'interprete php-cgi.
Riavviando il servizio uhttod e creando una file info.php (phpinfo) nella root si ottiene la risposta che l'interprete funziona


Tocca adesso a Mysql. Per avere un po' piu' di spazio ho spostato il database sulla scheda SD (che e' montata in /mnt/sda1)

opkg install libpthread libncurses libreadline mysql-server
sed -i 's,^datadir.*,datadir = /mnt/sda1/mysql,g' /etc/my.cnf
sed -i 's,^tmpdir.*,tmpdir = /tmp/,g' /etc/my.cnf
mkdir -p /mnt/sda1/mysql
mysql_install_db –-force
/etc/init.d/mysqld start
/etc/init.d/mysqld enable
mysqladmin -u root password 'password_root_mysql'


adesso e' il momento dei connettori
PHP5-Mysql

opkg install php5-mod-mysql
sed -i 's,;extension=mysql.so,extension=mysql.so,g' /etc/php.ini


Python-Mysql (Python 2.7 e' incluso di default per cui non risulta necessario installarlo)

opkg install python-mysql

e per terminare qualcosa che non deve mai mandare ovvero il server SFTP (che non e' montato di defualt)

opkg install openssh-sftp-server

Per iniziare a lavorarci sopra e' meglio inserire i  file per il webserver sulla scheda SD, sia per problemi di spazio che per il numero di cicli di lettura/scrittura limitati della memoria della Yun. Senza modificare le impostazioni del webserver la cosa piu' semplice e' creare un link simbolico (in questo modo funzionano pero' solo i file html, per i file in php deve essere riconfigurato il server)

Skanect

Un po' di tempo fa avevo fatto degli esperimenti con Freenect (qui, qui e qui) ma cio' che mancava era la fusione tra il dato di profondita' e quello della foto


Mi e' stato segnalato il softwareSkanect (disponibile su Windows, Mac e Linux) che fa esattamente quanto richiesto (un esempio nel video soprastante, il soggetto e' quello che e'......)
Il programma e' costoso ma per un uso semiprofessionale puo' valere la spesa.

mercoledì 31 dicembre 2014

Ipad come secondo monitor

Avendo preso un MacBook da 13 (soprattutto per problemi di peso e venendo dal 15) mi sono trovato ad avere uno schermo piu' piccolo dell'usuale.
Per questo motivo ho provato ad estendere il monitor provando i programmi che usano lo schermo dell'Ipad come estensione del portatile



Vi sono molte soluzioni a pagamento sia con connessione wifi che con connessione mediante cavo lightning (quest'ultima mi sembrava la migliore fino a quando non ho scoperto che l'Ipad non si ricarica mentre e' in modalita' dual monitor) ma a fronte di recensioni non tutte positive non ho voluto spendere una decina di euro per una prova

Mi sono orientato quindi verso l'unico software che permette una demo ovvero VtDisplay Lite.
Si devono montare sul portatile e sull'Ipad (che devono esssere agganciati alla stessa wifi)  i rispettivi programmi e poi si effettua la connessione

Le impressioni d'uso non sono molto positive, c'e' un sensibile (e fastiidoso ritardo) del mouse quando ci si sposta sul monitor Ipad. Puo' essere una soluzione utile in caso di necessita' (vedi mancanza di secondo monitor fisico collegato via thunderbolt) e solo nel caso di tenere qualcosa da leggere sull'ipad (tipo un manuale) mentre si usa il portatile per lavorare ma diciamo che se avessi comprato il software me ne sarei sostanzialmente pentito

SismoArduino

Dopo i recenti terremoti vicino a Firenze mi e' tornata la voglia di lavorare ad un progetto che avevo in mente da tempo e che con somma fantasia ho denominato SismoArduino. Si tratta di un progetto da un giorno ovvero che non risolve in 10 minuti collegando 4 fili ma che non necessita comunque troppo impegno




Per questo progettino ho tirato fuori l'Arduino Uno (la scelta e' stata obbligata perche' Arduino Due non entra fisicamente nella scatola da esterni in cui alla fine deve essere alloggiato il tutto per metterlo in produzione), uno shield Ethernet originale Arduino e un accelerometro triassiale ADXL335





Per comodita' ho piegato il pin ST in modo da fare contatto ed ho poi inserito i pin Z,Y e X nelle porte A3,A4 ed A5 patchando poi al volo i cavi di alimentazione (collegati a 3.3V e GND)

Lo sketch montato su Arduino semplicemente legge i dati sulle porte analogiche e poi invia una stringa mediante UDP client ad un server
(Arduino e' 192.168.1.177 mentre il server e' 192.168.1.120 in ascolto su porta 5005)

-----------------------------------------------------------------------
#include <SPI.h>      
#include <Ethernet.h>
#include <EthernetUdp.h>
//Arduino
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 1, 177);
unsigned int localPort = 8888;    

//Server
byte remoteIP[4] = {192, 168, 1, 120};
int remotePort = 5005;

String dati;
char charBuf[1024];

EthernetUDP Udp;

void setup() {
  Serial.begin(9600);
  Ethernet.begin(mac,ip);
  Udp.begin(localPort);
}

void loop() {
  int x = analogRead(A5);
  delay(2);
  int y = analogRead(A4);
  delay(2);
  int z = analogRead(A3);
  delay(2);
  dati = String(x)+","+String(y)+","+String(z);
  Serial.println(dati);
  dati.toCharArray(charBuf, 1024);
  Udp.beginPacket(remoteIP, remotePort);
  Udp.write(charBuf);
  Udp.endPacket();
  delay(10);    
}
-----------------------------------------------------------------------

Sul server e' stato messo uno script Python che riceve i dati con un server UDP e li scrive su un database Mysql
-----------------------------------------------------------------------
#!/usr/bin/python

import socket
import MySQLdb as mdb
import  time

current_milli_time = lambda: int(round(time.time()*1000))

con = mdb.connect('localhost','root','chiara','sismoarduino')

sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
sock.bind(("192.168.1.120",5005))
while True:
data,addr=sock.recvfrom(1024)
with con:
cur = con.cursor()
cur.execute("INSERT INTO sisard (x1,y1,z1,milli,tempo) VALUES ("+data+","+str(current_milli_time())+",now())")

print data
-----------------------------------------------------------------------

Per la tabella Mysql c'e' un piccolo trucco. Mysql non accetta in modo semplice il formato tempo con i millisecondi. Per cui e' stato creato un campo milli come BIGINT dove e' registrato il tempo completo con i millisecondi ed un campo tempo come DATETIME per il lettore umano
-----------------------------------------------------------------------
CREATE TABLE `sisard` (
  `x1` int(11) DEFAULT NULL,
  `y1` int(11) DEFAULT NULL,
  `z1` int(11) DEFAULT NULL,
  `milli` bigint(20) DEFAULT NULL,
  `tempo` datetime NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
------------------------------------------------------------------------

La presentazione dei dati e' effettuata in tempo reale mediante un lettore fatto con le librerie Dygraph
I dati per la presentazione a video vengono generati dal seguente scritp php (in pratica viene generato al volo un CSV che viene dato in pasto a DyGraph
------------------------------------------------------------------------
<?php header('Content-Type: text/csv; charset=utf-8'); 
header('Content-Disposition: attachment; filename=data.csv');

$output = fopen('php://output', 'w');


$dbhost = 'localhost';
$dbuser = 'root';
$dbpass = 'chiara';
$dbdb = 'sismoarduino';
$conn = mysql_connect($dbhost, $dbuser, $dbpass);
if(! $conn )
{
  die('Could not connect: ' . mysql_error());
}
mysql_select_db($dbdb);

$result = mysql_query("SELECT * FROM sisard ORDER BY milli DESC LIMIT 1000");
while ($row = mysql_fetch_array($result)) {

$arr[0] = $row['milli'];
//$arr[0]=date("d-m-Y H:i:s",$row['milli']/1000);
$arr[1] = $row['x1'];
$arr[2] = $row['y1'];
$arr[3] = $row['z1'];
fputs($output,implode($arr,',')."\n");
}

mysql_close($conn);
?>
------------------------------------------------------------------------

E questa e' la pagina html che ospita Dygraph con aggiornamento automatico ogni secondo (la finestra e' degli ultimi 1000 dati
------------------------------------------------------------------------
<html>
<META HTTP-EQUIV="refresh" CONTENT="900">
<head>
<script type="text/javascript"
  src="http://localhost/dygraph-combined.js"></script>
</head>
<body>
<div id="graphdiv2"
  style="width:500px; height:300px;"></div>
  <br>

<script type="text/javascript">
  g2 = new Dygraph(
    document.getElementById("graphdiv2"),
    "http://localhost/sismodati.php", 
    {title: 'SismoArduino'}          // options
  );

 var update = function(){
g2.updateOptions({'file': 'http://localhost/sismodati.php'});  
};
  window.setInterval(update,1000);  
</script>
</body>
</html>
------------------------------------------------------------------------
il passo di campionamento misurato e' stato di circa 15-16 campioni al secondo (15 Hz) che non sono assolutamente paragonabili a strumenti professionali (i sismografi reali hanno passi di campionamento che vanno da 50 a 100 Hz)
Qui il video della prova



L'aspetto finale e' da sottolineare e' che il server (di recupero) impiegato e' stato un P3 a 700 Mhz con 128 Mb di ram con Debian Wheezy, Apache, Php, Mysql e Xwindow in funzione ed ha comunque funzionato dignitosamente

venerdì 26 dicembre 2014

IBeacon ed IOS8

In estate avevo scritto una piccola applicazione per IBeacon
E' passata l'estate e l'autunno ma sono rimasto fedele a IOS 7 e OS X 10.9 perche' i sistemi operativi troppo recenti sono sempre fonti di problemi; in questi giorni mi sono pero' convinto a passare ad IOS 8.1.2 sul telefono ed a OSX 10.10 sul portatile

La sorpresa e' venuta quando sono arrivato a compilare ed eseguire il codice per IBeacon che precedemente funzionava perfettamente. Nonostante non ci fossero errori di compilazione ne' errori di esecuzione il programma semplicemente aveva smesso di riconoscere i beacons vicini

Dopo un paio di giorni a battere il capo sul muro sono arrivato su questo link in cui si segnala che con l'arrivo di IOS 8 si devono aggiungere un paio di stringhe un info.plist del progetto
-----------------------------------------
<key>NSLocationAlwaysUsageDescription</key> 
<string>Messaggio Utente</string>
-----------------------------------------

oppure
-----------------------------------------
<key>NSLocationWhenInUseUsageDescription</key>
 <string>Your message goes here</string>
-----------------------------------------

effettuate queste modifiche il programma ha ricominciato a funzionare (e' in questi momenti che amo la programmazione :<<<<


mercoledì 24 dicembre 2014

Fallita migrazione Mac2Mac con Assistente Migrazione

Ieri mi sono trovato per la prima volta a fare una migrazione di dati ed impostazioni tra un vecchio MacBook A1286 verso un nuovo A1278. Considerando che entrambi i sistemi montano 10.10 e che disponevo di un backup di Time Machine, ho sfoderato Assistente di Migrazione ed ho aspettato un paio di ore


Al termine della barra  ho visto che l'indicatore era bloccato sulla scritta "Due minuti al termine"; fiducioso ho lasciato che il computer continuasse ma dopo altre due ore era tutto bloccato ed il led del disco esterno mi segnalava che non era piu' il caso di aspettare perche' non c'era attivita' di trasferimento dati


Riacceso il computer ho trovato che era stato creato il nuovo utente ma all'interno del profilo non c'erano le impostazione personalizzate e nemmeno i dati. Ma cosa aveva fatto per tutto il tempo il calcolatore?? Dopo un controllo sullo spazio disco era chiaro che i dati erano stati copiati da qualche parte ma non erano accessibili in modo semplice. Da terminale ho quindi cercato i file piu' grandi di 500 Mb (nelle cartelle copiate c'erano dei video)

Mandando un find su tutto il disco 

sudo find / -type f -size +500M



i file sono stati effettivamente copiati in una directory temporanea /private/var/folders (piu' caratteri casuali)

Dopo tre prove fallite di Assistente di Migrazione la soluzione e' stata quella di cancellare tutti i file presenti e copiare a mano tutto quanto dal Finder (....just works :<<<)

Opencv camera calibration in cpp

Oltre che con uno script Python come visto qui la calibrazione della camera si puo' fare anche con il programma in CPP Questo il proce...