https://www.hackster.io/gavinchiong/digital-safe-box-rp2040-w5100s-fingerprint-part1-05082c
In Part 1 of the digital safe box project introduction, I introduced the previous project introduction, project preparation, functional testing, and shared the basic code framework. This week I completed the hardware welding and testing of this project, as well as the writing of the screen interface, the writing of the interaction logic, and the code debugging.
The safe box shell I designed is still made of PCB material, which is combined through a concave-convex structure. This is the designed PCB.
This is the final test before assembly after soldering the device.
This is the fully assembled safe box.
Finished all the debugging this week, and now follow part1 to explain the remaining part part2.
-------------------------------------------------------------------------
1. The Libraries and references-------------------------------------------------------------------------
I used arduino to develop this project, and arduino has various libraries that are very convenient for development and use. There are many libraries used in this project, as follows:
#include <SPI.h>
//SPI interface library used to connect W5100S of WIZNET
#include <Ethernet.h>
//Drive the Ethernet library of W5100S
#include <BlynkSimpleEthernet.h>
//Ethernet library used to communicate with BLYNK
#include <SoftwareSerial.h>
//The fingerprint identification module uses the software serial port library
#include <Wire.h>
//IIC interface library used to connect OLED screen
#include <Adafruit_GFX.h>
// The GFX library that drives the screen
#include <Adafruit_SH110X.h>
//OLED screen driver library
#include <Adafruit_Fingerprint.h>
//Driver library for fingerprint identification module
#include <Servo.h>
//Servo driver library
#include <EEPROM.h>
//EEPROM driver library
#include <WizFi360_arduino_library.h>
//Used to drive the WiFi module of Wizfi360
#include "TouchyTouch.h"
//Driver library for capacitive touch buttons
What needs special explanation is the library of the capacitive touch button "TouchyTouch.h" and the library of EEPROM <EEPROM.h>. The capacitive touch button refers to the capacitive button part program in the picotouch project of Mr. Todbot. Only a capacitor and a touch pad are needed to realize the function of the capacitive touch button. The EEPROM library is the reference Mr.Earlephilhower's EEPROM library, it simulates the 4K space in RP2040's built-in Flash as EEPROM, and then can save parameter data to the internal flash in the way of EEPROM. Thank you both very much for your contributions.
---------------------------------------------------
2.Capacitive touch keyboard---------------------------------------------------
I used a chip similar to TTP224 to realize the capacitive touch button before, but this time it is realized by adding a 1M resistor to the capacitive pad, and then directly connected to the GPIO of RP2040. My keyboard contains a total of 12 keys such as 0~9, * and #, which are used to input the password of the safe box and manage the logic.
GPIOs are used respectively: 14, 2, 3, 6, 7, 8, 9, 10, 11, 12, 15, 13 respectively correspond to ID0~1D12 in the buttons. Among them, 0~9 corresponds to digital input 0~9, 10 is input *, and 11 is input #.
#include "TouchyTouch.h"
const int touch_threshold_adjust = 300;
const int touch_pins[] = {14,2,3,6,7,8,9,10,11,12,15,13};
const int touch_count = sizeof(touch_pins) / sizeof(int);
TouchyTouch touches[touch_count];
Initialize the touch buttons in the Setup section:
for (int i = 0; i < touch_count; i++) {
touches[i].begin( touch_pins[i] );
touches[i].threshold += touch_threshold_adjust; /* make a bit more noise-proof */
}
The Touch_handling part of the Loop part contains the processing part of the touch button, mainly the touches[i].rose() processing and touches[i].fell() of each button, corresponding to the pressing and processing of each button Release processing:
void Touch_handling()
{
/* key handling*/
for ( int i = 0; i < touch_count; i++) {
touches[i].update();
if ( touches[i].rose() ) {
Serial.print("Button:");
if ( i <= 9 ) {
Serial.println(i);
{
if(Key_num == 0)
{
display.fillRect(0, 38, 128, 17, SH110X_BLACK);
}
display.setTextColor(SH110X_WHITE);
display.setTextSize(2);
if(Key_num < 6)
{
display.setCursor(32+Key_num*12, 38);
display.print("*");
Password[Key_num] = i;
// Serial.print("PSW:");
// Serial.println(Key_num);
// Serial.println(Password[Key_num]);
// Serial.println(Password_Flash[Key_num]);
Key_num ++;
}
display.display();
}
}
else if ( i == 10 ) {
time_hold = millis();
Serial.println("*");
display.fillRect(0, 38, 128, 17, SH110X_BLACK);
display.display();
Key_num = 0;
for(int i =0; i<6; i++)
{
Password[i] = 0;
}
}
else if ( i == 11 ) {
Serial.println("#");
display.fillRect(0, 38, 128, 17, SH110X_BLACK);
if((change_password_flag == 2)||(change_password_flag == 3)) //
{
if(Key_num == 6)
{
Key_num = 0;
display.fillRect(0, 38, 128, 17, SH110X_BLACK);
display.setTextSize(1);
display.setTextColor(SH110X_WHITE);
if(change_password_flag == 2)
{
display.setCursor(6, 43);
display.println("Please Enter Again");
for(int i =0; i<6; i++)
{
Password_New[i]= Password[i];
}
change_password_flag = 3;
}
else
{
if(Password[0] == Password_New[0] && Password[1] == Password_New[1] && Password[2] == Password_New[2] && Password[3] == Password_New[3] && Password[4] == Password_New[4] && Password[5] == Password_New[5] )
{
display.setCursor(9, 43);
display.println("New Password Saved");
display.display();
change_password_flag = 0;
for(int i = 0; i<6; i++)
{
//Wrire d NEW password to flash
EEPROM.write(i, Password[i]);
Password_Flash[i]= Password[i];
}
EEPROM.commit();
delay(2000);
display.fillRect(0, 38, 128, 17, SH110X_BLACK);
}
else
{
display.println("Do Not Match");
change_password_flag = 0;
}
}
display.display();
}
else
{
display.fillRect(0, 38, 128, 17, SH110X_BLACK);
display.setCursor(1, 43);
display.setTextSize(1);
display.setTextColor(SH110X_WHITE);
display.println("Only Allows 6 Digits");
display.display();
Key_num = 0;
for(int i =0; i<6; i++)
{
Password[i] = 0;
}
}
}
else if(change_password_flag == 4)
{
display.fillRect(0, 38, 128, 26, SH110X_BLACK);
display.setCursor(12, 43);
display.setTextSize(1);
display.setTextColor(SH110X_WHITE);
display.println("Enter New Password");
display.setTextSize(1);
display.setCursor(0, 56);
display.println("*:Clear #:Enter");
display.display();
change_password_flag =2;
}
else
{
display.setTextColor(SH110X_WHITE);
display.setTextSize(2);
if(lock_status == 0)
{
if(Password[0] == )
{
}
if(Password[0] == Password_Flash[0] && Password[1] == Password_Flash[1] && Password[2] == Password_Flash[2] && Password[3] == Password_Flash[3] && Password[4] == Password_Flash[4] && Password[5] == Password_Flash[5] )
{
Key_num = 0;
for(int i =0; i<6; i++)
{
Password[i] = 0;
}
if(change_password_flag == 1)
{
display.setCursor(25, 38);
display.println("correct");
display.display();
delay(1000);
display.fillRect(0, 38, 128, 26, SH110X_BLACK);
display.setCursor(16, 43);
display.setTextSize(1);
display.setTextColor(SH110X_WHITE);
display.println("Select to change");
display.setTextColor(SH110X_WHITE);
display.setTextSize(1);
display.setCursor(0, 56);
display.println("*:Finger #:Password");
display.display();
change_password_flag =4;
}
else
{
display.setCursor(25, 38);
display.println("correct");
display.display();
unlockSafebox();
lock_status = 1;
}
}
else if(Key_num == 0)
{
display.fillRect(0, 38, 128, 17, SH110X_BLACK);
display.setCursor(1, 43);
display.setTextSize(1);
display.setTextColor(SH110X_WHITE);
display.println("Please enter password");
display.display();
delay(1000);
display.fillRect(0, 38, 128, 17, SH110X_BLACK);
display.display();
}
else{
display.setCursor(38, 38);
display.println("Error");
display.display();
for(int i=200;i<=800;i++) /*Increase the frequency from 200HZ to 800HZ in a loop*/
{
pinMode(29,OUTPUT);
tone(29,i);
delay(5);
}
delay(1000);
noTone(29);
for(int i =0; i<6; i++)
{
Password[i] = 0;
}
delay(2000);
display.fillRect(0, 38, 128, 17, SH110X_BLACK);
display.display();
lock_status = 0;
Key_num = 0;
}
}
else
{
lock_status = 0;
display.fillRect(0, 38, 128, 17, SH110X_BLACK);
lockSafebox();
}
}
}
}
if ( touches[i].fell() ) {
Serial.printf("Release:");
if ( i <= 9 ) {
Serial.println(i);
}
else if ( i == 10 )
{
Serial.println("*");
if((millis()-time_hold)>500)
{
Serial.println("hold enough");
display.fillRect(0, 38, 128, 17, SH110X_BLACK);
display.setCursor(1, 43);
display.setTextSize(1);
display.setTextColor(SH110X_WHITE);
display.println("Please Enter Password");
display.display();
change_password_flag = 1;
time_hold = 0;
}
else if(change_password_flag == 4)
{
display.fillRect(0, 38, 128, 26, SH110X_BLACK);
display.setCursor(3, 43);
display.setTextSize(1);
display.setTextColor(SH110X_WHITE);
display.println("Put Finger to Sensor");
display.setTextSize(1);
display.setCursor(0, 56);
display.println("*:Clear #:Enter");
display.display();
while(!getFingerprintEnroll(1));
change_password_flag =0;
}
}
else if ( i == 11 ) {
Serial.println("#");
}
}
}
}
I will explain the specific key processing flow in the logic part later.
---------------------------------------------------------------
3.Fingerprint identificationFor the fingerprint identification part, I use the <Adafruit_Fingerprint.h> library. I am not actually using the fingerprint identification module of adafruit, but it is also perfectly compatible with the fingerprint identification module I use after testing. These fingerprint identification modules should be used for standard communication. protocol. The output software serial port used by this module,
I use IO23 and 24 to simulate the software serial port to communicate with the fingerprint recognition module
#include <SoftwareSerial.h>
#include <Adafruit_Fingerprint.h>
#define FINGERPRINT_RX_PIN 23
#define FINGERPRINT_TX_PIN 24
SoftwareSerial fingerprintSerial(FINGERPRINT_RX_PIN, FINGERPRINT_TX_PIN); /* Declare SoftwareSerial obj first*/
Adafruit_Fingerprint finger = Adafruit_Fingerprint(&fingerprintSerial);
Initialize the fingerprint recognition module in the “Setup()” part of the program,The baud rate of the serial port for fingerprint identification is 57600. In the Setup() section, the ID number registered by the fingerprint identification module will be read. If no fingerprint is entered, this section will prompt to enter the fingerprint and store it inside the fingerprint identification module.
This fingerprint identification module can actually store 50 sets of fingerprint information, but I just use an identification ID to avoid complicated logic causing operational confusion.
fingerprintSerial.begin(57600);
finger.getTemplateCount();
while (finger.templateCount == 0)
{
finger.getTemplateCount();
getFingerprintEnroll(1);
}
Serial.print("Finger Count:");
Serial.println(finger.templateCount);
In the “Loop () ”part, the main program of fingerprint recognition is set. This part will recognize the fingerprint information touched on the fingerprint sensor, and after the correct recognition, call Servo to open the door lock of the safe box, and recognize the unregistered After fingerprinting, it will alarm through buzzer.
uint8_t getFingerprintID() {
uint8_t p = finger.getImage();
switch (p) {
case FINGERPRINT_OK:
Serial.println("Image taken");
break;
case FINGERPRINT_NOFINGER:
//Serial.println("No finger detected");
return p;
case FINGERPRINT_PACKETRECIEVEERR:
Serial.println("Communication error");
return p;
case FINGERPRINT_IMAGEFAIL:
Serial.println("Imaging error");
return p;
default:
Serial.println("Unknown error");
return p;
}
// OK success!
p = finger.image2Tz();
switch (p) {
case FINGERPRINT_OK:
Serial.println("Image converted");
break;
case FINGERPRINT_IMAGEMESS:
Serial.println("Image too messy");
return p;
case FINGERPRINT_PACKETRECIEVEERR:
Serial.println("Communication error");
return p;
case FINGERPRINT_FEATUREFAIL:
Serial.println("Could not find fingerprint features");
return p;
case FINGERPRINT_INVALIDIMAGE:
Serial.println("Could not find fingerprint features");
return p;
default:
Serial.println("Unknown error");
return p;
}
// OK converted!
p = finger.fingerSearch();
if (p == FINGERPRINT_OK)
{
Serial.println("Found a print match!");
unlockSafebox();
lock_status = 1;
}
else if (p == FINGERPRINT_PACKETRECIEVEERR)
{
Serial.println("Communication error");
return p;
} else if (p == FINGERPRINT_NOTFOUND) {
Serial.println("Did not find a match");
// Display initialization message
display.fillRect(21, 20, 89, 17, SH110X_WHITE);
display.setTextColor(SH110X_BLACK);
display.setTextSize(2);
display.setCursor(36, 21);
display.println("ALARM");
// Send it to the server
// Blynk.virtualWrite(V5, "ALARM!");
display.display();
for(int n=0; n<5; n++)
{
for(int i=200;i<=800;i++) /*Increase the frequency from 200HZ to 800HZ in a loop*/
{
pinMode(29,OUTPUT);
tone(29,i);
delay(5);
}
delay(2000);
}
noTone(29);
// Display initialization message
display.fillRect(21, 20, 89, 17, SH110X_WHITE);
display.setTextColor(SH110X_BLACK);
display.setTextSize(2);
display.setCursor(45, 21);
display.println("lOCK");
display.display();
// Blynk.virtualWrite(V5, "Lock!");
return p;
} else {
Serial.println("Unknown error");
return p;
}
// found a match!
Serial.print("Found ID #"); Serial.print(finger.fingerID);
Serial.print(" with confidence of "); Serial.println(finger.confidence);
return finger.fingerID;
}
Another important thing about the fingerprint recognition program is the fingerprint entry. In the test of Part1, I passed the enroll program in the fingerprint recognition routine and then tested it. This time I also put the fingerprint entry part in the program.
uint8_t getFingerprintEnroll(uint8_t id) {
int p = -1;
Serial.print("Waiting for valid finger to enroll as #"); Serial.println(id);
while (p != FINGERPRINT_OK) {
p = finger.getImage();
switch (p) {
case FINGERPRINT_OK:
Serial.println("Image taken");
break;
case FINGERPRINT_NOFINGER:
Serial.println(".");
break;
case FINGERPRINT_PACKETRECIEVEERR:
Serial.println("Communication error");
break;
case FINGERPRINT_IMAGEFAIL:
Serial.println("Imaging error");
break;
default:
Serial.println("Unknown error");
break;
}
}
// OK success!
p = finger.image2Tz(1);
switch (p) {
case FINGERPRINT_OK:
Serial.println("Image converted");
break;
case FINGERPRINT_IMAGEMESS:
Serial.println("Image too messy");
return p;
case FINGERPRINT_PACKETRECIEVEERR:
Serial.println("Communication error");
return p;
case FINGERPRINT_FEATUREFAIL:
Serial.println("Could not find fingerprint features");
return p;
case FINGERPRINT_INVALIDIMAGE:
Serial.println("Could not find fingerprint features");
return p;
default:
Serial.println("Unknown error");
return p;
}
Serial.println("Remove finger");
delay(2000);
p = 0;
while (p != FINGERPRINT_NOFINGER) {
p = finger.getImage();
}
Serial.print("ID "); Serial.println(id);
p = -1;
Serial.println("Place same finger again");
display.fillRect(0, 38, 128, 17, SH110X_BLACK);
display.setCursor(1, 43);
display.setTextSize(1);
display.setTextColor(SH110X_WHITE);
display.println("Move and Touch again");
display.display();
while (p != FINGERPRINT_OK) {
p = finger.getImage();
switch (p) {
case FINGERPRINT_OK:
Serial.println("Image taken");
break;
case FINGERPRINT_NOFINGER:
//Serial.print(".");
break;
case FINGERPRINT_PACKETRECIEVEERR:
Serial.println("Communication error");
break;
case FINGERPRINT_IMAGEFAIL:
Serial.println("Imaging error");
break;
default:
Serial.println("Unknown error");
break;
}
}
// OK success!
p = finger.image2Tz(2);
switch (p) {
case FINGERPRINT_OK:
Serial.println("Image converted");
break;
case FINGERPRINT_IMAGEMESS:
Serial.println("Image too messy");
return p;
case FINGERPRINT_PACKETRECIEVEERR:
Serial.println("Communication error");
return p;
case FINGERPRINT_FEATUREFAIL:
Serial.println("Could not find fingerprint features");
return p;
case FINGERPRINT_INVALIDIMAGE:
Serial.println("Could not find fingerprint features");
return p;
default:
Serial.println("Unknown error");
return p;
}
// OK converted!
Serial.print("Creating model for #"); Serial.println(id);
p = finger.createModel();
if (p == FINGERPRINT_OK) {
Serial.println("Prints matched!");
} else if (p == FINGERPRINT_PACKETRECIEVEERR) {
Serial.println("Communication error");
return p;
} else if (p == FINGERPRINT_ENROLLMISMATCH) {
Serial.println("Fingerprints did not match");
return p;
} else {
Serial.println("Unknown error");
return p;
}
Serial.print("ID "); Serial.println(id);
p = finger.storeModel(id);
if (p == FINGERPRINT_OK) {
Serial.println("Stored!");
} else if (p == FINGERPRINT_PACKETRECIEVEERR) {
Serial.println("Communication error");
return p;
} else if (p == FINGERPRINT_BADLOCATION) {
Serial.println("Could not store in that location");
return p;
} else if (p == FINGERPRINT_FLASHERR) {
Serial.println("Error writing to flash");
return p;
} else {
Serial.println("Unknown error");
return p;
}
return true;
}
The recognition process needs to put the same finger on the sensor twice, that is, remove the finger and put it on the sensor again. I also gave instructions on the operation steps on the screen, which will be explained in detail later.
----------------------------------------------------------------
4.Unlocking and lockingThe part about the lock is realized through the action of Servo. The following is the action for unlocking.
The following is the action code for unlocking.
This part will also update the display of the lock status part of the screen, and will send a reminder of the current status to the BLYNK server.
void unlockSafebox() {
servo.write(180); /* Unlock the safebox*/
/* Display initialization message*/
display.fillRect(21, 20, 89, 17, SH110X_WHITE);
display.setTextColor(SH110X_BLACK);
display.setTextSize(2);
display.setCursor(32, 21);
display.println("Unlock");
display.display();
delay(2000);
display.fillRect(0, 38, 128, 17, SH110X_BLACK);
display.setCursor(16, 43);
display.setTextSize(1);
display.setTextColor(SH110X_WHITE);
display.println("Press \"#\" to lock");
display.display();
/* Send it to the server*/
Blynk.virtualWrite(V5, String("Found a Finger ID:" + String(finger.fingerID)));
}
The following is the action code for locking.
void lockSafebox() {
servo.write(360); /* Lock the safebox again*/
/* Display initialization message*/
display.fillRect(21, 20, 89, 17, SH110X_WHITE);
display.setTextColor(SH110X_BLACK);
display.setTextSize(2);
display.setCursor(45, 21);
display.println("Lock");
display.display();
delay(2000);
/* Send it to the server*/
Blynk.virtualWrite(V5, "Lock!");
}
----------------------------------------------------------------
5.Display interface and menu designThe display part is a 128*64 OLED screen,
The initialization part is as follows:
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SH110X.h>
#define SCREEN_WIDTH 128 /* OLED display width, in pixels*/
#define SCREEN_HEIGHT 64 /* OLED display height, in pixels*/
#define OLED_RESET -1 /* Reset pin # (or -1 if sharing Arduino reset pin)*/
#define i2c_Address 0x3c /*initialize with the I2C addr 0x3C Typically eBay OLED's*/
Adafruit_SH1106G display = Adafruit_SH1106G(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
The display interface consists of 4 main parts:
1. Logo area, this area displays the Safebox logo;
2. The status display area displays the lock status. There are roughly three statuses, namely lock status, unlock status, and alarm status;
3. Operation prompt display area, this area is used to prompt the user to operate the steps;
4. The button prompt area mainly prompts the functions of "*" and "#";
Initialize the display interface during initialization, the code is as follows:
void display_logo(uint16_t x,uint16_t y)
{
uint8_t cloud_pixel[5*8]=
{
0b00110010,0b01001001,0b01001001,0b01001001,0b00100110, // S
0b00000010,0b00010101,0b00010101,0b00010101,0b00001111, // a
0b00001000,0b00111111,0b01001000,0b01001000,0b00100000, // f
0b00001110,0b00010101,0b00010101,0b00010101,0b00001100, // e
0b00000000,0b00000000,0b00000000,0b00000000,0b00000000, // space
0b01111111,0b01001001,0b01001001,0b01001001,0b00110110, // B
0b00001110,0b00010001,0b00010001,0b00010001,0b00001110, // o
0b00010001,0b00001010,0b00000100,0b00001010,0b00010001, // x
};
uint16_t _x = x - 40;
uint16_t _y = y - 10;
for(uint8_t i=0;i<8;i++)
{
for(uint8_t m=0;m<5;m++)
{
_y = y - 8;
for(uint8_t n=0;n<8;n++)
{
if((cloud_pixel[i*5+m]>>(7-n))&0x01)
{
display.fillRect(_x+1, _y+1, 1, 1, SH110X_WHITE);
}
_y += 2;
}
_x = _x + 2;
}
}
display.setTextSize(2);
display.fillRect(21, 20, 89, 17, SH110X_WHITE);
display.setTextColor(SH110X_BLACK);
display.setCursor(45, 21);
display.println("Lock");
display.setTextColor(SH110X_WHITE);
display.setTextSize(1);
display.setCursor(0, 56);
display.println("*:Clear #:Enter");
display.display();
}
The cloud_pixel[5*8] in the code above stores the dot matrix information of the SAFEBOX logo, because I think the Adafruit_GFX.h built-in text display is not very beautiful, so I redesigned the logo.
The interaction logic is mainly divided into the following parts:
1. Password input and correction;
2. Change password and fingerprints;
The logic processing of keyboard password input is much more complicated than that of fingerprint recognition, because there are libraries for fingerprint recognition, we only need to add the function of unlocking at the position where the recognition is successful, but the password input of the digital keyboard does not Library, so only we design the operation logic, so explain it separately,
I will introduce these parts separately below.
5.1. Password input and submit;In the setup() part of the program, that is, when the safe box is powered on, the stored password “Password_Flash” is read from the flash. The password is 6 digits, and the default password is 111111.
byte Password[6];
byte Password_Flash[6];
When inputting on the keys 0~9, the screen will display * at the corresponding position, Then the password entered by the keyboard is stored in "Password", In the pressed part of the touch button, this part of the code handles the input of the password.
if ( i <= 9 ) {
Serial.println(i);
{
if(Key_num == 0)
{
display.fillRect(0, 38, 128, 17, SH110X_BLACK);
}
display.setTextColor(SH110X_WHITE);
display.setTextSize(2);
if(Key_num < 6)
{
display.setCursor(32+Key_num*12, 38);
display.print("*");
Password[Key_num] = i;
Key_num ++;
}
display.display();
}
}
and if the input is wrong, you can press the * key to cancel the input, and clear the entered password.
else if ( i == 10 ) {
time_hold = millis();
Serial.println("*");
display.fillRect(0, 38, 128, 17, SH110X_BLACK);
display.display();
Key_num = 0;
for(int i =0; i<6; i++)
{
Password[i] = 0;
}
}
and after the password input is completed, press the # key to submit the password.
if(Password[0] == Password_Flash[0] && Password[1] == Password_Flash[1] && Password[2] == Password_Flash[2] && Password[3] == Password_Flash[3] && Password[4] == Password_Flash[4] && Password[5] == Password_Flash[5] )
{
Key_num = 0;
for(int i =0; i<6; i++)
{
Password[i] = 0;
}
if(change_password_flag == 1)
{
display.setCursor(25, 38);
display.println("correct");
display.display();
delay(1000);
display.fillRect(0, 38, 128, 26, SH110X_BLACK);
display.setCursor(16, 43);
display.setTextSize(1);
display.setTextColor(SH110X_WHITE);
display.println("Select to change");
display.setTextColor(SH110X_WHITE);
display.setTextSize(1);
display.setCursor(0, 56);
display.println("*:Finger #:Password");
display.display();
change_password_flag =4;
}
else
{
display.setCursor(25, 38);
display.println("correct");
display.display();
unlockSafebox();
lock_status = 1;
}
}
else if(Key_num == 0)
{
display.fillRect(0, 38, 128, 17, SH110X_BLACK);
display.setCursor(1, 43);
display.setTextSize(1);
display.setTextColor(SH110X_WHITE);
display.println("Please enter password");
display.display();
delay(1000);
display.fillRect(0, 38, 128, 17, SH110X_BLACK);
display.display();
}
else{
display.setCursor(38, 38);
display.println("Error");
display.display();
for(int i=200;i<=800;i++) //用循环的方式将频率从200HZ 增加到800HZ
{
pinMode(29,OUTPUT);
tone(29,i); //在四号端口输出频率
delay(5); //该频率维持5毫秒
}
delay(1000);
noTone(29);
for(int i =0; i<6; i++)
{
Password[i] = 0;
}
delay(2000);
display.fillRect(0, 38, 128, 17, SH110X_BLACK);
display.display();
lock_status = 0;
Key_num = 0;
}
if "Password" and "Password_Flash" exactly match, that is, the password is correct. It will prompt "Press "#" to lock" in the input prompt area on the screen.
If you need to lock the safe, you only need to press the "#" key after closing the safe door to lock the safe box.If the input is wrong, the buzzer will sound to warn, and the screen will also prompt that the input password is wrong.
5.2. Change password and fingerprints;I also designed the steps to change the password:
5.2.1. Press and hold the * button for more than 3 seconds to start the setup procedure;
Record the current time when the * key is pressed time_hold = millis(), and compare the time when the * key is released, if it exceeds 3 seconds, enter the setting step. At this time, a key flag bit change_password_flag for step management from 0 to 1;
if((millis()-time_hold)>500)
{
Serial. println("hold enough");
display.fillRect(0, 38, 128, 17, SH110X_BLACK);
display.setCursor(1, 43);
display.setTextSize(1);
display.setTextColor(SH110X_WHITE);
display.println("Please Enter Password");
display. display();
change_password_flag = 1;
time_hold = 0;
}
5.2.2. Enter the password to perform authorization authentication;
The operation prompt area of the screen will prompt "Please Enter Password" at this time. When the password is entered and the password is confirmed to be correct, the state of change_password_flag will change from 1 to 4;
if(Password[0] == Password_Flash[0] && Password[1] == Password_Flash[1] && Password[2] == Password_Flash[2] && Password[3] == Password_Flash[3] && Password[4] == Password_Flash[4] && Password[5] == Password_Flash[5] )
{
Key_num = 0;
for(int i =0; i<6; i++)
{
Password[i] = 0;
}
if(change_password_flag == 1)
{
display.setCursor(25, 38);
display. println("correct");
display. display();
delay(1000);
display.fillRect(0, 38, 128, 26, SH110X_BLACK);
display.setCursor(16, 43);
display.setTextSize(1);
display.setTextColor(SH110X_WHITE);
display.println("Select to change");
display.setTextColor(SH110X_WHITE);
display.setTextSize(1);
display.setCursor(0, 56);
display.println("*:Finger #:Password");
display. display();
change_password_flag = 4;
}
else
{
display.setCursor(25, 38);
display. println("correct");
display. display();
unlockSafebox();
lock_status = 1;
}
}
5.2.3. Choose to change the password or fingerprint of the safe box;
In the operation prompt area of the screen in the previous step, we can choose password or fingerprint. Among them, the * key represents changing the fingerprint, and the # key represents changing the password; if you touch the # key, you can choose to change the password. The operation prompt area of the screen is "Enter New Password", at this time change_password_flag is changed from 4 to 2;
else if(change_password_flag == 4)
{
display.fillRect(0, 38, 128, 26, SH110X_BLACK);
display.setCursor(12, 43);
display.setTextSize(1);
display.setTextColor(SH110X_WHITE);
display.println("Enter New Password");
display.setTextSize(1);
display.setCursor(0, 56);
display.println("*:Clear #:Enter");
display. display();
change_password_flag = 2;
}
5.2.4. Enter the password twice, if the password is the same twice, save it in flash and become the new password;
When entering a new password for the first time, the password is transferred from the entered Password[6] to Password_new[6], and change_password_flag is changed from 2 to 3;
The second time to enter the password is to compare whether the Password[6] this time is the same as the Password_new saved in the previous step. If they are the same, it will prompt "New Password Saved" and store it in the flash. At this time, change_password_flag is changed from 3 to 0, and the steps of changing the password are completed;
if((change_password_flag == 2)||(change_password_flag == 3)) //
{
if(Key_num == 6)
{
Key_num = 0;
display.fillRect(0, 38, 128, 17, SH110X_BLACK);
display.setTextSize(1);
display.setTextColor(SH110X_WHITE);
if(change_password_flag == 2)
{
display.setCursor(6, 43);
display.println("Please Enter Again");
for(int i =0; i<6; i++)
{
Password_New[i]= Password[i];
}
change_password_flag = 3;
}
else
{
if(Password[0] == Password_New[0] && Password[1] == Password_New[1] && Password[2] == Password_New[2] && Password[3] == Password_New[3] && Password[4] == Password_New[4] && Password[5] == Password_New[5] )
{
display.setCursor(9, 43);
display.println("New Password Saved");
display. display();
change_password_flag = 0;
for(int i = 0; i<6; i++)
{
//Write d NEW password to flash
EEPROM.write(i, Password[i]);
Password_Flash[i]= Password[i];
}
EEPROM.commit();
delay(2000);
display.fillRect(0, 38, 128, 17, SH110X_BLACK);
}
else
{
display.println("Do Not Match");
change_password_flag = 0;
}
}
display. display();
}
else
{
display.fillRect(0, 38, 128, 17, SH110X_BLACK);
display.setCursor(1, 43);
display.setTextSize(1);
display.setTextColor(SH110X_WHITE);
display.println("Only Allows 6 Digits");
display. display();
Key_num = 0;
for(int i =0; i<6; i++)
{
Password[i] = 0;
}
}
}
5.2.5 change fingerprint
In step 5.2.3, click * to select to change the fingerprint, that is, when change_password_flag is equal to 4.
I put the fingerprint change steps in touches[i].fell() of the * key release operation, because there is a while(!getFingerprintEnroll(1)) operation in the middle of the operation, if it is placed alone in the button press operation touches[i] In.rose(), the program will continue to execute the release operation touches[i].fell(), resulting in misoperation.
[This is a very critical Tip, I have been debugging this step for a long time. ]
{
display.fillRect(0, 38, 128, 26, SH110X_BLACK);
display.setCursor(3, 43);
display.setTextSize(1);
display.setTextColor(SH110X_WHITE);
display.println("Put Finger to Sensor");
display.setTextSize(1);
display.setCursor(0, 56);
display.println("*:Clear #:Enter");
display. display();
while(!getFingerprintEnroll(1));
change_password_flag = 0;
}
Like changing the password, changing the fingerprint also needs to touch the fingerprint sensor twice with the same finger.
the screen will prompt Move and Touch again.
If the fingerprint is changed successfully, the change_password_flag will be changed from 4 to 0, and the fingerprint change process is completed.
display.fillRect(0, 38, 128, 17, SH110X_BLACK);
display.setCursor(1, 43);
display.setTextSize(1);
display.setTextColor(SH110X_WHITE);
display.println("Move and Touch again");
display. display();
----------------------------------------------------------------
6.Ethernet and BLYNK communication---------------------------------------------------------------
Blynk communication is carried out by us through Ethernet (W5100S), or through WLAN network (Wizfi360), and information can be notified to the mobile phone through the network, such as "the current safe is opened", "Warning: Fingerprint recognition error", "Warning: wrong password" and so on.
We can download the reference history through Blynk's website, as well as download the Blynk communication library. Apply for an account on the Blynk website and get a Token for communication.
/* Fill-in information from Blynk Device Info here */
#define BLYNK_TEMPLATE_ID "TMPL26_JX2Nd5"
#define BLYNK_TEMPLATE_NAME "Quickstart Template"
#define BLYNK_AUTH_TOKEN "5S0f6Q-4H4zOmZOhdn*************************"
/* Comment this out to disable prints and save space */
#define BLYNK_PRINT Serial
#include <SPI.h>
#include <Ethernet.h>
#include <BlynkSimpleEthernet.h>
/* Enter a MAC address and IP address for your controller below.*/
/* The IP address will be dependent on your local network:*/
byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};
IPAddress ip(10, 0, 1, 226);
Initialize the Ethernet chip W5100S in the Setup () part of the program, and set the MAC address and IP address of the network, but the BLYNK library will re-apply for an IP address through DHCP in the next step;
Ethernet.init(17); /* WIZnet W5100S-EVB-Pico*/
/* start the Ethernet connection and the server:*/
Ethernet.begin(mac, ip);
if (Ethernet.linkStatus() == LinkOFF) {
Serial.println("Ethernet cable is not connected.");
}
Blynk.begin(BLYNK_AUTH_TOKEN);
In Loop(), the following code is used to keep the information of blynk cloud in sync;
Blynk.run();
timer.run();
If we need to send information to Blynk Cloud, we only need to send it in the following format:
// Send it to the server
Blynk.virtualWrite(V5, "ALARM!");
The above is to send a text message "ALARM!" to "V5"
When we were in Part 1, there was a function of Blynk that was not implemented. It was completely feasible to receive the "SafeBox" notification information through the mobile phone and tested it. As shown below:
If you need to alarm through notification messages, you need to set the "EVENT" message on Blynk's web page now:
Set to send notifications via Mobile APP and add to timeline.
Then send the EVENT code in the following format, and Blynk's Mobile APP will send a notification message.
Blynk.logEvent("lock");
-----------------------------------------------------------------------------------------------------------------------
After several weeks, this small project is finally completed, and I am quite satisfied.
Done!
Comments