epd-waveshare icon indicating copy to clipboard operation
epd-waveshare copied to clipboard

Doesn't work on the esp32

Open EnvOut opened this issue 5 months ago • 8 comments

Hey I use ESP32 controller and example with 2.13bc doesnt work beacause it use embeded_linux :( Could you please fix or made sample for ESP32?

EnvOut avatar Jul 06 '25 12:07 EnvOut

Hi, I just stumbled accros your comment. I've spend the past couple hours working on figuring out the same questing you have. I'll try to get a pul request in with a full example after I've cleaned up my code. In the meantime what worked for me is included below (im using an ESP32-S3 so you might have to change a few things around). I hope this helps:

#![no_std]
#![no_main]
#![deny(
    clippy::mem_forget,
    reason = "mem::forget is generally not safe to do with esp_hal types, especially those \
    holding buffers for the duration of a data transfer."
)]

use embassy_executor::Spawner;
use embedded_graphics::{
    mono_font::MonoTextStyleBuilder,
    prelude::*,
    text::{Baseline, Text, TextStyleBuilder},
};
use embedded_hal_bus::spi::ExclusiveDevice;
use epd_waveshare::{
    epd7in5_v2::{Display7in5, Epd7in5},
    prelude::*,
};
use esp_hal::{
    clock::CpuClock,
    delay::Delay,
    gpio::{Input, InputConfig, Level, OutputConfig},
    spi::master::{Config, Spi},
    time::Rate,
};
use esp_hal::{gpio::Output, spi::Mode};

#[panic_handler]
fn panic(_: &core::panic::PanicInfo) -> ! {
    loop {}
}

use log::info; // add this at the top // SpiDevice wrapper
extern crate alloc;

// This creates a default app-descriptor required by the esp-idf bootloader.
// For more information see: <https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/system/app_image_format.html#application-description>
esp_bootloader_esp_idf::esp_app_desc!();

#[esp_hal_embassy::main]
async fn main(_spawner: Spawner) {
    // generator version: 0.5.0

    esp_println::logger::init_logger_from_env();

    let peripherals = esp_hal::init(esp_hal::Config::default().with_cpu_clock(CpuClock::max()));
    esp_alloc::heap_allocator!(size: 64 * 1024);

    // let _init = esp_wifi::init(timg0.timer0, esp_hal::rng::Rng::new(peripherals.RNG)).unwrap();
    // Setup pins for the e-paper display
    info!("Setting up GPIO pins");
    let cs = Output::new(peripherals.GPIO10, Level::High, OutputConfig::default());
    let dc = Output::new(peripherals.GPIO17, Level::High, OutputConfig::default());
    let busy = Input::new(peripherals.GPIO15, InputConfig::default());
    let mut rst = Output::new(peripherals.GPIO7, Level::High, OutputConfig::default());

    info!("Initializing SPI for EPD");
    let spi_cfg = Config::default()
        .with_frequency(Rate::from_mhz(10))
        .with_mode(Mode::_0);
    let spi = Spi::new(peripherals.SPI2, spi_cfg)
        .expect("failed to create SPI A")
        .with_sck(peripherals.GPIO12)
        .with_mosi(peripherals.GPIO11);

    let mut delay = Delay::new();
    let mut spi_dev = ExclusiveDevice::new(spi, cs, delay).expect("Failed to create SPI device");
    info!("SPI initialized");
    // Check BUSY pin after reset

    // First, perform a proper hardware reset
    rst.set_low();
    delay.delay_millis(10); // hold low for at least 10ms
    rst.set_high();
    delay.delay_millis(200); // wait 200ms for power-up
                             //
    while busy.is_low() {
        delay.delay_millis(10);
    }
    info!("BUSY pin is HIGH after reset, proceeding with initialization");
    // Check BUSY pin
    let is_busy_low = busy.is_low();
    info!(
        "BUSY pin state: {}",
        if is_busy_low { "LOW" } else { "HIGH" }
    );

    // Force a direct command sequence for initialization, bypassing the library's busy checks
    info!("Manual initialization sequence");

    // First reset the display

    info!("Power-on command sent");

    // Create a display buffer and try a direct update

    // Init EPD
    info!("Creating EPD instance");
    let mut epd = Epd7in5::new(&mut spi_dev, busy, dc, rst, &mut delay, None)
        .expect("Failed to create EPD instance");

    info!("Creating display buffer");
    let mut display = Display7in5::default();
    display.clear(Color::Black).ok();
    draw_text(&mut display, "Hello, EPD!", 10, 10);
    epd.update_and_display_frame(&mut spi_dev, display.buffer(), &mut delay)
        .expect("Failed to update and display frame");
    epd.sleep(&mut spi_dev, &mut delay)
        .expect("Failed to put EPD to sleep");

    loop {
        // // Nothing to do, just loop
        delay.delay_millis(1000);
        //
        // let _ = Text::with_text_style("IT WORKS!", Point::new(0, 0), style, text_style);
        // epd.update_and_display_frame(&mut spi_dev, display.buffer(), &mut delay)
        //     .expect("Failed to update and display frame");
    }

    // for inspiration have a look at the examples at https://github.com/esp-rs/esp-hal/tree/esp-hal-v1.0.0-rc.0/examples/src/bin
}
fn draw_text(display: &mut Display7in5, text: &str, x: i32, y: i32) {
    let style = MonoTextStyleBuilder::new()
        .font(&embedded_graphics::mono_font::ascii::FONT_6X10)
        .text_color(Color::White)
        .background_color(Color::Black)
        .build();

    let text_style = TextStyleBuilder::new().baseline(Baseline::Top).build();

    let _ = Text::with_text_style(text, Point::new(x, y), style, text_style).draw(display);
}

