Tastiera apriporta con arduino
In questo articolo viene descritto un dispositivo in grado di azionare un relè se viene digitata una corretta sequenza numerica su una tastiera. L’utilizzo è stato pensato come apriporta, ma non si vogliono porre limiti alla fantasia. Il codice, per un massimo di 20 cifre, può essere cambiato in qualsiasi momento tramite procedura direttamente dalla stessa tastiera e viene memorizzato nella memoria non volatile di un Arduino utilizzante un processore atmel 328 (arduino 1, nano, mini ….) funzionante a 5V. Se non si ricorda più la combinazione, un pulsante, che non deve essere accessibile esternamente, resetterà il dispositivo ad un valore prestabilito.
E’ possibile inserire, come opzione, un display a 7 segmenti per visualizzare il tasto premuto.
Un led, che segnala anche se il dispositivo è attivo, è previsto come aiuto nella digitazione.
Il numero dei componenti è minimo. Nel caso di un apriporta con serratura elettrica a 12 V alternati, si può prelevare questa tensione direttamente dal trasformatore o dal citofono per alimentare il circuito.
Il consumo è ridotto alle decine di milliampere come massimo. La tastiera può essere autocostruita. Nel prototipo e sul definitivo ho preferito usare una tastiera a matrice ultrapiatta con adesivo. E’ fatta per l’uso in ambiente esterno e si trova nel WEB a basso costo.
In aggiunta al relè, in parallelo e all’occorrenza, si può abbinare un buzzer piezoelettrico autooscillante per evidenziare l’attivazione.
FUNZIONAMENTO:
Il led si accende con un lampeggio ogni 6 secondi circa. Dopo circa 10 sec di inattività si resettano tutte le operazioni intraprese se non portate a termine.
Digitare il codice giusto e attendere 2 sec per apertura (sicurezza di codice corretto e conosciuto) – il LED lampeggia 3 volte e sul display appare il simbolo H. La durata della attivazione del relè puo essere definita cambiando il valore temporele in millisecondi
CAMBIO PASSWORD: premere il tasto # per 3 sec. Il LED si accende fisso per 2 sec. Appena spento, digitare il codice CORRENTE. Se è giusto si attiva la chiave (come aver digitato codice per apertura) e il LED inizia a lampeggiare velocemente. Attendere la fine del lampeggio ed inserire il nuovo codice. Confermare tenendo premuto per 3 sec (fino a che la luce non diventa fissa) il tasto #
il codice resta memorizzato.
RESET codice: tenendo premuto il trasto reset per almeno 3 secondi inizierà sul display un conto alla rovescia che azzera il codice e lo riporta al valore iniziale 25122000 (Natale 2000)

