Welcome to Giovanni's Blog

PiFace Digital 2 - Applicazioni avanzate in Python

 | #InternetofThings#IoT#piface#piface digital 2#pifaceio#Programmazione#Python#raspberry#raspberrypi

In questo articolo vedremo come realizzare delle applicazioni più avanzate per il nostro PiFace Digital. In particolare vi mostrerò come creare un’applicazione multithread, ovvero come definire dei sottoprogrammi all’interno della nostra applicazione, che andranno a fare polling (si metteranno in ascolto) su diverse porte di input, eseguendo task differenti. Vedremo inoltre come condividere una variabile tra i thread in esecuzione e come gestire la pressione prolungata di un tasto.

Il programma di esempio che andremo a vedere, crea quattro thread che saranno lanciati parallelamente in esecuzione. I primi tre svolgono essenzialmente le stesse operazioni, ovvero aggiornano e poi stampano a video il valore della variabile condivisa che è stata creata. Il quarto thread invece, alla pressione prolungata per almeno 2 secondi, accende in sequenza tutti i led presenti sulla scheda PiFace. Di seguito è mostrato il codice che poi andremo a commentare. Suppongo che il lettore abbia già conoscenza del linguaggio Python, dunque eviterò di dare spiegazioni dettagliate per ciò che riguarda la sintassi e la logica del linguaggio.

#!/usr/bin/env python3

from time import sleep
from timeit import default_timer
import pifaceio
import threading

pfio = pifaceio.PiFace()

#------ Shared variable -------
class Variable(object):
   value = None

myVar = Variable()

def myVarSet(stato):
   myVar.value = stato

def myVarValue():
   return myVar.value


#----- Pin read and write methods -----
def read_pin(pin):
   pfio.read()
   return pfio.read_pin(pin)

def write_pin(pin, state):
   pfio.write_pin(pin, state)
   pfio.write()


#------ Threads defining-------
class myThread (threading.Thread):
   def __init__(self, name):
      threading.Thread.__init__(self)
      self.name = name
 
   def run(self):
      if self.name == 'f1':
         f1()
      elif self.name == 'f2':
         f2()
      elif self.name == 'f3':
         f3()
      elif self.name == 'ledShow':
         ledShow()

def f1():
   while True: 
      if read_pin(0):
         print 'Previous state: ', myVarValue()
         myVarSet(1)
         print 'Current state: ', myVarValue()
         sleep(1)
      if read_pin(0) and read_pin(2):
         print 'Thread 1 terminated'
         break

def f2():
   while True: 
      if read_pin(1):
         print 'Previous state: ', myVarValue()
         myVarSet(2)
         print 'Current state: ', myVarValue()
         sleep(1)
      if read_pin(0) and read_pin(2):
         print 'Thread 2 terminated'
         break

def f3():
   while True: 
      if read_pin(2):
         print 'Previous state: ', myVarValue()
         myVarSet(3)
         print 'Current state: ', myVarValue()
         sleep(1)
      if read_pin(0) and read_pin(2):
         print 'Thread 3 terminated'
         break 


def ledShow():
   while True:
      if read_pin(3):
         start = default_timer()
         now = default_timer()
         endsBefore = False
         while ((now - start) <= 2):
            if not read_pin(3):
               endsBefore = True
               break
            now = default_timer() 

         if not endsBefore:
            leds = range(0,8)
            for led in leds:
               write_pin(led, 1)
               sleep(0.5)
               write_pin(led, 0)

      if read_pin(0) and read_pin(2):
         print 'Thread 4 terminated'
         break 


#---- Shared variable initialiting
myVarSet(0)


#---- Starting threads -----
func1 = myThread('f1')
func2 = myThread('f2')
func3 = myThread('f3')
func4 = myThread('ledShow')

func1.start()
func2.start()
func3.start()
func4.start()

print 'Hold down the buttons 0 and 2 to terminate the program'

func1.join()
func2.join()
func3.join()
func4.join()

Come si può vedere dal codice, è stata definita una classe myThread per la creazione dei threads. Quando un nuovo oggetto della classe myThread viene istanziato e lanciato, viene eseguita una specifica funzione in base al parametro name passato al costruttore. Questo approccio ha consentito di definire una singola classe dinamica per la creazione dei thread. Per poter condividere una variabile tra i vari thread in esecuzione, è necessario creare un oggetto e inizializzare il valore della variabile in esso contenuta solo dopo la definizione delle varie ‘funzioni thread’. Il quarto thread, che corrisponde alla funzione ledShow, effettua polling sull’input 3 e una volta che viene trovato attivo, controlla che per i prossimi 2 secondi resti in quello stato; in caso positivo entra nel blocco if successivo e accende tutti i led in sequenza.

Sulla base del programma appena visto potrete creare applicazioni avanzate e personalizzate per il vostro PiFace Digital, dando spazio alla creatività. I thread visti in questo esempio eseguono azioni molto banali, ma potrebbero eseguire operazioni molto più interessanti come l’invio di un’email, lo scatto di una foto da una webcam, accendere il sistema di riscaldamento di casa, ecc. Dunque non dovete fare altro che dare spazio all’immaginazione e creare il vostro sistema IoT!

Sulla pagina ufficiale di PiFace potete trovare moltissime idee e guide su come realizzarle (in lingua inglese).

About Giovanni De Costanzo

Photo of Giovanni De Costanzo

My name is Giovanni De Costanzo and I'm a Sr.Research Engineer at Malwarebytes. I'm a geek, passionate about all the tech world since early age.