lunedì 16 gennaio 2012

Arduino + Python

Esempio di come pilotare una Arduino mediante Python

Ho fatto molte prove ma al momento l'unico sistema funzionate e' quello di impiegare le librerie che si trovano qui.

Prima di deve caricare lo sketch sulla scheda (il file pde) mediante il programmatore della Arduino ed in seguito si puo' lanciare lo script da computer


Esiste un problema: deve essere ricaricato lo sketch per ogni volta che si deve lanciare lo script Python
Di seguito lo script leggermente modificato rispetto a quello dell'esempio
-----------------------------------------------------------------------------------------
from arduino import Arduino
import time
my_board = Arduino('/dev/ttyUSB0')
my_board.output([11,12,13])
i=0
while(i<3):
    my_board.setHigh(13)
    time.sleep(1)
    my_board.setHigh(12)
    time.sleep(1)
    my_board.setLow(13)
    time.sleep(1)
    my_board.setLow(12)
    time.sleep(1)
    i+=1

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

Oggi mi gira il cubo

Un merge tra il codice ripreso qui del wireframe_cube.py ed il mio codice di datalogger_udp_client/server



Lato server
-------------------------------------------------------------------------------------------
"""
 Wireframe 3D cube simulation.
 Developed by Leonel Machava <leonelmachava@gmail.com>


 http://codeNtronix.com
modificato da Luca Innocenti
"""
import sys, math, pygame
from pygame.locals import *
import string
from socket import *


host = "192.168.0.1"
port = 21567
buf = 1024
addr = (host,port)




class Point3D:
    def __init__(self, x = 0, y = 0, z = 0):
        self.x, self.y, self.z = float(x), float(y), float(z)

    def rotateX(self, angle):
        """ Rotates the point around the X axis by the given angle in degrees. """
        rad = angle * math.pi / 180
        cosa = math.cos(rad)
        sina = math.sin(rad)
        y = self.y * cosa - self.z * sina
        z = self.y * sina + self.z * cosa
        return Point3D(self.x, y, z)

    def rotateY(self, angle):
        """ Rotates the point around the Y axis by the given angle in degrees. """
        rad = angle * math.pi / 180
        cosa = math.cos(rad)
        sina = math.sin(rad)
        z = self.z * cosa - self.x * sina
        x = self.z * sina + self.x * cosa
        return Point3D(x, self.y, z)

    def rotateZ(self, angle):
        """ Rotates the point around the Z axis by the given angle in degrees. """
        rad = angle * math.pi / 180
        cosa = math.cos(rad)
        sina = math.sin(rad)
        x = self.x * cosa - self.y * sina
        y = self.x * sina + self.y * cosa
        return Point3D(x, y, self.z)

    def project(self, win_width, win_height, fov, viewer_distance):
        """ Transforms this 3D point to 2D using a perspective projection. """
        factor = fov / (viewer_distance + self.z)
        x = self.x * factor + win_width / 2
        y = -self.y * factor + win_height / 2
        return Point3D(x, y, 1)


class Simulation:
    def __init__(self, win_width = 640, win_height = 480):
        pygame.init()


        self.screen = pygame.display.set_mode((win_width, win_height))
        pygame.display.set_caption("3D Wireframe Cube Simulation (http://codeNtronix.com)")
        
        self.clock = pygame.time.Clock()


        self.vertices = [
            Point3D(-1,1,-1),
            Point3D(1,1,-1),
            Point3D(1,-1,-1),
            Point3D(-1,-1,-1),
            Point3D(-1,1,1),
            Point3D(1,1,1),
            Point3D(1,-1,1),
            Point3D(-1,-1,1)
        ]


        # Define the vertices that compose each of the 6 faces. These numbers are
        # indices to the vertices list defined above.
        self.faces = [(0,1,2,3),(1,5,6,2),(5,4,7,6),(4,0,3,7),(0,4,5,1),(3,2,6,7)]


        self.angleX, self.angleY, self.angleZ = 0, 0, 0
        
    def run(self):
        """ Main Loop """
