mercoledì 7 gennaio 2015

SismoYUN (30 Hz)

Non contento del passo di campionamento ottenuto nel precedente post ho provato a migliorare le prestazioni svincolandomi dalla libreria Bridge

SismoYUN in questo caso alimentata da un comune PowerBank da 1000 mA


Il suggerimento mi e' venuto leggendo questo post. In pratica Linux puo' leggere i dati di Arduino, Arduino li puo' spedire sulla Serial1 e Linux li puo' leggere su /dev/ttyATH0.
Per fare cio' si deve pero' modificare il file /etc/inittab commentando la linea che setta questa porta seriale e riavviando



questo e' lo sketch Arduino
e' fondamentale la riga in giallo. Se Arduino inizi a sparare dati sulla seriale a Linux mentre questo e' in fase di boot, il boot stesso si blocca in modo irrecuperabile (limite di 50 secondi prima di iniziare ad inviare dati)!!!!
--------------------------------------------
void setup() {
  delay(50000);
  Serial1.begin(115200);

}

void loop() {
  Serial1.print(millis());
  Serial1.print(",");

  Serial1.print(analogRead(A3));
  Serial1.print(",");
  delay(10);
  Serial1.print(analogRead(A4));
  Serial1.print(",");
  delay(10);
  Serial1.println(analogRead(A5));
  delay(10);    
}
--------------------------------------------

per la parte Linux i dati sulla seriale li ho letti con Python. Per fare cio' ho usato la libreria Python Serial che non e' disponibile mediante opkg ma deve essere installata manualmente con il setup normale di Python

i dati passati sono il tempo in millisecondi e poi i tre valori di accelerazione. Questi vengono salvati sulla sdcard

--------------------------------------------
#!/usr/bin/python

import serial


ser = serial.Serial('/dev/ttyATH0',115200)
out_file = open("/mnt/sda1/dati_veloci.txt","w")

while True:
             lettura = ser.readline()
            out_file.write(lettura)
--------------------------------------------

Con queste impostazioni i dati vengono registrati e salvati alla velocita' di circa 30 Hz. Forse passando ad una SdCard di classe 10 (o piu' veloci) le cose possono ancora migliorare ma gia' cosi' il miglioramento e' significativo
Per la presentazione dei dati a Web e' stato utilizzato il sistema precedente modificando leggermente gli script

venerdì 2 gennaio 2015

SismoYUN

Il tentativo di SismoArduino mi e' piaciuto ma volevo vedere se si riusciva ad integrare tutto dentro ad un solo controllore ovvero acquisizione dati e presentazione dati.



Cosi' e' nata SismoYUN
Come visto nel precedente post e' piuttosto lento scambiare i dati dalla parte Arduino (quella deputata alla acquisizione del dato) a quella di presentazione del dato di Linux; per questo motivo ho cercato un escamotage ovvero di salvare i dati sulla scheda SD dallo sketch di Arduino per poi recuperarli in PHP

I dati per motivi di spazio sono salvati sulla scheda SD
--------------------------------------------------------------
#include <FileIO.h>

void setup() {
  Bridge.begin();
  Serial.begin(9600);
  FileSystem.begin();
}

void loop() {
  char buf[50];
  File dataFile = FileSystem.open("/mnt/sda1/datalog.txt",FILE_APPEND);
  unsigned long tempo = millis();
  sprintf(buf,"%lu",tempo);
  dataFile.print(tempo);
  dataFile.print(",");
  dataFile.print(analogRead(A3));
  dataFile.print(",");
  dataFile.print(analogRead(A4));
  dataFile.print(",");
  dataFile.println(analogRead(A5));
  
  delay(2);
}
--------------------------------------------------------------
La velocita' di scrittura sulla SD e' diciamo pessima. Ogni ciclo di scrittura impiega 150 ms (6.6Hz) :<<
ma dato e' poco piu' di un test facciamo finta che vada bene

Per la parte Linux ho configurato il webserver con PHP5 come indicato nel predecente post ed ho usato la libreria DyGraph per plottare i dati
Lo script in PHP recupera le ultime 100 linee del file di datalog.txt e crea un csv
--------------------------------------------------------------
<?php
function tailShell($filepath, $lines = 1) {
ob_start();
passthru('tail -'  . $lines . ' ' . escapeshellarg($filepath));
return trim(ob_get_clean());
}

header('Content-Type: text/csv; charset=utf-8');
$output = fopen('php://output','w');

$dati = tailShell("/mnt/sda1/datalog.txt",100);
$dati2 = str_replace(" ","\r\n",$dati);
fputs($output,$dati2);
?>
--------------------------------------------------------------

e questa e' la pagina di presentazione
--------------------------------------------------------------
<html>
<META HTTP-EQUIV="refresh" CONTENT="900">
<head>
<script type="text/javascript"
  src="dygraph-combined.js"></script>
</head>
<body>
<div id="graphdiv2"
  style="width:1000px; height:700px;"></div>
  <br>

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

 var update = function(){
 g2.updateOptions({'file': 'dati.php'});  
 };
  window.setInterval(update,1000);  
</script>
</body>
</html>
--------------------------------------------------------------



Considerando che tutto gira su una schedina che sta nel palmo di una manno (connessione Wifi e wired incluse) con un server web completo e che fa acquisizione realtime non e' proprio male

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

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