Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Sistema di videosorveglianza
comandato da Arduino Mega 2560
Docente:
Prof. Ing. Nicola Ivan Giannoccaro
22/04/2016
Generalit
Il lavoro danno inerente il corso di Meccatronica consiste in un
sistema di videosorveglianza comandato per mezzo della scheda
programmabile Arduino Mega 2560. Tale sistema dallarme si
avvale di sensori di rilevamento di tipo PIR per lindividuazione di
eventuali infrazioni allinterno di ununit abitativa, che attivano dei
dispositivi acustici e luminosi dallarme. La sua
attivazione/disattivazione avviene per mezzo dell inserimento di
unapposita password tramite tastierino numerico. Le informazioni
relative al sistema dallarme sono visualizzate a mezzo di schermo
LCD .
a)
b)
c)
c) Schermo LCD 20 x 4
d)
d) Orologio (RTC)
e)
e) Tastiera numerica 4 x 4
f) Servo motore
f)
b)
c)
d)
e)
f)
Microcontrollore:
Tensione di lavoro:
Tensione di input (consigliata):
Tensione di input (limite):
Pin digitali I/O:
Pin di input analogici:
Corrente continua per i Pin I/O:
Corrente continua per i Pin a 3.3 V:
Memoria Flash:
SRAM:
EEPROM:
Frequenza di Clock:
Lunghezza:
Larghezza:
Peso:
ATmega2560, 8bit
5V
7-12 V
6-20 V
54
16
20 mA
50 mA
256 kB
8 kB
4 kB
16 MHz
101,52 mm
53,3 mm
37 g
Pulsante di reset
a)
b)
c)
c) Schermo LCD 20 x 4
d)
d) Orologio (RTC)
e)
e) Tastiera numerica 4 x 4
f) Servo motore
f)
a)
Principio fisico
Un sensore infrarossi passivo (PIR) un sensore elettronico in
grado di rilevare i raggi infrarossi (IR) irradiati dagli oggetti nel suo
campo di vista. Tutti gli oggetti con temperatura superiore allo zero
assoluto emettono energia sotto forma di radiazioni luminose. La
maggior parte delle volte queste radiazioni sono invisibili allocchio
umano, poich a frequenza inferiore a quella della luce dello
spettro visibile, ma possono essere rilevate tramite specifici
dispositivi elettronici progettati a tal scopo.
Il termine passivo si riferisce al fatto che i PIR non emettono
energia, ma lavorano esclusivamente rilevando lenergia irradiata
dagli oggetti. Allinterno di un PIR presente un sensore di
materiale piroelettrico, in grado cio di accumulare cariche
elettriche di segno opposto sulle facce opposte di certi cristalli
(nitruro di Gallio, nitruro di Cesio) in risposta ad un cambiamento di
temperatura.
Questi sensori sono molto usati come rilevatori di movimento.
c)
d)
e)
f)
Tensione di funzionamento:
Corrente di riposo:
Range di rilevamento:
Livello di uscita:
Tempo di attesa:
Angolo di rilevamento:
Misura della lente del sensore:
Temperatura di funzionamento:
Dimensioni scheda:
Peso:
4.5 ~ 20Vcc
<50uA
0~7m
alto 3,3V / basso 0V
5-200s (regolabile)
<100
diametro 23 mm
-15/ +70 C
32 x 24 x 2 mm
6g
GND
Regolatore 3V DC
Sensibilit
Tempo di attesa
Digital OUT
Pin 7-9
3-5V DC
Dichiarazione variabili:
int Pir_garage = 9;
int Pir_caveau= 7;
Void setup:
pinMode(Pir_garage, INPUT);
pinMode(Pir_caveau, INPUT);
Void loop:
Serial.println(digitalRead(Pir_garage));
Serial.println(digitalRead(Pir_caveau));
if (digitalRead(Pir_garage) == HIGH)
{
zone = 0;
alarmTriggered();
}
if (digitalRead(Pir_caveau) == HIGH)
{
zone = 3;
alarmTriggered();
}
a)
b)
c)
c) Schermo LCD 20 x 4
d)
d) Orologio (RTC)
e)
e) Tastiera numerica 4 x 4
f) Servo motore
f)
c) Schermo LCD 20 x 4
Il Dislay LCD un interessante strumento, utile
per interfacciare il mondo digitale con quello
umano. Con questo strumento, sar possibile
leggere unit fisiche, come il rilevamento da parte
del PIR, lora, lo stato di accensione di un LED,
oppure potremmo comporre testo, scritte
scorrevoli e tanto altro ancora.
In commercio ne esistono di diversi tipi e modelli.
Questo in figura un display LCD retroilluminato 4
x 20 a 16 contatti. La luminosit viene regolata
agendo sul pin 15 e 16.
a)
b)
d)
e)
f)
c) Schermo LCD 20 x 4
Collegamenti
I display a matrice di punti utilizzano un protocollo
comune basato sul chip HD44780 prodotto dalla Hitachi.
Sono formati da diverse righe ed i valori tipici vengono
espressi nella forma COLONNE x RIGHE, nel caso in
esame il display un 20 x 4, quindi composto da 20
colonne per ognuna delle 4 righe.
Linterfaccia per poter inviare i comandi ed i dati di tipo
parallelo, composta da 16 pin.
La piedinatura riportata accanto ha ordine e significato
ben precisi.
N Pin
Simbolo
Descrizione
Vss
Vcc
Vee
RS
2 Vcc
R/W
DB0
DB1
DB2
10
DB3
11
DB4
12
DB5
13
DB6
14
DB7
3 Vee
4 RS
5 R/W
6 E
7 DB0
8 DB1
9 DB2
10 DB3
11 DB4
12 DB5
13 DB6
14 DB7
15 LED+
16 LED-
15
LED+
16
LED-
1 Vss
c) Schermo LCD 20 x 4
Collegamenti
I pin Data servono per inviare un byte al chip del display. Il
valore inviato pu essere interpretato sia come comando
(ad esempio per spostare il cursore, per posizionarsi su
una riga specifica, per pulire il display) sia un valore ASCII
da scrivere sulla matrice. La scelta tra comando e carattere
ASCII viene gestita dal livello logico posto sul pin RS.
Il pin E abilita lesecuzione del comando o la scrittura sulla
matrice.
Nello schema desempio accanto, si nota che i Data Pin
non sono collegati completamente ma vengono utilizzati
solo i bit pi significativi (bus line 4, 5, 6, 7). Questa
peculiarit possibile poich il display supporta la
modalit a 4 bit, che essendo implementata anche dalla
libreria LiquidCristal, fa in modo di usare solo 4
collegamenti piuttosto che 8.
Librerie:
#include <LiquidCrystal.h>
Inclusione della libreria per il display LCD.
LiquidCrystal lcd(12,11, 5, 4, 3, 2); Assegnazione dei pin di collegamento sulla scheda Arduino.
Void setup:
lcd.begin(20, 4);
Void loop:
lcd.clear();
lcd.setCursor(0,0);
lcd.print("INFRAZIONE RILEVATA!");
lcd.setCursor(7,1);
if(zone == 0){
lcd.print("Garage");
lcd.setCursor(0,3);
lcd.print("ULT.INF.");
else if(zone == 3){
lcd.print("Caveau");
lcd.setCursor(0,3);
lcd.print("ULT.INF.");
Void Schermata_iniziale:
lcd.clear();
lcd.setCursor(0,3);
lcd.print("Inserire PIN:");
lcd.setCursor(1,0);
lcd.print("Video sorveglianza");
lcd.setCursor(4,1);
lcd.print("Casa Laplace");
a)
b)
c)
c) Schermo LCD 20 x 4
d)
d) Orologio (RTC)
e)
e) Tastiera numerica 4 x 4
f) Servo motore
f)
d) Orologio (RTC)
Un real-time clock (RTC), o orologio in tempo reale, un
dispositivo con funzione di orologio, solitamente
costituito da un processore a circuito integrato, in grado
di scandire il tempo (anno, mese, giorno, ore, minuti e
secondi) anche nel caso di utilizzatore spento. Viene
usato in molti campi dellelettronica ed presente in tutti
i moderni PC. Il modello utilizzato nel presente progetto
il DS1307 di Maxim.
Questo modello possiede la caratteristica di essere molto
preciso grazie alla presenza di un oscillatore a
temperatura controllata ed il rispettivo sensore di
temperatura, utilizzato per compensare la frequenza di
oscillazione.
a)
b)
c)
e)
f)
d) Orologio (RTC)
Principio di funzionamento
I microcontrollori funzionano grazie ad una sorgente di clock che
permette di temporizzare e sincronizzare tutti i moduli che lo
compongono. Il clock un segnale con frequenza fissa e stabile
tipicamente prodotta da un oscillatore al quarzo. Questo segnale
la base per tutte quelle applicazioni che devono gestire date e
orari. In effetti esistono molte applicazioni in cui la gestione del
tempo il fattore principale, come ad esempio tutti gli
automatismi attivati in funzione dellora e della data corrente o
che devono compiere delle azioni cicliche.
La gestione del tempo viene affidata a librerie esterne allArduino
IDE, quella impiegata nel progetto denominata Arduino Time.
Questa libreria contiene le classi Time, TimeAlarms e DS1307RTC,
con cui stato possibile avere controllo pressoch completo sulla
data e sullorario.
La sorgente di clock alla base della generazione del dato di tempo
pu essere quella interna al microcontrollore oppure quella
gestita da un circuito esterno, tipicamente chiamato Real Time
Clock (RTC) come lintegrato DS1307.
d) Orologio (RTC)
Collegamenti
Nel caso dellRTC , i Pin 20 e 21 non hanno bisogno di essere
dichiarati, sufficiente collegarli direttamente alle porte SDA
ed SDC.
Librerie:
#include <Wire.h>
#include "RTClib.h
RTC_DS1307 RTC;
Void setup:
Wire.begin();
RTC.begin();
if (! RTC.isrunning()) {
RTC.adjust(DateTime(__DATE__, __TIME__)); }
Void loop:
DateTime now = RTC.now();
lcd.setCursor(0,2);
if(now.day()<10)lcd.print(0);
lcd.print(now.day(),DEC);
lcd.print("/");
if(now.month()<10)lcd.print(0);
lcd.print(now.month(),DEC);
lcd.print("/");
lcd.print(now.year(),DEC);
lcd.setCursor(12,2);
if(now.hour()<10)lcd.print(0);
lcd.print(now.hour(),DEC);
lcd.print(":");
if(now.minute()<10)lcd.print(0);
lcd.print(now.minute(),DEC);
lcd.print(":");
if(now.second()<10)lcd.print(0);
lcd.print(now.second(),DEC);
Void alarm_Triggered:
lcd.print("ULT.INF.");
Comandi per la lettura di data e ora da RTC e conseguente stampa a video su display LCD.
I cicli IF sono stati utilizzati per la corretta visualizzazione a due digit di data e ora.
La presente stringa, seguita dal codice sopracitato, stata utilizzata per la stampa a video di data e ora dellultima infrazione rilevata.
a)
b)
c)
c) Schermo LCD 20 x 4
d)
d) Orologio (RTC)
e)
e) Tastiera numerica 4 x 4
f) Servo motore
f)
e) Tastiera numerica 4 x 4
Il tastierino numerico una periferica di input.
Per il sistema di video sorveglienza stato impiegato il
modello a matrice 4 x 4.
La sua struttura permette di verificare facilmente con
lausilio di un microcontrollore quale dei tasti sia stato
digitato tramite la lettura dei pin di output del
tastierino stesso.
Il tastierino accanto ha un totale di 16 tasti e presenta
unuscita con 8 pin che permettono la lettura della
matrice righe/colonne.
a)
b)
c)
d)
f)
e) Tastiera numerica 4 x 4
Layout tastiera
Riga/Colonna
Tasti collegati
Pin
Colonna 1
14-7-*
Colonna 2
2-5-8-0
Colonna 3
3-6-9-#
Colonna 4
A-B-CD
Riga 1
1-2-3-A
Riga 2
4-5-6-B
Riga 3
7-8-9-C
Riga 4
*-0-#-D
Librerie:
#include <Keypad.h>
const byte RIGHE = 4;
const byte COLONNE = 4;
char tasti[RIGHE][COLONNE] = {
{ '1','2','3','A' } ,
{ '4','5','6','B' } ,
{ '7','8','9','C' } ,
{ '*','0','#','D' }};
byte rowPins[RIGHE] = { 22, 23, 24, 25};
byte colPins[COLONNE] = { 26, 27, 28, 29};
if(passwd_pos>20)
{ passwd_pos = 15;
Ciclo IF di controllo del numero di caratteri della password inseriti. Se la condizione verificata, si ha il reset della password e la
invalidCode2();
visualizzazione della schermata iniziale.
passwd_pos = 15;
break; }
switch (eKey){
case '#':
passwd_pos = 15;
checkPassword();
break;
Ciclo Switch-Case per la conferma (#) e successivo controllo, o cancellazione(*) della
case '*':
password inserita.
passwd_pos = 15;//* resetta la password
invalidCode2();
passwd_pos = 15;
break;}
a)
b)
c)
c) Schermo LCD 20 x 4
d)
d) Orologio (RTC)
e)
e) Tastiera numerica 4 x 4
f) Servo motore
f)
f) Servo motore
a)
b)
c)
d)
Arduino dispone, secondo i modelli, di
uscite PWM ossia pin digitali in grado
di generare un duty-cycle utilizzabile
per far muovere un servo. Il modo pi
semplice per pilotare i servomotori
utilizzare una libreria che traduca
angoli in segnali ed evitare di
impiegare i duty-cycle e i relativi calcoli
dei tempi. La libreria in questione e la
Servo.
e)
Void setup:
myservo.attach(8);
myservo.write(pos);
Void alarm_triggered:
int Posizione_servo;
int incr;
Posizione_servo = 60;
Posizione_servo = 120;
Ciclo IF di controllo della posizione del servomotore rispetto alla posizione iniziale e
conseguente assegnazione del valore della variabile " incr ".
a)
b)
c)
c) Schermo LCD 20 x 4
d)
d) Orologio (RTC)
e)
e) Tastiera numerica 4 x 4
f) Servo motore
f)
Flow Chart
void setup(){
Serial.begin(9600);
lcd.begin(20, 4);
Wire.begin();
RTC.begin();
if (! RTC.isrunning()) {
RTC.adjust(DateTime(__DATE__, __TIME__));
}
myservo.attach(8);
Schermata_iniziale();
pinMode(redPin, OUTPUT);
pinMode(bluePin, OUTPUT);
pinMode(redLED, OUTPUT);
pinMode(greenLED, OUTPUT);
pinMode(speakerPin, OUTPUT);
pinMode(Led_garage, OUTPUT);
pinMode(Led_caveau, OUTPUT);
pinMode(Pir_garage, INPUT);
pinMode(Pir_caveau, INPUT);
digitalWrite(redLED, LOW);
digitalWrite(greenLED, HIGH);
keypad.addEventListener(keypadEvent);
myservo.write(pos);
}
void Schermata_iniziale(){
Serial.begin(9600);
lcd.clear();
lcd.begin(20, 4);
lcd.setCursor(0,3);
Wire.begin();
lcd.print("Inserire PIN:");
RTC.begin();
lcd.setCursor(1,0);
if (! RTC.isrunning()) {
lcd.print("Video
sorveglianza");
RTC.adjust(DateTime(__DATE__, __TIME__));
}
myservo.attach(8);
Schermata_iniziale();
pinMode(redPin, OUTPUT);
pinMode(bluePin, OUTPUT);
pinMode(redLED, OUTPUT);
pinMode(greenLED, OUTPUT);
pinMode(speakerPin, OUTPUT);
pinMode(Led_garage, OUTPUT);
pinMode(Led_caveau, OUTPUT);
pinMode(Pir_garage, INPUT);
pinMode(Pir_caveau, INPUT);
digitalWrite(redLED, LOW);
digitalWrite(greenLED, HIGH);
keypad.addEventListener(keypadEvent);
myservo.write(pos);
}
switch (keypad.getState()){
case PRESSED:
lcd.setCursor((passwd_pos++),3);
if(passwd_pos>20){
void invalidCode2(){
passwd_pos = 15;
password.reset();
invalidCode2();
lcd.clear();
passwd_pos = 15;
Schermata_iniziale();
lcd.setCursor(4,1);
break;
lcd.print("Casa Laplace");
switch (eKey){
case '#':
passwd_pos = 15;
checkPassword();
break;
case '*':
passwd_pos = 15;
invalidCode2();
passwd_pos = 15;
break;
default:
password.append(eKey);
lcd.print("*");
}
}
}
void invalidCode2(){
passwd_pos = 15;
password.reset();
invalidCode2();
lcd.clear();
passwd_pos = 15;
Schermata_iniziale();
break;
void checkPassword(){
if (password.evaluate()){
if(Allarme_attivo == 0 && Stato_allarme == 0){
}
switch (eKey){
activate();
case '#':
passwd_pos = 15;
checkPassword();
deactivate();
break;
}
}
case '*':
passwd_pos = 15;
else {
invalidCode2();
invalidCode();
passwd_pos = 15;
break;
default:
password.append(eKey);
lcd.print("*");
}
}
}
void activate(){
if((digitalRead(Pir_garage) == LOW) && (digitalRead(Pir_caveau) == LOW)){
digitalWrite(redLED, HIGH);
digitalWrite(greenLED, LOW);
digitalWrite(8, HIGH);
lcd.clear();
void checkPassword(){
void deactivate(){
lcd.setCursor(3,0);
if (password.evaluate()){
Stato_allarme = 0;
lcd.print("ALLARME ATTIVO");
digitalWrite(redLED, LOW);
Allarme_attivo = 1;
activate();
digitalWrite(greenLED, HIGH);
password.reset();
lcd.clear();
delay(2000);
void invalidCode(){
lcd.setCursor(0,0);
deactivate();
password.reset();
lcd.print("ALLARME DISATTIVATO");
lcd.clear();
digitalWrite(speakerPin, LOW);
deactivate();
lcd.setCursor(3,0);
Allarme_attivo = 0;
lcd.print("CODICE ERRATO");
password.reset();
invalidCode();
lcd.setCursor(1,1);
delay(5000);
lcd.print("REINSERIRE CODICE");
Schermata_iniziale();
digitalWrite(greenLED, LOW);
}
else {
digitalWrite(redLED, HIGH);
delay(2000);
digitalWrite(redLED, LOW);
delay(1000);
Schermata_iniziale();
else{
void loop(){
Serial.println(digitalRead(Pir_garage));
Serial.println(digitalRead(Pir_caveau));
lcd.setCursor(0,2);
if (Allarme_attivo == 1){
if(now.day()<10)lcd.print(0);
if (digitalRead(Pir_garage) == HIGH){
lcd.print(now.day(),DEC);
zone = 0;
lcd.print("/");
alarmTriggered();
if(now.month()<10)lcd.print(0);
lcd.print(now.month(),DEC);
if (digitalRead(Pir_caveau) == HIGH){
lcd.print("/");
zone = 3;
lcd.print(now.year(),DEC);
alarmTriggered();
lcd.setCursor(12,2);
if(now.hour()<10)lcd.print(0);
lcd.print(now.hour(),DEC);
lcd.print(":");
if(now.minute()<10)lcd.print(0);
lcd.print(now.minute(),DEC);
lcd.print(":");
if(now.second()<10)lcd.print(0);
lcd.print(now.second(),DEC);
keypad.getKey();
lcd.print(now.hour(),DEC);
void alarmTriggered(){
lcd.print(":");
Serial.println(digitalRead(Pir_garage));
int Posizione_servo;
if(now.minute()<10)lcd.print(0);
incr = 1;
Serial.println(digitalRead(Pir_caveau));
int incr;
lcd.print(now.minute(),DEC);
if (Allarme_attivo == 1){
digitalWrite(Led_garage, HIGH);
digitalWrite(redPin, HIGH);
delay(1000);
incr = -1;
zone = 0;
password.reset();
alarmTriggered();
Stato_allarme = 1;
lcd.clear();
Posizione_servo = 120;
myservo.write(pos);
lcd.setCursor(0,0);
lcd.print("Caveau");
delay(5);
zone = 3;
lcd.print("INFRAZIONE RILEVATA!");
lcd.setCursor(0,3);
alarmTriggered();
lcd.setCursor(7,1);
lcd.print("ULT.INF.");
if(zone == 0){
if(now.day()<10)lcd.print(0);
StrokeLight();
if (digitalRead(Pir_garage) == HIGH){
if (digitalRead(Pir_caveau) == HIGH){
else {
Posizione_servo = 60;
lcd.print(now.day(),DEC);
lcd.print("Garage");
lcd.print("/");
lcd.setCursor(0,3);
if(now.month()<10)lcd.print(0);
speaker();
lcd.print("ULT.INF.");
lcd.print(now.month(),DEC);
if(now.day()<10)lcd.print(0);
lcd.setCursor(15,3);
lcd.print(now.day(),DEC);
if(now.hour()<10)lcd.print(0);
digitalWrite(Led_garage, LOW);
lcd.print("/");
lcd.print(now.hour(),DEC);
digitalWrite(Led_caveau, LOW);
if(now.month()<10)lcd.print(0);
lcd.print(":");
lcd.print(now.month(),DEC);
if(now.minute()<10)lcd.print(0);
lcd.setCursor(15,3);
lcd.print(now.minute(),DEC);
if(now.hour()<10)lcd.print(0);
digitalWrite(Led_caveau, HIGH);
delay(1000);
}
void StrokeLight(){
digitalWrite(redPin, HIGH);
incr = 1;
delay(ledDelay);
digitalWrite(redPin, LOW);
delay(ledDelay);
else {
incr = -1;
digitalWrite(redPin, HIGH);
delay(ledDelay);
void speaker(){
digitalWrite(redPin, LOW);
for(t=0;t<3;t++){
delay(ledDelay);
for(i=0;i<350;i++){
delay(5);
digitalWrite(43,HIGH);
}
{
delay(1);
StrokeLight();
digitalWrite(43,LOW);
delay(1);
digitalWrite(redPin, HIGH);
delay(ledDelay);
digitalWrite(redPin, LOW);
delay(ledDelay);
delay(10);
speaker();
delay (50);
for(i=0;i<150;i++){
digitalWrite(bluePin, HIGH);
delay(ledDelay);
digitalWrite(bluePin, LOW);
delay(ledDelay);
digitalWrite(43,HIGH);
digitalWrite(bluePin, HIGH);
digitalWrite(Led_garage, LOW);
delay(2);
delay(ledDelay);
digitalWrite(Led_caveau, LOW);
digitalWrite(43,LOW);
digitalWrite(bluePin, LOW);
delay(2);
delay(ledDelay);
digitalWrite(bluePin, HIGH);
delay(50);
delay(ledDelay);
digitalWrite(bluePin, LOW);
delay(ledDelay);
}