My Cargo.toml looks like this:

[package]
edition = "2021"
name = "esp_home_no_std"
rust-version = "1.86"
version = "0.1.0"

[lib]
test = false

[[bin]]
test = false
name = "esp_home_no_std"
path = "./src/bin/main.rs"

[dependencies]
epd-waveshare = "0.6.0"
embedded-graphics = "0.8.1"
esp-bootloader-esp-idf = { version = "0.2.0", features = ["esp32s3"] }
esp-hal = { version = "=1.0.0-rc.0", features = [
  "esp32s3",
  "log-04",
  "unstable",
] }
log = "0.4.27"

bleps = { git = "https://github.com/bjoernQ/bleps", package = "bleps", rev = "a5148d8ae679e021b78f53fd33afb8bb35d0b62e", features = [
  "async",
  "macros",
] }
critical-section = "1.2.0"
embedded-io = "0.6.1"
embassy-executor = { version = "0.7.0", features = ["task-arena-size-20480"] }
embassy-time = "0.4.0"
esp-hal-embassy = { version = "0.9.0", features = ["esp32s3"] }
embassy-embedded-hal = "0.3.1"
embedded-hal = "1.0.0"
embedded-hal-bus = "0.3.0"
esp-alloc = "0.8.0"
esp-println = { version = "0.15.0", features = ["esp32s3", "log-04"] }
esp-wifi = { version = "0.15.0", features = [
  "ble",
  "builtin-scheduler",
  "coex",
  "esp-alloc",
  "esp32s3",
  "log-04",
  "smoltcp",
  "wifi",
] }
smoltcp = { version = "0.12.0", default-features = false, features = [
  "log",
  "medium-ethernet",
  "multicast",
  "proto-dhcpv4",
  "proto-dns",
  "proto-ipv4",
  "socket-dns",
  "socket-icmp",
  "socket-raw",
  "socket-tcp",
  "socket-udp",
] }


[profile.dev]
# Rust debug is too slow.
# For debug builds always builds with some optimization
opt-level = "s"

[profile.release]
codegen-units = 1        # LLVM can perform better optimizations using a single thread
debug = 2
debug-assertions = false
incremental = false
lto = 'fat'
opt-level = 's'
overflow-checks = false

BitsAndDroids avatar Jul 18 '25 16:07 BitsAndDroids

And for a std version:

use embedded_graphics::{
    image::{Image, ImageRaw},
    mono_font::MonoTextStyleBuilder,
    pixelcolor::{raw::BigEndian, BinaryColor},
    prelude::*,
    text::{Baseline, Text, TextStyleBuilder},
};
use epd_waveshare::{
    color::Color,
    epd7in5_v2::{Display7in5, Epd7in5},
    prelude::*,
};
use esp_idf_svc::hal::{
    delay::Delay,
    gpio::PinDriver,
    prelude::Peripherals,
    spi::{
        config::{Config, MODE_0},
        SpiDeviceDriver, SpiDriver, SpiDriverConfig,
    },
    units::Hertz,
};

fn main() {
    // It is necessary to call this function once. Otherwise some patches to the runtime
    // implemented by esp-idf-sys might not link properly. See https://github.com/esp-rs/esp-idf-template/issues/71
    esp_idf_svc::sys::link_patches();
    // Bind the log crate to the ESP Logging facilities
    esp_idf_svc::log::EspLogger::initialize_default();

    const MARGIN: i32 = 10; // Margin for text and icons

    let peripherals = match Peripherals::take() {
        Ok(peripherals) => peripherals,
        Err(e) => {
            log::error!("Failed to take peripherals: {e}");
            panic!("Failed to take peripherals");
        }
    };

    // Setup pins for the e-paper display
    log::info!("Setting up GPIO pins");
    let cs = peripherals.pins.gpio10;
    let mut dc = PinDriver::output(peripherals.pins.gpio17).unwrap();
    let mut rst = PinDriver::output(peripherals.pins.gpio7).unwrap();
    let busy = PinDriver::input(peripherals.pins.gpio15).unwrap();

    dc.set_high().unwrap(); // Set DC high for command mode
    rst.set_high().unwrap(); // Set RST high initially

    let sclk = peripherals.pins.gpio12;
    let mosi = peripherals.pins.gpio11;
    //
    log::info!("Initializing SPI for EPD");

    let delay = Delay::default();
    log::info!("SPI initialized");

    rst.set_low().expect("error setting pin low");
    delay.delay_ms(10); // Hold low for at least 10ms
    rst.set_high().expect("error setting pin high");
    delay.delay_ms(200); // Hold high for at least 200ms
    while busy.is_low() {
        delay.delay_ms(10); // Wait for BUSY to go high
    }
    log::info!("BUSY pin is HIGH after reset, proceeding with initialization");
    // Check BUSY pin
    let is_busy_low = busy.is_low();
    log::info!(
        "BUSY pin state: {}",
        if is_busy_low { "LOW" } else { "HIGH" }
    );
    // // Init EPD
    log::info!("Creating EPD instance");

    let spi_cfg = Config::default()
        .baudrate(Hertz(10_000_000))
        .data_mode(MODE_0);
    let spi = peripherals.spi2;
    let spi_driver_cfg = SpiDriverConfig::new();

    let spi_driver = SpiDriver::new(
        spi,
        sclk,
        mosi,
        None::<esp_idf_svc::hal::gpio::Gpio0>,
        &spi_driver_cfg,
    )
    .unwrap();

    let mut device = SpiDeviceDriver::new(&spi_driver, Some(cs), &spi_cfg).unwrap();

    let mut delay = Delay::default(); // or FreeRtos if safer
    let mut epd = Epd7in5::new(&mut device, busy, dc, rst, &mut delay, None)
        .expect("Failed to create EPD instance");

    log::info!("EPD instance created successfully");
    log::info!("Initializing EPD display");
    let mut display = Box::new(Display7in5::default());
    log::info!("Display locked for drawing");
    display.clear(Color::Black).expect("error clearing screen");
    draw_text(&mut display, "Hello, EPD!", MARGIN, MARGIN);

    draw_text(&mut display, "This is a test.", MARGIN, 30);

    draw_wifi_icon(&mut display, 750, MARGIN);

    epd.update_and_display_frame(&mut device, display.buffer(), &mut delay)
        .expect("Failed to update and display frame");
    epd.sleep(&mut device, &mut delay)
        .expect("Failed to put EPD to sleep");

    loop {
        delay.delay_ms(1000);
    }
}

fn draw_wifi_icon(display: &mut Display7in5, x: i32, y: i32) {
    // Draw a simple Wi-Fi icon
    let data = include_bytes!("./assets/wifi.raw");
    let raw_image = ImageRaw::<BinaryColor, BigEndian>::new(data, 40);
    let image = Image::new(&raw_image, Point::new(x, y));
    image.draw(&mut display.color_converted()).unwrap();
}

fn draw_text(display: &mut Display7in5, text: &str, x: i32, y: i32) {
    let style = MonoTextStyleBuilder::new()
        .font(&embedded_graphics::mono_font::ascii::FONT_9X15_BOLD)
        .text_color(Color::White)
        .background_color(Color::Black)
        .build();

    let text_style = TextStyleBuilder::new().baseline(Baseline::Top).build();

    let _ = Text::with_text_style(text, Point::new(x, y), style, text_style).draw(display);
}

used these deps:

[dependencies]
embedded-hal-bus = "0.3.0"
log = "0.4"
anyhow = "1.0"
esp-idf-svc = { version = "0.51", features = ["panic_handler"] }
epd-waveshare = { version = "0.6.0", features = ["graphics"] }
embedded-graphics = "0.8.0"

BitsAndDroids avatar Jul 19 '25 14:07 BitsAndDroids

And for a std version:

use embedded_graphics::{ image::{Image, ImageRaw}, mono_font::MonoTextStyleBuilder, pixelcolor::{raw::BigEndian, BinaryColor}, prelude::, text::{Baseline, Text, TextStyleBuilder}, }; use epd_waveshare::{ color::Color, epd7in5_v2::{Display7in5, Epd7in5}, prelude::, }; use esp_idf_svc::hal::{ delay::Delay, gpio::PinDriver, prelude::Peripherals, spi::{ config::{Config, MODE_0}, SpiDeviceDriver, SpiDriver, SpiDriverConfig, }, units::Hertz, };

fn main() { // It is necessary to call this function once. Otherwise some patches to the runtime // implemented by esp-idf-sys might not link properly. See https://github.com/esp-rs/esp-idf-template/issues/71 esp_idf_svc::sys::link_patches(); // Bind the log crate to the ESP Logging facilities esp_idf_svc::log::EspLogger::initialize_default();

const MARGIN: i32 = 10; // Margin for text and icons

let peripherals = match Peripherals::take() {
    Ok(peripherals) => peripherals,
    Err(e) => {
        log::error!("Failed to take peripherals: {e}");
        panic!("Failed to take peripherals");
    }
};

// Setup pins for the e-paper display
log::info!("Setting up GPIO pins");
let cs = peripherals.pins.gpio10;
let mut dc = PinDriver::output(peripherals.pins.gpio17).unwrap();
let mut rst = PinDriver::output(peripherals.pins.gpio7).unwrap();
let busy = PinDriver::input(peripherals.pins.gpio15).unwrap();

dc.set_high().unwrap(); // Set DC high for command mode
rst.set_high().unwrap(); // Set RST high initially

let sclk = peripherals.pins.gpio12;
let mosi = peripherals.pins.gpio11;
//
log::info!("Initializing SPI for EPD");

let delay = Delay::default();
log::info!("SPI initialized");

rst.set_low().expect("error setting pin low");
delay.delay_ms(10); // Hold low for at least 10ms
rst.set_high().expect("error setting pin high");
delay.delay_ms(200); // Hold high for at least 200ms
while busy.is_low() {
    delay.delay_ms(10); // Wait for BUSY to go high
}
log::info!("BUSY pin is HIGH after reset, proceeding with initialization");
// Check BUSY pin
let is_busy_low = busy.is_low();
log::info!(
    "BUSY pin state: {}",
    if is_busy_low { "LOW" } else { "HIGH" }
);
// // Init EPD
log::info!("Creating EPD instance");

let spi_cfg = Config::default()
    .baudrate(Hertz(10_000_000))
    .data_mode(MODE_0);
let spi = peripherals.spi2;
let spi_driver_cfg = SpiDriverConfig::new();

let spi_driver = SpiDriver::new(
    spi,
    sclk,
    mosi,
    None::<esp_idf_svc::hal::gpio::Gpio0>,
    &spi_driver_cfg,
)
.unwrap();

let mut device = SpiDeviceDriver::new(&spi_driver, Some(cs), &spi_cfg).unwrap();

let mut delay = Delay::default(); // or FreeRtos if safer
let mut epd = Epd7in5::new(&mut device, busy, dc, rst, &mut delay, None)
    .expect("Failed to create EPD instance");

log::info!("EPD instance created successfully");
log::info!("Initializing EPD display");
let mut display = Box::new(Display7in5::default());
log::info!("Display locked for drawing");
display.clear(Color::Black).expect("error clearing screen");
draw_text(&mut display, "Hello, EPD!", MARGIN, MARGIN);

draw_text(&mut display, "This is a test.", MARGIN, 30);

draw_wifi_icon(&mut display, 750, MARGIN);

epd.update_and_display_frame(&mut device, display.buffer(), &mut delay)
    .expect("Failed to update and display frame");
epd.sleep(&mut device, &mut delay)
    .expect("Failed to put EPD to sleep");

loop {
    delay.delay_ms(1000);
}

}

