6° Maratona....stesso sudicio
Anche quest'anno sono stato ripreso in foto andate su giornali on line (firenze.repubblica.it)
lunedì 30 novembre 2015
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;
}
--------------------------------------------------------------------------
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)
conn = pq_connect (setdbopts ("dbname", "test"));
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 databaseconn = 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
----------------------------------------------------------------------------
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
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
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)
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 |
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);
}
----------------------------------------------------------------
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)
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)
--------------------------------------------------------------------------------
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 microAmpereAttenzione : 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
Nokia Lumia 630 Hard Reset
Il Nokia 630 ha smesso in maniera del tutto improvvisa di rispondere ai comandi (qualcosa mi dice che Windows non perde il vizio di freezare in modo inaspettato)
L'unico sistema per riconquistare il controllo e' stato effettuare un hard reset. La procedura e' la seguente
a questo punto appare un punto esclamativo sullo schermo. Si procede con la sequenza
A questo punto compare l'immagine con gli ingranaggi (vedi foto).
Con questa procedura si ottiene la completa formattazione (non ci sono piu' contatti, foto, messaggi ecc.) ma le foto possono essere recuperati da OneDrive. Si deve quindi riprocedere con tutta la configurazione del telefono come se fosse uscito dal negozio
L'unico sistema per riconquistare il controllo e' stato effettuare un hard reset. La procedura e' la seguente
- Spengere il telefono
- Riaccenderlo con il tasto Vol Giu' premuto e collegando l'alimentazione
a questo punto appare un punto esclamativo sullo schermo. Si procede con la sequenza
- Vol Su
- Vol Giu'
- Tasto accensione
- Vol Giu'
A questo punto compare l'immagine con gli ingranaggi (vedi foto).
Con questa procedura si ottiene la completa formattazione (non ci sono piu' contatti, foto, messaggi ecc.) ma le foto possono essere recuperati da OneDrive. Si deve quindi riprocedere con tutta la configurazione del telefono come se fosse uscito dal negozio
mercoledì 11 novembre 2015
Vertici IGM e Regione Toscana
Frugando su Internet ho scoperto per caso che nel paese in cui vivo e' presente
Sul sito dell'IGM all'ID 106602 e' presente la scheda di un punto geodetico della rete di raffittimento a 7 Km
Come si vede chiaramente anche dalla nota riportata a margine dell'immagine, la precisione del punto e' al secondo d'arco. Alle latitudine di interesse un secondo di arco di latitudine vale circa 22.3 m mentre un secondo d'arco di longitudine vale circa 30.8 m, una precisione del tutto inutile per utilizzi "seri". All'IGM non sono impazziti, semplicemente per avere dati piu' dettagliati questi devono essere pagati...
Ero gia' pronto all'esborso quando ho fatto una prova sul SIT della Regione Toscana.
Sul tema Punti geodetici di raffittimento 7 Km e' presente un punto a Caldine che ha lo stesso codice di quello del database IGM ma qui le coordinate sono espresse in Gauss Boaga con la precisione al centimetro
In estrema sintesi la Regione Toscana offre gratuitamente la stessa informazione che IGM pone a pagamento
A questo punto rimane la conversione delle coordinate del punto da Gauss Boaga in WGS 84, realizzata mediante il programma Traspunto
Gauss Boaga piane: 1685517.43 E, 4855934.06E
Gauss Boaga geografiche : 43.49566281,-1.08420721
WGS 84 geografiche gradi,primi,secondi: 43°49'58.9742",11°18'25.4385"
WGS 84 geografiche gradi decimali : 43.83304838,11.30706625
Riportando il punto su Google Earth si vede che la georefenziazione delle immagini di Google e' molto, molto buona nella zona di interesse
Dopo aver spostato un po' di erba e scavato un po' ecco il chiodo di riferimento
Sul sito dell'IGM all'ID 106602 e' presente la scheda di un punto geodetico della rete di raffittimento a 7 Km
Come si vede chiaramente anche dalla nota riportata a margine dell'immagine, la precisione del punto e' al secondo d'arco. Alle latitudine di interesse un secondo di arco di latitudine vale circa 22.3 m mentre un secondo d'arco di longitudine vale circa 30.8 m, una precisione del tutto inutile per utilizzi "seri". All'IGM non sono impazziti, semplicemente per avere dati piu' dettagliati questi devono essere pagati...
Ero gia' pronto all'esborso quando ho fatto una prova sul SIT della Regione Toscana.
Sul tema Punti geodetici di raffittimento 7 Km e' presente un punto a Caldine che ha lo stesso codice di quello del database IGM ma qui le coordinate sono espresse in Gauss Boaga con la precisione al centimetro
In estrema sintesi la Regione Toscana offre gratuitamente la stessa informazione che IGM pone a pagamento
A questo punto rimane la conversione delle coordinate del punto da Gauss Boaga in WGS 84, realizzata mediante il programma Traspunto
Gauss Boaga piane: 1685517.43 E, 4855934.06E
Gauss Boaga geografiche : 43.49566281,-1.08420721
WGS 84 geografiche gradi,primi,secondi: 43°49'58.9742",11°18'25.4385"
WGS 84 geografiche gradi decimali : 43.83304838,11.30706625
Riportando il punto su Google Earth si vede che la georefenziazione delle immagini di Google e' molto, molto buona nella zona di interesse
Dopo aver spostato un po' di erba e scavato un po' ecco il chiodo di riferimento
martedì 10 novembre 2015
Validazione MTK3339 (3)
Seguendo quanto iniziato qui, ho fatto una nuova serie di misure il 6 novembre 2015 (piu' ridotta nel tempo, circa 5000 misure) di giorno in modo da testare il sistema ricarica a pannello solare (misura dalle 12:13 alle 14:41)
La prima novita' e' stata che la qualita' della tramissione radio e' stranamente peggiorata con circa il 7 per mille dei messaggi giunti corrotti (nel dettaglio sono arrivati 5262 pacchetti corretti su un totale di 5655)
Il punto medio e' stato misurato in
Latitudine : 43.8335234
Longitudine : 11.3105038
nella misura precedente il punto medio era
Latitudine : 43.8335196
Longitudine : 11.310521
La distanza tra i due punti e' calcolata in circa 2 m (in realta' il punto era il medesimo per entrambe le misure)
Durante questa prova non e' mai stata attivata la Fix Quality 2
I valori di tensione della batteria sono variabili perche', essendo una misura fatta di giorno, il pannello solare ha funzionato in ricarica. Si vede intorno alla misura 2000 la ricarica del pannello verso la batteria Lipo
Il grafico di quota e' invece (per quanto inutile)
In definitiva l'MTK3339 risulta avere misure confrontabili nell'intorno di un paio di metri abbastanza indipendentemente dalla copertura dei satelliti
La prima novita' e' stata che la qualita' della tramissione radio e' stranamente peggiorata con circa il 7 per mille dei messaggi giunti corrotti (nel dettaglio sono arrivati 5262 pacchetti corretti su un totale di 5655)
Il punto medio e' stato misurato in
Latitudine : 43.8335234
Longitudine : 11.3105038
nella misura precedente il punto medio era
Latitudine : 43.8335196
Longitudine : 11.310521
Durante questa prova non e' mai stata attivata la Fix Quality 2
I valori di tensione della batteria sono variabili perche', essendo una misura fatta di giorno, il pannello solare ha funzionato in ricarica. Si vede intorno alla misura 2000 la ricarica del pannello verso la batteria Lipo
Il grafico di quota e' invece (per quanto inutile)
In definitiva l'MTK3339 risulta avere misure confrontabili nell'intorno di un paio di metri abbastanza indipendentemente dalla copertura dei satelliti
lunedì 9 novembre 2015
Gpsbabel
Un paio di comandi per scaricare i dati da un Gps Garmin (in questo caso un vecchio modello con la seriale collegata ad un cavo Serial2Usb). Il Gps deve essere impostato con interfaccia Garmin
Nel primo caso i dati vengono scaricati e salvati sul file dati.nmea in formato nmea (viene scritta solo la stringa $GPWPL e quindi ci sono le informazioni latitudine e longitudine)
gpsbabel -i garmin -f /dev/ttyUSB1 -o nmea -F dati.nmea
Per estrarre altri dati come l'ora di acquisizione ed i metadati del punto (come il nome) si puo' salvare in formato garmin_txt che estrae un csv con tabulatori come separatori
gpsbabel -i garmin_txt,date="MM/DD/YYYY",time="hh:mm:ss xx" -f /dev/ttyUSB1 -o garmin_txt,date="DD.MM.YYYY",datum="WGS 84",dist=m,prec=6,temp=c,time="HH:mm:ss",utc=+2 -F dati.txt
Nel primo caso i dati vengono scaricati e salvati sul file dati.nmea in formato nmea (viene scritta solo la stringa $GPWPL e quindi ci sono le informazioni latitudine e longitudine)
gpsbabel -i garmin -f /dev/ttyUSB1 -o nmea -F dati.nmea
Per estrarre altri dati come l'ora di acquisizione ed i metadati del punto (come il nome) si puo' salvare in formato garmin_txt che estrae un csv con tabulatori come separatori
gpsbabel -i garmin_txt,date="MM/DD/YYYY",time="hh:mm:ss xx" -f /dev/ttyUSB1 -o garmin_txt,date="DD.MM.YYYY",datum="WGS 84",dist=m,prec=6,temp=c,time="HH:mm:ss",utc=+2 -F dati.txt
Lo scaricamento dei dati non e' particolarmente veloce. Per 500 punti ci vogliono circa 49 secondi da Garmin V.
Garmin GPS V e raw data
Mi e' stato prestato un Garmin GPS V, un modello piuttosto vecchiotto ed uscito piu' o meno in contemporanea del modello 12XL visto qui.
A differenza del 12XL il modelloV non e' esattamente un modello cartografico ma piu' un navigatore stradale (qualunque cosa volesse dire navigatore stradale nel 1998!!)
Questo Gps monta un software che ricorda molto da vicino i primi Etrex ed ha anche l'opzione WAAS oltre ad una antenna orientabile per mettere il display in orizzontale (uso in macchina) od in verticale.
L'antenna ha una sensibilita' decisamente pessima e bisogna armarsi di pazienza ed un cielo sgombro di ostacoli per ottenere la propria posizione (basta entrare in una via stretta con palazzi alti per perdere immediatamente il segnale)
Il connettore posteriore e' uguale al modello 12XL ed ho quindi provato a vedere se era possibile effettuare una acquisione raw con il programma async.
Il programma e' riuscito ad acquisire i pacchetti (importante che al momento dell'inizio dell'acquisizione il display mostri la scritta indichi GPS 3D) ma al momento della conversione in formato RINEX con la stessa stringa vista nel precedente post, veniva generata solo l'intestazione del file RINEX.
Visto pero' che il software assomiglia all'Etrex ho provato ad aggiungere lo switch -rinex -etrex ed ecco che e' stato generato il file RINEX idoneo per il postprocessing
Per esteso il comando di conversione e' qualcosa del tipo
./gar2rnx_1_48 057615.g12 -f -rinex -etrex -area test
(come curiosita' il file RINEX indica che l'antenna del Garmin V e' una GPS12 a sottolineare la somiglianza tra l'hardware dei due modelli)
A differenza del 12XL il modelloV non e' esattamente un modello cartografico ma piu' un navigatore stradale (qualunque cosa volesse dire navigatore stradale nel 1998!!)
Questo Gps monta un software che ricorda molto da vicino i primi Etrex ed ha anche l'opzione WAAS oltre ad una antenna orientabile per mettere il display in orizzontale (uso in macchina) od in verticale.
L'antenna ha una sensibilita' decisamente pessima e bisogna armarsi di pazienza ed un cielo sgombro di ostacoli per ottenere la propria posizione (basta entrare in una via stretta con palazzi alti per perdere immediatamente il segnale)
Il connettore posteriore e' uguale al modello 12XL ed ho quindi provato a vedere se era possibile effettuare una acquisione raw con il programma async.
Il programma e' riuscito ad acquisire i pacchetti (importante che al momento dell'inizio dell'acquisizione il display mostri la scritta indichi GPS 3D) ma al momento della conversione in formato RINEX con la stessa stringa vista nel precedente post, veniva generata solo l'intestazione del file RINEX.
Visto pero' che il software assomiglia all'Etrex ho provato ad aggiungere lo switch -rinex -etrex ed ecco che e' stato generato il file RINEX idoneo per il postprocessing
Per esteso il comando di conversione e' qualcosa del tipo
./gar2rnx_1_48 057615.g12 -f -rinex -etrex -area test
(come curiosita' il file RINEX indica che l'antenna del Garmin V e' una GPS12 a sottolineare la somiglianza tra l'hardware dei due modelli)
giovedì 5 novembre 2015
Arduino Xbee/GPS Solar Powered con ibernazione
Questo e' uno dei progetti piu' completo a cui lavoro da un po' di tempo a questa parte
Si tratta di un sistema GPS con microcontrollore Arduino e trasmissione dati via Xbee con alimentazione da batteria Lipo e ricarica solare
Il sistema in completo funzionamento (trasmissione dati + acquisizione GPS) consuma circa da 50 a 70 mA. Con ibernazione del sistema GPS ed dello XBee scende intorno a 20 mA
La batteria completamente carica misura 4.1-4.12 V; il limite inferiore a cui il sistema continua ad essere operativo e stabile e' circa 3.65 V
In uso continuativo con la tramissione dati ed il Gps accesi si ha un consumo di 0.03V/ora di esercizio
E' piu' difficile sitmare la ricarica derivante dal pannello solare. A sistema spento, quindi solo in ricarica, in un paio di giornate soleggiate di novembre la ricarica e' stata compresa tra 0.1 e 0.2 V per giorno
Nello sketch seguente l'Arduino acquisisce e trasmette per circa 10 minuti i dati GPS (la trasmissione si attiva solo dopo il fix GPS) ed iberna sia il GPS che la trasmissione per circa un minuto. In queste condizioni, senza ricarica solare, si ha un consumo sulla batteria di circa 0.3 V/h.
--------------------------------------------------------------------
#include <Adafruit_GPS.h>
#include <SoftwareSerial.h>
#define XBEE_SLEEP 9
const int analogInPin = A0;
int BatteryValue = 0;
float outputValue = 0;
unsigned long delaytime=250;
//GESTIONE DEL RISPAMIO ENERGETICO
// in max_misure c'e' il valore di quante misure consecutive vengono effettuate
// in sleep_time il numero di millisecondi in cui il GPS deve risultare spento
const int max_misure = 600;
int conta_misure = 0;
unsigned long sleep_time = 60000; //in millesimi di secondo
SoftwareSerial mySerial(3, 2);
Adafruit_GPS GPS(&mySerial);
#define GPSECHO true
boolean usingInterrupt = false;
void useInterrupt(boolean);
void setup() {
Serial.begin(9600);
GPS.begin(9600);
GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ); // 1 Hz update rate
GPS.sendCommand(PGCMD_ANTENNA);
//enable DPGS
GPS.sendCommand(PMTK_ENABLE_SBAS);
GPS.sendCommand(PMTK_ENABLE_WAAS);
useInterrupt(true);
delay(1000);
mySerial.println(PMTK_Q_RELEASE);
//setta il pin 9 come controllo dello sleep di XBEE
pinMode(XBEE_SLEEP,OUTPUT);
//mette a ground il pin ovvero sveglia la trasmissione
analogWrite(XBEE_SLEEP,0);
//digitalWrite(XBEE_SLEEP,LOW);
}
SIGNAL(TIMER0_COMPA_vect) {
char c = GPS.read();
#ifdef UDR0
//if (GPSECHO)
//if (c) UDR0 = c;
#endif
}
void useInterrupt(boolean v) {
if (v) {
OCR0A = 0xAF;
TIMSK0 |= _BV(OCIE0A);
usingInterrupt = true;
} else {
TIMSK0 &= ~_BV(OCIE0A);
usingInterrupt = false;
}
}
uint32_t timer = millis();
void loop() {
if (! usingInterrupt) {
char c = GPS.read();
//if (GPSECHO)
//if (c) Serial.print(c);
}
if (GPS.newNMEAreceived()) {
if (!GPS.parse(GPS.lastNMEA()))
return;
}
if (timer > millis()) timer = millis();
if (millis() - timer > 1000) {
timer = millis(); // reset the timer
if (GPS.fix)
{
//NOME DELLA STAZIONE
Serial.print("ST01-");
//carica della batteria
BatteryValue = analogRead(analogInPin);
// Calculate the battery voltage value
outputValue = (float(BatteryValue)*5)/1023*2;
Serial.print(outputValue);
Serial.print("-");
//GPS
if (GPS.hour < 10) Serial.print("0");
Serial.print(GPS.hour,DEC);
Serial.print(":");
if (GPS.minute < 10) Serial.print("0");
Serial.print(GPS.minute,DEC);
Serial.print(":");
if (GPS.seconds < 10) Serial.print("0");
Serial.print(GPS.seconds,DEC);
//Serial.print(".");
//Serial.print(GPS.milliseconds,DEC);
Serial.print(" ");
if (GPS.day < 10) Serial.print("0");
Serial.print(GPS.day, DEC); Serial.print('/');
if (GPS.month < 10) Serial.print("0");
Serial.print(GPS.month, DEC); Serial.print("/20");
Serial.print(GPS.year, DEC);
Serial.print("-");
/*Serial.print(GPS.latitude,4);
Serial.print("-");
Serial.print(GPS.lat);
Serial.print("-");
Serial.print(GPS.longitude,4);
Serial.print("-");
Serial.print(GPS.lon);
Serial.print("-");*/
Serial.print(GPS.latitude_fixed);
Serial.print("-");
Serial.print(GPS.longitude_fixed);
Serial.print("-");
Serial.print(GPS.altitude,1);
Serial.print("-");
Serial.print(GPS.HDOP,1);
Serial.print("-");
Serial.print((int)GPS.fixquality);
Serial.print("-");
if (GPS.satellites < 10) Serial.print("0");
Serial.print((int)GPS.satellites);
Serial.println("-LU");
//conta_misure++;
}
conta_misure++;
//GESTIONE RISPARMIO ENERGETICO
//controlla se e' stato raggiunto il numero limite di misure
if (conta_misure >= max_misure)
{
//se e' stato raggiunto spenge il GPS, attende lo sleep_time e lo riaccende
conta_misure = 0;
GPS.standby(); //spenge il GPS
analogWrite(XBEE_SLEEP,168); //spenge XBEE, 3.3V PWM
//digitalWrite(XBEE_SLEEP,HIGH);
delay(sleep_time); //tempo di standby
GPS.wakeup(); //risveglia il GPS
analogWrite(XBEE_SLEEP,0); //risveglia XBEE
//digitalWrite(XBEE_SLEEP,LOW);
}
}
}
--------------------------------------------------------------------
La ricevente e' un sistema Xbee in modalita' coordinator montato su Xbee Explorer e collegato ad un PC
Lo script per ricevere i dati in Python e' il seguente
--------------------------------------------------------------------
s = serial.Serial('/dev/ttyUSB1',9600)
while 1:
try:
if s.inWaiting():
val = s.readline(s.inWaiting())
sys.stdout.write(val)
except serial.serialutil.SerialException:
pass
--------------------------------------------------------------------
Si tratta di un sistema GPS con microcontrollore Arduino e trasmissione dati via Xbee con alimentazione da batteria Lipo e ricarica solare
Penna per riferimento di scala sulla sinistra |
I componenti utilizzati sono
- Arduino Uno
- Adafruit GPS Breakeout (gia' visto in questo post)
- Shield Xbee e Xbee (gia' visto in questo post)
- Solar Charger Shield v2.2. (gia' visto in questo post con le modifiche apportate)
- Pannello solare da 1W (8x10 cm)
- Batteria Lipo da 3000 mAh
- Scatola per esterni 10x6.8x5.0 mm
- Accelerometro ADXL335 (attualmente non in uso)
La batteria completamente carica misura 4.1-4.12 V; il limite inferiore a cui il sistema continua ad essere operativo e stabile e' circa 3.65 V
In uso continuativo con la tramissione dati ed il Gps accesi si ha un consumo di 0.03V/ora di esercizio
E' piu' difficile sitmare la ricarica derivante dal pannello solare. A sistema spento, quindi solo in ricarica, in un paio di giornate soleggiate di novembre la ricarica e' stata compresa tra 0.1 e 0.2 V per giorno
Nello sketch seguente l'Arduino acquisisce e trasmette per circa 10 minuti i dati GPS (la trasmissione si attiva solo dopo il fix GPS) ed iberna sia il GPS che la trasmissione per circa un minuto. In queste condizioni, senza ricarica solare, si ha un consumo sulla batteria di circa 0.3 V/h.
--------------------------------------------------------------------
#include <Adafruit_GPS.h>
#include <SoftwareSerial.h>
#define XBEE_SLEEP 9
const int analogInPin = A0;
int BatteryValue = 0;
float outputValue = 0;
unsigned long delaytime=250;
//GESTIONE DEL RISPAMIO ENERGETICO
// in max_misure c'e' il valore di quante misure consecutive vengono effettuate
// in sleep_time il numero di millisecondi in cui il GPS deve risultare spento
const int max_misure = 600;
int conta_misure = 0;
unsigned long sleep_time = 60000; //in millesimi di secondo
SoftwareSerial mySerial(3, 2);
Adafruit_GPS GPS(&mySerial);
#define GPSECHO true
boolean usingInterrupt = false;
void useInterrupt(boolean);
void setup() {
Serial.begin(9600);
GPS.begin(9600);
GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ); // 1 Hz update rate
GPS.sendCommand(PGCMD_ANTENNA);
//enable DPGS
GPS.sendCommand(PMTK_ENABLE_SBAS);
GPS.sendCommand(PMTK_ENABLE_WAAS);
useInterrupt(true);
delay(1000);
mySerial.println(PMTK_Q_RELEASE);
//setta il pin 9 come controllo dello sleep di XBEE
pinMode(XBEE_SLEEP,OUTPUT);
//mette a ground il pin ovvero sveglia la trasmissione
analogWrite(XBEE_SLEEP,0);
//digitalWrite(XBEE_SLEEP,LOW);
}
SIGNAL(TIMER0_COMPA_vect) {
char c = GPS.read();
#ifdef UDR0
//if (GPSECHO)
//if (c) UDR0 = c;
#endif
}
void useInterrupt(boolean v) {
if (v) {
OCR0A = 0xAF;
TIMSK0 |= _BV(OCIE0A);
usingInterrupt = true;
} else {
TIMSK0 &= ~_BV(OCIE0A);
usingInterrupt = false;
}
}
uint32_t timer = millis();
void loop() {
if (! usingInterrupt) {
char c = GPS.read();
//if (GPSECHO)
//if (c) Serial.print(c);
}
if (GPS.newNMEAreceived()) {
if (!GPS.parse(GPS.lastNMEA()))
return;
}
if (timer > millis()) timer = millis();
if (millis() - timer > 1000) {
timer = millis(); // reset the timer
if (GPS.fix)
{
//NOME DELLA STAZIONE
Serial.print("ST01-");
//carica della batteria
BatteryValue = analogRead(analogInPin);
// Calculate the battery voltage value
outputValue = (float(BatteryValue)*5)/1023*2;
Serial.print(outputValue);
Serial.print("-");
//GPS
if (GPS.hour < 10) Serial.print("0");
Serial.print(GPS.hour,DEC);
Serial.print(":");
if (GPS.minute < 10) Serial.print("0");
Serial.print(GPS.minute,DEC);
Serial.print(":");
if (GPS.seconds < 10) Serial.print("0");
Serial.print(GPS.seconds,DEC);
//Serial.print(".");
//Serial.print(GPS.milliseconds,DEC);
Serial.print(" ");
if (GPS.day < 10) Serial.print("0");
Serial.print(GPS.day, DEC); Serial.print('/');
if (GPS.month < 10) Serial.print("0");
Serial.print(GPS.month, DEC); Serial.print("/20");
Serial.print(GPS.year, DEC);
Serial.print("-");
/*Serial.print(GPS.latitude,4);
Serial.print("-");
Serial.print(GPS.lat);
Serial.print("-");
Serial.print(GPS.longitude,4);
Serial.print("-");
Serial.print(GPS.lon);
Serial.print("-");*/
Serial.print(GPS.latitude_fixed);
Serial.print("-");
Serial.print(GPS.longitude_fixed);
Serial.print("-");
Serial.print(GPS.altitude,1);
Serial.print("-");
Serial.print(GPS.HDOP,1);
Serial.print("-");
Serial.print((int)GPS.fixquality);
Serial.print("-");
if (GPS.satellites < 10) Serial.print("0");
Serial.print((int)GPS.satellites);
Serial.println("-LU");
//conta_misure++;
}
conta_misure++;
//GESTIONE RISPARMIO ENERGETICO
//controlla se e' stato raggiunto il numero limite di misure
if (conta_misure >= max_misure)
{
//se e' stato raggiunto spenge il GPS, attende lo sleep_time e lo riaccende
conta_misure = 0;
GPS.standby(); //spenge il GPS
analogWrite(XBEE_SLEEP,168); //spenge XBEE, 3.3V PWM
//digitalWrite(XBEE_SLEEP,HIGH);
delay(sleep_time); //tempo di standby
GPS.wakeup(); //risveglia il GPS
analogWrite(XBEE_SLEEP,0); //risveglia XBEE
//digitalWrite(XBEE_SLEEP,LOW);
}
}
}
--------------------------------------------------------------------
La ricevente e' un sistema Xbee in modalita' coordinator montato su Xbee Explorer e collegato ad un PC
Lo script per ricevere i dati in Python e' il seguente
--------------------------------------------------------------------
import serial
import syss = serial.Serial('/dev/ttyUSB1',9600)
while 1:
try:
if s.inWaiting():
val = s.readline(s.inWaiting())
sys.stdout.write(val)
except serial.serialutil.SerialException:
pass
--------------------------------------------------------------------
Iscriviti a:
Post (Atom)
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...
-
In questo post viene indicato come creare uno scatterplot dinamico basato da dati ripresi da un file csv (nel dettaglio il file csv e' c...
-
La scheda ESP32-2432S028R monta un Esp Dev Module con uno schermo TFT a driver ILI9341 di 320x240 pixels 16 bit colore.Il sito di riferiment...
-
Questo post e' a seguito di quanto gia' visto nella precedente prova Lo scopo e' sempre il solito: creare un sistema che permet...