Updates to LCD firmware and service
This commit is contained in:
@@ -1,60 +0,0 @@
|
|||||||
#include <Wire.h>
|
|
||||||
#include <LiquidCrystal_PCF8574.h>
|
|
||||||
|
|
||||||
#define I2C_ADDR 0x27 // I2C address of the LCD module
|
|
||||||
#define SDA_PIN 8 // ESP32-C3 SuperMini SDA
|
|
||||||
#define SCL_PIN 9 // ESP32-C3 SuperMini SCL
|
|
||||||
|
|
||||||
LiquidCrystal_PCF8574 lcd(I2C_ADDR);
|
|
||||||
|
|
||||||
void setup() {
|
|
||||||
Serial.begin(115200); // USB/UART Serial for PC communication
|
|
||||||
Wire.begin(SDA_PIN, SCL_PIN); // Set I2C pins
|
|
||||||
|
|
||||||
// Initialize LCD
|
|
||||||
lcd.begin(16, 2);
|
|
||||||
lcd.setBacklight(255);
|
|
||||||
lcd.clear();
|
|
||||||
lcd.setCursor(2, 0);
|
|
||||||
lcd.print("ThermalTake");
|
|
||||||
lcd.setCursor(3, 1);
|
|
||||||
lcd.print("Tower 300");
|
|
||||||
|
|
||||||
Serial.println("ESP32-C3 SuperMini Ready");
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop() {
|
|
||||||
if (Serial.available()) {
|
|
||||||
String command = Serial.readStringUntil('\n'); // Read input from PC
|
|
||||||
command.trim();
|
|
||||||
|
|
||||||
if (command.startsWith("CMD:LCD,")) {
|
|
||||||
handleLCDCommand(command);
|
|
||||||
} else if (command == "CMD:GET_LCD_TYPE") {
|
|
||||||
Serial.println("LCD_TYPE:1602A");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse and execute LCD update command
|
|
||||||
void handleLCDCommand(String command) {
|
|
||||||
command.replace("CMD:LCD,", ""); // Remove the command header
|
|
||||||
int commaIndex = command.indexOf(',');
|
|
||||||
|
|
||||||
if (commaIndex == -1) return; // Invalid format
|
|
||||||
|
|
||||||
String lineNumber = command.substring(0, commaIndex);
|
|
||||||
String text = command.substring(commaIndex + 1);
|
|
||||||
|
|
||||||
int line = lineNumber.toInt();
|
|
||||||
if (line >= 0 && line < 2) { // Only two lines (0 and 1)
|
|
||||||
lcd.setCursor(0, line);
|
|
||||||
lcd.print(" "); // Clear line
|
|
||||||
lcd.setCursor(0, line);
|
|
||||||
lcd.print(text);
|
|
||||||
Serial.println("LCD Updated");
|
|
||||||
} else {
|
|
||||||
Serial.println("ERROR: Invalid LCD Line");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@ namespace PCPalConfigurator
|
|||||||
|
|
||||||
private static string GetConfigPath()
|
private static string GetConfigPath()
|
||||||
{
|
{
|
||||||
string folder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "ESP32Display");
|
string folder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "PCPal");
|
||||||
Directory.CreateDirectory(folder);
|
Directory.CreateDirectory(folder);
|
||||||
return Path.Combine(folder, "config.json");
|
return Path.Combine(folder, "config.json");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,32 +38,53 @@ namespace PCPalService
|
|||||||
{
|
{
|
||||||
Log("ESP32 Background Service Starting...");
|
Log("ESP32 Background Service Starting...");
|
||||||
|
|
||||||
try
|
while (!stoppingToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
string portName = AutoDetectESP32();
|
try
|
||||||
if (portName == null)
|
|
||||||
{
|
{
|
||||||
Log("ESP32-C3 not found. Service stopping...");
|
if (!File.Exists(ConfigFile))
|
||||||
throw new Exception("ESP32 not detected.");
|
{
|
||||||
|
Log("Config file not found. Retrying in 5 seconds...");
|
||||||
|
await Task.Delay(5000, stoppingToken);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var config = LoadConfig();
|
||||||
|
if (serialPort == null || !serialPort.IsOpen)
|
||||||
|
{
|
||||||
|
string portName = AutoDetectESP32();
|
||||||
|
if (portName != null)
|
||||||
|
{
|
||||||
|
serialPort = new SerialPort(portName, 115200);
|
||||||
|
serialPort.Open();
|
||||||
|
Log($"Connected to ESP32-C3 on {portName}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log("ESP32-C3 not found. Retrying in 5 seconds...");
|
||||||
|
await Task.Delay(5000, stoppingToken);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string line1 = GetLCDContent(config.Line1Selection, config.Line1CustomText, config.Line1PostText);
|
||||||
|
string line2 = GetLCDContent(config.Line2Selection, config.Line2CustomText, config.Line2PostText);
|
||||||
|
|
||||||
|
SendCommand($"CMD:LCD,0,{line1}");
|
||||||
|
SendCommand($"CMD:LCD,1,{line2}");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log($"Error in service loop: {ex.Message}");
|
||||||
}
|
}
|
||||||
|
|
||||||
serialPort = new SerialPort(portName, 115200);
|
await Task.Delay(5000, stoppingToken);
|
||||||
serialPort.Open();
|
}
|
||||||
Log($"Connected to ESP32-C3 on {portName}");
|
|
||||||
|
|
||||||
while (!stoppingToken.IsCancellationRequested)
|
serialPort?.Close();
|
||||||
{
|
|
||||||
UpdateLCD();
|
|
||||||
await Task.Delay(5000, stoppingToken);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Log($"Fatal Error: {ex.Message}");
|
|
||||||
Environment.Exit(1); // Force exit, triggering restart
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private string AutoDetectESP32()
|
private string AutoDetectESP32()
|
||||||
{
|
{
|
||||||
foreach (string port in SerialPort.GetPortNames())
|
foreach (string port in SerialPort.GetPortNames())
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
74
PCPal_ESP32C3_Firmware/PCPal_ESP32C3_Firmware.ino
Normal file
74
PCPal_ESP32C3_Firmware/PCPal_ESP32C3_Firmware.ino
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
#include <Wire.h>
|
||||||
|
#include <LiquidCrystal_PCF8574.h>
|
||||||
|
|
||||||
|
LiquidCrystal_PCF8574 lcd(0x27); // I2C address for 1602A LCD
|
||||||
|
|
||||||
|
unsigned long lastMessageTime = 0;
|
||||||
|
const unsigned long timeoutDuration = 10000;
|
||||||
|
|
||||||
|
enum DisplayState { SPLASH, WAITING, ACTIVE };
|
||||||
|
DisplayState state = SPLASH;
|
||||||
|
unsigned long splashStartTime;
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Wire.begin(8, 9); // SDA = GPIO 8, SCL = GPIO 9 (XIAO ESP32-C3)
|
||||||
|
lcd.begin(16, 2);
|
||||||
|
lcd.setBacklight(255);
|
||||||
|
Serial.begin(115200);
|
||||||
|
|
||||||
|
showSplashScreen();
|
||||||
|
splashStartTime = millis();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// Transition from splash to waiting after 5 seconds
|
||||||
|
if (state == SPLASH && millis() - splashStartTime >= 5000) {
|
||||||
|
showWaitingScreen();
|
||||||
|
state = WAITING;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process incoming commands from the PC
|
||||||
|
if (Serial.available()) {
|
||||||
|
String command = Serial.readStringUntil('\n');
|
||||||
|
command.trim();
|
||||||
|
|
||||||
|
if (command == "CMD:GET_LCD_TYPE") {
|
||||||
|
Serial.println("LCD_TYPE:1602A");
|
||||||
|
}
|
||||||
|
else if (command.startsWith("CMD:LCD,")) {
|
||||||
|
int line = command.charAt(8) - '0';
|
||||||
|
String text = command.substring(10);
|
||||||
|
text = text.substring(0, (text.length() < 16 ? text.length() : 16));
|
||||||
|
|
||||||
|
lcd.setCursor(0, line);
|
||||||
|
lcd.print(" "); // Clear line
|
||||||
|
lcd.setCursor(0, line);
|
||||||
|
lcd.print(text);
|
||||||
|
|
||||||
|
state = ACTIVE;
|
||||||
|
lastMessageTime = millis();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no message for a while, return to "waiting" screen
|
||||||
|
if (state == ACTIVE && millis() - lastMessageTime > timeoutDuration) {
|
||||||
|
showWaitingScreen();
|
||||||
|
state = WAITING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void showSplashScreen() {
|
||||||
|
lcd.clear();
|
||||||
|
lcd.setCursor(2, 0);
|
||||||
|
lcd.print("Thermaltake");
|
||||||
|
lcd.setCursor(3, 1);
|
||||||
|
lcd.print("Tower 300");
|
||||||
|
}
|
||||||
|
|
||||||
|
void showWaitingScreen() {
|
||||||
|
lcd.clear();
|
||||||
|
lcd.setCursor(0, 0);
|
||||||
|
lcd.print("Waiting for");
|
||||||
|
lcd.setCursor(0, 1);
|
||||||
|
lcd.print("connection...");
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user