firmware: scaffold optional cargo OLED display
This commit is contained in:
@@ -3,6 +3,15 @@
|
||||
#include <Preferences.h>
|
||||
#include <esp_wifi.h>
|
||||
#include <esp_system.h>
|
||||
|
||||
#define OLED_ENABLED 0
|
||||
|
||||
#if OLED_ENABLED
|
||||
#include <Wire.h>
|
||||
#include <Adafruit_GFX.h>
|
||||
#include <Adafruit_SSD1306.h>
|
||||
#endif
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
#include "config.h"
|
||||
@@ -1163,6 +1172,231 @@ void handleUpdateApConfig() {
|
||||
server.send(200, "application/json", output);
|
||||
}
|
||||
|
||||
|
||||
#if OLED_ENABLED
|
||||
const int OLED_SCREEN_WIDTH = 128;
|
||||
const int OLED_SCREEN_HEIGHT = 64;
|
||||
const int OLED_RESET_PIN = -1;
|
||||
const uint8_t OLED_I2C_ADDR = 0x3C;
|
||||
|
||||
// Default ESP32 I2C pins. Change these if the cargo controller wiring uses a different I2C bus.
|
||||
const int OLED_I2C_SDA = 21;
|
||||
const int OLED_I2C_SCL = 22;
|
||||
|
||||
// Optional future setup/status button. Leave disabled until hardware is wired.
|
||||
const int OLED_BUTTON_PIN = -1;
|
||||
|
||||
Adafruit_SSD1306 oled(OLED_SCREEN_WIDTH, OLED_SCREEN_HEIGHT, &Wire, OLED_RESET_PIN);
|
||||
|
||||
bool oledReady = false;
|
||||
unsigned long lastOledUpdateMs = 0;
|
||||
unsigned long lastOledPageChangeMs = 0;
|
||||
uint8_t oledPage = 0;
|
||||
|
||||
void oledClear(const char* title) {
|
||||
oled.clearDisplay();
|
||||
oled.setTextSize(1);
|
||||
oled.setTextColor(SSD1306_WHITE);
|
||||
oled.setCursor(0, 0);
|
||||
oled.println(title);
|
||||
oled.drawLine(0, 10, OLED_SCREEN_WIDTH - 1, 10, SSD1306_WHITE);
|
||||
}
|
||||
|
||||
void oledPrintTrimmed(const String& value, int maxChars = 21) {
|
||||
if (value.length() <= maxChars) {
|
||||
oled.println(value);
|
||||
} else {
|
||||
oled.println(value.substring(0, maxChars));
|
||||
}
|
||||
}
|
||||
|
||||
void oledShowBoot() {
|
||||
if (!oledReady) return;
|
||||
|
||||
oledClear("Overland Controller");
|
||||
oled.setCursor(0, 18);
|
||||
oled.println("Booting...");
|
||||
oled.println();
|
||||
oled.println("Cargo Controller");
|
||||
oled.display();
|
||||
}
|
||||
|
||||
void oledShowSetupPage() {
|
||||
if (!oledReady) return;
|
||||
|
||||
oledClear("Setup / AP");
|
||||
oled.setCursor(0, 14);
|
||||
oled.print("SSID: ");
|
||||
oledPrintTrimmed(apSsid, 15);
|
||||
oled.print("PASS: ");
|
||||
oledPrintTrimmed(apPassword, 15);
|
||||
oled.print("IP: ");
|
||||
oled.println(WiFi.softAPIP());
|
||||
oled.display();
|
||||
}
|
||||
|
||||
void oledShowBatteryPage() {
|
||||
if (!oledReady) return;
|
||||
|
||||
oledClear("Battery");
|
||||
oled.setCursor(0, 16);
|
||||
|
||||
if (bmsData.valid) {
|
||||
oled.print("SOC: ");
|
||||
oled.print(bmsData.soc);
|
||||
oled.println("%");
|
||||
|
||||
oled.print("V: ");
|
||||
oled.print(bmsData.voltage, 2);
|
||||
oled.println("V");
|
||||
|
||||
oled.print("A: ");
|
||||
oled.print(bmsData.current, 1);
|
||||
oled.println("A");
|
||||
|
||||
oled.print("Temp: ");
|
||||
oled.print(bmsData.temperatureF, 1);
|
||||
oled.println("F");
|
||||
} else {
|
||||
oled.println("BMS unavailable");
|
||||
oled.println();
|
||||
oled.println("Check BLE/config");
|
||||
}
|
||||
|
||||
oled.display();
|
||||
}
|
||||
|
||||
void oledShowRelayPage() {
|
||||
if (!oledReady) return;
|
||||
|
||||
oledClear("Relays");
|
||||
oled.setCursor(0, 16);
|
||||
|
||||
oled.print(appConfig.relays[0].name);
|
||||
oled.print(": ");
|
||||
oled.println(relays.relay1 ? "ON" : "OFF");
|
||||
|
||||
oled.print(appConfig.relays[1].name);
|
||||
oled.print(": ");
|
||||
oled.println(relays.relay2 ? "ON" : "OFF");
|
||||
|
||||
oled.display();
|
||||
}
|
||||
|
||||
void oledShowNetworkPage() {
|
||||
if (!oledReady) return;
|
||||
|
||||
oledClear("Network");
|
||||
oled.setCursor(0, 14);
|
||||
|
||||
oled.print("AP: ");
|
||||
oledPrintTrimmed(apSsid, 17);
|
||||
|
||||
oled.print("AP IP: ");
|
||||
oled.println(WiFi.softAPIP());
|
||||
|
||||
oled.print("STA: ");
|
||||
if (WiFi.status() == WL_CONNECTED) {
|
||||
oled.println(WiFi.localIP());
|
||||
} else {
|
||||
oled.println("not connected");
|
||||
}
|
||||
|
||||
oled.display();
|
||||
}
|
||||
|
||||
void oledShowAlarmPage() {
|
||||
if (!oledReady) return;
|
||||
|
||||
oledClear("Alarms");
|
||||
oled.setCursor(0, 14);
|
||||
|
||||
bool any = false;
|
||||
|
||||
if (alarms.lowSoc) {
|
||||
oled.println("LOW SOC");
|
||||
any = true;
|
||||
}
|
||||
if (alarms.criticalSoc) {
|
||||
oled.println("CRITICAL SOC");
|
||||
any = true;
|
||||
}
|
||||
if (alarms.bmsDisconnected) {
|
||||
oled.println("BMS DISCONNECTED");
|
||||
any = true;
|
||||
}
|
||||
if (alarms.highBatteryTemp) {
|
||||
oled.println("HIGH BATT TEMP");
|
||||
any = true;
|
||||
}
|
||||
if (alarms.cellImbalance) {
|
||||
oled.println("CELL IMBALANCE");
|
||||
any = true;
|
||||
}
|
||||
|
||||
if (!any) {
|
||||
oled.println("No active alarms");
|
||||
}
|
||||
|
||||
oled.display();
|
||||
}
|
||||
|
||||
void oledRenderPage() {
|
||||
switch (oledPage) {
|
||||
case 0:
|
||||
oledShowBatteryPage();
|
||||
break;
|
||||
case 1:
|
||||
oledShowRelayPage();
|
||||
break;
|
||||
case 2:
|
||||
oledShowNetworkPage();
|
||||
break;
|
||||
case 3:
|
||||
oledShowAlarmPage();
|
||||
break;
|
||||
default:
|
||||
oledPage = 0;
|
||||
oledShowBatteryPage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void oledBegin() {
|
||||
Wire.begin(OLED_I2C_SDA, OLED_I2C_SCL);
|
||||
|
||||
oledReady = oled.begin(SSD1306_SWITCHCAPVCC, OLED_I2C_ADDR);
|
||||
|
||||
if (!oledReady) {
|
||||
Serial.println("OLED not detected");
|
||||
return;
|
||||
}
|
||||
|
||||
Serial.println("OLED initialized");
|
||||
oledShowBoot();
|
||||
}
|
||||
|
||||
void oledLoop() {
|
||||
if (!oledReady) return;
|
||||
|
||||
unsigned long now = millis();
|
||||
|
||||
if (now - lastOledPageChangeMs > 5000) {
|
||||
oledPage = (oledPage + 1) % 4;
|
||||
lastOledPageChangeMs = now;
|
||||
}
|
||||
|
||||
if (now - lastOledUpdateMs > 1000) {
|
||||
oledRenderPage();
|
||||
lastOledUpdateMs = now;
|
||||
}
|
||||
}
|
||||
#else
|
||||
void oledBegin() {}
|
||||
void oledShowSetupPage() {}
|
||||
void oledLoop() {}
|
||||
#endif
|
||||
|
||||
int findNextWifiIndexByPriority(bool tried[]) {
|
||||
int bestIndex = -1;
|
||||
int bestPriority = 1000000;
|
||||
@@ -3139,6 +3373,8 @@ void setup() {
|
||||
Serial.println("Overland Controller Booting");
|
||||
Serial.println("==================================");
|
||||
|
||||
oledBegin();
|
||||
|
||||
loadConfig();
|
||||
printConfig();
|
||||
|
||||
@@ -3153,6 +3389,7 @@ void setup() {
|
||||
|
||||
WiFi.mode(WIFI_AP_STA);
|
||||
startAccessPoint();
|
||||
oledShowSetupPage();
|
||||
|
||||
connectStaWifi();
|
||||
|
||||
@@ -3235,6 +3472,7 @@ void loop() {
|
||||
updateBms();
|
||||
updateAlarms();
|
||||
pollDashboardUart();
|
||||
oledLoop();
|
||||
|
||||
static unsigned long lastSensorUpdate = 0;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user