Disclaimer: I'm a total novice to Arduino so please forgive me if the question may seem trivial, I'm trying my best to learn :)
I'm working on a small project where I have a fingerprint sensor, a servo and an OLED display. The goal is to be able to register a fingerprint and then use the fingerprint to move the servo, whilst the OLED display gives instruction / messages to the user.
I noticed a few days ago an issue whereby my OLED wouldn't simply stop working if I had some Serial.println in my code. Without understanding the root cause, by trial and error I got to the conclusion that the issue was with that specific function, so I proceeded to remove it and everything went ok.
Then I noticed that the display stopped working also by adding extremely simple pieces of code that should not be related in ANY way to how the OLED works (at least to the best of my very limited knowledge).
The code below works as expected, each and every call to the oledPrint function yields the expected result on the OLED itself.
#include <EEPROM.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define OLED_RESET -1
Adafruit_SSD1306 display(OLED_RESET);
#include <Adafruit_Fingerprint.h>
#include <SoftwareSerial.h>
#define ISPRESSED LOW
#define BASE_MAX 200
#define MASTER_MAX 200
SoftwareSerial mySerial(2, 3);
Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);
uint8_t id;
const int buttonRegisterPin = 8; // the number of the pushbutton pin - NOTE: RED BUTTON
const int buttonRegisterMasterPin = 7; // the number of the pushbutton pin - NOTE: GREEN BUTTON
const int buttonClearPin = 6; // the number of the pushbutton pin - NOTE: BLACK BUTTON
const int buttonClearMasterPin = 12; // the number of the pushbutton pin - NOTE: YELLOW BUTTON
const int baseState = HIGH;
int ledStatus = HIGH;
int baseCount;
int masterCount;
void setup() {
//Serial.begin (9600);
Serial.begin (115200);
//initialize counters
initializeCounters();
//initialize buttons
initializeButton(buttonRegisterPin);
initializeButton(buttonRegisterMasterPin);
initializeButton(buttonClearPin);
initializeButton(buttonClearMasterPin);
//initialize the fingerprint sensor
initializeFingerPrintSensor();
//initialize the OLED display
initializeOledDisplay();
}
void loop() {
bool skip = false;
oledPrint("Welcome to your fingerprint locker");
//base registration case
if(digitalRead(buttonRegisterPin) == ISPRESSED && skip == false){
while(!baseRegistration());
skip = true;
}
//master registration case
if(digitalRead(buttonRegisterMasterPin) == ISPRESSED && skip == false){
while(!masterRegistration());
skip = true;
}
//base clear case
if(digitalRead(buttonClearPin) == ISPRESSED && skip == false){
clearRegistrations(false);
//do stuff for base clear
skip = true;
}
//master clear case
if(digitalRead(buttonClearMasterPin) == ISPRESSED && skip == false){
//do stuff for master clear
skip = true;
}
}
/**
* Initializes a button
* @Param: buttonPin = number of the pin used by the button
*/
void initializeButton(int buttonPin){
pinMode(buttonPin, INPUT_PULLUP);
}
/**
* Initializes the OLED display
*/
void initializeOledDisplay(){
Wire.begin();
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64
Serial.println(F("SSD1306 allocation failed"));
for(;;);
}
delay(2000);
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(0, 10);
}
/**
* initializes the fingerprint sensor
*/
void initializeFingerPrintSensor(){
finger.begin(57600);
if (finger.verifyPassword()) {
Serial.println("Found fingerprint sensor!");
}
else {
Serial.println("Did not find fingerprint sensor :(");
while (1) { delay(1); }
}
}
boolean baseRegistration(){
boolean check = false;
int tempBaseCount = baseCount + 1;
/*
if(tempBaseCount > BASE_MAX){
oledPrint("Too many users already registered");
return true;
}*/
oledPrint("Starting registration");
while(check == false){
oledPrint("Please put your finger on the reader");
id = tempBaseCount;
if (id == 0) {// ID #0 not allowed, try again!
return;
}
if(getFingerprintEnroll(tempBaseCount, false)){
check = true;
}
}
return check;
}
boolean masterRegistration(){
boolean check = false;
int tempMasterCount = baseCount + 1;
/*
if(tempMasterCount > MASTER_MAX){
oledPrint("Too many master keys already registered");
return true;
}
*/
oledPrint("Starting master key registration");
while(check == false){
oledPrint("Please put your finger on the reader");
id = tempMasterCount;
if (id == 0) {// ID #0 not allowed, try again!
return;
}
if(getFingerprintEnroll(tempMasterCount, true)){
check = true;
}
}
return check;
}
boolean clearRegistrations(bool master){
if(master){
//to do
}
else{
//increaseBaseCounter(0);
id = 900;
int p = finger.deleteModel(id);
if(p == FINGERPRINT_OK){
// Serial.println("success");
// Serial.println(p);
return true;
}
// Serial.println("FAIL");
// Serial.println(p);
return false;
}
}
// returns -1 if failed, otherwise returns ID #
int getFingerprintIDez() {
uint8_t p = finger.getImage();
if (p != FINGERPRINT_OK) return -1;
p = finger.image2Tz();
if (p != FINGERPRINT_OK) return -1;
p = finger.fingerFastSearch();
if (p != FINGERPRINT_OK) return -1;
// found a match!
oledPrint2Lines("Match found, ID #", finger.fingerID);
/* Serial.print("Found ID #");
Serial.print(finger.fingerID);
Serial.print(" with confidence of ");
Serial.println(finger.confidence);*/
return finger.fingerID;
}
uint8_t getFingerprintEnroll(int count, bool master) {
int p = -1;
while (p != FINGERPRINT_OK) {
p = finger.getImage();
switch (p) {
case FINGERPRINT_OK:
//oledPrint("Image taken");
break;
case FINGERPRINT_NOFINGER:
break;
case FINGERPRINT_PACKETRECIEVEERR:
oledPrint("Communication error");
break;
case FINGERPRINT_IMAGEFAIL:
oledPrint("Imaging error");
break;
default:
oledPrint("Unknown error");
break;
}
}
// OK success!
p = finger.image2Tz(1);
switch (p) {
case FINGERPRINT_OK:
//oledPrint("Image converted");
break;
case FINGERPRINT_IMAGEMESS:
oledPrint("Image too messy");
return p;
case FINGERPRINT_PACKETRECIEVEERR:
oledPrint("Communication error");
return p;
case FINGERPRINT_FEATUREFAIL:
oledPrint("Could not find fingerprint features");
return p;
case FINGERPRINT_INVALIDIMAGE:
oledPrint("Could not find fingerprint features");
return p;
default:
oledPrint("Unknown error");
return p;
}
oledPrint("Remove finger");
delay(2000);
p = 0;
while (p != FINGERPRINT_NOFINGER) {
p = finger.getImage();
}
p = -1;
oledPrint("Place the same finger again");
while (p != FINGERPRINT_OK) {
p = finger.getImage();
switch (p) {
case FINGERPRINT_OK:
//oledPrint("Image taken");
break;
case FINGERPRINT_NOFINGER:
break;
case FINGERPRINT_PACKETRECIEVEERR:
oledPrint("Comunication error");
break;
case FINGERPRINT_IMAGEFAIL:
oledPrint("Imaging error");
break;
default:
oledPrint("Unknown error");
break;
}
}
// OK success!
p = finger.image2Tz(2);
switch (p) {
case FINGERPRINT_OK:
//oledPrint("Image converted");
break;
case FINGERPRINT_IMAGEMESS:
oledPrint("Image too messy");
return p;
case FINGERPRINT_PACKETRECIEVEERR:
oledPrint("Communication error");
return p;
case FINGERPRINT_FEATUREFAIL:
oledPrint("Could not find fingerprint features");
return p;
case FINGERPRINT_INVALIDIMAGE:
oledPrint("Could not find fingerprint features");
return p;
default:
oledPrint("Unknown error");
return p;
}
// OK converted!
//oledPrint2Lines("Creating model number:", count);
p = finger.createModel();
if (p == FINGERPRINT_OK) {
//oledPrint("Prints matched!");
} else if (p == FINGERPRINT_PACKETRECIEVEERR) {
oledPrint("Communication error");
return p;
} else if (p == FINGERPRINT_ENROLLMISMATCH) {
oledPrint("Fingerprints did not match");
return p;
} else {
oledPrint("Unknown errro");
return p;
}
p = finger.storeModel(id);
if (p == FINGERPRINT_OK) {
if(master == false){
oledPrint2Lines("Registered with id number:", count);
increaseBaseCounter(count);
}
else{
oledPrint2Lines("Registered master key number:", count - 50);
increaseMasterCounter(count);
}
return 1;
} else if (p == FINGERPRINT_PACKETRECIEVEERR) {
oledPrint("Communication error");
return p;
} else if (p == FINGERPRINT_BADLOCATION) {
oledPrint("Could not store in that location");
return p;
} else if (p == FINGERPRINT_FLASHERR) {
oledPrint("Error writing to flash");
return p;
} else {
oledPrint("Unknown error");
return p;
}
}
uint8_t readnumber(void) {
uint8_t num = 0;
while (num == 0) {
while (! Serial.available());
num = Serial.parseInt();
}
return num;
}
void oledPrint(char* text){
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println(text);
display.display();
delay(2000);
}
void oledPrint2Lines(char* text, int val){
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.print(text);
display.print(val);
display.display();
delay(2000);
}
void initializeCounters(){
//address 0 is BASE
baseCount = EEPROM.read(0);
Serial.println(baseCount);
//address 1 is MASTER
masterCount = EEPROM.read(1);
if(masterCount < 50)
masterCount = 50; //will get to 51 once first registered - 51 = master key #1
Serial.println(masterCount);
}
void increaseBaseCounter(int count){
baseCount = count;
EEPROM.write(0, baseCount);
}
void increaseMasterCounter(int count){
masterCount = count;
EEPROM.write(1, masterCount);
}
However, if I uncomment the code in the baseRegistration and/or masterRegistration functions (see code snippet below), the display starts to act up: some text is displayed, some other isn't, some other again is displayed partially. I just can't find a sensible explanation anywhere, and being used to work on much higher abstraction levels this is to me completely absurd :D
boolean baseRegistration(){
boolean check = false;
int tempBaseCount = baseCount + 1;
//PART THAT CAUSES ISSUES - STARRT
if(tempBaseCount > BASE_MAX){
oledPrint("Too many users already registered");
return true;
}
//PART THAT CAUSES ISSUES - END
oledPrint("Starting registration");
while(check == false){
oledPrint("Please put your finger on the reader");
id = tempBaseCount;
if (id == 0) {// ID #0 not allowed, try again!
return;
}
if(getFingerprintEnroll(tempBaseCount, false)){
check = true;
}
}
return check;
}
Even more oddly, if I remove the part above from those two functions and I had one more simple call to the fingerprint sensor in the loop function, the OLED just stops working altogether (and again, absolutely crazy for me :P). See below the loop function with the addition of the line that breaks the OLED altogether:
void loop() {
bool skip = false;
oledPrint("Welcome to your fingerprint locker");
//base registration case
if(digitalRead(buttonRegisterPin) == ISPRESSED && skip == false){
while(!baseRegistration());
skip = true;
}
//master registration case
if(digitalRead(buttonRegisterMasterPin) == ISPRESSED && skip == false){
while(!masterRegistration());
skip = true;
}
//base clear case
if(digitalRead(buttonClearPin) == ISPRESSED && skip == false){
clearRegistrations(false);
//do stuff for base clear
skip = true;
}
//master clear case
if(digitalRead(buttonClearMasterPin) == ISPRESSED && skip == false){
//do stuff for master clear
skip = true;
}
int fingerprintID = getFingerprintIDez(); //THIS IS THE LINE
delay(50);
}
I just don't know how to proceed, if any of you would be so kind to help a novice out I'd be extremely grateful! Thanks in advance to anyone who could point me in the right direction!!
For the sake of completeness, I'm using the adafruit libraries for the fingerprint sensor as well as the oled.