host = "192.168.0.1"
port = 21567
buf = 1024
addr = (host,port)

UDPSock = socket(AF_INET,SOCK_DGRAM)
UDPSock.bind(addr)


        while 1:
data,addr = UDPSock.recvfrom(buf)
valori = string.split(data,";")


#            for event in pygame.event.get():
#                if event.type == pygame.QUIT:
#                    sys.exit()
# if (event.type == KEYUP) or (event.type == KEYDOWN):
# if (event.key == K_a):
# self.angleX = self.angleX + 1
# if (event.key == K_z):
# self.angleX = self.angleX - 1


            self.clock.tick(50)
            self.screen.fill((0,0,0))


            # Will hold transformed vertices.
            t = []
            
for v in self.vertices:
       # Rotate the point around X axis, then around Y axis, and finally around Z axis.
       r = v.rotateX(self.angleX).rotateY(self.angleY).rotateZ(self.angleZ)
       # Transform the point from 3D to 2D
       p = r.project(self.screen.get_width(), self.screen.get_height(), 256, 4)
       # Put the point in the list of transformed vertices
       t.append(p)


for f in self.faces:
       pygame.draw.line(self.screen, (255,255,255), (t[f[0]].x, t[f[0]].y), (t[f[1]].x, t[f[1]].y))
       pygame.draw.line(self.screen, (255,255,255), (t[f[1]].x, t[f[1]].y), (t[f[2]].x, t[f[2]].y))
       pygame.draw.line(self.screen, (255,255,255), (t[f[2]].x, t[f[2]].y), (t[f[3]].x, t[f[3]].y))
       pygame.draw.line(self.screen, (255,255,255), (t[f[3]].x, t[f[3]].y), (t[f[0]].x, t[f[0]].y))
       
self.angleX = round(float(valori[0]),0)
self.angleY = round(float(valori[1]),0)
self.angleZ = round(float(valori[2]),0)
   
pygame.display.flip()


if __name__ == "__main__":
    Simulation().run()

-------------------------------------------------------------------------------------------
Lato client
-------------------------------------------------------------------------------------------

import android
import socket
import time
import math




droid = android.Android();




hostname = "192.168.0.1"; 
port = 21567;
data = "";
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM);
s.connect((hostname,port));


droid.startSensingTimed(1,1000)
time.sleep(3)
while True:
az = str(math.degrees(droid.sensorsReadOrientation().result[0]))
pitch = str(math.degrees(droid.sensorsReadOrientation().result[1]))
roll =  str(math.degrees(droid.sensorsReadOrientation().result[2]))
s.sendto(az+";"+pitch+";"+roll,(hostname,port));

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

domenica 15 gennaio 2012


Un semplicissimo web server in Python per Android (risponde sulla porta 8000)
Nell'esempio mostra le fotografie presenti nel telefono
-----------------------------------------------------------------------------------------------------------------------------
import SimpleHTTPServer
from os import chdir
chdir('/sdcard/DCIM/Camera')
SimpleHTTPServer.test()

Limitazioni sui sensori dei telefoni Android

Accelerometri
Come riportato qui la misura delle accelerazioni con i sensori dei telefoni e' chiaramente dipendente dal tipo di chip che si utilizza ma in ogni caso Android mostrera' un valore con un numero di cifre decimali che e' di molto superiore a quello realmente significativo per lo strumento. Per esempio (qui) il sensore Bosch BMA 150 campiona solo su 8 bit quindi in un range 0-2g vede solo variazioni di 0.08g.
In generale inoltre i sensori a basso costo sono molto rumorosi; il comando StartSensing cerca di ridurre il rumore dello strumento.
In alcuni casi il costruttore limita il range di misura da 0 a 2g

Sensore di luce
In molti casi il sensore di luce viene impiegato come sensore di prossimita' quindi in alcuni casi la risposta del sensore e', a livello software, limitata ad una risposta di tipo binario anche se di fatto l'hardware sarebbe in grado di effettuare misure piu' precise. Inoltre il sensore di luce puo' essere molto lento nel refresh del proprio stato anche a valori prossimi ad 1 secondo