fn draw_wifi_icon(display: &mut Display7in5, x: i32, y: i32) { // Draw a simple Wi-Fi icon let data = include_bytes!("./assets/wifi.raw"); let raw_image = ImageRaw::<BinaryColor, BigEndian>::new(data, 40); let image = Image::new(&raw_image, Point::new(x, y)); image.draw(&mut display.color_converted()).unwrap(); }

fn draw_text(display: &mut Display7in5, text: &str, x: i32, y: i32) { let style = MonoTextStyleBuilder::new() .font(&embedded_graphics::mono_font::ascii::FONT_9X15_BOLD) .text_color(Color::White) .background_color(Color::Black) .build();

let text_style = TextStyleBuilder::new().baseline(Baseline::Top).build();

let _ = Text::with_text_style(text, Point::new(x, y), style, text_style).draw(display);

} used these deps:

[dependencies] embedded-hal-bus = "0.3.0" log = "0.4" anyhow = "1.0" esp-idf-svc = { version = "0.51", features = ["panic_handler"] } epd-waveshare = { version = "0.6.0", features = ["graphics"] } embedded-graphics = "0.8.0"

I tried std version and my esp32 restarts with this output:

ets Jul 29 2019 12:21:46

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0030,len:7104
load:0x40078000,len:15576
load:0x40080400,len:4
0x40080400 - _invalid_pc_placeholder
    at ??:??
ho 8 tail 4 room 4
load:0x40080404,len:3876
entry 0x4008064c
I (31) boot: ESP-IDF v5.1-beta1-378-gea5e0ff298-dirt 2nd stage bootloader
I (31) boot: compile time Jun  7 2023 07:48:23
I (33) boot: Multicore bootloader
I (37) boot: chip revision: v3.1
I (41) boot.esp32: SPI Speed      : 40MHz
I (46) boot.esp32: SPI Mode       : DIO
I (50) boot.esp32: SPI Flash Size : 4MB
I (55) boot: Enabling RNG early entropy source...
I (60) boot: Partition Table:
I (64) boot: ## Label            Usage          Type ST Offset   Length
I (71) boot:  0 nvs              WiFi data        01 02 00009000 00006000
I (79) boot:  1 phy_init         RF data          01 01 0000f000 00001000
I (86) boot:  2 factory          factory app      00 00 00010000 003f0000
I (94) boot: End of partition table
I (98) esp_image: segment 0: paddr=00010020 vaddr=3f400020 size=263c8h (156616) map
I (163) esp_image: segment 1: paddr=000363f0 vaddr=3ffb0000 size=02b70h ( 11120) load
I (168) esp_image: segment 2: paddr=00038f68 vaddr=40080000 size=070b0h ( 28848) load
I (181) esp_image: segment 3: paddr=00040020 vaddr=400d0020 size=56c38h (355384) map
I (309) esp_image: segment 4: paddr=00096c60 vaddr=400870b0 size=062f8h ( 25336) load
I (327) boot: Loaded app from partition at offset 0x10000
I (327) boot: Disabling RNG early entropy source...
I (339) cpu_start: Multicore app
I (348) cpu_start: Pro cpu start user code
I (348) cpu_start: cpu freq: 160000000 Hz
I (348) app_init: Application information:
I (351) app_init: Project name:     libespidf
I (356) app_init: App version:      92933f9-dirty
I (361) app_init: Compile time:     Jul 20 2025 03:18:40
I (367) app_init: ELF file SHA256:  000000000...
I (372) app_init: ESP-IDF:          v5.3.2
I (377) efuse_init: Min chip rev:     v0.0
I (382) efuse_init: Max chip rev:     v3.99 
I (387) efuse_init: Chip rev:         v3.1
I (392) heap_init: Initializing. RAM available for dynamic allocation:
I (399) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (405) heap_init: At 3FFB38E8 len 0002C718 (177 KiB): DRAM
I (411) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM
I (417) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (424) heap_init: At 4008D3A8 len 00012C58 (75 KiB): IRAM
I (431) spi_flash: detected chip: generic
I (435) spi_flash: flash io: dio
W (439) pcnt(legacy): legacy driver is deprecated, please migrate to `driver/pulse_cnt.h`
W (447) i2c: This driver is an old driver, please migrate your application code to adapt `driver/i2c_master.h`
W (458) timer_group: legacy driver is deprecated, please migrate to `driver/gptimer.h`
I (467) main_task: Started on CPU0
I (477) main_task: Calling app_main()
I (477) project3: Setting up GPIO pins
I (477) gpio: GPIO[17]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 
ets Jul 29 2019 12:21:46

rst:0x8 (TG1WDT_SYS_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
ets Jul 29 2019 12:21:46

errors:

rst:0x7 (TG0WDT_SYS_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
ets Jul 29 2019 12:21:46

rst:0x7 (TG0WDT_SYS_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
ets Jul 29 2019 12:21:46

rst:0x7 (TG0WDT_SYS_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
ets Jul 29 2019 12:21:46

rst:0x7 (TG0WDT_SYS_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
ets Jul 29 2019 12:21:46

rst:0x7 (TG0WDT_SYS_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
ets Jul 29 2019 12:21:46

EnvOut avatar Jul 20 '25 05:07 EnvOut

what kind of esp32 are you using? I've got almost most available. So if you let me know I'll have a look with the specific board.

BitsAndDroids avatar Jul 20 '25 08:07 BitsAndDroids

what kind of esp32 are you using? I've got almost most available. So if you let me know I'll have a look with the specific board.

I have board and display from the same comapany (waveshare): https://www.waveshare.com/e-paper-esp32-driver-board.htm

EnvOut avatar Jul 20 '25 17:07 EnvOut

what kind of esp32 are you using? I've got almost most available. So if you let me know I'll have a look with the specific board.

I have board and display from the same comapany (waveshare): https://www.waveshare.com/e-paper-esp32-driver-board.htm

I try this pins (form arduino example):

   let cs = peripherals.pins.gpio15;
    let mut dc = PinDriver::output(peripherals.pins.gpio27).unwrap();
    let mut rst = PinDriver::output(peripherals.pins.gpio26).unwrap();
    let busy = PinDriver::input(peripherals.pins.gpio25).unwrap();

    dc.set_high().unwrap(); // Set DC high for command mode
    rst.set_high().unwrap(); // Set RST high initially

    let sclk = peripherals.pins.gpio13;
    let mosi = peripherals.pins.gpio14;
    //

But it also doenst work. It waits indefinitely at this stage:

 while busy.is_low() {
        delay.delay_ms(10); // Wait for BUSY to go high
    }

My sreen: https://www.waveshare.com/wiki/2.13inch_e-Paper_HAT_(B)_Manual#Python_2 Esp32: https://www.waveshare.com/wiki/E-Paper_ESP32_Driver_Board#Specifications

EnvOut avatar Jul 20 '25 17:07 EnvOut

I had a similar problem. Initializing the epd struct on the heap solved it for me, see https://github.com/caemor/epd-waveshare/issues/188#issuecomment-1925760963

mbrattinga avatar Oct 20 '25 17:10 mbrattinga

Some EPDs do not require the busy to be high after the initial reset. I am using a GoodDisplay GDEY029T94 (epd2in9_v2) and it does not set the busy high so I skip that part of the code.

acedogblast avatar Oct 26 '25 22:10 acedogblast