Sensore di movimento PIR

Sensore di movimento PIR

Se stai pensando di construire un sistema di allarme, o semplicemente accendere una luce quando vi è un movimento, probabilmente ti servirà un PIR.

Un PIR è un sensore passivo piroelettrico, ed il più comune è il HC-SR501. Il modulo è abbastanza piccolo e leggero, può essere quindi posizionato facilmente dove si vuole.



In questo articolo vedremo come utilizzare un PIR con Arduino, successivamente con l’ausilio dello shield ethernet vedremo come notificare via MQTT il movimento rilevato. Lo stesso progetto può essere sviluppato con un NodeMcu ESP8266 utilizzando la connessione wifi.

Iniziamo a vedere come è fatto questo sensore e come andrà collegato ad Arduino. Il PIR è dotato di 3 pin: Vcc , Gnd e out dove viene dato il segnale di presenza movimento. Oltre ai pin sono presenti due trimmer.

Il primo trimmer serve a gestire la sensibilità, ruotando il trimmer con un cacciavite andremo ad aumentarla (senso orario) o diminuirla (senso antiorario). La sensibilità generalmente varia da 3 a 7 metri.

Il secondo trimmer gestisce i tempi di uscita, anche qui con un cacciavite possiamo aumentare (senso orario) o diminuire (senso antiorario) il tempo che varia dai 3 ai 300 secondi.

I PIR che ho acquistato io sono poi dotati di un jumper o ponticello per gestire il ripristino. Alcuni PIR al posto del jumper hanno semplicemente i contatti da saldare manualmente.



Vi sono due posizioni disponibili H o L. Quando il jumper è su H il PIR è in ripristino automatico, vuol dire che il segnale rimarrà alto finchè vi è movimento e andrà basso quando il movimento non è più rilevato. Al contrario se è posizionato su L il PIR è impostato come nessun ripristino per la quale una volta rilevato il movimento l’uscita sarà alta per un tempo prestabilito per poi tornare bassa.

Quindi colleghiamo il PIR ad Arduino, Vcc con 5V, Gnd con Gnd e l’output lo collegheremo ad esempio al pin numero 12. Andiamo a scrivere lo sketch.

Prima di tutto definiremo i pin da utilizzare, oltre al 12 utilizzerò anche il 13 come led interno ad Arduino e poi definiamo una variabile boolean che ci servirà da flag per evitare di continuare a scrivere in console finchè il segnale sarà alto o basso.

#define PIN_PIR 12 // Out of PIR is connected with pin 12
#define PIN_LED 13 // built-in led

boolean motionDetected = false;

Nel setup inizializziamo la console e definiamo le modalità di utilizzo dei pin. PIN_PIR sarà il nostro input che leggeremo, mentre PIN_LED verrà scritto in modo da accendere o spegnere il led. Forziamo PIN_PIR a Low e stampiamo in console il messaggio che ci dirà che il loop sta per iniziare.

void setup() {
  Serial.begin(9600);
  pinMode(PIN_PIR, INPUT);
  pinMode(PIN_LED, OUTPUT);

  // reset PIR 
  digitalWrite(PIN_PIR, LOW);
  
  Serial.println("PIR active");
  delay(100);
}

Nel loop andremo a testare il nostro PIN_PIR. Quando questo sarà alto accenderemo il led e stamperemo il messaggio in console, grazie alla variabile booleana prima definita tale messaggio sarà scritto una sola volta finchè il PIN_PIR sarà alto. Nello stesso modo ma al contrario se il PIN_PIR sarà basso, spegneremo il led e stamperemo un messaggio in console.

void loop() {

  // IF PIN_PIR is High => motion detected by sensor
  if (digitalRead(PIN_PIR) == HIGH) {
    digitalWrite(PIN_LED, HIGH);   //Turnon Led
    if (!motionDetected) {
      motionDetected = true;
      Serial.println("---");
      Serial.println("Motion Detected!");
      delay(50);
    }
  }
  // IF PIN_PIR is Low => no motion detected by sensor
  if (digitalRead(PIN_PIR) == LOW) {
    digitalWrite(PIN_LED, LOW);  //Turn off Led
   if (motionDetected) {
      motionDetected = false;
      Serial.println("---");
      Serial.println("No motion detected");   
      delay(50);
    }
  }
}

Trovate lo sketch completo su github.

A questo punto siamo pronti a muoverci davanti al nostro nuovo sensore per capirne il funzionamento e i tempi di risposta e attesa. Una volta compreso il tutto possiamo sbizzarrirci nel creare il nostro progetto, come ad esempio un antifurto.

Come detto prima però in questo articolo vedremo anche come inviare questo segnale fornitoci dal PIR in rete via MQTT con l’ausilio di una shield ethernet!



