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):

[sourcecode language=”c” wraplines=”true” collapse=”true”]
/* #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(" ");
}
[/sourcecode]

A breve, un video dimostrativo del progetto.

Lascia un commento