Introduzione
Questa è la seconda parte dell’articolo pubblicato circa una settimana fa che riguardava i sensori di movimento PIR, spiegandone i dettagli tecnici sul loro utilizzo e funzionamento (vedi qui). In questo articolo, continueremo l’argomento vedendo come utilizzarli in modo pratico utilizzando una scheda Arduino (nel mio caso un Arduino UNO).
Connettere il PIR ad Arduino
Continuiamo quindi, precisamente dal punto in cui avevamo interrotto l’articolo, cioè con lo schema di connessione realizzato con il software Fritzing. Ho modificato il colore del cavo centrale del PIR rendendolo bianco, in modo che sia coerente con il mio modello PIR.
Nel precedente articolo avevamo visto che a seconda del modello di PIR, il colore, la funzionalità e la disposizione dei tre cavi in uscita potrebbe variare. Quindi, prima di fare qualsiasi collegamento, è importante controllare sul datasheet del modello in possesso.
Nello schema appena mostrato ho basato i collegamenti sul mio tipo di PIR, il modello SE-10. Se il vostro modello dovesse risultare diverso, e soprattutto avere dei cavi diversi, modificate i collegamenti di conseguenza. Un modello molto buono è per esempio l’ HC-SR501 dell’Aukru. Nello schema il cavo rosso rappresenta l’alimentazione +5V, il bianco il GROUND, ed il nero l’ALARM che è il segnale di rilevazione proveniente dal sensore. Dallo schema potete notare l’utilizzo anche di una resistenza, questa deve essere da 1KΩ.
Ecco come risulta nella realtà…
Primo esempio: contare i movimenti rilevati.
Come primo esempio, scriveremo un programma che conterà tutte le volte che il PIR ha rilevato un movimento. Per prima cosa impostiamo il PIN 2 come input con la funzione pinMode(). Il programma pressochè consiste nel far leggere ad Arduino il valore proveniente dal PIN2, appunto, in modo continuo. Generalmente, cioè in assenza di segnale di rilevazione lo stato di questo pin sara HIGH. Quando il sensore PIR rileverà un movimento porterà il livello del pin a livello LOW. Quando questo avviente, la condizione if() all’interno del loop viene attivata e quindi si può creare un evento di risposta. In questo caso sarà un semplice messaggio inviato via seriale contenente la dicitura “Motion Detected” e il numero di movimento rilevato.
Una volta editato il codice, compiliamo e inviamolo sulla scheda Arduino. Se non ci sono stati errori, Arduino comincerà ad eseguire il codice non appena si effettuerà la connessione seriale. Per aprire una comunicazione seriale, su Arduino IDE andate su Strumenti > Monitor Seriale. Vi apparirà una nuova finestra, in cui ogni volta che il PIR rileverà un movimento scriverà la dicitura “Motion Detected” con il numero di conteggio.
Oppure se preferite utilizzare Python da riga di comando, aprite una sessione da terminale (cmd da Windows) e lanciate il comando:
$ python
e poi inserite i seguenti comandi
>>>import serial >>>arduinoSerialData = serial.Serial('/dev/ttyACM0',9600) >>>while 1: if(arduinoSerialData.inWaiting()>0): myData = arduinoSerialData.readline() print myData
Otterrete l’output seriale inviato da Arduino.
Se al momento di immettere il comando import serial, ricevete messaggio di errore, allora la libreria pySerial (necessaria per la comunicazione seriale tramite Python) non è stata ancora installata. Potete farlo con pip o con Anaconda (a seconda di quale sistema stiate utilizzando).
$ pip install pyserial
oppure
$ conda install pyserial
Lo stato HIGH e LOW del PIN di Input grazie alla resistenza di Pull Up
Quando il sensore viene alimentato, come già descritto nel precedente articolo, il modulo PIR impiegherà 1-2 secondi per calibrarsi. Una volta effettuata la calibrazione, si avrà lo stato di LOW sul PIN alarm (open-collector) solo nel periodo in cui il movimento viene rilevato (lo stato del PIN alarm non è latched). Quando non viene rilevato nessun movimento, il PIN alarm è in stato di floating.
Questa impostazione dell’open-collector permette di poter collegare più PIR sullo stesso PIN di input sulla scheda di Arduino, ma significa anche che sarà necessario utilizzare una resistenza esterna di pull-up sul pin ALARM. Quando uno qualsiasi dei sensori percepirà un movimento, lo stato del PIN andrà a LOW.
Secondo esempio: visualizzazione dello stato del PIN
Modificheremo l’esempio precedente in modo da osservare attraverso il computer lo stato del voltaggio. Utilizzeremo infatti Arduino stesso, come una sorta di voltmetro per osservare quello che succede al segnale ALARM quando il PIR è in stato di quiete e quando rileva un movimento.
Per fare questo, utilizzeremo due PIN analogici presenti sulla scheda A0 e A1, e connettendoci due cavetti jumper dupont, li useremo come sonde per seguire in tempo reale l’andamento del voltaggio in due punti diversi del circuito.
Lo schema Fritzing sottostante riporta il circuito dove tutte le connessioni precedenti sono riportate in nero mentre le due nuove connessioni con i colori verde (Ch1) e rosso (Ch2). Analizzeremo quindi il segnale ai due capi della resistenza di pull-up.
Questo quello che compare nella realtà
Adesso possiamo modificare il codice presedente sull’Arduino IDE, aggiungendo il codice destintato al controllo dei due canali, e rimuovendo la gestione dell’evento di rilevazione del movimento, che in questo esempio non ci interessa gestire.
Per prima cosa abbiamo definito i due nuovi canali analogici Ch1 e Ch2 sui PIN analogici A0 e A1 presenti su Arduino che utilizzeremo come sonde da inserire in punti precisi del circuito. Le letture vengono effettuate attraverso la funzione analogRead(). I valori letti devono essere convertiti in voltaggio, considerando che il valore massimo è 1023 ed equivale a 5V, apponiamo le opportune modifiche ai valori di lettura val1 e val2. I valori floating point v1 e v2 verranno inviati serialmente in una stessa riga.
Questi dati vengono ricevuti da un programma scritto in Python e visualizzati in tempo reale. Ho trovato in rete un programma in python adatto allo scopo di Mahesh Venkitachalam (vedi qui), l’ho modificato leggermente per adattarlo a ricevere i valori in Volt (float e non interi).
import sys, serial, argparse import numpy as np from time import sleep from collections import deque import matplotlib.pyplot as plt import matplotlib.animation as animation # plot class class AnalogPlot: # constr def __init__(self, strPort, maxLen): # open serial port self.ser = serial.Serial(strPort, 9600) self.ax = deque([0.0]*maxLen) self.ay = deque([0.0]*maxLen) self.maxLen = maxLen # add to buffer def addToBuf(self, buf, val): if len(buf) < self.maxLen: buf.append(val) else: buf.pop() buf.appendleft(val) # add data def add(self, data): assert(len(data) == 2) self.addToBuf(self.ax, data[0]) self.addToBuf(self.ay, data[1]) # update plot def update(self, frameNum, a0, a1): try: line = self.ser.readline() data = [float(val) for val in line.split()] # print data if(len(data) == 2): self.add(data) a0.set_data(range(self.maxLen), self.ax) a1.set_data(range(self.maxLen), self.ay) except KeyboardInterrupt: print('exiting') return a0, # clean up def close(self): # close serial self.ser.flush() self.ser.close() # main() function def main(): # create parser parser = argparse.ArgumentParser(description="LDR serial") # add expected arguments parser.add_argument('--port', dest='port', required=True) # parse args args = parser.parse_args() strPort = args.port print('reading from serial port %s...' % strPort) # plot parameters analogPlot = AnalogPlot(strPort, 100) print('plotting data...') # set up animation fig = plt.figure() ax = plt.axes(xlim=(0, 100), ylim=(0, 6)) ax.set_ylabel('Voltage V') a0, = ax.plot([], []) a1, = ax.plot([], []) anim = animation.FuncAnimation(fig, analogPlot.update, fargs=(a0, a1), interval=50) # show plot plt.show() # clean up analogPlot.close() print('exiting.') # call main if __name__ == '__main__': main()
Una volta finito di scriverlo, l’ho salvato come voltage_reader.py. Il programma può essere eseguito da linea di comando, passando come argomento la porta in ascolto. Nel mio caso, trovandomi su Windows, la porta in ascolo è la COM5.
python voltage_reader.py --port COM5
e subito si aprirà una finestra che leggendo i due voltaggi da Arduino, mostrerà il loro andamento nel tempo.
Come possiamo vedere, il tratto verde che corrisponde all’alimentazione rimane stabile sui 5.00V mentre il tratto blu, che corrisponde al PIN Alarm passa allo stato LOW (0.70V) ogni volta che viene rilevato un movimento dal sensore PIR. La durata dello stato PIR dipenderà dalla durata del movimento. Non appena cessato il movimento lo stato ritornerà su HIGH (5.00V).
Adesso per curiosità spostiamo una delle due sonde, e più precisamente quella che rimane stabile a 5.00V (cioè quella sull’alimentazione). Per curiosità la facciamo puntare direttamente su uno dei tre terminali del sensore (e non del modulo). Vediamo cosa succede.
Io ho utilizzato il kit di PCBGrip per costruirmi le sonde (se siete interessati all’argomento vi consiglio questo articolo ).
Adesso riavviamo il programma Python e vediamo.
Arduino rileverà questo andamento…
Quindi in blu abbiamo il vero segnale ALARM non filtrato dall’elettronica presente nel modulo. 🙂
Conclusioni
L’argomento certamente non si esaurisce qui. Ma lo scopo di questo articolo era illustrare come utilizzare i sensori PIR con la scheda Arduino, ma anche mostrare nuovi approcci per poter studiare al meglio il comportamento di questi sensori.
Hai esperienze con Arduino da condividere? Stiamo cercando persone interessate a pubblicare nuovi articoli sull’argomento. Non cerchiamo esperti, ma appassionati. Facci sapere. Non aver paura (per qualsiasi problema ti possiamo aiutare). Per ulteriori informazioni contattaci direttamente a meccanismo.complesso@gmail.com, oppure lascia un commento!