- Modificato
Oggi vedremo come creare una cassaforte sfruttando il nostro Arduino e il Keypad!
La cassaforte appena accesa mostra il display LCD con un messaggio di benvenuto e chiede all'utente di inserire un nuovo codice di sicurezza.
L'utente inserisce il codice segreto utilizzando il tastierino. Dopo aver inserito il nuovo codice la cassaforte si blocca. "A" per inserire un nuovo pin e "#" per bloccare la cassaforte.
Materiali necessari:
- Arduino UNO
- Keypad
- LCD 16x2
- Resistenza da 220 ohm
- Servo motore
- Vari cavi
- Breadboard
Vediamo i vari collegamenti! Per quanto riguarda il Display LCD: RS (Register Select) deve essere collegato al pin 13, RS seleziona tra l'invio di comandi e i dati all'LCD.
E (Enable) al pin 12, abilita la ricezione dei comandi o dei dati inviati al display.
D4-D7 (dati) ai pin 11, 10, 9 e 8, trasmettono i dati al display per visualizzare caratteri, numeri e simboli.
VCC (Alimentazione) ai +5V e GND a terra.
Il tastierino ha in tutto 8 pin: 4 righe (Row Pins) ai pin digitali 5, 4, 3 e 2, vengono utilizzati per leggere le righe. Le 4 colonne (Col Pins) ai pin analogici A0, A1, A2 e A3, utilizzati per leggere le colonne.
Per il servo motore le prime due uscite vanno rispettivamente a GND e a +5V mentre l'uscita del segnale al pin 7.
Scriviamo il codice! Iniziamo con la funzione setup()
, inizializziamo l'LCD e del servo, il servo motore viene collegato al pin 7. Viene letto lo stato della memoria EEPROM, se lo stato è "bloccato" il servo motore viene posizionato in modo che sia chiuso altrimenti viene posizionato sullo stato aperto. Sempre nel setup viene scritto il messaggio di benvenuto.
Nel loop()
si verifica sempre se la cassaforte è sullo stato bloccato o sbloccato. Se lo stato è sulla logica del blocco, viene mostrato un messaggio sull'LCD indicando che la cassaforte è sbloccata, si verifica che il pin segreto è corretto ed è già presente nella memoria EEPROM. In caso affermativo viene data la possibilità di impostare un nuovo pin. Se l'utente vuole impostare un nuovo pin, inizialmente si richiede il precedente e se è presente in EEPROM verrà autorizzato altrimenti verrà visualizzato un messaggio di errore.
La funzione blocca()
ha il compito di posizionare il servo motore in modo che la cassaforte sia in blocco e aggiorna lo stato della sicurezza, simile a sblocca()
.
inserisciPin()
gestisce l'inserimento e restituisce il codice inserito come stringa.
disp_wait
restituisce a schermo l'attesa sul display LCD con una barra di caricamento.
new_Pin()
gestisce l'impostazione di un eventuale nuovo pin di sicurezza.
#include <LiquidCrystal.h>
#include <Keypad.h>
#include <Servo.h>
#include <Arduino.h>
#include <EEPROM.h>
/* meccanismo di blocco */
#define PIN_SERVO 7
#define POS_BLOCCATO 20
#define POS_SBLOCCATO 90
Servo servo;
/* Display */
LiquidCrystal lcd(13, 12, 11, 10, 9, 8);
/* tastierino */
const byte RIGHE_TASTIERA = 4;
const byte COLONNE_TASTIERA = 4;
byte pinRighe[RIGHE_TASTIERA] = {5, 4, 3, 2};
byte pinColonne[COLONNE_TASTIERA] = {A3, A2, A1, A0};
char tasti[RIGHE_TASTIERA][COLONNE_TASTIERA] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
Keypad tastiera = Keypad(makeKeymap(tasti), pinRighe, pinColonne, RIGHE_TASTIERA, COLONNE_TASTIERA);
#define I_B 0
#define I_L_C 1
#define I_C 2
#define V_VUOTO 0xff
#define S_APERTO (char)0
#define S_CHIUSO (char)1
class safe {
private:
bool bloccoAttivo;
public:
safe() {
this->bloccoAttivo = EEPROM.read(I_B) == S_CHIUSO;
}
void blocca() {
this->impostaBlocco(true);
}
bool statoBlocco() {
return this->bloccoAttivo;
}
bool PinPresente() {
auto lunghezzaPin = EEPROM.read(I_L_C);
return lunghezzaPin != V_VUOTO;
}
void impostaPin(String nuovoPin) {
EEPROM.write(I_L_C, nuovoPin.length());
for (byte i = 0; i < nuovoPin.length(); i++) {
EEPROM.write(I_C + i, nuovoPin[i]);
}
}
bool sblocca(String Pin) {
auto lunghezzaPin = EEPROM.read(I_L_C);
if (lunghezzaPin == V_VUOTO) {
// Non c'era alcun Pin, quindi lo sblocco avviene sempre
this->impostaBlocco(false);
return true;
}
if (Pin.length() != lunghezzaPin) {
return false;
}
for (byte i = 0; i < Pin.length(); i++) {
auto cifra = EEPROM.read(I_C + i);
if (cifra != Pin[i]) {
return false;
}
}
this->impostaBlocco(false);
return true;
}
void impostaBlocco(bool attivo) {
this->bloccoAttivo = attivo;
EEPROM.write(I_B, attivo ? S_CHIUSO : S_APERTO);
}
};
safe safe;
void blocca() {
servo.write(POS_BLOCCATO);
safe.blocca();
}
void sblocca() {
servo.write(POS_SBLOCCATO);
}
void restart_lobby() {
lcd.setCursor(4, 0);
lcd.print("Benvenuto!");
delay(1000);
lcd.setCursor(0, 2);
String messaggio = "Cassaforte EHF";
for (byte i = 0; i < messaggio.length(); i++) {
lcd.print(messaggio[i]);
delay(100);
}
delay(500);
}
String inserisciPin() {
lcd.setCursor(5, 1);
lcd.print("[____]");
lcd.setCursor(6, 1);
String risultato = "";
while (risultato.length() < 4) {
char tasto = tastiera.getKey();
if (tasto >= '0' && tasto <= '9') {
lcd.print('*');
risultato += tasto;
}
}
return risultato;
}
void disp_wait(int delayMillis) {
lcd.setCursor(2, 1);
lcd.print("[..........]");
lcd.setCursor(3, 1);
for (byte i = 0; i < 10; i++) {
delay(delayMillis);
lcd.print("=");
}
}
bool new_Pin() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" New pin: ");
String nuovoPin = inserisciPin();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Conferma");
String confermaPin = inserisciPin();
if (nuovoPin.equals(confermaPin)) {
safe.impostaPin(nuovoPin);
return true;
} else {
lcd.clear();
lcd.setCursor(1, 0);
lcd.print("Errore!");
lcd.setCursor(0, 1);
lcd.print("Sblocco");
delay(2000);
return false;
}
}
void unlock_text() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Sbloccato!");
delay(1000);
}
void unlock_safe() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Sbloccato!");
bool nuovoPinNecessario = true;
if (safe.PinPresente()) {
lcd.setCursor(0, 1);
lcd.print("New code");
nuovoPinNecessario = false;
}
auto tasto = tastiera.getKey();
while (tasto != 'A' && tasto != '#') {
tasto = tastiera.getKey();
}
bool ready_lock = true;
if (tasto == 'A' || nuovoPinNecessario) {
ready_lock = new_Pin();
}
if (ready_lock) {
lcd.clear();
lcd.setCursor(5, 0);
lcd.print("Bloccato!");
safe.blocca();
blocca();
disp_wait(100);
}
}
void logic_safelock() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Bloccato!");
String PinUtente = inserisciPin();
bool sbloccatoConSuccesso = safe.sblocca(PinUtente);
disp_wait(200);
if (sbloccatoConSuccesso) {
unlock_text();
sblocca();
} else {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Errore");
disp_wait(1000);
}
}
void setup() {
lcd.begin(16, 2);
servo.attach(PIN_SERVO);
/* verifica EEPROM */
Serial.begin(115200);
if (safe.statoBlocco()) {
blocca();
} else {
sblocca();
}
restart_lobby();
}
void loop() {
if (safe.statoBlocco()) {
logic_safelock();
} else {
unlock_safe();
}
}
Video funzionamento: