Color mapping issues on Waveshare ESP32-S3 Touch LCD 7" (LVGL 8.4.0)

Hello everyone,

I am having trouble with color reproduction on my Waveshare ESP32-S3 Touch LCD 7". While the sketch uploads successfully, the colors displayed on the screen do not match the hex codes in the code.

Environment:

  • Hardware: Waveshare ESP32-S3-Touch-LCD-7
  • LVGL Version: 8.4.0
  • Arduino-ESP32 Core: 2.0.17

The Problem:
Specifically, I encounter issues with the following values:

  • ORANGE (0xFD20): Displays as a slightly dark yellow.
  • BROWN/Sienna (0xA2A5): Displays as turquoise/cyan.
  • BROWN/Chocolate (0x8200): Displays as black (it seems the screen might be turning off or failing to render).

It looks like there might be a color format mismatch (RGB565 vs BGR565) or an issue with how the byte order is handled in the display driver configuration.

Has anyone encountered this specific issue with this Waveshare board? Any advice on how to fix the color mapping would be greatly appreciated.

Thank you!

#include <Arduino.h>
#include <Wire.h>
#include "esp_lcd_types.h"
#include "esp_lcd_panel_ops.h"
#include "esp_lcd_panel_rgb.h"

// I2C для CH32V003
#define SDA_PIN 8
#define SCL_PIN 9
#define ADDR 0x24

esp_lcd_panel_handle_t panel_handle = NULL;
uint16_t *buf = NULL;

struct TestColor {
    uint16_t hex;
    const char* name;
};

TestColor colors[] = {
    {0xF800, "PURE RED"},
    {0x07E0, "PURE GREEN"},
    {0x001F, "PURE BLUE"},
    {0xFD20, "ORANGE"},
    {0xA2A5, "BROWN (Sienna)"},
    {0x8200, "BROWN (Chocolate)"},
    {0xFFFF, "WHITE"},
    {0x0000, "BLACK"}
};
static inline uint16_t rgb565_to_bgr565(uint16_t c) {
    uint16_t r = (c >> 11) & 0x1F;
    uint16_t g = (c >> 5)  & 0x3F;
    uint16_t b =  c        & 0x1F;
    return (b << 11) | (g << 5) | r;
}
int color_idx = 0;
const int num_colors = sizeof(colors) / sizeof(colors[0]);

void expanderWrite(uint8_t reg, uint8_t data) {
  Wire.beginTransmission(ADDR);
  Wire.write(reg);
  Wire.write(data);
  Wire.endTransmission();
}

