Per la realizzazione della lezione sull’uso del PIR HC-SR501 pubblicato alcuni giorni fa, per lavorare agevolmente con il sensore ho creato un semplice supporto che poi ho stampato in più copie per le sperimentazioni di laboratorio di Sistemi a scuola. Non appena ho pubblicato il post ho ricevuto alcune mail da parte di colleghi e studenti che mi hanno chiesto i sorgenti grafici del supporto.
Potete prelevare i file per la stampa 3D direttamente dalla mia pagina su Thingiverse: PIR HC-SR501 support
Noto spesso nei progetti dei miei studenti il divertimento che nasce nell’utilizzo di un sensore ad infrarossi passivo che viene utilizzato per realizzare dei semplici dispositivi antintrusione, attualmente alcuni allievi li stanno utilizzando in due diversi progetti:
all’interno del kit EduRobot Home in cui il PIR HC-SR501 viene utilizzato come sensore di rilevamento per realizzare un antifurto
attività di PCTO in cui i ragazzi devono implementare un misuratore di sedentarietà, la rilevazione dell’essere umano davanti la computer avviene mediante un PIR.
Questa tipologia di sensore è molto diffuso, li utilizziamo ogni giorno: antifurto di casa, interruttori automatici di luci e molto altro in generale in tutti quei sistemi in cui è indispensabile attivare un’azione nel caso in cui venga rilevata la presenza di un essere umano o di un animale.
Come funziona il sensore di movimento PIR?
Come sicuramente saprete tutti gli oggetti con una temperatura superiore allo zero assoluto (0 Kelvin / -273,15 ° C) emettono energia termica sotto forma di radiazione infrarossa, inclusi i corpi umani. Più un oggetto è caldo, più radiazioni emette.
Il sensore PIR è appositamente progettato per rilevare tali livelli di radiazione infrarossa, è in grado di percepire oggetti caldi in movimento con uno lunghezza d’onda compreso tra i 700 nm e 1 mm . Nel caso della rilevazione di esseri umani la lunghezza d’onda da rilevare è compresa tra 8-14 micrometri.
Il mercato offre diverse tipologie di PIR in funzione del campo di impiego, i più comuni, quelli a lente di Fresnel hanno un range tra i 10 m e i 12 m con un campo di visivo di 300°. E’ possibile trovare sul mercato PIR con un campo visivo che raggiunge i 360° e distanze dell’oggetto rilevato fino a 30 m.
Il PIR fondamentalmente si compone di due parti principali: un sensore piroelettrico e una lente speciale chiamata lente di Fresnel che focalizza i segnali a infrarossi sul sensore piroelettrico.
Un sensore piroelettrico è dotato di due fessure rettangolari al suo interno fatte di un materiale che permette il passaggio della radiazione infrarossa, ciò che verrà rilevato dal sensore sarà la variazione della quantità di raggi infrarossi causata ad esempio dal passaggio di un essere umano e non la quantità di infrarossi totale dell’ambiente.
Le due fessure sono da considerare come due finestre che verranno colpite dai raggi infrarossi e se attraverso le due fessure viene rilevata la stessa quantità di infrarosso allora il segnale risultante di uscita sarà pari a zero, ovvero corpo non rilevato.
Quando però davanti al sensore passa un corpo caldo, come un essere umano, attraverso una finestra verrà rilevata una certa quantità di infrarosso che causerà una differenza di potenziale positiva tra le due finestra, quando il corpo caldo lascia l’area di rilevamento, avviene il contrario, per cui il sensore genera una variazione differenziale negativa. L’impulso di segnali corrispondente fa sì che il sensore imposti il pin di uscita alto, indicandoci quindi la presenza di una persona.
Il sensore HC-SR501, trattandosi di un sensore molto economico, possiede caratteristiche limitate rispetto a quelli che potremo utilizzare per scopi civili o industriali, ma il loro principio di funzionamento è il medesimo.
Analizziamo la scheda
Pinout
Caratteristiche tecniche
Tensione continua di lavoro compresa tra i 4,5V e i 20V
Livelli di tensione di uscita: 3,3V HIGH – 0V LOW
Massimo angolo di visione 110°
Distanza rilevata compresa tra i 3 m e i 7 m
Sulla scheda sono presenti i due trimmer
PIR Range Adjustment (Sensibilità)
Ruotando in senso orario si avrà una diminuzione della sensibilità con decremento della distanza di rilevamento, a fine corsa si avranno approssimativamente una sensibilità di 3 metri.
Ruotando in senso antiorario aumentiamo la sensibilità per raggiungere approssimativamente 7 m.
Time Delay Adjustment (Tempo di delay)
determina la quantità di tempo in cui l’output del sensore PIR rimarrà alto dopo il rilevamento del movimento. L’intervallo è compreso tra circa 3 secondi e 5 minuti. Girando in senso orario, a fine corsa si avrà un delay di 5 minuti, ruotando in senso antiorario, a fine corsa si otterrà un delay di circa 3 secondi.
Si ricordi che impostato il tempo di delay, ad esempio a 5 secondi, ciò comporterà che se viene rilevato il passaggio di un essere umano l’uscita del sensore sarà alta per 5 secondi e in questi 5 secondi il sensore è bloccato, cioè non sarà in grado di rilevare altri movimenti causati da altri corpi.
IMPORTANTE
Dopo il completamento del Time Delay l’uscita sarà a LOW (off) per circa 3 secondi , ciò vuol dire che in questi 3 secondi non verrà rilevato nulla dal sensore.
Sulla scheda è presente un jumper che ha la seguente funzionalità:
Con questo Jumper è possibile impostare le seguenti modalità:
Single Trigger Mode
Il Time Delay viene avviato immediatamente al rilevamento del movimento e il rilevamento continuo viene bloccato.
Questo vuol dire che se ad esempio viene impostato un Time Delay di 5 secondi, al rilevamento di una persona l’uscita passa ad HIGH, se nei 5 secondi passano davanti al sensore un’altra persone questa non viene rilevata e non viene aggiunto un’ulteriore Time Delay.
Immaginate di essere in modalità Single Trigger Mode con un Time Delay di 5 secondi.
Il PIR rileverà il movimento e lo imposterà ad HIGH per 5 secondi.
Dopo cinque secondi il PIR imposta la sua uscita bassa per circa 3 secondi.
Durante i tre secondi, il PIR non rileverà il movimento.
Dopo tre secondi di di LOW, il PIR è abilitato nuovamente al rilevamento di movimenti, al passaggio di una persona verrà impostata nuovamente l’uscita alta per il Time Delay impostato.
Repetable Trigger
Ogni movimento rilevato ripristina il Time Delay, pertanto il Time Delay inizia con l’ultimo movimento rilevato.
Questo vuol dire che se ad esempio viene impostato un Time Delay di 5 secondi, al rilevamento di una persona l’uscita passa ad HIGH se nei 5 secondi viene rilevato il passaggio di un’altra persona il Time Delay riparte nuovamente. Quindi supponendo che:
Persona 1 passa davanti al PIR, parte il Time Delay
Persona 2 passa davanti al PIR al secondo 3, se non passa nessuna persona il Time Delay cesserà ad 8 secondi ed il sensore potrà leggere nuovamente il passaggio di una persona al secondo 11.
IMPORTANTE
Prima di progettare un sistema in cui sono presenti dei PIR ricordare che questi sensori richiedono un po’ di tempo prima di adattarsi alla quantità di energia infrarossa presente nella stanza in cui vengono inseriti, per l’HC-SR501 sono necessari dai 30 ai 60 secondi da quando il sensore viene alimentato.
Ricordare inoltre che il sensore ha un periodo di reset che può oscillare dai 3 ai 6 secondi dopo aver effettuato la lettura, durante tale periodo non verrà rilevato nessun movimento.
Esempio 01
Lettura dello stato del PIR e relativa accensione del LED 13
Schema di collegamento
Il codice per l’utilizzo del sensore è estremamente semplice, è necessario solamente rilevare se il pin OUT si trova a valore alto o basso. Il funzionamento è dettagliato nei commenti.
/*
* Prof. Michele Maffucci
* data: 28.02.2021
*
* Esempio 01
* Utilizzo del sensore PIR: PIR HC-SR501
* Lettura dello stato del PIR e relativa accensione
* del LED 13
*
*/
byte pinLed = 13; // pin a cui è collegato il LED
byte pinInput = 8; // pin di input a cui è collegato l'OUT del PIR
bool valPIR = 0; // variabile utilizzata per memorizzre lo stato del PIR
void setup() {
pinMode(pinLed, OUTPUT); // pin a cui è collegato il LED è un output
pinMode(pinInput, INPUT); // pin a cui è collegato il PIR è un input
Serial.begin(9600);
}
void loop() {
valPIR = digitalRead(pinInput); // viene letto il valore restituito dal PIR
digitalWrite(pinLed, valPIR); // il LED sulla scheda verrà acceso se viene
// rilevata una persona altrimenti il LED
// resterà spento. valPIR assume i valori 0 o 1
}
Esempio 02
Lettura dello stato del PIR e relativa accensione del LED 13 e stampa dello stato sulla Serial Monitor
/*
* Prof. Michele Maffucci
* data: 28.02.2021
*
* Esempio 02
* Utilizzo del sensore PIR: PIR HC-SR501
* Lettura dello stato del PIR e relativa accensione
* del LED 13 e stampa dello stato sulla Serial Monitor
*/
byte pinLed = 13; // pin a cui è collegato il LED
byte pinInput = 8; // pin di input a cui è collegato l'OUT del PIR
bool valPIR = 0; // variabile utilizzata per memorizzre lo stato del PIR
void setup() {
pinMode(pinLed, OUTPUT); // pin a cui è collegato il LED è un output
pinMode(pinInput, INPUT); // pin a cui è collegato il PIR è un input
Serial.begin(9600);
}
void loop() {
valPIR = digitalRead(pinInput); // viene letto il valore restituito dal PIR
Serial.println(valPIR); // stampa sulla Serial Monitor il valore letto
delay(150); // ritardo per rallentare la frequenza di stampa
// sulla Serial Monitor
// Viene controllato se il PIR rileva una persona
// Nota: scrivere "if (valPIR)" è analogo che scrivere
// "if (valPIR == HIGH)" in quanto valPIR assume i valori 0 o 1
if (valPIR) {
digitalWrite(pinLed, HIGH);
Serial.println("Rilevata una persona");
}
else
{
digitalWrite(pinLed, LOW);
Serial.println("Non è presente nessuno");
}
}
Esercizio 01
Realizzare un semplice sistema di allarme costituito dal sensore PIR, un buzzer e due LED uno rosso ed uno verde.
Se il PIR non rileva nessuna persona il LED verde risulta acceso, il LED rosso spento ed il buzzer non emette nessun suono.
Se il PIR rileva una persona il LED verde risulta spento, il LED rosso acceso ed il buzzer emette un suono.
Esercizio 02
Realizzare le medesime funzionalità dell’esercizio 01 ed aggiungere un display I2C su cui inviare l’output:
Questa lezione nasce da un commento di Aldo Biscotti(seguite il link), che ha la necessità di realizzare l’illuminazione temporizzata delle scale di casa. Si sta cimentando in questo progetto e la sua richiesta di aiuto mi da parecchi spunti per la realizzazione di una lezione ad hoc per i miei allievi.
Per la realizzazione del suo progetto avrà la necessità di usare dei sensori di presenza, che in questa lezione saranno sostituiti da semplici pulsanti.
Dal commento che mi è stato lasciato desumo che la necessità descritta da Aldo è quella di comandare due lampade di due ambienti diversi mediante due distinti rilevatori di presenza.
Nel realizzare un primo prototipo di studio Aldo giustamente, visto che sta imparando a programmare Arduino, utilizza i pulsanti in sostituzione dei rilevatori e i diodi led in sostituzione delle lampade.
Questa la sua necessità:
Pulsante 1:
(salita) start,
accensione del led 1,
dopo 2 secondi accensione led 2,
dopo 2 secondi spegnimento led 1,
dopo 2 secondi spegnimento led 2,
end.
Pulsante 2:
(discesa) start,
accensione del led 2,
dopo 2 secondi accensione led 1,
dopo 2 secondi spegnimento led 2,
dopo 2 secondi spegnimento led 1,
end.
Grazie Aldo.
Risponderò ad Aldo prendendo in analisi il suo primo sketch e da questo ne svilupperò una serie di programmi in cui introdurrò nuovi concetti.
Innanzitutto realizziamo il primo circuito di test, costituito da due diodi led, una resistenza ed un pulsante, in questa lezione vedrete che utilizzerò sia una scheda Arduino UNO, che Arduino 2009, assolutamente simili dal punto di vista della programmazione:
// Esempio 1: accensione led
int led_1 = 8;
int led_2 = 9;
int btn_pin = 2;
void setup() {
pinMode(led_1, OUTPUT);
pinMode(led_2, OUTPUT);
pinMode(btn_pin, INPUT);
}
void loop()
{
int in = digitalRead(btn_pin);
if (in == LOW)
{
digitalWrite(led_1, LOW);
delay (2000);
digitalWrite(led_2, LOW);
delay (2000);
}
else
{
digitalWrite(led_1, HIGH);
delay (2000);
digitalWrite(led_2, HIGH);
delay (2000);
}
}
Non funziona molto bene, come si desume dal filmato vi sono alcune correzioni da fare:
Nell’if viene controllato se il pulsante non è stato premuto “in == LOW”, se vero vengono spenti in modo sequenziale i due LED, domanda:
Se una luce è già spenta perché aggiungere un ritardo?
Ciò implica che se il programma è in esecuzione nella prima parte dell’if non verrà rilevata la presenza di una persona al massimo per 4 secondi ed è come dire che appena entro nella stanza sarò al buio per 4 secondi prima che le luci vengano accese e quindi una persona potrà:
fermarsi ed attendere 4 secondi
oppure camminare per 4 secondi al buio compiendo circa 5 metri di spazio camminando, presumibilmente supererà la prima stanza al buio.
Questa la mia prima variazione:
// Esempio 2: accensione temporizzata di un led in una sola direzione
#define led_1 8 // il pin 8 è usato per il LED
#define led_2 9 // il pin 9 è usato per il LED
#define btn_pin 2 // il pin 2 è usato per il PULSANTE 1
// Variabili
int in = 0;
void setup() {
pinMode(led_1, OUTPUT); // impostiamo il pin led_1 come output
pinMode(led_2, OUTPUT); // impostiamo il pin led_2 come output
pinMode(btn_pin, INPUT); // impostiamo il pin btn_pin come input
}
void loop()
{
in = digitalRead(btn_pin); // assegna lo stato del pulsante
if (in == HIGH) // controlla se il pulsante è stato premuto
{
digitalWrite(led_1, HIGH); // accendiamo il LED 1
delay (2000); // attesa di 2 sec
digitalWrite(led_2, HIGH); // accendiamo il LED 2
delay (2000); // attesa di 2 sec
digitalWrite(led_1, LOW); // spegniamo il LED 1
delay (2000); // attesa di 2 sec
digitalWrite(led_2, LOW); // spegniamo il LED 2
}
}
Controllo se il pulsante e premuto, se vero inizia la sequenza di accensione, altrimenti se il pulsante non è premuto l’if non viene eseguito, le luci continuano a rimanere spente e ricomincia nuovamente il loop().
Ovviamente se durante la sequenza di accensione e spegnimento di 6 secondi viene premuto nuovamente il pulsante non accade nulla, vedremo più avanti che questa soluzione potrebbe causare qualche problema.
Vediamo adesso come utilizzare due pulsanti (o rilevatori di presenza) per governare l’accensione in senso opposto, il circuito realizzato è il seguente:
Questo lo sketch
// Esempio 3: accensione temporizzata di due led
// in due direzioni con uso dell'if
#define led_1 8 // il pin 8 è usato per il LED
#define led_2 9 // il pin 9 è usato per il LED
#define btn_pin1 2 // il pin 2 è usato per il PULSANTE 1
#define btn_pin2 3 // il pin 3 è usato per il PULSANTE 2
// Variabili
int in1 = 0; // variabile per memorizzare lo stato del PULSANTE 1
int in2 = 0; // variabile per memorizzare lo stato del PULSANTE 2
void setup() {
pinMode(led_1, OUTPUT);
pinMode(led_2, OUTPUT);
pinMode(btn_pin1, INPUT);
pinMode(btn_pin2, INPUT);
}
void loop()
{
in1 = digitalRead(btn_pin1);
in2 = digitalRead(btn_pin2);
if (in1 == HIGH && in2 == LOW) // se PULSANTE 1 premuto e PULSANTE 2 no sequenza 1
{
digitalWrite(led_1, HIGH);
delay (2000);
digitalWrite(led_2, HIGH);
delay (2000);
digitalWrite(led_1, LOW);
delay (2000);
digitalWrite(led_2, LOW);
}
if (in1 == LOW && in2 == HIGH) // se PULSANTE 1 premuto e PULSANTE 2 no sequenza 2
{
digitalWrite(led_2, HIGH);
delay (2000);
digitalWrite(led_1, HIGH);
delay (2000);
digitalWrite(led_2, LOW);
delay (2000);
digitalWrite(led_1, LOW);
}
}
Come potete notare ho usato l’operatore logico AND (&&) che effettua un controllo su quale dei pulsanti è acceso in questo modo controllo la direzione di accensione.
Per chiarire meglio ho realizzato uno schema che visualizza meglio cosa accade:
Si ricordi che la progettazione viene fatta usando pulsanti, ma voi estrapolate e pensate a dei rilevatori di presenza.
Supponiamo che la direzione sia da destra a sinistra, la persona 1 viene rilevata dal sensore R1, si accende la luce L1 per 2 secondi, entra nella stanza 2 e supponendo che non sia più veloce di due secondi, rischiando di entrare in una stanza buia, viene rilevato dal sensore R2, si accende la luce L2 e dopo 4 secondi si spegne la luce L1.
Ma cosa accade se nei primi 2 secondi entra un’altra persona nella prima stanza a destra?
La seconda persona resta al buio.
Stesso inconveniente accade nella direzione opposta da sinistra verso destra.
Quindi per superare questo incoveniente è necessario che l’accensione delle luci non duri solamente per un tempo prefissato, ma per tutto il tempo in cui la persona è presente nel locale, dopo di che la luce può spegnersi.
La soluzione più semplice di tutte è quella descritta dallo sketch che segue, si ricordi che premere il pulsante corrisponde a: “persona rilevata”
// Esempio 4: accensione di due led comandati da due pulsanti
#define led_1 8 // il pin 8 è usato per il LED
#define led_2 9 // il pin 9 è usato per il LED
#define btn_pin1 2 // il pin 2 è usato per il PULSANTE 1
#define btn_pin2 3 // il pin 3 è usato per il PULSANTE 2
// Variabili
int in1 = 0;
int in2 = 0;
void setup() {
pinMode(led_1, OUTPUT);
pinMode(led_2, OUTPUT);
pinMode(btn_pin1, INPUT);
pinMode(btn_pin2, INPUT);
}
void loop()
{
in1 = digitalRead(btn_pin1);
in2 = digitalRead(btn_pin2);
if (in1 == HIGH) // PULSANTE 1 premuto
{
digitalWrite(led_1, HIGH); // accensione LED 1
}
else
{
digitalWrite(led_1, LOW); // seil PULSANTE 1 non premuto LED 1 spento
}
if (in2 == HIGH) // PULSANTE 2 premuto
{
digitalWrite(led_2, HIGH); // accensione LED 2
}
else
{
digitalWrite(led_2, LOW); // seil PULSANTE 2 non premuto LED 2 spento
}
}
Per evitare che ci sia uno spegnimento brusco dell’illuminazione appena si esce dalla stanza, ritardo lo spegnimento dell’illuminazione della stanza che ho appena abbandonato:
// Esempio 5: accensione di due led comandati da due pulsanti
// con ritardo di spegnimento di due secondi
#define led_1 8 // il pin 8 è usato per il LED
#define led_2 9 // il pin 9 è usato per il LED
#define btn_pin1 2 // il pin 2 è usato per il PULSANTE 1
#define btn_pin2 3 // il pin 3 è usato per il PULSANTE 2
// Variabili
int in1 = 0;
int in2 = 0;
void setup() {
pinMode(led_1, OUTPUT);
pinMode(led_2, OUTPUT);
pinMode(btn_pin1, INPUT);
pinMode(btn_pin2, INPUT);
}
void loop()
{
in1 = digitalRead(btn_pin1);
in2 = digitalRead(btn_pin2);
if (in1 == HIGH){ // PULSANTE 1 premuto
digitalWrite(led_1, HIGH); // accensione LED 1
delay (2000); // ritardo di 2 sec
}
else
{
digitalWrite(led_1, LOW); // se il PULSANTE 1 non premuto LED 1 spento
}
if (in2 == HIGH){ // PULSANTE 2 premuto
digitalWrite(led_2, HIGH); // accensione LED 2
delay (2000); // ritardo di 2 sec
}
else
{
digitalWrite(led_2, LOW); // seil PULSANTE 2 non premuto LED 2 spento
}
}
Nella prossima lezione al fine di rendere più utile e gradevole il controllo sull’illuminazione della stanza vedremo come aumentare e diminuire gradualmente l’illuminazione usando una tecnica che sfrutta la modulazione di larghezza di impulso (PWM).