diff --git a/platformio.ini b/platformio.ini index e76bcfb5..a829e1c7 100644 --- a/platformio.ini +++ b/platformio.ini @@ -167,6 +167,8 @@ lib_deps = AsyncTCP@1.0.3 Esp Async WebServer@1.2.0 IRremoteESP8266@2.7.3 + #For use of the TTGO T-Display ESP32 Module with integrated TFT display uncomment the following line + #TFT_eSPI #For use SSD1306 OLED display uncomment following #U8g2@~2.27.2 #For Dallas sensor uncomment following 2 lines diff --git a/usermods/TTGO-T-Display/README.md b/usermods/TTGO-T-Display/README.md new file mode 100644 index 00000000..58309e35 --- /dev/null +++ b/usermods/TTGO-T-Display/README.md @@ -0,0 +1,59 @@ +# TTGO T-Display ESP32 with 240x135 TFT via SPI with TFT_eSPI +This usermod allows use of the TTGO T-Display ESP32 module with integrated 240x135 display +for controlling WLED and showing the following information: +* Current SSID +* IP address if obtained + * in AP mode and turned off lightning AP password is shown +* Current effect +* Current palette + +Usermod based on a rework of the ssd1306_i2c_oled_u8g2 usermod from the WLED repo. + +## Hardware +![Hardware](assets/ttgo_hardware1.png) + +## Github reference for TTGO-Tdisplay + +* [TTGO T-Display](https://github.com/Xinyuan-LilyGO/TTGO-T-Display) + +## Requirements +Functionality checked with: +* TTGO T-Display +* PlatformIO +* Group of 4 individual Neopixels from Adafruit, and a full string of 68 LEDs. + +## Platformio Requirements +### Platformio.ini changes +Under the root folder of the project, in the `platformio.ini` file, uncomment the `TFT_eSPI` line within the [common] section, under `lib_deps`: +```ini +# platformio.ini +... +[common] +... +lib_deps = + ... + #For use of the TTGO T-Display ESP32 Module with integrated TFT display uncomment the following line + #TFT_eSPI +... +``` + +### Platformio_overrides.ini (added) +Copy the `platformio_overrides.ini` file which is contained in the `usermods/TTGO-T-Display/` folder into the root of your project folder. This file contains an override that remaps the button pin of WLED to use the on-board button to the right of the USB-C connector (when viewed with the port oriented downward - see hardware photo). + +### TFT_eSPI Library Adjustments (board selection) +NOTE: I am relatively new to Platformio and VS Code, but I find that in order to get the project populated with the TFT_eSPI library (so the following changes can be made), I need to attempt an initial build that I know will fail. There is probably a better way to accomplish this, but it worked for me. Once the first build fails, the `User_Setup_Select.h` file can be found in the `/.pio/libdeps/esp32dev/TFT_eSPI_ID1559` folder. + +Modify the `User_Setup_Select.h` file as follows: +* Comment out the following line (which is the 'default' setup file): +```ini +//#include // Default setup is root library folder +``` +* Uncomment the following line (which points to the setup file for the TTGO T-Display): +```ini +#include // Setup file for ESP32 and TTGO T-Display ST7789V SPI bus TFT +``` + +Run the build again and it should complete correctly. + +## Arduino IDE +- UNTESTED \ No newline at end of file diff --git a/usermods/TTGO-T-Display/assets/ttgo_hardware1.png b/usermods/TTGO-T-Display/assets/ttgo_hardware1.png new file mode 100644 index 00000000..42d338db Binary files /dev/null and b/usermods/TTGO-T-Display/assets/ttgo_hardware1.png differ diff --git a/usermods/TTGO-T-Display/platformio_override.ini b/usermods/TTGO-T-Display/platformio_override.ini new file mode 100644 index 00000000..4b176096 --- /dev/null +++ b/usermods/TTGO-T-Display/platformio_override.ini @@ -0,0 +1,8 @@ +[env:esp32dev] +build_flags = ${common.build_flags_esp32} +; PIN defines - uncomment and change, if needed: +; -D LEDPIN=2 + -D BTNPIN=35 +; -D IR_PIN=4 +; -D RLYPIN=12 +; -D RLYMDE=1 diff --git a/usermods/TTGO-T-Display/usermod.cpp b/usermods/TTGO-T-Display/usermod.cpp new file mode 100644 index 00000000..a4bb28c8 --- /dev/null +++ b/usermods/TTGO-T-Display/usermod.cpp @@ -0,0 +1,214 @@ + +/* + * This file allows you to add own functionality to WLED more easily + * See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality + * EEPROM bytes 2750+ are reserved for your custom use case. (if you extend #define EEPSIZE in const.h) + * bytes 2400+ are currently ununsed, but might be used for future wled features + */ + +/* + * Pin 2 of the TTGO T-Display serves as the data line for the LED string. + * Pin 35 is set up as the button pin in the platformio_overrides.ini file. + * The button can be set up via the macros section in the web interface. + * I use the button to cycle between presets. + * The Pin 35 button is the one on the RIGHT side of the USB-C port on the board, + * when the port is oriented downwards. See readme.md file for photo. + * The display is set up to turn off after 5 minutes, and turns on automatically + * when a change in the dipslayed info is detected (within a 5 second interval). + */ + + +//Use userVar0 and userVar1 (API calls &U0=,&U1=, uint16_t) + +#include "wled.h" +#include +#include +#include "WiFi.h" +#include + +#ifndef TFT_DISPOFF +#define TFT_DISPOFF 0x28 +#endif + +#ifndef TFT_SLPIN +#define TFT_SLPIN 0x10 +#endif + +#define TFT_MOSI 19 +#define TFT_SCLK 18 +#define TFT_CS 5 +#define TFT_DC 16 +#define TFT_RST 23 + +#define TFT_BL 4 // Display backlight control pin +#define ADC_EN 14 // Used for enabling battery voltage measurements - not used in this program + +TFT_eSPI tft = TFT_eSPI(135, 240); // Invoke custom library + +//gets called once at boot. Do all initialization that doesn't depend on network here +void userSetup() { + Serial.begin(115200); + Serial.println("Start"); + tft.init(); + tft.setRotation(3); //Rotation here is set up for the text to be readable with the port on the left. Use 1 to flip. + tft.fillScreen(TFT_BLACK); + tft.setTextSize(2); + tft.setTextColor(TFT_WHITE); + tft.setCursor(1, 10); + tft.setTextDatum(MC_DATUM); + tft.setTextSize(2); + tft.print("Loading..."); + + if (TFT_BL > 0) { // TFT_BL has been set in the TFT_eSPI library in the User Setup file TTGO_T_Display.h + pinMode(TFT_BL, OUTPUT); // Set backlight pin to output mode + digitalWrite(TFT_BL, HIGH); // Turn backlight on. + } + + // tft.setRotation(3); +} + +// gets called every time WiFi is (re-)connected. Initialize own network +// interfaces here +void userConnected() {} + +// needRedraw marks if redraw is required to prevent often redrawing. +bool needRedraw = true; + +// Next variables hold the previous known values to determine if redraw is +// required. +String knownSsid = ""; +IPAddress knownIp; +uint8_t knownBrightness = 0; +uint8_t knownMode = 0; +uint8_t knownPalette = 0; +uint8_t tftcharwidth = 19; // Number of chars that fit on screen with text size set to 2 + +long lastUpdate = 0; +long lastRedraw = 0; +bool displayTurnedOff = false; +// How often we are redrawing screen +#define USER_LOOP_REFRESH_RATE_MS 5000 + +void userLoop() { + + // Check if we time interval for redrawing passes. + if (millis() - lastUpdate < USER_LOOP_REFRESH_RATE_MS) { + return; + } + lastUpdate = millis(); + + // Turn off display after 5 minutes with no change. + if(!displayTurnedOff && millis() - lastRedraw > 5*60*1000) { + digitalWrite(TFT_BL, LOW); // Turn backlight off. + displayTurnedOff = true; + } + + // Check if values which are shown on display changed from the last time. + if (((apActive) ? String(apSSID) : WiFi.SSID()) != knownSsid) { + needRedraw = true; + } else if (knownIp != (apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP())) { + needRedraw = true; + } else if (knownBrightness != bri) { + needRedraw = true; + } else if (knownMode != strip.getMode()) { + needRedraw = true; + } else if (knownPalette != strip.getSegment(0).palette) { + needRedraw = true; + } + + if (!needRedraw) { + return; + } + needRedraw = false; + + if (displayTurnedOff) + { + digitalWrite(TFT_BL, TFT_BACKLIGHT_ON); // Turn backlight on. + displayTurnedOff = false; + } + lastRedraw = millis(); + + // Update last known values. + #if defined(ESP8266) + knownSsid = apActive ? WiFi.softAPSSID() : WiFi.SSID(); + #else + knownSsid = WiFi.SSID(); + #endif + knownIp = apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP(); + knownBrightness = bri; + knownMode = strip.getMode(); + knownPalette = strip.getSegment(0).palette; + + tft.fillScreen(TFT_BLACK); + tft.setTextSize(2); + // First row with Wifi name + tft.setCursor(1, 10); + tft.print(knownSsid.substring(0, tftcharwidth > 1 ? tftcharwidth - 1 : 0)); + // Print `~` char to indicate that SSID is longer, than our dicplay + if (knownSsid.length() > tftcharwidth) + tft.print("~"); + + // Second row with IP or Psssword + tft.setCursor(1, 40); + // Print password in AP mode and if led is OFF. + if (apActive && bri == 0) + tft.print(apPass); + else + tft.print(knownIp); + + // Third row with mode name + tft.setCursor(1, 70); + uint8_t qComma = 0; + bool insideQuotes = false; + uint8_t printedChars = 0; + char singleJsonSymbol; + // Find the mode name in JSON + for (size_t i = 0; i < strlen_P(JSON_mode_names); i++) { + singleJsonSymbol = pgm_read_byte_near(JSON_mode_names + i); + switch (singleJsonSymbol) { + case '"': + insideQuotes = !insideQuotes; + break; + case '[': + case ']': + break; + case ',': + qComma++; + default: + if (!insideQuotes || (qComma != knownMode)) + break; + tft.print(singleJsonSymbol); + printedChars++; + } + if ((qComma > knownMode) || (printedChars > tftcharwidth - 1)) + break; + } + // Fourth row with palette name + tft.setCursor(1, 100); + qComma = 0; + insideQuotes = false; + printedChars = 0; + // Looking for palette name in JSON. + for (size_t i = 0; i < strlen_P(JSON_palette_names); i++) { + singleJsonSymbol = pgm_read_byte_near(JSON_palette_names + i); + switch (singleJsonSymbol) { + case '"': + insideQuotes = !insideQuotes; + break; + case '[': + case ']': + break; + case ',': + qComma++; + default: + if (!insideQuotes || (qComma != knownPalette)) + break; + tft.print(singleJsonSymbol); + printedChars++; + } + // The following is modified from the code from the u8g2/u8g8 based code (knownPalette was knownMode) + if ((qComma > knownPalette) || (printedChars > tftcharwidth - 1)) + break; + } + +} \ No newline at end of file