Magnetometro
Questo sensore, che fornisce informazioni anche di orientamento, e' fortemente affetto dalla presenza di sostanze metalliche nelle vicinanze

Da un breve test basato su 120 misure effettuate lasciando il telefono su un tavolo senza muoverlo ho registrato che

Accelerazione X = -0.41 +- 0.11 m/sec2
Accelerazione Y = -0.032 +- 0.23 m/sec2

Accelerazione Z = 9.91 +- 0.14 m/sec2

Azimuth = -0.44 +- 0.075 (errore di circa 4.2°)
Pitch = 0.0017 +- 0.024 (errore di circa 1.35°)
Roll = 0.04 +- 0.014 (errore di circa 0.8°)

sabato 14 gennaio 2012

FTP Client su Android + Python

per utilizzare il telefono Android come client FTP e' piuttosto semplice utilizzando la libreria ftplib

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

import ftplib
s = ftplib.FTP('192.168.0.1','luca','password')
f = open('/mnt/sdcard/datalogger.db','rb')      #path del file che deve essere inviato         
s.storbinary('STOR datalogger.db', f)         #come deve essere salvato il file sul server
                                                                            #il comando STOR non accetta il percorso ma solo il 
                                                                            #nome del file per cui per porlo in directory particolare
                                                                           # si deve usare il comando CWD
f.close()                               
s.quit()

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

Qualche problema in piu' deriva dal lato server. Per esempio installando su Linux il server FTP VsFtp si avra' una configurazione  di base sostanzialmente paranoica che non permette di fare quasi niente oltre a loggarsi per cui si deve editare il file di configurazione in modo da permettere la scrittura agli utenti

venerdì 13 gennaio 2012

Datalogger + Twetter

Una versione del Datalogger con salvataggio su Twetter (poco utile a fini scientifici). Dalle prime prove  la latenza di Twetter e' decisamente superiore a quella di GDocs

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

import android, time, tweepy
from time import strftime


CONSUMER_KEY = 'xxxxxxxxx'
CONSUMER_SECRET = 'xxxxxxxxxxxxx'
ACCESS_KEY = 'xxxxxxxxxxxxxxxx'
ACCESS_SECRET = 'xxxxxxxxxxxxxxxxxxx'
auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
auth.set_access_token(ACCESS_KEY, ACCESS_SECRET)
api = tweepy.API(auth)


droid = android.Android()


droid.startSensingTimed(1,1000)
time.sleep(3)
acq = 0
while True:
accx = str(droid.sensorsReadAccelerometer().result[0])
accy = str(droid.sensorsReadAccelerometer().result[1])
accz = str(droid.sensorsReadAccelerometer().result[2])
az = str(droid.sensorsReadOrientation().result[0])
pitch = str(droid.sensorsReadOrientation().result[1])
roll =  str(droid.sensorsReadOrientation().result[2])
orario = strftime("%Y-%m-%d %H:%M:%S")

outString = "Azimuth: " + az + " Pitch: " + pitch + " Roll: " + roll + " - " + orario
api.update_status(outString)


acq = acq + 1
print "Dato " + str(acq)
time.sleep(30)


droid.stopSensing()
---------------------------------------------------------------------------------------------


FPing

In modo piu' o meno puntuale mi capita di aver bisogno di un apparato di rete sepolto in qualche cassetto di cui ho perso l'indirizzo IP per l'amministrazione (...il foglio allegato e' regolarmente sbagliato)

In particolare con gli Access Point

In questi casi e' fondamentale il programma FPing che permette di automatizzare il Ping su intere classi di indirizzi (in genere finisco abbastanza alla svelta perche' le classi che uso sono quasi sempre la 192.168.0.x, 192.168.1.x e 10.0.0.x)

un esempio (si rimanda al man) per limitare la ricerca ai primi 100 indirizzi


fping -g 192.168.1.1 192.168.1.100



PS: ovviamente si deve sperare che l'apparato di rete non sia in modalita' No_ping come spesso vedono impostati molti server...

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