ESP32-P4 4″ Wi-Fi 6 touch panel with built-in voice – the next-gen wall panel?

On the home page config, I see heating_status, but if in my climate , when heating is active, I don’t see on the home page this is active?

1 Like

Hi! The project is still under development. The icon display isn’t finished yet. But it will be soon.

Hi, I tried to get some more information about whats new for P4 in dev version. I am trying to get OTA working on my device - ESP-P4-ETH from waveshare. I basically coppied bits of essential configuration from this project.

Hi! In version 2025.12.0 dev OTA works in my project, but there is screen flickering

What does anyone think about an intercom function? Perhaps a “Push to announce/talk” setup. This is not a feature request, just looking for input on utility and feasibility.

funny, i also have screen flickering with the old guition 4" when doing ota, not that it matters

On Guition ESP32-48480S40, it also flickers during OTA if you don’t specify rodata in the SDK settings, but on Waveshare-86-panel this doesn’t help.

Qualcuno ha delle info sulle impostazioni inerenti al settaggio del nuovo display elecrow 9 pollici esp32p4?

Use the execute_from_psram option rather than setting sdkconfig options.

1 Like

I’ve just bought a Waveshare ESP32-P4-WIFI6-Touch-LCD-4B and have got @alaltitov’s project working on it, but the wifi range on it is absolutely terrible. Even at 3m with direct line of sight to the router, it’s less than 50% signal strength. By contrast, I have plenty of other ESP32 devices with PCB antennas working reliably off the same routers in different rooms.

Are reasons other than broken hardware that might explain this? I’ve checked that the antenna is attached and not visibly damaged.

I’m using esphome 2025.11.5.

Mine is about 25 feet and two floors away from my access point and I get about 70% signal strength. It could be a hardware issue or an issue with your access point.

My button panel is working great with this screen if you want to try the latest.

Thank you - I have also got your configuration working too, with exactly the same wifi issue.

I’ve tried two completely different access points and both show the same issue (and both work just fine with plenty of other ESP32 devices).

I’m going to attempt to update the co-processor firmware, but I fear this may be a hardware issue. EDIT: now done, no change.

Unfortunately, I didn’t try connecting to wifi using the demo firmware that it shipped with, and that firmware doesn’t seem to be available anywhere.

Turns out that it’s a faulty antenna - it’s shorted in the connector on the cable. I’ve not got anything with the right connector to replace it with, but if I carefully touch the centre pin of the connector on the PCB with tweezers, wifi strength jumps to 75%.

Good find. This unit does have an external antenna at the top of the housing. This is a good design unless the cable is damaged or disconnected!

I figured I had nothing to lose, so I got the microscope and tweezers out and had a go at fixing it. I managed to prise open the ipex connector and sure enough, found a single loose strand of wire. Probably less than 1mm long, but obviously enough to short it. Against the odds I managed to get it back together and it’s now working perfectly!

Now I can get on with playing with LVGL :slight_smile:

1 Like

The wifi on these is so bad, so lucky that I bought the Ethernet version.

Has anybody found a way to stop this screen from flickering during OTA?

Does it happen over USB as well? I typically only flash by usb and don’t see any flickering. I noticed some of the earlier codes by people have some weird libraries and display settings that did it. I wrote mine from scratch and I don’t see it anymore.

No only over Wi-Fi

This is my config. I removed the "CONFIG_SPIRAM_XIP_FROM_PSRAM: y " because my ESP won’t boot if I use it.

# Hardware configuration file for Waveshare ESP32-P4-86-Panel 720px x 720px smart panel
# https://www.waveshare.com/wiki/ESP32-P4-86-Panel-ETH-2RO

esphome:
  min_version: 2025.12.0
  project:
    name: "Waveshare.ESP32-P4-86-Panel"
    version: "1.0.0"

