caemor / epd-waveshare

Drivers for various EPDs from Waveshare
ISC License
207 stars 128 forks source link

Waveshare 7.5 (B) v3 stuck on Display7in5 #188

Closed NE4Y closed 5 months ago

NE4Y commented 5 months ago

Hi all,

im currently trying to connect a Waveshare 7.5 (B) v3 e ink display (https://www.waveshare.com/product/7.5inch-e-paper-hat-b.htm) to an esp32.

I'm using the master branch of the epd-waveshare repo.

The problem is, as soon as i call update_and_display_frame, the program stops at calling app_main() (without printing the first Start).

Bildschirmfoto 2024-01-28 um 20 12 46

My rust code:

use esp_idf_svc;

use anyhow::{Result};
use epd_waveshare::epd7in5_v2::{Display7in5, Epd7in5};
use epd_waveshare::prelude::WaveshareDisplay;
use esp_idf_svc::hal::peripherals::Peripherals;
use esp_idf_svc::hal::{gpio, spi};
use esp_idf_svc::hal::delay::Delay;
use esp_idf_svc::hal::gpio::{AnyInputPin, AnyOutputPin, PinDriver};
use esp_idf_svc::hal::prelude::FromValueType;
use log::info;

fn main() -> Result<()> {
    esp_idf_svc::sys::link_patches();
    esp_idf_svc::log::EspLogger::initialize_default();

    info!("Start.");

    let peripherals = Peripherals::take().unwrap();
    let pins = peripherals.pins;
    let spi_p = peripherals.spi3;
    let sclk: AnyOutputPin = pins.gpio18.into();
    let sdo: AnyOutputPin = pins.gpio23.into();
    let cs: AnyOutputPin = pins.gpio5.into();
    let busy_in: AnyInputPin = pins.gpio4.into();
    let rst: AnyOutputPin = pins.gpio16.into();
    let dc: AnyOutputPin = pins.gpio17.into();

    let mut driver = spi::SpiDeviceDriver::new_single(
        spi_p,
        sclk,
        sdo,
        Option::<gpio::AnyIOPin>::None,
        Option::<gpio::AnyOutputPin>::None,
        &spi::config::DriverConfig::new(),
        &spi::config::Config::new().baudrate(10.MHz().into()),
    )?;

    let mut delay = Delay::new_default();

    let mut epd = Epd7in5::new(
        &mut driver,
        PinDriver::input(busy_in)?,
        PinDriver::output(dc)?,
        PinDriver::output(rst)?,
        &mut delay,
        None
    ).expect("Setup epd failed.");

    info!("Setup complete.");

    let mut display = Display7in5::default();

    epd.update_and_display_frame(&mut driver, display.buffer(), &mut delay)?;

    info!("After display");

    Ok(())

}

If i remove epd.update_and_display_frame(&mut driver, display.buffer(), &mut delay)?; i get both prints.

Bildschirmfoto 2024-01-28 um 20 15 11

Any idea whats going on? I also tried v0.5.0 but got the same results.

Cargo.toml

[package]
name = "eink"
version = "0.1.0"
authors = ["NE4Y"]
edition = "2021"
resolver = "2"
rust-version = "1.71"

[profile.release]
opt-level = "s"

[profile.dev]
debug = true    # Symbols are nice and they don't increase the size on Flash
opt-level = "z"

[features]
default = ["std", "embassy", "esp-idf-svc/native"]

pio = ["esp-idf-svc/pio"]
std = ["alloc", "esp-idf-svc/binstart", "esp-idf-svc/std"]
alloc = ["esp-idf-svc/alloc"]
nightly = ["esp-idf-svc/nightly"]
experimental = ["esp-idf-svc/experimental"]
embassy = ["esp-idf-svc/embassy-sync", "esp-idf-svc/critical-section", "esp-idf-svc/embassy-time-driver"]

[dependencies]
log = { version = "0.4", default-features = false }
esp-idf-svc = { version = "0.48", default-features = false }
esp-idf-sys = { version = "0.34.0" }
epd-waveshare = { git = "https://github.com/caemor/epd-waveshare" }
anyhow = "1.0.79"

[build-dependencies]
embuild = "0.31.3"
bemyak commented 5 months ago

I'm having exactly the same issue with an even simpler setup:

use std::{thread, time::Duration};

use embedded_graphics::{
    geometry::Point,
    primitives::{Line, PrimitiveStyle, StyledDrawable},
};
use epd_waveshare::{color::Color, epd7in5_v2::Display7in5};

use log::info;

fn main() -> anyhow::Result<()> {
    esp_idf_svc::sys::link_patches();
    esp_idf_svc::log::EspLogger::initialize_default();
    info!("Init complete");
    let mut display = Display7in5::default();
    Line::new(Point::new(0, 0), Point::new(1, 1))
        .draw_styled(&PrimitiveStyle::with_stroke(Color::Black, 3), &mut display)?;
    loop {
        info!("Done!");
        thread::sleep(Duration::from_secs(1));
    }
}

If I comment out the draw call, everything works as expected, but even Init complete isn't being printed when trying to draw.

bemyak commented 5 months ago

After some digging and asking around, I've found the answer. The epd7in5_v2::Display7in5 struct size is 800*480=375KB + some additional fields and vtable. It's way too big to live on stack, so it must be put on heap:

let mut display = Box::new(Display7in5::default());
NE4Y commented 5 months ago

Oh wow, of course. I haven't thought about that. Now it works! Thanks!

NE4Y commented 5 months ago

@bemyak Did you find a way to speed up the update time of the screen? If flickers for like 20 seconds when updating data (update_color_frame) which is somewhat unsatisfying. Do you know if there is a way to transmit the data (without the flickering) and then update the display quickly?

bemyak commented 5 months ago

That's just how the color displays are. The spec says that the full update time is 26s, I don't think there are any workarounds, at least not through the SPI. Maybe if you connect directly to it through 24 pin bus, you'll be able to find some shortcuts.

That's the main reason why I chose the B&W one :)

bemyak commented 5 months ago

It would be actually nice, if this library would take care of that, or at least have some comment to give users a hint how to use it