I’ve been putting off writing about the Seeed Xiao display panel (ESP32 powered) as I could not initially figure out how to start the ball rolling – then this morning it started to fall into place. Here’s a product link that Seeed sent to me.
The display is touted as working with Home Assistant – and it does. I initially turned on the (rechargeable) display a while back and got no-where. I have ESPHome installed in Home Assistant (trivial to install) and I’ve used it to integrate some Apollo sensors into HA but that’s about it.
So when I originally opened ESPHome inside Home Assistant and it noticed the ePaper display magically appear as an entry, I did the factory install (pressing a couple of buttons) and no joy. That’s when it went in the cupboard.
Today, I took another look and noted I’d put in the simple initialisation YAML file my WiFi SSID and password….. and missed off the quotes.
What a difference realising that made – I corrected the problem and told ESPHome to install the basic settings – done. NOW I noted that it knew about the display – and the display would now work wirelessly – but to do WHAT?
It turns out that a page initially missing from the Seeed website now has all the information needed to get a basic display up and running… so I took the minimal install – went to edit in ESPHome – and added this code (from the examples) to the very basic initial information…
# define font to display words font: - file: "gfonts://Inter@700" id: font1 size: 24 # define SPI interface spi: clk_pin: GPIO8 mosi_pin: GPIO10 display: - platform: waveshare_epaper cs_pin: GPIO3 dc_pin: GPIO5 busy_pin: number: GPIO4 inverted: true reset_pin: GPIO2 model: 7.50inv2 update_interval: 30s lambda: |- it.print(0, 0, id(font1), "Hello World!");
Well, that proved useful – I saved the edit in ESPHome and hit install and now this code was loaded onto the display WIRELESSLY.
Of course copying someone’s example is good but leaves you wondering – could I simply add more text? Could I add another example on the end? The good news is YES.
Was I excited? Sure.
Next, add something from Home Assistant. I blindly followed another example in the link above – this time not so good – as I don’t have the exact same entity in Home Assistant – but now I’m a convert so I asked Seeed to help me out with a simple example of one of my sensors in HA. I’m usually slow to get started with something new but very quickly learn given a little help. How long would it be before I had a full wall display with all of my Home Assistant temperature, humidity and pressure sensors etc in pretty boxes? Not long.
HOLD THE PHONE – CRACKED IT… my hot water tank in HA…
Wheee – here’s the additional code in total INCLUDING the basic setup.. clearly I’ve changed the codes that ESPHOME put in for my unit – to protect the innocent (me)..
esphome: name: epaper friendly_name: ePaper esp32: board: esp32-c3-devkitm-1 framework: type: esp-idf # Enable logging logger: # Enable Home Assistant API api: encryption: key: "VAd7nWQjMA6y3X4T4wwemZmQmdJVH348xG+2K+dLcrg=" ota: - platform: esphome password: "7f1e735d102694ff4f32358b24253bd62" wifi: ssid: "wmywifi" password: "1122222" # Enable fallback hotspot (captive portal) in case wifi connection fails ap: ssid: "Epaper Fallback Hotspot" password: "3jaZ44GN8n" captive_portal: sensor: - platform: homeassistant id: temp1 entity_id: sensor.snzb_02ld_temperature # define font to display words font: - file: "gfonts://Inter@700" id: font1 size: 24 # define SPI interface spi: clk_pin: GPIO8 mosi_pin: GPIO10 display: - platform: waveshare_epaper cs_pin: GPIO3 dc_pin: GPIO5 busy_pin: number: GPIO4 inverted: true reset_pin: GPIO2 model: 7.50inv2 update_interval: 30s lambda: |- it.print(0, 300, id(font1), "Hello World!"); it.print(0, 330, id(font1), "I'll eventually figure out a use for this display !"); it.filled_rectangle(10, 80, 100, 50); it.filled_rectangle(150, 80, 50, 50); it.filled_circle(250, 105, 25); it.printf(it.get_width() - 10, 10, id(font1), COLOR_ON, TextAlign::RIGHT, "Tank temperature %.1f°C", id(temp1).state);
There is absolutely no stopping me now..
Really worth a play and if you’re not into Home Assistant they have examples for Arduino and other platforms – as usual it is support and software that makes or breaks a project.
An why this instead of pretty LCD or LED? Power. Turn it off – display goes blank, turn it back on, same display comes up again and only uses power on change – that display can sit there showing static info for months on a charge it seems – but see comments later.
I could not wait to get this populated with info and up on the wall in our hallway. No leads – really thin… easily views in bright light.
Go on – ask if it’ll handle sunlight… yes but here’s a thing, I recently put an solar powered temperature sensor out in the Spanish summer sun – 40c in the shade – but over 50c in direct sunlight – so be careful (I temporarily killed the sensor – won’t do that again). This is fun – wall mounted or desk mounted and light enough to fasten with nanotape to the wall.
And now… I added a couple of icons…. mounted in the hallway – enough for one day..
Just for completeness – here’s the code (after the captive_portal line) for the above display – I had to load up a couple of Google fonts after making a fonts folder under the esphome folder in Home Assistant…
Note in the code below I’ve (obviously) figured out how to use conditionals (the lights on the right and UK boiler). That’s a plus. I think I’m going to reduce the temperature and humidity values to integers.. it’s a bit pointless having decimal points – 1 metre higher up the temperature will be at least a degree or two higher.
Note – no power plugged into the unit and I’m still updating it over WiFi. See comments section re: battery life…
sensor: - platform: homeassistant id: temp1 entity_id: sensor.snzb_02ld_temperature - platform: homeassistant id: inside_temperature entity_id: sensor.cabinet_am2301_temperature - platform: homeassistant id: inside_humidity entity_id: sensor.cabinet_am2301_humidity - platform: homeassistant id: outside_temperature entity_id: sensor.new_aqara_temperature - platform: homeassistant id: outside_humidity entity_id: sensor.new_aqara_humidity - platform: homeassistant id: forecast_temperature entity_id: sensor.lumi_lumi_weather_temperature - platform: homeassistant id: forecast_humidity entity_id: sensor.lumi_lumi_weather_humidity - platform: homeassistant id: forecast_pressure entity_id: sensor.lumi_lumi_weather_pressure text_sensor: - platform: homeassistant id: airquality entity_id: sensor.aqara_outside_kitchen_voc_air_quality - platform: homeassistant id: forecast_home entity_id: weather.forecast_home - platform: homeassistant id: livingroom_lights entity_id: light.patio_lights - platform: homeassistant id: outside_lights entity_id: light.outside_lights - platform: homeassistant id: ukht entity_id: switch.sonoff_1001f87263 time: - platform: homeassistant id: homeassistant_time # define font to display words font: - file: "gfonts://Inter@700" id: font0 size: 72 # big size icon - file: 'fonts/materialdesignicons-webfont.ttf' id: font3 # small size icon size: 40 glyphs: &mdi-weather-glyphs # https://pictogrammers.com/library/mdi/ - "\U000F050F" # Thermometer - "\U000F058E" # Humidity - "\U000F1AAF" # heating coil - "\U000F059D" # Wind speed - "\U000F0D60" # Atmospheric pressure - "\U000F0590" # Cloudy weather - "\U000F0596" # Rainy weather - "\U000F0598" # Snowy weather - "\U000F0599" # Sunny weather - "\U000F078F" # light bulb on - "\U000F171E" # light bulb off - "\U000F0F92" # boiler on - "\U000F11B4" # boiler off - file: "gfonts://Inter@700" id: font1 size: 36 - file: "gfonts://Inter@700" id: font2 size: 24 # define SPI interface spi: clk_pin: GPIO8 mosi_pin: GPIO10 display: - platform: waveshare_epaper cs_pin: GPIO3 dc_pin: GPIO5 busy_pin: number: GPIO4 inverted: true reset_pin: GPIO2 model: 7.50inv2 update_interval: 30s lambda: |- it.filled_rectangle(0, 0, it.get_width(), 82); it.printf(10, 110, id(font1), COLOR_ON, TextAlign::LEFT, "H/W"); it.printf(140, 110, id(font3), COLOR_ON, TextAlign::LEFT, "\U000F050F"); it.printf(170, 110, id(font1), COLOR_ON, TextAlign::LEFT, ": %.1f°C", id(temp1).state); it.strftime(it.get_width()/2, 40, id(font0), COLOR_OFF, TextAlign::CENTER, "%H:%M %b %d", id(homeassistant_time).now()); it.printf(10, 150, id(font1), COLOR_ON, TextAlign::LEFT, "Inside"); it.printf(140, 150, id(font3), COLOR_ON, TextAlign::LEFT, "\U000F050F"); it.printf(170, 150, id(font1), COLOR_ON, TextAlign::LEFT, ": %.1f°C", id(inside_temperature).state); it.printf(330, 150, id(font3), COLOR_ON, TextAlign::LEFT, "\U000F058E"); it.printf(360, 150, id(font1), COLOR_ON, TextAlign::LEFT, ": %.1f%%", id(inside_humidity).state); it.printf(10, 190, id(font1), COLOR_ON, TextAlign::LEFT, "Outside"); it.printf(140, 190, id(font3), COLOR_ON, TextAlign::LEFT, "\U000F050F"); it.printf(170, 190, id(font1), COLOR_ON, TextAlign::LEFT, ": %.1f°C", id(outside_temperature).state); it.printf(330, 190, id(font3), COLOR_ON, TextAlign::LEFT, "\U000F058E"); it.printf(360, 190, id(font1), COLOR_ON, TextAlign::LEFT, ": %.1f%%", id(outside_humidity).state); it.printf(10, 250, id(font1), COLOR_ON, TextAlign::LEFT, "Air Quality:"); it.printf(220, 250, id(font1), COLOR_ON, TextAlign::LEFT, "%s", id(airquality).state.c_str()); it.printf(10, 290, id(font1), COLOR_ON, TextAlign::LEFT, "Weather:"); it.printf(220, 290, id(font1), COLOR_ON, TextAlign::LEFT, "%s", id(forecast_home).state.c_str()); it.printf(550, 110, id(font1), COLOR_ON, TextAlign::LEFT, "LR:"); if (id(livingroom_lights).state == "on") { it.printf(740, 110, id(font3), COLOR_ON, TextAlign::LEFT, "\U000F078F"); } else { it.printf(740, 110, id(font3), COLOR_ON, TextAlign::LEFT, "\U000F171E"); } it.printf(550, 150, id(font1), COLOR_ON, TextAlign::LEFT, "OS:"); if (id(outside_lights).state == "on") { it.printf(740, 150, id(font3), COLOR_ON, TextAlign::LEFT, "\U000F078F"); } else { it.printf(740, 150, id(font3), COLOR_ON, TextAlign::LEFT, "\U000F171E"); } it.printf(550, 190, id(font1), COLOR_ON, TextAlign::LEFT, "UK BOIL:"); if (id(ukht).state == "on") { it.printf(740, 190, id(font3), COLOR_ON, TextAlign::LEFT, "\U000F0F92"); } else { it.printf(740, 190, id(font3), COLOR_ON, TextAlign::LEFT, "\U000F11B4"); } it.line(0, it.get_height()-63,it.get_width(),it.get_height()-63,COLOR_ON); it.printf(it.get_width()/2, it.get_height()-32, id(font0), COLOR_ON, TextAlign::CENTER, "BEDROCK");
Checkout the video – refresh rate and battery charging… this after a full day USB charge…
And finally for now – the battery issue mentioned in the comments… I managed a whole 2-3 days between charges with a 30 second update interval – so I guess updating lighting status is a non-starter on battery power – and this morning – a message from Seeed….”Please try to enter the Deep sleep mode”. They sent me a link suggesting updates every 6 hours and the use of Sleep mode.
Seeed have a demo on their Wiki for this. No problem but that’s my planned use for the device gone – with 6-hour updates you can get up to 3 months on the battery – but that’s pushing it even for temperature/weather updates – now it’s down to deciding whether I need to rethink what to do with this display – or going for USB power. Here’s the deep-sleep link.
Update guys – battery voltage not included as standard. Adding a little YAML to the file puts it that facility in but you also have to add a pair of resistors…(bit messy unless you’re good with a soldering iron) See here.. https://forum.seeedstudio.com/t/seeed-studio-xiao-7-5-epaper-panel-battery-status/292932/2
Ok, more updates – that last writing when I had to charge the battery was September 9 – I left the battery on charge ALL DAY… just looked now, the display stopped on September 11. I’ve just checked now… Obviously the display is still on – but reset and boot separately failed to provoke an update so I guess the battery is flat again.
Plug into power – the display refreshed at January 1 – just under a minute later updated correctly to September 14 – i.e. today – SO – all works well but forget about long battery charge life with refreshes every minute. That’s a shame.
Really interesting to see how the Seeed 7.5″ ePaper Display combines clarity with low power consumption, making it ideal for modern IoT projects. Displays like these show how hardware is getting smarter and more efficient. On the software side, the gcmob apk 2025 update continues the trend by offering smoother performance and new features for Android users. Together, they represent the balance between efficient hardware and powerful apps.
Ok, some initial answers for you perhaps. I last updated this display on September 4 and left it on the wall in our hallway displaying various data. I’ve been busy and not noticed that although the display is still white and looks good – it’s not actuallyt doing anything. Whether this is down to a Home Assistant update or flat battery… anyway the date is stuck on September 5.
I hot reset and nothing happened.. So now for USB. Ok, 01:00 Jan 01… OH… it is now up to date. I guess I’ll leave it on USB charge for several hours – I never did give it a full charge so the definitive answer will have to wait I’m afraid.
Can you already see how much energy is consumed with a 30s update interval? And how long this display would last before a recharge is in order?
Not yet, had to make room for a life after spending hours getting this far – but I will do a full charge and long term test – it’s on the wall already but I’ve a few more sensors to add in tiny print. However, as the claim is 3 months max in deep sleep – it’s clearly going to be well below 3 months between charges – and I’m doing the default refresh around 30 seconds.. right now I’m doing regular updates as I think of more things to add (plenty of RAM and storage left).
See above – the answer is going to take some time – I’ve just put the unit on USB charge right now after realising it stopped updating on September 5 and a reset made no difference – I’ll leave it on charge for the rest of the morning/afternoon then put it back on the wall. Hmm, I wonder if there is a way to see battery charge state – I’ll go look.