esp32:
  variant: esp32p4
  flash_size: 32MB
  framework:
    type: esp-idf
    advanced:
      enable_idf_experimental_features: true
  cpu_frequency: 400MHz

psram:
  speed: 200MHz

preferences:
  flash_write_interval: 5min

esp_ldo:
  - channel: 3
    voltage: 2.5V

#-------------------------------------------
# Network hardware
#-------------------------------------------  

# Ethernet settings
# ethernet:
  # type: IP101
  # mdc_pin: GPIO31
  # mdio_pin: GPIO52
  # clk: 
    # pin: GPIO50
    # mode: CLK_EXT_IN
  # phy_addr: 1
  # power_pin: GPIO51

esp32_hosted:
  active_high: true
  variant: ESP32C6
  reset_pin: GPIO54
  cmd_pin: GPIO19
  clk_pin: GPIO18
  d0_pin: GPIO14
  d1_pin: GPIO15
  d2_pin: GPIO16
  d3_pin: GPIO17  

#-------------------------------------------
# LCD Back light and Relays
#-------------------------------------------
output:
  - platform: ledc
    id: gpio_backlight_pwm
    pin: GPIO26
    frequency: 100Hz
    inverted: true
    min_power: 0.1 # To prevent the backlight from being too dim
    max_power: 0.8 # To prevent overheating due to excessive lighting

  - id: internal_relay_1
    platform: gpio
    pin: GPIO32
    
  - id: internal_relay_2
    platform: gpio
    pin: GPIO46    
    
light:
  - platform: monochromatic
    output: gpio_backlight_pwm
    name: Display Backlight
    icon: mdi:lightbulb-on
    id: display_backlight
    restore_mode: ALWAYS_ON

#-------------------------------------------
# Touchscreen gt911
#-------------------------------------------
i2c:
  - id: i2c_bus_a
    sda: GPIO7
    scl: GPIO8
    scan: true
    frequency: 400kHz

touchscreen:
  platform: gt911
  id: my_touchscreen
  display: my_display
  i2c_id: i2c_bus_a
  # on_touch:
    # - lambda: |-
        # ESP_LOGI("Touch", "Touch detected at x=%d, y=%d", touch.x, touch.y);
  # on_update:
    # - lambda: |-
          # for (auto touch: touches)  {
              # if (touch.state <= 2) {
                # ESP_LOGI("Touch points:", "id=%d x=%d, y=%d x.raw=%d, y.raw=%d", touch.id, touch.x, touch.y, touch.x_raw, touch.y_raw);
              # }
          # }

#-------------------------------------------
# Display mipi_dsi
#-------------------------------------------
display:
  - platform: mipi_dsi
    id: my_display
    model: WAVESHARE-P4-86-PANEL
  
# Special LVGL settings required for this display  
lvgl:
  buffer_size: 100%
  byte_order: little_endian    

#-------------------------------------------
# Audio
#-------------------------------------------
i2s_audio:
  - id: i2s_audio_bus
    i2s_mclk_pin: GPIO13
    i2s_lrclk_pin: GPIO10
    i2s_bclk_pin: GPIO12

audio_dac:
  - platform: es8311
    id: es8311_dac
    i2c_id: i2c_bus_a
    address: 0x18

audio_adc:
  - platform: es7210
    id: es7210_adc
    i2c_id: i2c_bus_a
    address: 0x40

microphone:
  - platform: i2s_audio
    id: esp32_microphone
    i2s_audio_id: i2s_audio_bus
    i2s_din_pin: GPIO11
    sample_rate: 16000
    bits_per_sample: 16bit
    adc_type: external
    # on_data:
    #   - logger.log:
    #       format: "Microphone data received: %d bytes"
    #       args: [x.size()]

