From d18662d9261170ce35499676deeef92ff840df42 Mon Sep 17 00:00:00 2001 From: Malko Gindrat Date: Wed, 20 May 2026 09:33:38 +0200 Subject: [PATCH] initial T-Beam Supreme listener --- platformio.ini | 14 ++++-- src/main.cpp | 120 ++++++++++++++++++++++++++++++++++++------------- 2 files changed, 100 insertions(+), 34 deletions(-) diff --git a/platformio.ini b/platformio.ini index 8d5edec..386aadb 100644 --- a/platformio.ini +++ b/platformio.ini @@ -8,14 +8,20 @@ ; Please visit documentation for the other options and examples ; https://docs.platformio.org/page/projectconf.html -[env:lilygo-t3-s3] +[env:t-beam-supreme] platform = espressif32 -board = lilygo-t3-s3 +board = esp32-s3-devkitc-1 framework = arduino + monitor_speed = 115200 +upload_speed = 921600 + build_flags = -D ARDUINO_USB_CDC_ON_BOOT=1 + -D ARDUINO_USB_MODE=1 + lib_deps = jgromes/RadioLib - adafruit/Adafruit SSD1306 - adafruit/Adafruit GFX Library \ No newline at end of file + adafruit/Adafruit GFX Library + adafruit/Adafruit SH110X + lewisxhe/XPowersLib \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index e75cec6..f312a87 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,26 +3,40 @@ #include #include #include -#include +#include +#define XPOWERS_CHIP_AXP2101 +#include -// LoRa pins - LilyGO T3S3 SX1262 -static const int PIN_LORA_SCK = 5; -static const int PIN_LORA_MISO = 3; -static const int PIN_LORA_MOSI = 6; -static const int PIN_LORA_CS = 7; -static const int PIN_LORA_RST = 8; -static const int PIN_LORA_DIO1 = 33; -static const int PIN_LORA_BUSY = 34; +// LilyGO T-Beam Supreme V3.0 / ESP32-S3 / SX1262 / u-blox MAX-M10S +// Pin values follow LilyGO's T_BEAM_S3_SUPREME_SX1262 definitions. +// LoRa pins - T-Beam Supreme SX1262 +static const int PIN_LORA_SCK = 12; +static const int PIN_LORA_MISO = 13; +static const int PIN_LORA_MOSI = 11; +static const int PIN_LORA_CS = 10; +static const int PIN_LORA_RST = 5; +static const int PIN_LORA_DIO1 = 1; +static const int PIN_LORA_BUSY = 4; -// OLED pins - LilyGO T3S3 OLED -static const int OLED_SDA = 18; -static const int OLED_SCL = 17; +// OLED pins - T-Beam Supreme SH1106, I2C bus 0 +static const int OLED_SDA = 17; +static const int OLED_SCL = 18; static const int OLED_ADDR = 0x3C; static const int SCREEN_WIDTH = 128; static const int SCREEN_HEIGHT = 64; +// PMU pins - AXP2101, I2C bus 1 +static const int PMU_SDA = 42; +static const int PMU_SCL = 41; + +// GPS pins - u-blox MAX-M10S +static const int GPS_RX_PIN = 9; // ESP32 RX, connect to GPS TX +static const int GPS_TX_PIN = 8; // ESP32 TX, connect to GPS RX +static const int GPS_EN_PIN = 7; +static const uint32_t GPS_BAUD = 9600; + // ACTIVE PROFILE (Shelly / custom LoRa) static const float LORA_FREQ_MHZ = 865.000; static const float LORA_BW_KHZ = 125.0; @@ -36,7 +50,6 @@ static const bool LORA_USE_LDO = false; static const bool LORA_USE_CRC = false; static const bool LORA_EXPLICIT_HDR = true; - // MESHCORE SWITZERLAND PROFILE (COMMENTED) /* static const float LORA_FREQ_MHZ = 869.618; @@ -52,9 +65,11 @@ static const bool LORA_USE_CRC = true; static const bool LORA_EXPLICIT_HDR = true; */ - // Objects -Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1); +TwoWire PMUWire = TwoWire(1); +XPowersPMU PMU; +Adafruit_SH1106G display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1); +HardwareSerial GPSSerial(1); SX1262 radio = new Module(PIN_LORA_CS, PIN_LORA_DIO1, PIN_LORA_RST, PIN_LORA_BUSY); // Runtime state @@ -64,6 +79,7 @@ float lastSnr = 0.0; unsigned long rxCount = 0; unsigned long lastIdleRefresh = 0; unsigned long showPacketUntil = 0; +bool pmuOk = false; // Helpers String formatCR(uint8_t cr) { @@ -76,15 +92,13 @@ String formatHexByte(uint8_t value) { return String(buf); } -// Draw one line safely void drawLine(int x, int y, const String& text) { display.setCursor(x, y); display.print(text); } -// Simple text wrapper for packet display void drawWrappedText(const String& text, int startY, int maxLines) { - const int charsPerLine = 21; // approx for 128 px at text size 1 + const int charsPerLine = 21; int len = text.length(); int index = 0; int line = 0; @@ -100,10 +114,10 @@ void drawWrappedText(const String& text, int startY, int maxLines) { void drawListeningScreen() { display.clearDisplay(); display.setTextSize(1); - display.setTextColor(SSD1306_WHITE); + display.setTextColor(SH110X_WHITE); - drawLine(0, 0, "Listening"); - drawLine(70, 0, String(rxCount) + " pk"); + drawLine(0, 0, "T-Beam Supreme RX"); + drawLine(92, 0, String(rxCount)); drawLine(0, 10, "F:" + String(LORA_FREQ_MHZ, 3)); drawLine(0, 20, "BW:" + String(LORA_BW_KHZ, 1) + " SF:" + String(LORA_SF)); @@ -118,7 +132,7 @@ void drawListeningScreen() { void drawPacketScreen() { display.clearDisplay(); display.setTextSize(1); - display.setTextColor(SSD1306_WHITE); + display.setTextColor(SH110X_WHITE); drawLine(0, 0, "PACKET RECEIVED"); drawLine(0, 10, "RSSI:" + String(lastRssi, 1) + " SNR:" + String(lastSnr, 1)); @@ -133,7 +147,7 @@ void drawPacketScreen() { void drawErrorScreen(const String& title, int code) { display.clearDisplay(); display.setTextSize(1); - display.setTextColor(SSD1306_WHITE); + display.setTextColor(SH110X_WHITE); drawLine(0, 0, title); drawLine(0, 12, "code: " + String(code)); @@ -141,27 +155,69 @@ void drawErrorScreen(const String& title, int code) { display.display(); } +void initPower() { + PMUWire.begin(PMU_SDA, PMU_SCL); + pmuOk = PMU.begin(PMUWire, AXP2101_SLAVE_ADDRESS, PMU_SDA, PMU_SCL); + + if (!pmuOk) { + Serial.println("PMU init failed - continuing, but OLED/LoRa/GPS power may be off"); + return; + } + + // T-Beam Supreme PMU channels: + // ALDO1 = BME280 + display + magnetometer + // ALDO3 = radio + // ALDO4 = GPS + PMU.setALDO1Voltage(3300); + PMU.enableALDO1(); + + PMU.setALDO3Voltage(3300); + PMU.enableALDO3(); + + PMU.setALDO4Voltage(3300); + PMU.enableALDO4(); + + PMU.disableTSPinMeasure(); + PMU.enableBattVoltageMeasure(); + PMU.enableVbusVoltageMeasure(); + + Serial.print("PMU AXP2101 OK, chip ID: 0x"); + Serial.println(PMU.getChipID(), HEX); +} + +void initGpsPowerOnly() { + pinMode(GPS_EN_PIN, OUTPUT); + digitalWrite(GPS_EN_PIN, HIGH); + GPSSerial.begin(GPS_BAUD, SERIAL_8N1, GPS_RX_PIN, GPS_TX_PIN); + Serial.println("GPS UART started, GPS data not parsed in this listener sketch"); +} + void setup() { Serial.begin(115200); delay(1500); + initPower(); + delay(200); + Wire.begin(OLED_SDA, OLED_SCL); - if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) { - Serial.println("OLED init failed"); + if (!display.begin(OLED_ADDR, true)) { + Serial.println("SH1106 OLED init failed"); while (true) delay(1000); } display.clearDisplay(); display.setTextSize(1); - display.setTextColor(SSD1306_WHITE); + display.setTextColor(SH110X_WHITE); drawLine(0, 0, "Booting..."); display.display(); + initGpsPowerOnly(); + SPI.begin(PIN_LORA_SCK, PIN_LORA_MISO, PIN_LORA_MOSI, PIN_LORA_CS); Serial.println(); - Serial.println("Starting LoRa receiver..."); + Serial.println("Starting LoRa receiver on T-Beam Supreme..."); int state = radio.begin( LORA_FREQ_MHZ, @@ -226,18 +282,22 @@ void loop() { Serial.println(); drawPacketScreen(); - showPacketUntil = millis() + 2500; // show packet screen for 2.5 s + showPacketUntil = millis() + 2500; } else if (state != RADIOLIB_ERR_RX_TIMEOUT) { Serial.print("Receive failed, code "); Serial.println(state); } - // after packet screen timeout, return to listening screen + // Drain GPS UART to avoid buffer filling. This sketch does not parse GPS. + while (GPSSerial.available()) { + Serial.write(GPSSerial.read()); + } + if (millis() > showPacketUntil) { if (millis() - lastIdleRefresh > 500) { drawListeningScreen(); lastIdleRefresh = millis(); } } -} \ No newline at end of file +}