Un allarme fai-da-te [ver.3]

In questo breve articolo vedremo come costruire un allarme domestico con Arduino utilizzando i più svariati componenti di cui dispongo.

In particolare, ho elaborato un modello semplice di allarme che viene azionato con due differenti modalità:

  • la prima consiste nel rilevamento di un qualunque movimento nel raggio d’azione del sensore ad infrarossi PIR (motion sensor);
  • la seconda,  invece, si basa su una semplice lettura della luminosità su un foto-resistore (LDR), verso il quale è direzionato il fascio luminoso di un mini-laser (creando così una sorta di “fotocellula”, come quelle situate dinanzi ai cancelli automatici) e, nel momento in cui un oggetto intralcia la traiettoria “laser-ldr”, il sistema reagisce.

In risposta all’allarme, il modello emetterà un suono dallo speaker (che dovrebbe imitare un effetto sirena) e, contemporaneamente, un LED rosso inizierà a lampeggiare. Inoltre, l’intero sistema di allarme è attivabile e disattivabile tramite la pressione di opportuni tasti di un telecomando ad infrarossi. Il sistema terrà anche un conteggio degli allarmi scattati.

Tutte le procedure di inserimento, disinnesco e conteggio dell’allarme sono guidate da un testo mostrato sul display LCD che indica lo stato attuale del sistema e, nella seconda riga, il giorno e l’ora attuali (a questo scopo, mi sono servito di un modulo RTC per avere dati sempre aggiornati al secondo, anche con alimentazione scollegata).

p.s. sono ancora i miei primi approcci con Arduino, pertanto, se dovessi risultare poco chiaro nella spiegazione, sono contento di dare ulteriori chiarimenti nei commenti a questo post. 🙂

Componenti utilizzati:

Arduino UNO, breadboards e cavi di collegamento

  • 1x sensore per rilevamento dei movimenti a infrarossi (PIR)
  • 1x RealTimeClock (RTC)
  • 1x LED rosso
  • 1x speaker piezoelettrico (buzzer)
  • 1x display LCD + Keypad shield
  • 1x ricevitore segnali ad infrarossi (IR-remote) + Telecomando
  • 1x mini laser 5mW
  • 1x foto-resistore (LDR)
  • 2x resistori (220 e 100 ohm)

– input –

  1. un movimento nel raggio d’azione del sensore per il rilevamento dei movimenti, oppure
  2. un ostacolo nella traiettoria di proiezione del raggio mini-laser sul foto-resistore

– output –

  1. led-blinking
  2. riproduzione di una sirena dallo speaker
  3. messaggio sul display

Altre funzionalità:

  • esecuzione guidata di ogni procedura grazie alle informazioni visualizzate sul display LCD.
  • inserimento/disattivazione dell’allarme dal telecomando tramite i pulsanti 1 e 2 rispettivamente.
  • visualizzazione del numero di allarmi già registrati alla pressione del pulsante 3.
N.B.: Questo progetto nasce come ” versione aggiornata” di una precedente revisione.
 

IMG_20140726_191915


Codice sorgente (ver.3):

/* #rogosprojects
#  Realizzazione di un allarme fai-da-te (ver.3)
#
#  Creato il 25/07/14
#  Autore: Gianmarco Rogo
#  https://plus.google.com/+GianmarcoRogo
*/

//inclusione librerie
#include <LiquidCrystal.h>    //display
#include <IRremote.h>        //telecomando
#include <Wire.h>            //RealTimeClock
#include "RTClib.h"          //RealTimeClock

int RECV_PIN = 10;    //collegamento uscita digitale ricevitore al pin 10
//configurazione ricevitore IR
IRrecv irrecv(RECV_PIN);
decode_results results;

//configurazione RTC
RTC_DS1307 rtc;

//configurazione crepuscolare
int laserCrep = A3;           //collegamento uscita analogica crepuscolare al pin A3
int crepValue = 0;            //valore iniziale di lettura
int soglia;                   //soglia crepuscolare
boolean crepuscON;
int minilaser= 12;            //collegamento mini-laser al pin 12

//configurazione pannello LCD
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);  //collegamento dei pin 8,9,4,5,6,7

boolean ALattivo = false;         //l'allarme è attivato o disattivato? (in base alla pressione del telecomando)

int cont_alarm =0;          //contatore allarmi attivati. 0 = l'allarme non è mai scattato

int ledPin = 13;                //LED al pin 13
int PIR = 2;               //sensore di movimenti (PIR) al pin 2
int PIRvar;                //movimento rilevato? 1= si, 0= no
int pinSpeaker = 11;       //collegamento speaker piezoelettrico al pin 11
int varLCD;                //variabile utilizzata per l'LCD

//_________________________________________________________________________________________
void setup() {
  pinMode(PIR, INPUT);
  pinMode(ledPin, OUTPUT);
  pinMode(pinSpeaker, OUTPUT);
  pinMode(minilaser, OUTPUT);

  Serial.begin(9600);

//crepuscolare
digitalWrite(minilaser, HIGH);      //accensione mini-laser -> proiezione del fascio sul fotoresistore per successiva calibrazione (..)

//Telecomando
  irrecv.enableIRIn();     //avvia il ricevitore IR

//LCD
  varLCD=0;           //0= LCD avviato per la prima volta
  lcd.begin(16, 2);  //dichiaro 16 colonne e 2 righe per l'LCD

//configurazione RTC
#ifdef AVR
  Wire.begin();
#else
  Wire1.begin();
#endif
  rtc.begin();

  if (! rtc.isrunning()) {    //seguqendo questa procedura, il programma imposta l'ora e la data al tempo di compilazione (se non già fatto precedenemente)
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }

 delay(500); 

 //configurazione crepuscolare
 soglia = analogRead(laserCrep)+20;  //(..) Calibrazione: imposta il valore soglia al valore di luminosità attualmente rilevato (con 20 punti di tolleranza)
 delay(500);
 digitalWrite(minilaser, LOW);      //spegne il mini-laser una volta completata la calibrazione
}