speaker:
  - platform: i2s_audio
    id: esp32_speaker
    i2s_audio_id: i2s_audio_bus
    i2s_dout_pin: GPIO9
    audio_dac: es8311_dac
    dac_type: external
    channel: mono
    buffer_duration: 100ms
    bits_per_sample: 16bit
    sample_rate: 48000

  - platform: mixer
    id: mixing_speaker
    output_speaker: esp32_speaker
    source_speakers:
      - id: announcement_mixing_input
        timeout: never
      - id: media_mixing_input
        timeout: never

  - platform: resampler
    id: announcement_resampling_speaker
    output_speaker: announcement_mixing_input
    sample_rate: 48000
    bits_per_sample: 16

  - platform: resampler
    id: media_resampling_speaker
    output_speaker: media_mixing_input
    sample_rate: 48000
    bits_per_sample: 16

switch:
  - platform: gpio
    pin: GPIO53  # BSP_POWER_AMP_IO
    name: "Audio Amplifier"
    id: audio_amplifier
    restore_mode: ALWAYS_OFF

# Media Player
media_player:
  - platform: speaker
    name: "ESP32 P4 Media Player"
    id: speaker_media_player
    codec_support_enabled: true
    # buffer_size: 2000000
    # task_stack_in_psram: true
    volume_min: 0.5
    volume_max: 0.75
    volume_increment: 0.05
    announcement_pipeline:
      speaker: announcement_resampling_speaker
      format: FLAC
      sample_rate: 48000
      num_channels: 1
    media_pipeline:
      speaker: media_resampling_speaker
      format: FLAC
      num_channels: 1
      sample_rate: 48000
    on_announcement:
      - if:
          condition:
            - microphone.is_capturing:
          then:
            - micro_wake_word.stop
            - voice_assistant.stop
      - mixer_speaker.apply_ducking:
          id: media_mixing_input
          decibel_reduction: 20
          duration: 0.0s
      - switch.turn_on: audio_amplifier
      - delay: 100ms
    on_state:
      if:
        condition:
          and:
            - not:
                voice_assistant.is_running:
            - not:
                media_player.is_announcing:
        then:
          - mixer_speaker.apply_ducking:
              id: media_mixing_input
              decibel_reduction: 0
              duration: 1.0s
    on_play:
      - logger.log: "Media player started playing, disabling microphone"
      - switch.turn_on: audio_amplifier
      - delay: 100ms
      - micro_wake_word.stop
      - voice_assistant.stop
    on_idle:
      - delay: 100ms
      - switch.turn_off: audio_amplifier
      - if:
          condition:
            not:
              voice_assistant.is_running:
          then:
            - micro_wake_word.start

sensor:
  - platform: template
    name: "Voice Assistant State"
    lambda: |-
      if (id(esp32_microphone).is_running()) {
        return 1;
      } else {
        return 0;
      }
    update_interval: 2s

text_sensor:
  - platform: template
    name: "Voice Assistant Status"
    id: voice_status
    update_interval: 5s
    lambda: |-
      if (id(esp32_microphone).is_running()) {
        return {"Listening"};
      } else {
        return {"Idle"};
      }

micro_wake_word:
  id: my_wake_word
  models:
    - model: alexa
  on_wake_word_detected:
    then:
      - logger.log: "Wake word detected"
      - voice_assistant.start:
          wake_word: !lambda return wake_word;

voice_assistant:
  microphone: esp32_microphone
  media_player: speaker_media_player
  micro_wake_word: my_wake_word
  noise_suppression_level: 2
  auto_gain: 31dBFS
  volume_multiplier: 2.0
  conversation_timeout: 300s
  on_end:
    # Wait a short amount of time to see if an announcement starts
    - wait_until:
        condition:
          - media_player.is_announcing:
        timeout: 0.5s
    # Announcement is finished and the I2S bus is free
    - wait_until:
        - and:
            - not:
                media_player.is_announcing:
            - not:
                media_player.is_playing:
    - micro_wake_word.start:
  on_client_connected:
    - micro_wake_word.start:
  on_client_disconnected:
    - micro_wake_word.stop