Il PIR motion detector – un sensore di movimento per Arduino (parte 2)

Meccanismo Complesso - The PIR motion detector banner

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.

Meccanismo Complesso - PIR arduino sketch Fritzing 01

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à…

Meccanismo Complesso - Pir e Arduino 01

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.

Meccanismo Complesso - Pir e Arduino code 01

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.

Meccanismo Complesso - Pir motion Arduino output 01

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.

Meccanismo Complesso - Pir motion Arduino cmd 01

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.

Meccanismo Complesso - PIR arduino sketch Fritzing 02

Questo quello che compare nella realtà

Meccanismo Complesso - PIR motion control Arduino Probe

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.

Meccanismo Complesso - PIR motion arduino 3

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.

Meccanismo Complesso - PIR motion arduino scope 3

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.

Meccanismo Complesso - PIR motion control Arduino Probe 02

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…

Meccanismo Complesso - PIR arduino scope pcbgrip

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!

Lascia un commento