//_________________________________________________________________________________________
void loop(){

  //configurazione RTC
    DateTime now = rtc.now();

  PIRvar= digitalRead(PIR);    //PIRvar memorizza ogni movimento rilevato dal sensore PIR: 1=movimento

  //LCD
  printTime();      //funzione di stampa a video dell'orario e data attuali (aggiornata costantemente)
  printState();    //identifica lo stato attuale dell'allarme (attivo, spento, allarmato, ..) e lo stampa a video

  //telecomando
  if (irrecv.decode(&results)) {  //inizializza il ricevitore IR per accettare i segnali esterni

   if (results.value == 16724175){    //pressione del tasto 1
     digitalWrite(minilaser, HIGH);    //accensione mini-laser per future rilevazioni di cambiamento di luminosità
      delay(500);
      ALattivo = true;                  //attiva allarme
      varLCD=1;                          //salta a printState()

   } else if (results.value == 16718055){    //pressione del tasto 2
      digitalWrite(minilaser, LOW);
      ALattivo = false;                        //disattiva allarme
      varLCD=0;                                //salta a printState()

    } else if (results.value == 16743045){    //pressione del tasto 3
      varLCD=3;                                //salta a printState()
      }
 irrecv.resume();                           //abilita il ricevitore IR ad accettare un nuovo segnale in ingresso
 }

  //crepuscolare
crepValue=analogRead(laserCrep);
 if(crepValue>soglia){    //se il crepuscolare nota un cambio di luminosità -> scatta l'allarme
     crepuscON= true;
          }
    else{
      crepuscON= false;
          }

//esecuzione del programma antifurto 

if(ALattivo){                             //l'allarme è attivo?

    if (PIRvar==1 || crepuscON){          //il crepuscolare o il sensore PIR fanno scattare l'allarme
      varLCD=4;                            //salta a printState()
      printState();
      cont_alarm++;                        //contatore degli allarmi
  }
}

delay(500);
}

//funzione per riproduzione del segnale sonoro dallo speaker
void playTone(long duration, int freq) {
    duration *= 1000;
    int period = (1.0 / freq) * 1000000;
    long elapsed_time = 0;
    while (elapsed_time < duration) {
        digitalWrite(pinSpeaker,HIGH);
        delayMicroseconds(period / 2);
        digitalWrite(pinSpeaker, LOW);
        delayMicroseconds(period / 2);
        elapsed_time += (period);
    }
  }

//funzione per far lampeggiare il led 2 volte
void ledblink(){
  for (int blk=0; blk<1; blk++){
    digitalWrite(ledPin, HIGH);   // turn the LED on (HIGH is the voltage level)
    delay(100);               // wait for a second
    digitalWrite(ledPin, LOW);    // turn the LED off by making the voltage LOW
    delay(100);
  }
}

//stampa dell'ora sulla riga 2 del display
void printTime(){
  DateTime now = rtc.now();    

  lcd.setCursor(0, 1);
          if (now.day()< 10){
            lcd.print(" ");
            lcd.print(now.day(), DEC);
            } else {
              lcd.print(now.day(), DEC);
            }
            lcd.print('/');

          if (now.month() < 10){
            lcd.print("0");
            lcd.print(now.month(), DEC);
            } else {
              lcd.print(now.month(), DEC);
            }
            lcd.print(' ');

          if (now.hour()< 10){
            lcd.print(" ");
            lcd.print(now.hour(), DEC);
            } else {
              lcd.print(now.hour(), DEC);
            }
            lcd.print(':');

          if (now.minute() < 10){ //my fix
            lcd.print("0");
            lcd.print(now.minute(), DEC);
            } else {
              lcd.print(now.minute(), DEC);
              }
          lcd.print(':');
          lcd.print(now.second(), DEC);
          lcd.print(" ");
}

//funzione per il controllo dello stato dell'allarme sulla riga 1 dell'LCD
void printState(){
  switch(varLCD){
    case 0:
        clearL(0);
        lcd.setCursor(1, 0);
        lcd.print("Allarme spento");
        varLCD=9;
        break;
     case 1:
        clearL(0);
        lcd.setCursor(1, 0);
        lcd.print("Allarme attivo");
        varLCD=9;
        break;
     case 3:        //direttamente al caso 3
        clearL(0);
        lcd.setCursor(1, 0);
        lcd.print("Allarmi: #");
        lcd.print(cont_alarm);
        delay(400);
        if (ALattivo){
          varLCD=1;   }
          else {
          varLCD=0;   }
         break;
     case 4:      //movitmento rilevato
       for (int i=0; i<3; i++){
          playTone(300,1000);
          ledblink();
          clearL(0);
          lcd.setCursor(1, 0);
          lcd.print("!! ALLARME !!");
          delay(200);
        }
       varLCD=1;
       break;
     case 9:
       break;
  }
}

//funzione per la puliziare della sola riga X del display
void clearL(int line) {
lcd.setCursor(0,line), lcd.print("                ");
}

A breve, un video dimostrativo del progetto.

Annunci

Rispondi

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione /  Modifica )

Google photo

Stai commentando usando il tuo account Google. Chiudi sessione /  Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione /  Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione /  Modifica )

Connessione a %s...