Change Display handler to also use widely used Adafruit library

This commit is contained in:
André Fiedler 2025-02-15 18:18:09 +01:00
parent a8596314ff
commit f5f663771f
3 changed files with 86 additions and 32 deletions

View File

@ -15,12 +15,11 @@ framework = arduino
monitor_speed = 115200 monitor_speed = 115200
lib_deps = lib_deps =
knolleary/PubSubClient@^2.8 knolleary/PubSubClient@^2.8
thingpulse/ESP8266 and ESP32 OLED driver for SSD1306 displays@^4.3.0
miguelbalboa/MFRC522@^1.4.10
thijse/ArduinoLog@^1.1.1 thijse/ArduinoLog@^1.1.1
uipethernet/UIPEthernet@^2.0.12 uipethernet/UIPEthernet@^2.0.12
bblanchon/ArduinoJson@^6.19.4 bblanchon/ArduinoJson@^6.19.4
mbed-feb11/Crypto@0.0.0+sha.f04410cef037 mbed-feb11/Crypto@0.0.0+sha.f04410cef037
adafruit/Adafruit PN532@^1.3.3 adafruit/Adafruit PN532@^1.3.3
adafruit/Adafruit SSD1306@^2.5.13
build_flags = build_flags =
-D PN532_I2C_ADDRESS=0x24 -D PN532_I2C_ADDRESS=0x24

View File

