From a1d5441cda0eb69319ca2fbddac8825e251b1a32 Mon Sep 17 00:00:00 2001 From: paulchilton Date: Sat, 31 Dec 2022 17:04:51 +0000 Subject: [PATCH 01/17] Added M5 Tough option --- components/axp192/axp192.h | 1 + 1 file changed, 1 insertion(+) diff --git a/components/axp192/axp192.h b/components/axp192/axp192.h index 1385f61..3c43b3f 100644 --- a/components/axp192/axp192.h +++ b/components/axp192/axp192.h @@ -11,6 +11,7 @@ namespace axp192 { enum AXP192Model { AXP192_M5STICKC = 0, AXP192_M5CORE2, + AXP192_M5TOUGH, }; #define SLEEP_MSEC(us) (((uint64_t)us) * 1000L) From 89bda5a50144c0a2ab15db4a99f88df5846736a8 Mon Sep 17 00:00:00 2001 From: paulchilton Date: Sat, 31 Dec 2022 17:05:29 +0000 Subject: [PATCH 02/17] Added M5 Tough Option --- components/axp192/sensor.py | 1 + 1 file changed, 1 insertion(+) diff --git a/components/axp192/sensor.py b/components/axp192/sensor.py index b4504ef..6781eb3 100644 --- a/components/axp192/sensor.py +++ b/components/axp192/sensor.py @@ -13,6 +13,7 @@ AXP192Model = axp192_ns.enum("AXP192Model") MODELS = { "M5CORE2": AXP192Model.AXP192_M5CORE2, "M5STICKC": AXP192Model.AXP192_M5STICKC, + "M5TOUGH": AXP192Model.AXP192_M5TOUGH, } AXP192_MODEL = cv.enum(MODELS, upper=True, space="_") From fc022332b375492c05fb972defadd7edb238af94 Mon Sep 17 00:00:00 2001 From: paulchilton Date: Sat, 31 Dec 2022 17:06:46 +0000 Subject: [PATCH 03/17] Added M5Tough Option --- components/axp192/axp192.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/components/axp192/axp192.cpp b/components/axp192/axp192.cpp index bdd2d11..1378779 100644 --- a/components/axp192/axp192.cpp +++ b/components/axp192/axp192.cpp @@ -18,6 +18,10 @@ void AXP192Component::setup() // disable LDO3 Vibration begin(false, true, false, false, false); } + case AXP192_M5TOUGH: + { + begin(false, false, false, false, false); + } } } @@ -63,6 +67,13 @@ void AXP192Component::begin(bool disableLDO2, bool disableLDO3, bool disableRTC, // Set LDO2 & LDO3(TFT_LED & TFT) 3.0V Write1Byte(0x28, 0xcc); } + case AXP192_M5TOUGH: + { + // Set DCDC3 (TFT_LED & TFT) 3.0V + Write1Byte(0x27, 0xcc); + // Set LDO2 & LDO3(TFT_LED & TFT) 3.0V + Write1Byte(0x28, 0xcc); + } } // Set ADC sample rate to 200hz From 48e528e8a34a23a652950fc68d47ea1e99f02dd4 Mon Sep 17 00:00:00 2001 From: paulchilton Date: Sat, 31 Dec 2022 17:10:18 +0000 Subject: [PATCH 04/17] Update README.md --- README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/README.md b/README.md index c61a044..52834ed 100644 --- a/README.md +++ b/README.md @@ -39,3 +39,18 @@ sensor: name: "${upper_devicename} Battery Level" id: "${devicename}_batterylevel" ``` + + +### M5Tough + +```yaml +sensor: + - platform: axp192 + model: M5Tough + address: 0x34 + i2c_id: bus_a + update_interval: 30s + battery_level: + name: "${upper_devicename} Battery Level" + id: "${devicename}_batterylevel" +``` From a6ea145770590467b5a27130ee7f2a2d8efc5948 Mon Sep 17 00:00:00 2001 From: paulchilton Date: Sat, 31 Dec 2022 20:08:15 +0000 Subject: [PATCH 05/17] Added check for first power on and reset so the display properly initialises --- components/axp192/axp192.cpp | 51 ++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/components/axp192/axp192.cpp b/components/axp192/axp192.cpp index 1378779..5dc39df 100644 --- a/components/axp192/axp192.cpp +++ b/components/axp192/axp192.cpp @@ -116,6 +116,13 @@ void AXP192Component::begin(bool disableLDO2, bool disableLDO3, bool disableRTC, // Enable bat detection Write1Byte(0x32, 0x46); + + // If we're waking from a cold boot, initialise power chip + if (GetStartupReason() == "ESP_RST_POWERON") + { + // Reboot the ESP with the axp initialised + ESP.restart(); + } } void AXP192Component::Write1Byte( uint8_t Addr , uint8_t Data ) @@ -569,6 +576,50 @@ void AXP192Component::SetAdcState(bool state) { Write1Byte(0x82, state ? 0xff : 0x00); } + +std::string AXP192InitComponent::GetStartupReason() { + esp_reset_reason_t reset_reason = ::esp_reset_reason(); + if (reset_reason == ESP_RST_DEEPSLEEP) { + esp_sleep_source_t wake_reason = esp_sleep_get_wakeup_cause(); + if (wake_reason == ESP_SLEEP_WAKEUP_EXT0) + return "ESP_SLEEP_WAKEUP_EXT0"; + if (wake_reason == ESP_SLEEP_WAKEUP_EXT0) + return "ESP_SLEEP_WAKEUP_EXT0"; + if (wake_reason == ESP_SLEEP_WAKEUP_EXT1) + return "ESP_SLEEP_WAKEUP_EXT1"; + if (wake_reason == ESP_SLEEP_WAKEUP_TIMER) + return "ESP_SLEEP_WAKEUP_TIMER"; + if (wake_reason == ESP_SLEEP_WAKEUP_TOUCHPAD) + return "ESP_SLEEP_WAKEUP_TOUCHPAD"; + if (wake_reason == ESP_SLEEP_WAKEUP_ULP) + return "ESP_SLEEP_WAKEUP_ULP"; + if (wake_reason == ESP_SLEEP_WAKEUP_GPIO) + return "ESP_SLEEP_WAKEUP_GPIO"; + if (wake_reason == ESP_SLEEP_WAKEUP_UART) + return "ESP_SLEEP_WAKEUP_UART"; + return std::string{"WAKEUP_UNKNOWN_REASON"}; + } + if (reset_reason == ESP_RST_UNKNOWN) + return "ESP_RST_UNKNOWN"; + if (reset_reason == ESP_RST_POWERON) + return "ESP_RST_POWERON"; + if (reset_reason == ESP_RST_SW) + return "ESP_RST_SW"; + if (reset_reason == ESP_RST_PANIC) + return "ESP_RST_PANIC"; + if (reset_reason == ESP_RST_INT_WDT) + return "ESP_RST_INT_WDT"; + if (reset_reason == ESP_RST_TASK_WDT) + return "ESP_RST_TASK_WDT"; + if (reset_reason == ESP_RST_WDT) + return "ESP_RST_WDT"; + if (reset_reason == ESP_RST_BROWNOUT) + return "ESP_RST_BROWNOUT"; + if (reset_reason == ESP_RST_SDIO) + return "ESP_RST_SDIO"; + return std::string{"RESET_UNKNOWN_REASON"}; +} + } } From fe779b86318d5cc2c1bc52bd78100f82af9f2f0a Mon Sep 17 00:00:00 2001 From: paulchilton Date: Sat, 31 Dec 2022 20:13:15 +0000 Subject: [PATCH 06/17] Update axp192.cpp --- components/axp192/axp192.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/components/axp192/axp192.cpp b/components/axp192/axp192.cpp index 5dc39df..e1a24c2 100644 --- a/components/axp192/axp192.cpp +++ b/components/axp192/axp192.cpp @@ -117,9 +117,13 @@ void AXP192Component::begin(bool disableLDO2, bool disableLDO3, bool disableRTC, // Enable bat detection Write1Byte(0x32, 0x46); + ESP_LOGD(TAG, GetStartupReason()); + // If we're waking from a cold boot, initialise power chip if (GetStartupReason() == "ESP_RST_POWERON") { + ESP_LOGD(TAG, "First power on, restarting ESP..."); + // Reboot the ESP with the axp initialised ESP.restart(); } From 93a89eb95dbd0be29c15824ae67ba2d388e072dd Mon Sep 17 00:00:00 2001 From: paulchilton Date: Sat, 31 Dec 2022 20:19:45 +0000 Subject: [PATCH 07/17] Testing different placement of auto-restart --- components/axp192/axp192.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/components/axp192/axp192.cpp b/components/axp192/axp192.cpp index e1a24c2..cdb8099 100644 --- a/components/axp192/axp192.cpp +++ b/components/axp192/axp192.cpp @@ -49,6 +49,15 @@ void AXP192Component::update() { } UpdateBrightness(); + + // If we're waking from a cold boot + if (GetStartupReason() == "ESP_RST_POWERON") + { + ESP_LOGD(TAG, "First power on, restarting ESP..."); + + // Reboot the ESP with the axp initialised + ESP.restart(); + } } @@ -117,16 +126,6 @@ void AXP192Component::begin(bool disableLDO2, bool disableLDO3, bool disableRTC, // Enable bat detection Write1Byte(0x32, 0x46); - ESP_LOGD(TAG, GetStartupReason()); - - // If we're waking from a cold boot, initialise power chip - if (GetStartupReason() == "ESP_RST_POWERON") - { - ESP_LOGD(TAG, "First power on, restarting ESP..."); - - // Reboot the ESP with the axp initialised - ESP.restart(); - } } void AXP192Component::Write1Byte( uint8_t Addr , uint8_t Data ) From 253aaccfa71aa909b97a607545b6fe39078cd290 Mon Sep 17 00:00:00 2001 From: paulchilton Date: Sat, 31 Dec 2022 20:34:23 +0000 Subject: [PATCH 08/17] Update axp192.cpp --- components/axp192/axp192.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/axp192/axp192.cpp b/components/axp192/axp192.cpp index cdb8099..981bcca 100644 --- a/components/axp192/axp192.cpp +++ b/components/axp192/axp192.cpp @@ -204,6 +204,7 @@ void AXP192Component::ReadBuff( uint8_t Addr , uint8_t Size , uint8_t *Buff ) void AXP192Component::UpdateBrightness() { + ESP_LOGD(TAG, GetStartupReason()); ESP_LOGD(TAG, "Brightness=%f (Curr: %f)", brightness_, curr_brightness_); if (brightness_ == curr_brightness_) { @@ -234,7 +235,7 @@ void AXP192Component::UpdateBrightness() } bool AXP192Component::GetBatState() -{ +{ if( Read8bit(0x01) | 0x20 ) return true; else From 4c91690d8de713dfba78fa2452c93e033f626572 Mon Sep 17 00:00:00 2001 From: paulchilton Date: Sat, 31 Dec 2022 20:41:23 +0000 Subject: [PATCH 09/17] Update axp192.cpp --- components/axp192/axp192.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/components/axp192/axp192.cpp b/components/axp192/axp192.cpp index 981bcca..a0adc26 100644 --- a/components/axp192/axp192.cpp +++ b/components/axp192/axp192.cpp @@ -229,7 +229,12 @@ void AXP192Component::UpdateBrightness() case AXP192_M5CORE2: { uint8_t buf = Read8bit( 0x27 ); - Write1Byte( 0x27 , ((buf & 0x80) | (ubri << 3)) ); + Write1Byte( 0x27 , ((buf & 0x80) | (ubri << 3)) ); + } + case AXP192_M5TOUGH: + { + uint8_t buf = Read8bit( 0x27 ); + Write1Byte( 0x27 , ((buf & 0x80) | (ubri << 3)) ); } } } @@ -563,7 +568,6 @@ void AXP192Component::SetLDO3(bool State) Write1Byte( 0x12 , buf ); } - void AXP192Component::SetChargeCurrent(uint8_t current) { uint8_t buf = Read8bit(0x33); @@ -603,6 +607,7 @@ std::string AXP192InitComponent::GetStartupReason() { return "ESP_SLEEP_WAKEUP_UART"; return std::string{"WAKEUP_UNKNOWN_REASON"}; } + if (reset_reason == ESP_RST_UNKNOWN) return "ESP_RST_UNKNOWN"; if (reset_reason == ESP_RST_POWERON) From 21078e5565112dc3f6fe7975ae6a7130182085ac Mon Sep 17 00:00:00 2001 From: paulchilton Date: Sat, 31 Dec 2022 20:45:39 +0000 Subject: [PATCH 10/17] Update axp192.cpp --- components/axp192/axp192.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/components/axp192/axp192.cpp b/components/axp192/axp192.cpp index a0adc26..3fa5416 100644 --- a/components/axp192/axp192.cpp +++ b/components/axp192/axp192.cpp @@ -1,6 +1,7 @@ #include "axp192.h" #include "esphome/core/log.h" #include "esp_sleep.h" +#include namespace esphome { namespace axp192 { From 3e3ec2366cb71f938e528330a3a25d574dd0e2af Mon Sep 17 00:00:00 2001 From: paulchilton Date: Sat, 31 Dec 2022 20:47:16 +0000 Subject: [PATCH 11/17] Added GetStartupReason method header --- components/axp192/axp192.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/components/axp192/axp192.h b/components/axp192/axp192.h index 3c43b3f..a5c46e0 100644 --- a/components/axp192/axp192.h +++ b/components/axp192/axp192.h @@ -41,6 +41,9 @@ public: float get_setup_priority() const override; void update() override; +private: + static std::string GetStartupReason(); + protected: sensor::Sensor *batterylevel_sensor_; float brightness_{1.0f}; From cb8a0e8364927e4f158e86f48825152f0d7fcbf5 Mon Sep 17 00:00:00 2001 From: paulchilton Date: Sat, 31 Dec 2022 20:47:27 +0000 Subject: [PATCH 12/17] Update axp192.cpp --- components/axp192/axp192.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/axp192/axp192.cpp b/components/axp192/axp192.cpp index 3fa5416..dae2310 100644 --- a/components/axp192/axp192.cpp +++ b/components/axp192/axp192.cpp @@ -586,7 +586,7 @@ void AXP192Component::SetAdcState(bool state) Write1Byte(0x82, state ? 0xff : 0x00); } -std::string AXP192InitComponent::GetStartupReason() { +std::string AXP192Component::GetStartupReason() { esp_reset_reason_t reset_reason = ::esp_reset_reason(); if (reset_reason == ESP_RST_DEEPSLEEP) { esp_sleep_source_t wake_reason = esp_sleep_get_wakeup_cause(); From 25fcd23de93b12462e9a61a9342887fef79ab122 Mon Sep 17 00:00:00 2001 From: paulchilton Date: Sat, 31 Dec 2022 20:48:08 +0000 Subject: [PATCH 13/17] Removed log entry --- components/axp192/axp192.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/components/axp192/axp192.cpp b/components/axp192/axp192.cpp index dae2310..2e25e56 100644 --- a/components/axp192/axp192.cpp +++ b/components/axp192/axp192.cpp @@ -205,7 +205,6 @@ void AXP192Component::ReadBuff( uint8_t Addr , uint8_t Size , uint8_t *Buff ) void AXP192Component::UpdateBrightness() { - ESP_LOGD(TAG, GetStartupReason()); ESP_LOGD(TAG, "Brightness=%f (Curr: %f)", brightness_, curr_brightness_); if (brightness_ == curr_brightness_) { From 97b6f0115f737ec3df002bc54ba85b2e8d882a89 Mon Sep 17 00:00:00 2001 From: paulchilton Date: Sat, 31 Dec 2022 20:51:02 +0000 Subject: [PATCH 14/17] Moved restart code to the correct place for the M5Tough --- components/axp192/axp192.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/components/axp192/axp192.cpp b/components/axp192/axp192.cpp index 2e25e56..7e60609 100644 --- a/components/axp192/axp192.cpp +++ b/components/axp192/axp192.cpp @@ -22,6 +22,15 @@ void AXP192Component::setup() case AXP192_M5TOUGH: { begin(false, false, false, false, false); + + // If we're waking from a cold boot + if (GetStartupReason() == "ESP_RST_POWERON") + { + ESP_LOGD(TAG, "First power on, restarting ESP..."); + + // Reboot the ESP with the axp initialised + ESP.restart(); + } } } } @@ -50,15 +59,6 @@ void AXP192Component::update() { } UpdateBrightness(); - - // If we're waking from a cold boot - if (GetStartupReason() == "ESP_RST_POWERON") - { - ESP_LOGD(TAG, "First power on, restarting ESP..."); - - // Reboot the ESP with the axp initialised - ESP.restart(); - } } From 6d87e2c74d5a832b753c1eb57fe9be9f79a7107e Mon Sep 17 00:00:00 2001 From: paulchilton Date: Sun, 1 Jan 2023 10:00:49 +0000 Subject: [PATCH 15/17] Changed brightness log so it only logs when the value is changed --- components/axp192/axp192.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/axp192/axp192.cpp b/components/axp192/axp192.cpp index 7e60609..dc745ea 100644 --- a/components/axp192/axp192.cpp +++ b/components/axp192/axp192.cpp @@ -205,11 +205,12 @@ void AXP192Component::ReadBuff( uint8_t Addr , uint8_t Size , uint8_t *Buff ) void AXP192Component::UpdateBrightness() { - ESP_LOGD(TAG, "Brightness=%f (Curr: %f)", brightness_, curr_brightness_); if (brightness_ == curr_brightness_) { return; } + + ESP_LOGD(TAG, "Brightness=%f (Curr: %f)", brightness_, curr_brightness_); curr_brightness_ = brightness_; const uint8_t c_min = 7; From bf415d05cc1aece93ff813652f4992d9110942c6 Mon Sep 17 00:00:00 2001 From: paulchilton Date: Mon, 2 Jan 2023 09:00:40 +0000 Subject: [PATCH 16/17] Added README details specific to this repo --- README.md | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 52834ed..33fb139 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,24 @@ # ESPHome AXP192 Component -This custom component it to implement support for the AXP192 for both the M5Stick-C, and the M5Stack Core2, building on top of airy10's code. +Built on top of martydingo's version of the axp192 power management IC library for ESPHome, I have added support for the M5Tough, which requires a different register configuration for the M5Tough ILI9342C display. Other changes include a fix to stop the log being spammed with brightness values continually, these are only logged on change. Also the M5Tough needs resetting once the axp192 registers are set for the display to properly initialise so this version sets up the axp and then resets the ESP32 automatically. ## Installation -Copy the components to a custom_components directory next to your .yaml configuration file. +Copy the components to a custom_components directory next to your .yaml configuration file, or include directly from this repository. ## Configuration -Sample configurations can be found within `/sample-config`. Please note that I've not yet been able to correctly configure the M5Stick-C screen just yet, however the AXP192 component does initalise it, and the sample configuration currently demostrates a white screen, when it should present some text. I plan to fix this soon. +Sample configurations are found in the `/sample-config` folder. -This component adds a new model configuration to the AXP192 sensor, `model: M5CORE2` & `model: M5STICKC`, as so the right pins are initalized and voltages go to the right places: +This component adds a new model configuration to the AXP192 sensor which determines which registers are needed for each device. Available models are `model: M5CORE2`, `model: M5STICKC` and `model: M5TOUGH`. + +### Include axp192 component + +```yaml +external_components: + - source: github://paulchilton/esphome-axp192 + components: [axp192] +``` ### M5Stick-C @@ -40,7 +48,6 @@ sensor: id: "${devicename}_batterylevel" ``` - ### M5Tough ```yaml @@ -54,3 +61,16 @@ sensor: name: "${upper_devicename} Battery Level" id: "${devicename}_batterylevel" ``` + +The display component required for the M5Tough is as follows: + +```yaml +display: + - platform: ili9341 + # 320x240 + model: M5STACK + cs_pin: GPIO5 + dc_pin: GPIO15 + lambda: |- + it.print(160, 0, id(title_font), id(color_white), TextAlign::TOP_CENTER, "Hello World"); +``` From 87875c10ef75cea3be5621bce647b2b4d00d668a Mon Sep 17 00:00:00 2001 From: paulchilton Date: Mon, 2 Jan 2023 09:11:26 +0000 Subject: [PATCH 17/17] Create m5tough.yaml --- sample-config/m5tough.yaml | 143 +++++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 sample-config/m5tough.yaml diff --git a/sample-config/m5tough.yaml b/sample-config/m5tough.yaml new file mode 100644 index 0000000..b7743c0 --- /dev/null +++ b/sample-config/m5tough.yaml @@ -0,0 +1,143 @@ +esphome: + name: m5tough + +esp32: + board: m5stack-core2 + framework: + type: arduino + +# Enable logging +logger: + +# Enable Home Assistant API +api: + +# Enable over the air programming +ota: + +# Enable WiFi connection +wifi: + ssid: !secret wifi_ssid + password: !secret wifi_pass + +# Include the required components for this device +external_components: + - source: github://paulchilton/esphome-axp192 + components: [axp192] + +# SPI bus +spi: + clk_pin: GPIO18 + mosi_pin: GPIO23 + miso_pin: GPIO38 + +# I2C bus +i2c: + - id: bus_a + sda: GPIO21 + scl: GPIO22 + +# Define sensors +sensor: + - platform: axp192 + model: M5TOUGH + address: 0x34 + i2c_id: bus_a + update_interval: 3s + brightness: 75% + + - platform: uptime + name: "Uptime" + + - platform: wifi_signal + name: "WiFi Signal" + update_interval: 60s + id: wifi_strength + +text_sensor: + - platform: wifi_info + ip_address: + id: ip_address + +# M5 Tough has a built in speaker which can be used by home assistant as a media player +media_player: + - platform: i2s_audio + name: M5TOUGH I2S Media Player + dac_type: external + i2s_lrclk_pin: GPIO0 + i2s_dout_pin: GPIO2 + i2s_bclk_pin: GPIO12 + mode: stereo + +# Setup a simple input that triggers when the screen is touched anywhere +binary_sensor: + - platform: gpio + id: touchscreen_pressed + name: Touch Screen Pressed + pin: + number: 39 + + on_press: + then: + - logger.log: "Screen was pressed" + + # Also, send an event to home assistant api to indicate someone has pressed the screen. + - homeassistant.event: + event: esphome.screen_pressed + data: + message: Toughscreen was pressed + +# Fonts used on the display +font: + - file: "gfonts://Roboto" + id: title_font + size: 38 + - file: "gfonts://Roboto" + id: large_font + size: 42 + - file: "gfonts://Roboto" + id: mid_font + size: 28 + - file: "gfonts://Roboto" + id: small_font + size: 18 + +# Colours used on the display +color: + - id: color_white + red: 100% + green: 100% + blue: 100% + - id: color_grey + red: 30% + green: 30% + blue: 40% + - id: color_red + red: 100% + green: 3% + blue: 5% + +# Display definition with a simple header and footer showing WiFi connection details +display: + - platform: ili9341 + # 320x240 + model: M5STACK + cs_pin: GPIO5 + dc_pin: GPIO15 + lambda: |- + // Header + it.print(160, 0, id(title_font), id(color_white), TextAlign::TOP_CENTER, "Hello World"); + it.line(0, 50, it.get_width(), 50, id(color_grey)); + + + // Footer + it.line(0, 215, it.get_width(), 215, id(color_grey)); + if(isnan(id(wifi_strength).state) == 0){ + it.printf(240, 220, id(small_font), id(color_white), TextAlign::TOP_LEFT, "%.1fdB", id(wifi_strength).state); + } + else + { + it.printf(160, 220, id(small_font), id(color_red), TextAlign::TOP_CENTER, "Disconnected"); + } + + it.printf(10, 220, id(small_font), id(color_white), TextAlign::TOP_LEFT, "%s", id(ip_address).state.c_str());