Andremo semplicemente ad unire lo sketch appena scritto con quello base per MQTT ed Ethernet che trovate su github.

Di seguito lo sketch completo:

/*
 Test MQTT publish and subscribe via etherner connection 
 PIR Sensor for motion detect

 by Alberto Celano
 http://www.caprasilana.it
*/
#include <Ethernet.h>
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"

/************************* Adafruit.io Setup *********************************/
#define AIO_SERVER "192.168.1.5" // IP of MQTT BROKER
#define AIO_SERVERPORT 1883 // use 8883 for SSL
#define AIO_USERNAME ""
#define AIO_KEY ""

/************************* Define PIR PIN *********************************/

#define PIN_PIR 12 // Out of PIR is connected with pin 12
#define PIN_LED 13 // built-in led

boolean motionDetected = false;

/************************* Network Properties *********************************/
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };; // Arduino MAC
IPAddress ip(192, 168, 1, 35); // Arduino IP
IPAddress server(192, 168, 1, 5); // MQTT Broker IP

/************************* Ethernet Client Setup *****************************/

EthernetClient ethClient;

// Setup the MQTT client class by passing in the WiFi client and MQTT server and login details.
Adafruit_MQTT_Client mqtt(&ethClient, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);

/****************************** Feeds ***************************************/

// Setup a feed called 'publishTopic' for publishing.
Adafruit_MQTT_Publish publishTopic = Adafruit_MQTT_Publish(&mqtt, "publishTopic");

// Setup a feed called 'subscribeTopic' for subscribing to changes.
Adafruit_MQTT_Subscribe subscribeTopic = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "subscribeTopic");

void MQTT_connect();

void setup()
{  
  Serial.begin(9600);

  pinMode(PIN_PIR, INPUT);
  pinMode(PIN_LED, OUTPUT);

  // reset PIR 
  digitalWrite(PIN_PIR, LOW);
  delay(10);
  Serial.println();
  Serial.print("Connecting to network");
  
  Ethernet.begin(mac, ip);
  Serial.println();
  
  // Setup MQTT subscription
  mqtt.subscribe(&subscribeTopic);
}

void loop()
{
  MQTT_connect();

  Adafruit_MQTT_Subscribe *subscription;
  while ((subscription = mqtt.readSubscription(5000)))
  {
    if (subscription == &subscribeTopic)
    {
      Serial.print(F("Got: "));
      Serial.println((char *)subscribeTopic.lastread);     
    }
  }

  // IF PIN_PIR is High => motion detected by sensor
  if (digitalRead(PIN_PIR) == HIGH) {
    digitalWrite(PIN_LED, HIGH);   //Turnon Led
    if (!motionDetected) {
      motionDetected = true;
      Serial.println("---");
      Serial.println("Motion Detected!");
      // send message via MQTT
      
      publishTopic.publish("MOTION_START"); 
      delay(50);
    }
  }
  // IF PIN_PIR is Low => no motion detected by sensor
  if (digitalRead(PIN_PIR) == LOW) {
    digitalWrite(PIN_LED, LOW);  //Turn off Led
   if (motionDetected) {
      motionDetected = false;
      Serial.println("---");
      Serial.println("No motion detected");   

      // send message via MQTT
      publishTopic.publish("MOTION_END"); 
      delay(50);
    }
  }
  
}

// Function to connect and reconnect as necessary to the MQTT server.
// Should be called in the loop function and it will take care if connecting.
void MQTT_connect()
{
  int8_t ret;

  // Stop if already connected.
  if (mqtt.connected())
  {
    return;
  }

  Serial.print("Connecting to MQTT... ");

  uint8_t retries = 3;
  while ((ret = mqtt.connect()) != 0)
  { // connect will return 0 for connected
    Serial.println(mqtt.connectErrorString(ret));
    Serial.println("Retrying MQTT connection in 5 seconds...");
    mqtt.disconnect();
    delay(5000); // wait 5 seconds
    retries--;
    if (retries == 0)
    {
      // basically die and wait for WDT to reset me
      while (1)
        ;
    }
  }
  Serial.println("MQTT Connected!");
  
  publishTopic.publish("Hello MQTT World!"); 
}

Trovate anche questo sketch su github.

Qui uno screen del risultato, dove ho usato Node-Red per leggere i messaggi inviati da Arduino al mio Broker MQTT installato sul Raspberry Pi 4.

Ora siamo davvero pronti ad affrontare il nostro primo progetto con i PIR, siamo in grado di catturare il segnale che ci indica che un movimento è stato rilevato, e siamo anche capaci di notificare questo via rete ad un Broker MQTT!

 

Nessun commento

Aggiungi il tuo commento