Беспорядочное поведение OLED-дисплея — вмешательство в другие части кода?
Отказ от ответственности: я новичок в Arduino, поэтому, пожалуйста, простите меня, если вопрос может показаться тривиальным, я изо всех сил стараюсь учиться :)
Я работаю над небольшим проектом, в котором у меня есть датчик отпечатков пальцев, сервопривод и OLED-дисплей. Цель состоит в том, чтобы иметь возможность зарегистрировать отпечаток пальца, а затем использовать его для перемещения сервопривода, в то время как OLED-дисплей выводит инструкции/сообщения пользователю.
Несколько дней назад я заметил проблему, из-за которой мой OLED-экран просто не переставал работать, если в моем коде был какой-то Serial.println. Не понимая первопричины, методом проб и ошибок я пришел к выводу, что проблема связана с этой конкретной функцией, поэтому я удалил ее, и все прошло нормально.
Затем я заметил, что дисплей перестал работать также из-за добавления очень простых фрагментов кода, которые НИКАК не должны быть связаны с тем, как работает OLED (по крайней мере, насколько я знаю).
Приведенный ниже код работает так, как ожидалось, каждый вызов функции oledPrint дает ожидаемый результат на самом OLED-дисплее.
#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; // номер вывода кнопки - ПРИМЕЧАНИЕ: КРАСНАЯ КНОПКА
const int buttonRegisterMasterPin = 7; // номер штифта кнопки - ПРИМЕЧАНИЕ: ЗЕЛЕНАЯ КНОПКА
const int buttonClearPin = 6; // номер штифта кнопки - ПРИМЕЧАНИЕ: ЧЕРНАЯ КНОПКА
const int buttonClearMasterPin = 12; // номер вывода кнопки - ПРИМЕЧАНИЕ: ЖЕЛТАЯ КНОПКА
const int baseState = HIGH;
int ledStatus = HIGH;
int baseCount;
int masterCount;
void setup() {
//Серийный.начало (9600);
Serial.begin (115200);
// инициализируем счетчики
initializeCounters();
// инициализируем кнопки
initializeButton(buttonRegisterPin);
initializeButton(buttonRegisterMasterPin);
initializeButton(buttonClearPin);
initializeButton(buttonClearMasterPin);
// инициализируем датчик отпечатков пальцев
initializeFingerPrintSensor();
// инициализируем OLED-дисплей
initializeOledDisplay();
}
void loop() {
bool skip = false;
oledPrint("Welcome to your fingerprint locker");
//базовый случай регистрации
if(digitalRead(buttonRegisterPin) == ISPRESSED && skip == false){
while(!baseRegistration());
skip = true;
}
//основной регистрационный случай
if(digitalRead(buttonRegisterMasterPin) == ISPRESSED && skip == false){
while(!masterRegistration());
skip = true;
}
//базовый чистый регистр
if(digitalRead(buttonClearPin) == ISPRESSED && skip == false){
clearRegistrations(false);
// делаем что-то для базовой очистки
skip = true;
}
//освоить четкий регистр
if(digitalRead(buttonClearMasterPin) == ISPRESSED && skip == false){
//делаем что-то для мастера ясно
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)) { // Адрес 0x3D для 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 не разрешен, попробуйте еще раз!
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 не разрешен, попробуйте еще раз!
return;
}
if(getFingerprintEnroll(tempMasterCount, true)){
check = true;
}
}
return check;
}
boolean clearRegistrations(bool master){
if(master){
//делать
}
else{
// увеличить базовый счетчик (0);
id = 900;
int p = finger.deleteModel(id);
if(p == FINGERPRINT_OK){
// Serial.println("успех");
// Serial.println(p);
return true;
}
// Serial.println("FAIL");
// Serial.println(p);
return false;
}
}
// возвращает -1 в случае неудачи, иначе возвращает 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;
// найдено совпадение!
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("Изображение сделано");
break;
case FINGERPRINT_NOFINGER:
break;
case FINGERPRINT_PACKETRECIEVEERR:
oledPrint("Communication error");
break;
case FINGERPRINT_IMAGEFAIL:
oledPrint("Imaging error");
break;
default:
oledPrint("Unknown error");
break;
}
}
// ОК, успех!
p = finger.image2Tz(1);
switch (p) {
case FINGERPRINT_OK:
//oledPrint("Изображение преобразовано");
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("Изображение сделано");
break;
case FINGERPRINT_NOFINGER:
break;
case FINGERPRINT_PACKETRECIEVEERR:
oledPrint("Comunication error");
break;
case FINGERPRINT_IMAGEFAIL:
oledPrint("Imaging error");
break;
default:
oledPrint("Unknown error");
break;
}
}
// ОК, успех!
p = finger.image2Tz(2);
switch (p) {
case FINGERPRINT_OK:
//oledPrint("Изображение преобразовано");
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;
}
// ОК сконвертировано!
//oledPrint2Lines("Создание номера модели:", count);
p = finger.createModel();
if (p == FINGERPRINT_OK) {
//oledPrint("Отпечатки совпали!");
} 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(){
//адрес 0 является БАЗОВЫМ
baseCount = EEPROM.read(0);
Serial.println(baseCount);
//адрес 1 является ГЛАВНЫМ
masterCount = EEPROM.read(1);
if(masterCount < 50)
masterCount = 50; // доберёмся до 51 после первой регистрации - 51 = мастер-ключ #1
Serial.println(masterCount);
}
void increaseBaseCounter(int count){
baseCount = count;
EEPROM.write(0, baseCount);
}
void increaseMasterCounter(int count){
masterCount = count;
EEPROM.write(1, masterCount);
}
Однако, если я раскомментирую код в функциях baseRegistration и/или masterRegistration (см. фрагмент кода ниже), отображение начинает барахлить: какой-то текст отображается, какой-то нет, какой-то снова отображается частично. Я просто нигде не могу найти разумного объяснения, а поскольку я привык работать на гораздо более высоких уровнях абстракции, это для меня совершенно абсурдно :D
boolean baseRegistration(){
boolean check = false;
int tempBaseCount = baseCount + 1;
// ЧАСТЬ, ВЫЗЫВАЮЩАЯ ПРОБЛЕМЫ - STARTRT
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 не разрешен, попробуйте еще раз!
return;
}
if(getFingerprintEnroll(tempBaseCount, false)){
check = true;
}
}
return check;
}
Что еще более странно, если я уберу вышеуказанную часть из этих двух функций и у меня будет еще один простой вызов датчика отпечатков пальцев в функции цикла, OLED просто перестанет работать (и опять же, для меня это просто безумие :P) . См. ниже функцию цикла с добавлением строки, которая полностью разрушает OLED:
void loop() {
bool skip = false;
oledPrint("Welcome to your fingerprint locker");
//базовый случай регистрации
if(digitalRead(buttonRegisterPin) == ISPRESSED && skip == false){
while(!baseRegistration());
skip = true;
}
//основной регистрационный случай
if(digitalRead(buttonRegisterMasterPin) == ISPRESSED && skip == false){
while(!masterRegistration());
skip = true;
}
//базовый чистый регистр
if(digitalRead(buttonClearPin) == ISPRESSED && skip == false){
clearRegistrations(false);
// делаем что-то для базовой очистки
skip = true;
}
//освоить четкий регистр
if(digitalRead(buttonClearMasterPin) == ISPRESSED && skip == false){
//делаем что-то для мастера ясно
skip = true;
}
int fingerprintID = getFingerprintIDez(); // ЭТО ЛИНИЯ
delay(50);
}
Я просто не знаю, как поступить, если кто-то из вас будет так любезен помочь новичку, я буду очень признателен! Заранее спасибо всем, кто может указать мне правильное направление!!
Для полноты картины я использую библиотеки adafruit для датчика отпечатков пальцев, а также для OLED-дисплея.
@HaXeT, 👍2
Обсуждение1 ответ
Похоже, ваша программа хорошо вписывается в память Arduino Uno. Если ваши выходные данные правильно отображаются через последовательный монитор, то, похоже, нет ничего плохого в ваших данных, отправленных на дисплей. Вы пробовали подключать подтягивающие резисторы к линиям SDA и SCL? Резисторы номиналом около 3,9 кОм прекрасно работают при использовании OLED-дисплеев.
- Отправка и получение различных типов данных через I2C в Arduino
- Как работают функции вне цикла void?
- Как отображать переменные на 0,96-дюймовом OLED-дисплее с библиотекой u8glib?
- OVF в последовательном мониторе вместо данных
- ЖК-дисплей I2C отображает странные символы
- Соединение I2C зависает Ведущий если ведомый отключается
- Экран LCD 16*02 I2C показывает только первый напечатанный символ
- Ведомое устройство Arduino с двумя мастерами, использующими одну и ту же шину I2C?
Библиотека SSD1306 использует *много* оперативной памяти. У вас могут быть проблемы из-за этого. Возможно, вам лучше использовать библиотеку «только для текста»: https://github.com/greiman/SSD1306Ascii., @Majenko