@ -1,28 +1,49 @@
#include <Display.h> #include "Display.h"
#include <SSD1306Wire.h> #include <Wire.h>
#include <stdio.h>
#include <string.h>
// Constructor: initializes I2C, creates the display object,
// initializes the display, clears it, and sets an initial rotation.
Display::Display(int sda, int scl, int readerid) Display::Display(int sda, int scl, int readerid)
{ {
this->readerid = readerid; this->readerid = readerid;
display = new SSD1306Wire(0x3c, sda, scl);
display->init();
display->setTextAlignment(TEXT_ALIGN_CENTER);
display->flipScreenVertically();
// Initialize I2C with custom SDA and SCL pins.
Wire.begin(sda, scl);
// Create display object (128x64) using I2C and default I2C address 0x3C.
display = new Adafruit_SSD1306(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
if (!display->begin(SSD1306_SWITCHCAPVCC, 0x3C))
{
Serial.println("SSD1306 allocation failed");
while (1)
{
yield(); // Infinite loop if display initialization fails
}
}
display->clearDisplay();
// Flip the display vertically (if needed)
display->setRotation(0);
// Initialize text buffers.
ReaderInfo[0] = '\0'; // Empty string ReaderInfo[0] = '\0'; // Empty string
strcpy(Title, "Boot ..."); // Set initial title strcpy(Title, "Boot ..."); // Initial title
Info[0] = '\0'; // Empty string Info[0] = '\0'; // Empty string
} }
void Display::clearReaderInfo() void Display::clearReaderInfo()
{ {
char buffer[DISPLAY_BUFFER_SIZE]; char buffer[DISPLAY_BUFFER_SIZE];
// Format the reader id as a 5-digit number.
sprintf(buffer, "%05d", readerid); sprintf(buffer, "%05d", readerid);
writeReaderInfo(buffer); writeReaderInfo(buffer);
} }
void Display::createReaderInfo(const char *state) void Display::createReaderInfo(const char *state)
{ {
// Ensure there is enough room in the buffer (6 extra chars for the readerid)
if (strlen(state) < DISPLAY_BUFFER_SIZE - 1 - 6) if (strlen(state) < DISPLAY_BUFFER_SIZE - 1 - 6)
{ {
char buffer[DISPLAY_BUFFER_SIZE]; char buffer[DISPLAY_BUFFER_SIZE];
@ -55,50 +76,71 @@ void Display::writeInfo(const char *text)
{ {
strcpy(Info, text); strcpy(Info, text);
} }
updateDisplay(); updateDisplay();
} }
// Helper: Draws the given text centered horizontally at vertical position y.
void Display::drawCenteredText(const char *text, int y)
{
int16_t x1, y1;
uint16_t w, h;
// Get the bounding box of the text.
display->getTextBounds(text, 0, y, &x1, &y1, &w, &h);
int x = (SCREEN_WIDTH - w) / 2;
display->setCursor(x, y);
display->print(text);
}
void Display::updateDisplay() void Display::updateDisplay()
{ {
display->clear(); display->clearDisplay();
display->setFont(ArialMT_Plain_10); // Draw ReaderInfo (using text size 1)
display->drawString(64, 0, ReaderInfo); display->setTextSize(1);
display->setTextColor(SSD1306_WHITE);
drawCenteredText(ReaderInfo, 0);
display->setFont(ArialMT_Plain_24); // Draw Title (using text size 2 for emphasis)
display->drawString(64, 13, Title); display->setTextSize(2);
// The y-coordinate is chosen to leave room for the first line.
drawCenteredText(Title, 16);
display->setFont(ArialMT_Plain_16); // Draw Info (using text size 1)
display->drawString(64, 40, Info); display->setTextSize(1);
drawCenteredText(Info, 40);
display->display(); display->display();
} }
void Display::updateByMQTT(const char *topic, byte *payload, unsigned int length) void Display::updateByMQTT(const char *topic, byte *payload, unsigned int length)
{ {
char topic_displayTitle[] = "fabreader/00000/display/title"; // Build expected MQTT topics for title, info, and stopping OTA.
sprintf(topic_displayTitle, "fabreader/%05d/display/title", readerid); char topic_displayTitle[32];
snprintf(topic_displayTitle, sizeof(topic_displayTitle), "fabreader/%05d/display/title", readerid);
char topic_displayInfo[] = "fabreader/00000/display/info"; char topic_displayInfo[32];
sprintf(topic_displayInfo, "fabreader/%05d/display/info", readerid); snprintf(topic_displayInfo, sizeof(topic_displayInfo), "fabreader/%05d/display/info", readerid);
char topic_stopOTA[] = "fabreader/00000/stopOTA"; char topic_stopOTA[32];
sprintf(topic_stopOTA, "fabreader/%05d/stopOTA", readerid); snprintf(topic_stopOTA, sizeof(topic_stopOTA), "fabreader/%05d/stopOTA", readerid);
// Copy the payload into a null-terminated string.
char *buffer = new char[length + 1]; char *buffer = new char[length + 1];
memcpy(buffer, payload, length); memcpy(buffer, payload, length);
buffer[length] = '\0';
if (!strcmp(topic, topic_displayTitle)) // Update display based on the topic.
if (strcmp(topic, topic_displayTitle) == 0)
{ {
writeTitle(buffer); writeTitle(buffer);
} }
else if (!strcmp(topic, topic_displayInfo)) else if (strcmp(topic, topic_displayInfo) == 0)
{ {
writeInfo(buffer); writeInfo(buffer);
} }
else if (!strcmp(topic, topic_stopOTA)) else if (strcmp(topic, topic_stopOTA) == 0)
{ {
clearReaderInfo(); clearReaderInfo();
} }
delete[] buffer;
} }

View File

@ -1,20 +1,32 @@
#ifndef DISPLAY_H #ifndef DISPLAY_H
#define DISPLAY_H #define DISPLAY_H
#include <SSD1306Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define DISPLAY_BUFFER_SIZE 30 #define DISPLAY_BUFFER_SIZE 30
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset)
class Display class Display
{ {
private: private:
SSD1306Wire *display; Adafruit_SSD1306 *display;
int readerid; int readerid;
char ReaderInfo[DISPLAY_BUFFER_SIZE]; char ReaderInfo[DISPLAY_BUFFER_SIZE];
char Title[DISPLAY_BUFFER_SIZE]; char Title[DISPLAY_BUFFER_SIZE];
char Info[DISPLAY_BUFFER_SIZE]; char Info[DISPLAY_BUFFER_SIZE];
// Helper function to center text horizontally at a given y coordinate.
void drawCenteredText(const char *text, int y);
public: public:
// The constructor takes the SDA and SCL pins (which are used to initialize Wire)
// and the reader ID.
Display(int sda, int scl, int readerid); Display(int sda, int scl, int readerid);
void createReaderInfo(const char *state); void createReaderInfo(const char *state);
void clearReaderInfo(); void clearReaderInfo();
void writeReaderInfo(const char *text); void writeReaderInfo(const char *text);
@ -23,4 +35,5 @@ public:
void updateDisplay(); void updateDisplay();
void updateByMQTT(const char *topic, byte *payload, unsigned int length); void updateByMQTT(const char *topic, byte *payload, unsigned int length);
}; };
#endif #endif