From f322abceb86d19d8649b93f083e5f9de2c85211d Mon Sep 17 00:00:00 2001 From: Ivan Boyarkin Date: Thu, 28 Nov 2019 22:34:13 +0100 Subject: [PATCH] usermods: Add SSD1306 display with u8g2 This commit adds example of usermod file for displaying basic infromation SSD1306 I2C OLED displya utilizing u8g2 library. Related to: https://github.com/Aircoookie/WLED/issues/389 --- usermods/ssd1306_i2c_oled_u8g2/README.md | 35 ++++ .../assets/hw_connection.png | Bin 0 -> 34900 bytes .../ssd1306_i2c_oled_u8g2/wled06_usermod.ino | 149 ++++++++++++++++++ 3 files changed, 184 insertions(+) create mode 100644 usermods/ssd1306_i2c_oled_u8g2/README.md create mode 100644 usermods/ssd1306_i2c_oled_u8g2/assets/hw_connection.png create mode 100644 usermods/ssd1306_i2c_oled_u8g2/wled06_usermod.ino diff --git a/usermods/ssd1306_i2c_oled_u8g2/README.md b/usermods/ssd1306_i2c_oled_u8g2/README.md new file mode 100644 index 000000000..70919cc54 --- /dev/null +++ b/usermods/ssd1306_i2c_oled_u8g2/README.md @@ -0,0 +1,35 @@ +# SSD1306 128x32 OLED via I2C with u8g2 +This usermod allows to connect 128x32 Oled display to WLED controlled and show +the next information: +- Current SSID +- IP address if obtained + * in AP mode and turned off lightning AP password is shown +- Current effect +- Current palette +- On/Off icon (sun/moon) + +## Hardware +![Hardware connection](assets/hw_connection.png) + +## Requirements +Functionality checked with: +- commit 095429a7df4f9e2b34dd464f7bbfd068df6558eb +- Wemos d1 mini +- PlatformIO +- Generic SSD1306 128x32 I2C OLED display from aliexpress + +### Platformio +Add `U8g2@~2.27.2` dependency to `lib_deps_external` under `[common]` section in `platformio.ini`: +```ini +# platformio.ini +... +[common] +... +lib_deps_external = + ... + U8g2@~2.27.2 +... +``` + +### Arduino IDE +Install library `U8g2 by oliver` in `Tools | Include Library | Manage libraries` menu. \ No newline at end of file diff --git a/usermods/ssd1306_i2c_oled_u8g2/assets/hw_connection.png b/usermods/ssd1306_i2c_oled_u8g2/assets/hw_connection.png new file mode 100644 index 0000000000000000000000000000000000000000..a0e51b4de4ef2063370c576547954c550d4fea0b GIT binary patch literal 34900 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 literal 0 HcmV?d00001 diff --git a/usermods/ssd1306_i2c_oled_u8g2/wled06_usermod.ino b/usermods/ssd1306_i2c_oled_u8g2/wled06_usermod.ino new file mode 100644 index 000000000..915289523 --- /dev/null +++ b/usermods/ssd1306_i2c_oled_u8g2/wled06_usermod.ino @@ -0,0 +1,149 @@ +#include // from https://github.com/olikraus/u8g2/ + +// If display does not work or looks corrupted check the +// constructor reference: +// https://github.com/olikraus/u8g2/wiki/u8x8setupcpp +// or check the gallery: +// https://github.com/olikraus/u8g2/wiki/gallery +U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(U8X8_PIN_NONE, 5, + 4); // Pins are Reset, SCL, SDA + +// gets called once at boot. Do all initialization that doesn't depend on +// network here +void userSetup() { + u8x8.begin(); + u8x8.setPowerSave(0); + u8x8.setFont(u8x8_font_chroma48medium8_r); + u8x8.drawString(0, 0, "Loading..."); +} + +// 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; + +long lastUpdate = 0; +// 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(); + + // Check if values which are shown on display changed from the last tiem. + if ((apActive == true ? 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; + + // Update last known values. + knownSsid = apActive ? WiFi.softAPSSID() : WiFi.SSID(); + knownIp = apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP(); + knownBrightness = bri; + knownMode = strip.getMode(); + knownPalette = strip.getSegment(0).palette; + + u8x8.clear(); + u8x8.setFont(u8x8_font_chroma48medium8_r); + + // First row with Wifi name + u8x8.setCursor(1, 0); + u8x8.print(ssid.substring(0, u8x8.getCols() > 1 ? u8x8.getCols() - 2 : 0)); + // Print `~` char to indicate that SSID is longer, than owr dicplay + if (ssid.length() > u8x8.getCols()) + u8x8.print("~"); + + // Second row with IP or Psssword + u8x8.setCursor(1, 1); + // Print password in AP mode and if led is OFF. + if (apActive && bri == 0) + u8x8.print(apPass); + else + u8x8.print(ip); + + // Third row with mode name + u8x8.setCursor(2, 2); + 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; + u8x8.print(singleJsonSymbol); + printedChars++; + } + if ((qComma > knownMode) || (printedChars > u8x8.getCols() - 2)) + break; + } + // Fourth row with palette name + u8x8.setCursor(2, 3); + 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; + u8x8.print(singleJsonSymbol); + printedChars++; + } + if ((qComma > knownMode) || (printedChars > u8x8.getCols() - 2)) + break; + } + + u8x8.setFont(u8x8_font_open_iconic_embedded_1x1); + u8x8.drawGlyph(0, 0, 80); // wifi icon + u8x8.drawGlyph(0, 1, 68); // home icon + u8x8.setFont(u8x8_font_open_iconic_weather_2x2); + u8x8.drawGlyph(0, 2, 66 + (bri > 0 ? 3 : 0)); // sun/moon icon +}