SKETCH:
/*
by Roberto Contessi - luglio 2013
Chiave elettronica con memorizzazione del codice anche senza alimentazione
tastiera :
3 colonne facenti capo a: 7 8 9
piedino 2 per la colonna con n. 1 4 5 6
piedino 3 per la colonna con n. 2 1 2 3
piedino 4 per la colonna con n. 3 R 0 #
piedino A2 per la riga con il 7
piedino A1 per la riga con il 4
piedino A0 per la riga con il 1
piedino A3 per la riga con il R
reset codici al codice di partenza --> 25122000 (Natale 2000)
tramite tasto collegato a A4
Piedino 5-11 da collegarsi ad un display 7 segmenti opzionale
piedino 13 led di verifica operazioni collegato ad un led alta efficienza
comando per azionamento rele' sul piedino 12 con definizione di temporele come tempo di attuazione rele in millisec
FUNZIONAMENTO:
Il led si accende con un lampeggio ogni 6 secondi circa.
digitare il codice giusto e attendere 2 sec per apertura (sicurezza di codice corretto e conosciuto)
il LED lampeggia 3 volte.
dopo circa 10 sec di inattività si resettano le operazioni intraprese.
CAMBIO PASSWORD: premere # per 3 sec il LED si accende fisso per 2 sec ALLA FINE del lampeggio ed entro 10 sec
digitare il codice CORRENTE. Se è giusto si attiva la chiave (come aver digitato codice per apertura) e il LED inizia a
lampeggiare velocemente per 3 sec. Attendere la fine del lampeggio ed inserire il nuovo codice.
Confermare tenendo premuto per 3 sec (fino a che la luce non diventa fissa) il tasto #
il codice resta memorizzato.
RESET codice: tenendo premuto il trasto reset per almeno 3 secondi inizierà sul display un conto alla rovescia che azzera il
codice e lo riporta al valore iniziale 25122000.
*/
#include <EEPROM.h>
// variabili di collegamento dei fili a piedini di arduino
// segmentoA-G = segmenti del display display
// Tastiera 3 colonne e 4 righe (vedi tastiera computer e non telefono)
// riga del 7, 4, 1, e ultima in basso tasto R o (*)
// colonna del 1, 2, 3
#define temporele 2000
#define segmentoA 5
#define segmentoB 6
#define segmentoC 7
#define segmentoD 8
#define segmentoE 9
#define segmentoF 11
#define segmentoG 10
int col1=2;
int col2=3;
int col3=4;
int riga7=A2;
int riga4=A1;
int riga1=A0;
int rigaR=A3;
int led=13;
int relay=12;
int tastoreset=A4;
// contatori al posto della funzione mills
long conta=0;
long tresec=0;
long tresec1=0;
long lampo=0;
long sicura=0;
int chiave[20]; // chiave
int accumulo[20]; // tentativo chiave
int nuova[20]; // nuova chiave
int pnu=0; // puntatore lunghezza chiave nuova
int punt=0; // puntatore del tentativo chiave
int pch=0; // puntatore lunghezza chiave
boolean bingo=LOW;
// boolean vai=HIGH;
int prog=0; // variabile che definisce stato di programmazione 0=normale 1=richiesta cambio password
int told=99; // variabile per vedere se il tasto premuto è lo stesso
// the setup routine runs once when you press reset:
void setup() {
// initialize the digital pin as an output.
pinMode(segmentoA, OUTPUT);
pinMode(segmentoB, OUTPUT);
pinMode(segmentoC, OUTPUT);
pinMode(segmentoD, OUTPUT);
pinMode(segmentoE, OUTPUT);
pinMode(segmentoF, OUTPUT);
pinMode(segmentoG, OUTPUT);
pinMode(col1, OUTPUT);
pinMode(col2, OUTPUT);
pinMode(col3, OUTPUT);
pinMode(riga7, INPUT);
pinMode(riga4, INPUT);
pinMode(riga1, INPUT);
pinMode(rigaR, INPUT);
pinMode(led,OUTPUT);
pinMode(relay,OUTPUT);
digitalWrite(relay,LOW);
pinMode(tastoreset,INPUT);
//pinMode(led1,OUTPUT);
digitalWrite(led,LOW);
//digitalWrite(led1,LOW);
delay(1000);
ntoBCD(99);
// settaggio della chiave invece che leggere da eeprom
pch=EEPROM.read(0);
// mai programmata inserisco la mia data di nascita come codice iniziale in eeprom
if (pch<50) { // massimo numero di caratteri = 50
for (int p=0; p<pch+1; p++) { // leggo la chiave
chiave[p]=EEPROM.read(p+1);
}
}
else { // mai scritta EEPROM --> valore FF
azzera_ee(); //azzera chiave
}
}
void loop() {
// alla lettura della tastiera se premuto un tasto
int t=99;
t=tastiera();
conta++;
lampo++;
//-------------------------------------------------------------- watch dogs
if (conta>200000){ // watch dogs --> reset per inutilizzo
conta=0;
punt=0;
pnu=0;
prog=0;
tresec=0;
digitalWrite(led,LOW);
}
// ------------------------------------------------------------- sempre lo stesso tasto premuto?
if (t==99 && told!=t) { // appena rilasciato il tasto
told=99; // riporto il vecchio valore a 99
tresec=0;
tresec1=0;
conta=0;
lampo=0;
}
//--------------------------------------------------------------- LAMPEGGIO LED IN STAND BY
if (lampo>60500){ // azzeramento lampeggio
digitalWrite(led,LOW);
lampo=0;
}
if (lampo==60000){ // LAMPEGGIO LED di presenza
digitalWrite(led,HIGH);
}
// -------------------------------------------------------------- ATTIVAZIONE CHIAVE
if (bingo && sicura<12000){ // CHIAVE CONFERMATA attesa fine sequenza 2 sec.
sicura++;
}
if (bingo && sicura>=12000){ // CHIAVE CONFERMATA Fine attesa --> attiva attuatore.
bingo=LOW;
punt=0;
sicura=0;
ntoBCD(10); // attivazione sul display simbolo apertura (H)
// lampeggio di avvertimento
for (int i=0;i<4;i++) {
digitalWrite(led,HIGH);
delay(60);
digitalWrite(led,LOW);
delay(60);
}
// Attivazione relay
digitalWrite(relay,HIGH);
delay(temporele);
digitalWrite(relay,LOW);
ntoBCD(99); // azzero display
// chiave confermata dopo richiesta di cambio password
if (prog==1) {
prog=2; //attivazione fase programmazione successiva
for (int i=0;i<6;i++){
digitalWrite(led,HIGH);
delay(60);
digitalWrite(led,LOW);
delay(60);
}
}
}
//--------------------------------------------------------------- RILEVAMENTO TASTI
if (t<10 && told!=t){ // E' stato premuto un tasto
// acquisisco numero digitato
told=t;
tresec1=0;
accumulo[punt]=t;
if (prog>1) { // creo nuova password fase di programmazione
nuova[pnu]=t;
pnu++;
}
// verifico se la sequenza è corretta
for (int i=0; i<=punt; i++){ // per tutti i caratteri accumulati
if (chiave[i]!=accumulo[i]){ // se non corrispondono i caratteri -> reset puntatori
bingo=LOW;
sicura=0;
punt=0;
accumulo[0]=55; // azzero primo carattere dell'array per verifica if sotto
}
}
if (pch == punt) {
// CHIAVE CONFERMATA CORRETTA
bingo=HIGH;
sicura=0;
}
if (chiave[punt]==accumulo[punt] && punt!=pch) punt++; // n corrispondenti aumento puntatore se sequenza non completa
}
// ---------------------------------------------------------- TASTO RESET PREMUTO
if (t==20){ //Tasto R reset
tresec1++;
conta=0;
if (tresec1>32000) { // partenza reset password
tresec1=0;
for (int i=9;i>-1;i--){
ntoBCD(i);
digitalWrite(led,LOW);
delay(100);
digitalWrite(led,HIGH);
delay(500);
}
ntoBCD(99);
// reset password a iniziale
azzera_ee(); //azzera chiave
prog=0;
pnu=0;
}
}
// ---------------------------------------------------------- TASTO #
if (t==12){ //Tasto # verificare se tenuto premuto per 3 secondi
tresec++;
if (tresec>25000){ // valore per cui si valida la pressione del tasto
tresec=0;
// -----------------------------------------------------
if (prog==0) prog=1; // prima fase del programma richiesta cambio password
// -----------------------------------------------------
if (prog==2){ // conferma pasasword
pnu--; // il contatore si è incrementato dopo l'ultimo numero ora è giusto
// qui scrivere il puntatore su EEPROM ************************************************************
EEPROM.write(0,pnu); // puntatore
for (int i=0; i<pnu+1; i++) { // nuovo array formato e pronto travaso su chiave
chiave[i]=nuova[i];
// qui scrivere la EEPROM **********************************************************************
EEPROM.write(i+1,chiave[i]); // scrivi su EEPROM
}
pch=pnu;
prog=0;
pnu=0;
}
// ----------------------------------------------------
ntoBCD(11);
digitalWrite(led,HIGH);
delay(2000);
ntoBCD(99);
digitalWrite(led,LOW);
}
}
}
// FUNZIONI
//----------------------------------------------------------------------------------
// Funzione che attiva il display
void ntoBCD(int x) {
switch (x) {
case 0:
digitalWrite(segmentoA,HIGH);
digitalWrite(segmentoB,HIGH);
digitalWrite(segmentoC,HIGH);
digitalWrite(segmentoD,HIGH);
digitalWrite(segmentoE,HIGH);
digitalWrite(segmentoF,HIGH);
digitalWrite(segmentoG,LOW);
break;
case 1:
digitalWrite(segmentoA,LOW);
digitalWrite(segmentoB,HIGH);
digitalWrite(segmentoC,HIGH);
digitalWrite(segmentoD,LOW);
digitalWrite(segmentoE,LOW);
digitalWrite(segmentoF,LOW);
digitalWrite(segmentoG,LOW);
break;
case 2:
digitalWrite(segmentoA,HIGH);
digitalWrite(segmentoB,HIGH);
digitalWrite(segmentoC,LOW);
digitalWrite(segmentoD,HIGH);
digitalWrite(segmentoE,HIGH);
digitalWrite(segmentoF,LOW);
digitalWrite(segmentoG,HIGH);
break;
case 3:
digitalWrite(segmentoA,HIGH);
digitalWrite(segmentoB,HIGH);
digitalWrite(segmentoC,HIGH);
digitalWrite(segmentoD,HIGH);
digitalWrite(segmentoE,LOW);
digitalWrite(segmentoF,LOW);
digitalWrite(segmentoG,HIGH);
break;
case 4:
digitalWrite(segmentoA,LOW);
digitalWrite(segmentoB,HIGH);
digitalWrite(segmentoC,HIGH);
digitalWrite(segmentoD,LOW);
digitalWrite(segmentoE,LOW);
digitalWrite(segmentoF,HIGH);
digitalWrite(segmentoG,HIGH);
break;
case 5:
digitalWrite(segmentoA,HIGH);
digitalWrite(segmentoB,LOW);
digitalWrite(segmentoC,HIGH);
digitalWrite(segmentoD,HIGH);
digitalWrite(segmentoE,LOW);
digitalWrite(segmentoF,HIGH);
digitalWrite(segmentoG,HIGH);
break;
case 6:
digitalWrite(segmentoA,HIGH);
digitalWrite(segmentoB,LOW);
digitalWrite(segmentoC,HIGH);
digitalWrite(segmentoD,HIGH);
digitalWrite(segmentoE,HIGH);
digitalWrite(segmentoF,HIGH);
digitalWrite(segmentoG,HIGH);
break;
case 7:
digitalWrite(segmentoA,HIGH);
digitalWrite(segmentoB,HIGH);
digitalWrite(segmentoC,HIGH);
digitalWrite(segmentoD,LOW);
digitalWrite(segmentoE,LOW);
digitalWrite(segmentoF,LOW);
digitalWrite(segmentoG,LOW);
break;
case 8:
digitalWrite(segmentoA,HIGH);
digitalWrite(segmentoB,HIGH);
digitalWrite(segmentoC,HIGH);
digitalWrite(segmentoD,HIGH);
digitalWrite(segmentoE,HIGH);
digitalWrite(segmentoF,HIGH);
digitalWrite(segmentoG,HIGH);
break;
case 9:
digitalWrite(segmentoA,HIGH);
digitalWrite(segmentoB,HIGH);
digitalWrite(segmentoC,HIGH);
digitalWrite(segmentoD,HIGH);
digitalWrite(segmentoE,LOW);
digitalWrite(segmentoF,HIGH);
digitalWrite(segmentoG,HIGH);
break;
case 10:
digitalWrite(segmentoA,LOW);
digitalWrite(segmentoB,HIGH);
digitalWrite(segmentoC,HIGH);
digitalWrite(segmentoD,LOW);
digitalWrite(segmentoE,HIGH);
digitalWrite(segmentoF,HIGH);
digitalWrite(segmentoG,HIGH);
break;
case 11:
digitalWrite(segmentoA,HIGH);
digitalWrite(segmentoB,LOW);
digitalWrite(segmentoC,LOW);
digitalWrite(segmentoD,HIGH);
digitalWrite(segmentoE,LOW);
digitalWrite(segmentoF,LOW);
digitalWrite(segmentoG,HIGH);
break;
default:
digitalWrite(segmentoA,LOW);
digitalWrite(segmentoB,LOW);
digitalWrite(segmentoC,LOW);
digitalWrite(segmentoD,LOW);
digitalWrite(segmentoE,LOW);
digitalWrite(segmentoF,LOW);
digitalWrite(segmentoG,LOW);
}
conta=0;
}
//----------------------------------------------------------------------------------
// Funzione che legge la tastiera - restituisce valore tasto
// 10 x R - 11 x #
int tastiera(){
int tasto=99;
digitalWrite(col1,HIGH);
if (digitalRead(riga7)) {tasto=7; goto finito;} // tasto 7
if (digitalRead(riga4)) {tasto=4; goto finito;} // tasto 4
if (digitalRead(riga1)) {tasto=1; goto finito;} // tasto 1
if (digitalRead(rigaR)) {tasto=11; goto finito;} // tasto R o *
digitalWrite(col1,LOW);
digitalWrite(col2,HIGH);
if (digitalRead(riga7)) {tasto=8; goto finito;} // tasto 8
if (digitalRead(riga4)) {tasto=5; goto finito;} // tasto 5
if (digitalRead(riga1)) {tasto=2; goto finito;} // tasto 2
if (digitalRead(rigaR)) {tasto=0; goto finito;} // tasto 0
digitalWrite(col2,LOW);
digitalWrite(col3,HIGH);
if (digitalRead(riga7)) {tasto=9; goto finito;} // tasto 9
if (digitalRead(riga4)) {tasto=6; goto finito;} // tasto 6
if (digitalRead(riga1)) {tasto=3; goto finito;} // tasto 3
if (digitalRead(rigaR)) tasto=12; // tasto #
finito:
digitalWrite(col1,LOW);
digitalWrite(col2,LOW);
digitalWrite(col3,LOW);
if (digitalRead(tastoreset)==LOW) {tasto=20;}
if (tasto<10){ // evita i rimbalzo del doppio numero e segnala tasto premuto
digitalWrite(led,HIGH);
ntoBCD(tasto); // visualizzo numero digitato
delay(120);
digitalWrite(led,LOW);
ntoBCD(99); // azzero display
}
return tasto;
}
// -----------------------------------------------------------------------------------
// Funzione scrittura EEPROM - Valore iniziale 25122000
void azzera_ee(){
EEPROM.write(0,7); // puntatore
EEPROM.write(1,2);
EEPROM.write(2,5);
EEPROM.write(3,1);
EEPROM.write(4,2);
EEPROM.write(5,2);
EEPROM.write(6,0);
EEPROM.write(7,0);
EEPROM.write(8,0);
pch=7; // lunghezza della chiave in caratteri -1 (parte da 0)
chiave[0]=2;
chiave[1]=5;
chiave[2]=1;
chiave[3]=2;
chiave[4]=2;
chiave[5]=0;
chiave[6]=0;
chiave[7]=0;
}
//-------------------------------------------------------------------------------------