void setup() {
  Serial.begin(115200);
  delay(2000);
  Serial.println("--- Starting LCD Color Test ---");

  Wire.begin(SDA_PIN, SCL_PIN);
  expanderWrite(0x4A, 0x00); 
  expanderWrite(0x4B, 0xFF); 
  Serial.println("Backlight ON");

  esp_lcd_rgb_panel_config_t panel_config = {
        .clk_src = (lcd_clock_source_t)0, 

    
        .timings = {
        .pclk_hz = 16000000, 
        .h_res = 1024,
        .v_res = 600,
        .hsync_pulse_width = 162, 
        .hsync_back_porch = 152,  
        .hsync_front_porch = 48,  
        .vsync_pulse_width = 45,  
        .vsync_back_porch = 13,   
        .vsync_front_porch = 3,   
        .flags = {
            .pclk_active_neg = 1,
        },
    },
    .data_width = 16,
    .sram_trans_align = 8,
    .psram_trans_align = 64,
    .hsync_gpio_num = 46,
    .vsync_gpio_num = 3,
    .de_gpio_num = 5,
    .pclk_gpio_num = 7,
.data_gpio_nums = {2, 40, 41, 42, 1, 21, 47, 48, 45, 0, 39, 10, 17, 18, 38, 14,},
    .disp_gpio_num = -1,
    .flags = {
        .fb_in_psram = 1,
    },
  };

  panel_config.flags.fb_in_psram = 1;


  Serial.println("Initializing LCD panel...");
  if (esp_lcd_new_rgb_panel(&panel_config, &panel_handle) != ESP_OK) {
      Serial.println("FAILED to create RGB panel!");
      return;
  }
  esp_lcd_panel_reset(panel_handle);
  esp_lcd_panel_init(panel_handle);
  Serial.println("LCD init done.");

  Serial.println("Allocating 1.2MB in PSRAM...");
  buf = (uint16_t *)heap_caps_malloc(1024 * 600 * 2, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
  
  if (buf == NULL) {
      Serial.println("!!! CRITICAL ERROR: PSRAM allocation failed! Check 'OPI PSRAM' setting.");
      while(1) delay(1000);
  }
  Serial.println("PSRAM allocated successfully.");
}

void loop() {
  if (buf == NULL) return;

  uint16_t current_hex = colors[color_idx].hex;
  const char* current_name = colors[color_idx].name;

  Serial.print(">>> Displaying: ");
  Serial.print(current_name);
  Serial.print(" | Code: 0x");
  Serial.println(current_hex, HEX);
  Serial.flush();

  for (int i = 0; i < 1024 * 600; i++) {
    buf[i] = rgb565_to_bgr565(current_hex);
  }

  esp_lcd_panel_draw_bitmap(panel_handle, 0, 0, 1024, 600, buf);

  color_idx = (color_idx + 1) % num_colors;

  delay(3000); //
}

Hi!

Can you try setting swap_color_bytes like this?

esp_lcd_rgb_panel_config_t panel_config = {
  ...
  .flags = {
    .fb_in_psram = 1,
    .swap_color_bytes = 1,   // <--- add this
  },
};

Let me know if it works.

Hello giobauermeister,
Thank you for your response. Unfortunately, that fix won’t work (Compilation error: ‘esp_lcd_rgb_panel_config_t::’ has no non-static data member named ‘swap_color_bytes’) because the swap_color_bytes member was removed from the esp_lcd_rgb_panel_config_t structure in newer versions of ESP-IDF .
Thank you!

Hi

Aren’t your data pins incorrect, according to the examples:

.data_gpio_nums = {
            // GPIOs for RGB data signals
            EXAMPLE_LCD_IO_RGB_DATA0,  // Data bit 0
            EXAMPLE_LCD_IO_RGB_DATA1,  // Data bit 1
            EXAMPLE_LCD_IO_RGB_DATA2,  // Data bit 2
            EXAMPLE_LCD_IO_RGB_DATA3,  // Data bit 3
            EXAMPLE_LCD_IO_RGB_DATA4,  // Data bit 4
            EXAMPLE_LCD_IO_RGB_DATA5,  // Data bit 5
            EXAMPLE_LCD_IO_RGB_DATA6,  // Data bit 6
            EXAMPLE_LCD_IO_RGB_DATA7,  // Data bit 7
            EXAMPLE_LCD_IO_RGB_DATA8,  // Data bit 8
            EXAMPLE_LCD_IO_RGB_DATA9,  // Data bit 9
            EXAMPLE_LCD_IO_RGB_DATA10, // Data bit 10
            EXAMPLE_LCD_IO_RGB_DATA11, // Data bit 11
            EXAMPLE_LCD_IO_RGB_DATA12, // Data bit 12
            EXAMPLE_LCD_IO_RGB_DATA13, // Data bit 13
            EXAMPLE_LCD_IO_RGB_DATA14, // Data bit 14
            EXAMPLE_LCD_IO_RGB_DATA15, // Data bit 15
        },

And

// Blue data signals
#define EXAMPLE_LCD_IO_RGB_DATA0        (GPIO_NUM_14) ///< B3
#define EXAMPLE_LCD_IO_RGB_DATA1        (GPIO_NUM_38) ///< B4
#define EXAMPLE_LCD_IO_RGB_DATA2        (GPIO_NUM_18) ///< B5
#define EXAMPLE_LCD_IO_RGB_DATA3        (GPIO_NUM_17) ///< B6
#define EXAMPLE_LCD_IO_RGB_DATA4        (GPIO_NUM_10) ///< B7

// Green data signals
#define EXAMPLE_LCD_IO_RGB_DATA5        (GPIO_NUM_39) ///< G2
#define EXAMPLE_LCD_IO_RGB_DATA6        (GPIO_NUM_0)  ///< G3
#define EXAMPLE_LCD_IO_RGB_DATA7        (GPIO_NUM_45) ///< G4
#define EXAMPLE_LCD_IO_RGB_DATA8        (GPIO_NUM_48) ///< G5
#define EXAMPLE_LCD_IO_RGB_DATA9        (GPIO_NUM_47) ///< G6
#define EXAMPLE_LCD_IO_RGB_DATA10       (GPIO_NUM_21) ///< G7

// Red data signals
#define EXAMPLE_LCD_IO_RGB_DATA11       (GPIO_NUM_1)  ///< R3
#define EXAMPLE_LCD_IO_RGB_DATA12       (GPIO_NUM_2)  ///< R4
#define EXAMPLE_LCD_IO_RGB_DATA13       (GPIO_NUM_42) ///< R5
#define EXAMPLE_LCD_IO_RGB_DATA14       (GPIO_NUM_41) ///< R6
#define EXAMPLE_LCD_IO_RGB_DATA15       (GPIO_NUM_40) ///< R7

At least according to the examples available on the Wiki page.