I just got a new ESP32 based screen from Waveshare. Looks really nice
They added control for the backlight which was an issue with the waveshare-esp32-s3-touch-lcd-7 and the also increased the screen resolution to 1024x600.
The problem is the older model used a ch422g_hub to access a bunch of pins including the backlight. The new screen uses a proprietary Waveshare chip for this.
Accessing that chip via i2c is the only way to control the back light.
Anybody interested in writing a drive for it. It looks very similar to the and the drive for it is simple.
/*****************************************************************************
* | File : io_extension.h
* | Author : Waveshare team
* | Function : GPIO control using io extension via I2C interface
* | Info :
* | Header file for controlling GPIO pins via the io extension
* | chip using I2C communication. This file defines the
* | necessary I2C addresses, commands, and GPIO pin control
* | functions.
* ----------------
* | This version : V1.0
* | Date : 2024-11-19
* | Info : Basic version
*
******************************************************************************/
#ifndef __IO_EXTENSION_H
#define __IO_EXTENSION_H
#include "i2c.h" // Include I2C header for I2C communication functions
/*
* IO EXTENSION GPIO control via I2C - Register and Command Definitions
*
*
* Example usage:
* 1. Set the working mode by writing to the register at address 0x24
* 2. Send function commands to control the GPIO pins and modes
*/
/* IO EXTENSION Function Register Addresses */
#define IO_EXTENSION_ADDR 0x24 // Slave address for mode configuration register
/* Mode control flags (from the chip manual) */
#define IO_EXTENSION_Mode 0x02 //
#define IO_EXTENSION_IO_OUTPUT_ADDR 0x03 //
#define IO_EXTENSION_IO_INPUT_ADDR 0x04 //
#define IO_EXTENSION_PWM_ADDR 0x05 //
#define IO_EXTENSION_ADC_ADDR 0x06 //
/* Specific IO pin assignments */
#define IO_EXTENSION_IO_0 0x00 // IO0
#define IO_EXTENSION_IO_1 0x01 // IO1 (used for touch reset)
#define IO_EXTENSION_IO_2 0x02 // IO2 (backlight control)
#define IO_EXTENSION_IO_3 0x03 // IO3 (used for lcd reset)
#define IO_EXTENSION_IO_4 0x04 // IO4 (SD card CS pin)
#define IO_EXTENSION_IO_5 0x05 // IO5 (Select communication interface: 0 for USB, 1 for CAN)
#define IO_EXTENSION_IO_6 0x06 // IO6
#define IO_EXTENSION_IO_7 0x07 // IO7
/* Structure to represent the IO EXTENSION device */
typedef struct _io_extension_obj_t {
i2c_master_dev_handle_t addr; // Handle for mode configuration
uint8_t Last_io_value;
uint8_t Last_od_value;
} io_extension_obj_t;
/* Function declarations */
void IO_EXTENSION_Init(); // Initialize the IO_EXTENSION device
void IO_EXTENSION_Output(uint8_t pin, uint8_t value); // Set IO pin output (high/low)
uint8_t IO_EXTENSION_Input(uint8_t pin); // Read IO pin input state
void IO_EXTENSION_Pwm_Output(uint8_t Value);
uint16_t IO_EXTENSION_Adc_Input();
#endif // __IO_EXTENSION_H
/*****************************************************************************
* | File : io_extension.c
* | Author : Waveshare team
* | Function : IO_EXTENSION GPIO control via I2C interface
* | Info :
* | I2C driver code for controlling GPIO pins using IO_EXTENSION chip.
* ----------------
* | This version : V1.0
* | Date : 2024-11-27
* | Info : Basic version, includes functions to read and write
* | GPIO pins using I2C communication with IO_EXTENSION.
*
******************************************************************************/
#include "io_extension.h" // Include IO_EXTENSION driver header for GPIO functions
io_extension_obj_t IO_EXTENSION; // Define the global IO_EXTENSION object
/**
* @brief Set the IO mode for the specified pins.
*
* This function sets the specified pins to input or output mode by writing to the mode register.
*
* @param pin An 8-bit value where each bit represents a pin (0 = input, 1 = output).
*/
void IO_EXTENSION_IO_Mode(uint8_t pin)
{
uint8_t data[2] = {IO_EXTENSION_Mode, pin}; // Prepare the data to write to the mode register
// Write the 8-bit value to the IO mode register
DEV_I2C_Write_Nbyte(IO_EXTENSION.addr, data, 2);
}
/**
* @brief Initialize the IO_EXTENSION device.
*
* This function configures the slave addresses for different registers of the
* IO_EXTENSION chip via I2C, and sets the control flags for input/output modes.
*/
void IO_EXTENSION_Init()
{
// Set the I2C slave address for the IO_EXTENSION device
DEV_I2C_Set_Slave_Addr(&IO_EXTENSION.addr, IO_EXTENSION_ADDR);
IO_EXTENSION_IO_Mode(0xff); // Set all pins to output mode
// Initialize control flags for IO output enable and open-drain output mode
IO_EXTENSION.Last_io_value = 0xFF; // All pins are initially set to high (output mode)
IO_EXTENSION.Last_od_value = 0xFF; // All pins are initially set to high (open-drain mode)
}
/**
* @brief Set the value of the IO output pins on the IO_EXTENSION device.
*
* This function writes an 8-bit value to the IO output register. The value
* determines the high or low state of the pins.
*
* @param pin The pin number to set (0-7).
* @param value The value to set on the specified pin (0 = low, 1 = high).
*/
void IO_EXTENSION_Output(uint8_t pin, uint8_t value)
{
// Update the output value based on the pin and value
if (value == 1)
IO_EXTENSION.Last_io_value |= (1 << pin); // Set the pin high
else
IO_EXTENSION.Last_io_value &= (~(1 << pin)); // Set the pin low
uint8_t data[2] = {IO_EXTENSION_IO_OUTPUT_ADDR, IO_EXTENSION.Last_io_value}; // Prepare the data to write to the output register
// Write the 8-bit value to the IO output register
DEV_I2C_Write_Nbyte(IO_EXTENSION.addr, data, 2);
}
/**
* @brief Read the value from the IO input pins on the IO_EXTENSION device.
*
* This function reads the value of the IO input register and returns the state
* of the specified pins.
*
* @param pin The bit mask to specify which pin to read (e.g., 0x01 for the first pin).
* @return The value of the specified pin(s) (0 = low, 1 = high).
*/
uint8_t IO_EXTENSION_Input(uint8_t pin)
{
uint8_t value = 0;
// Read the value of the input pins
DEV_I2C_Read_Nbyte(IO_EXTENSION.addr, IO_EXTENSION_IO_INPUT_ADDR, &value, 1);
// Return the value of the specific pin(s) by masking with the provided bit mask
return ((value & (1 << pin)) > 0);
}
/**
* @brief Set the PWM output value on the IO_EXTENSION device.
*
* This function sets the PWM output value, which controls the duty cycle of the PWM signal.
* The duty cycle is calculated based on the input value and the resolution (12 bits).
*
* @param Value The input value to set the PWM duty cycle (0-100).
*/
void IO_EXTENSION_Pwm_Output(uint8_t Value)
{
// Prevent the screen from completely turning off
if (Value >= 97)
{
Value = 97;
}
uint8_t data[2] = {IO_EXTENSION_PWM_ADDR, Value}; // Prepare the data to write to the PWM register
// Calculate the duty cycle based on the resolution (12 bits)
data[1] = Value * (255 / 100.0);
// Write the 8-bit value to the PWM output register
DEV_I2C_Write_Nbyte(IO_EXTENSION.addr, data, 2);
}
/**
* @brief Read the ADC input value from the IO_EXTENSION device.
*
* This function reads the ADC input value from the IO_EXTENSION device.
*
* @return The ADC input value.
*/
uint16_t IO_EXTENSION_Adc_Input()
{
// Read the ADC input value from the IO_EXTENSION device
return DEV_I2C_Read_Word(IO_EXTENSION.addr, IO_EXTENSION_ADC_ADDR);
}
I also just got my hands on this screen, and Iâm happy to report this driver works perfectly for my needs. This is still very much a work in progress, but so far I have not encountered any issues with it.
This screen is working well with the new code for the special Waveshare MUX provided by @latonita.
But I have a new problem. It was working well with 2025.7.5 but when I upgrade to 2025.8.0 the screen stops working and is black (no network). If I look at the logs it is getting the dreaded âInvalid image block, canât bootâ.
I have done all the usually troubleshooting. Delete my .esphome folder and recompiled etc. But it doesnât seem to work at all. When I go back to 2025.7.5 itâs fine.
Yes, I pasted your hardware YAML into an existing YAML and it all worked fine. Iâve been using the Waveshare 800x480 display and have been happy with them. I had a spare one that I planned on gifting to a pal, so I took the opportunity to get one of these 16MB flash 1024x600 displays with the adjustable backlight, especially since AliExpress had a great offer on them.
After about 15 minutes of using it, I realised it just wasnât for me, so I gave it to my pal and heâs super happy with it. He plans on creating an alarm panel type thing by the front door with sticky note style popups for leaving family members notes.
The only thing I couldnât get along with, and probably someone brighter than me could possibly resolve, was that even though the brightness can be adjusted, at its brightest it wasnât as bright as the 800x480 model. Thatâs just a personal preference thing. The second issue was that although I set the PSRAM to run at 120MHz and page switching was just as smooth as the 800x480 version, just a lot slower. My guess is maybe the higher resolution is causing this.
All that being said, if I hadnât had the 800x480 to compare it with, I would have been more than happy with it. For what they are, these things are so cheap.
Yes, thatâs what I did. Itâs super easy, even for a beginner like myself. One thing I didnât pick up on is that the 1024Ă600 chip runs really hot. I noticed the same on the Waveshare ESP32-S3 4.3-inch 800Ă480. I wasnât comfortable with that device and ended up returning it.
I donât think itâs an actual issue, since I believe these chips are designed to run at very high temperatures. It was just that mine are mounted in the wall with a flat bezel over the top. My pal isnât overly concerned, as heâs going to mount his in a picture frame, and itâll be on his exposed brickwork wall.
How does your esphome: and esp32: code look now? Im having the invalid image block" loop on my waveshare 7" 800x480 1.2 and commenting out cpu_frequency: fixes it, it boots, but the screen is black.
anyone having issues with a slight flickering with this display, kinda like a backlight frequency issue?
for me it flickers, the old display did not have this issue.
any ideas?
had the brightness set to 100, yup this took me hours to find, we live and we learn.
I am struggling to get the screen to turn fully off and back on again. Have tried various code fragments for controlling the chip that manages the backlight. Does anyone have a working yaml fragment that performs these functions and that is for the 7B variant? Thanks