caemor / epd-waveshare Goto Github PK
View Code? Open in Web Editor NEWDrivers for various EPDs from Waveshare
License: ISC License
Drivers for various EPDs from Waveshare
License: ISC License
I'm trying to get Rust working on the Watchy: watchy.sqfmi.com .
I've gotten everything to compile and even flash, and even clear the screen! But nothing beyond that.
I'm wondering why drawing doesn't work at all. I'm not sure what to think - this is all new to me.
I've attached my code, in hopes that with some expertise, this is trivial to fix.
#![no_std]
#![no_main]
use xtensa_lx_rt as _;
use xtensa_lx_rt::entry;
use panic_halt as _;
use esp32_hal::{
prelude::*,
dport::Split,
target,
gpio::*,
delay::Delay,
};
use epd_waveshare::{epd1in54::*, prelude::*};
#[entry]
fn main() -> ! {
let p = target::Peripherals::take().unwrap();
let (_, dport_clock_control) = p.DPORT.split();
let clkcntrl = esp32_hal::clock_control::ClockControl::new(
p.RTCCNTL,
p.APB_CTRL,
dport_clock_control,
esp32_hal::clock_control::XTAL_FREQUENCY_AUTO,
)
.unwrap();
let (clkcntrl_config, _) = clkcntrl.freeze().unwrap();
let gpios = p.GPIO.split();
let gpio18 = gpios.gpio18.into_push_pull_output();
let gpio23 = gpios.gpio23.into_push_pull_output();
let gpio5 = gpios.gpio5.into_push_pull_output();
let gpio19 = gpios.gpio19.into_pull_up_input();
let gpio10 = gpios.gpio10.into_push_pull_output();
let gpio9 = gpios.gpio9.into_push_pull_output();
let mut spi = esp32_hal::spi::SPI::<
target::SPI3,
Gpio18<Output<PushPull>>,
Gpio23<Output<PushPull>>,
Gpio1<Input<PullUp>>, // Not actually used...?
Gpio5<Output<PushPull>>
>::new(
p.SPI3,
esp32_hal::spi::Pins {
sclk: gpio18,
sdo: gpio23,
sdi: None, // No SDI needed by the epaper display
cs: None, // Used below?
},
esp32_hal::spi::config::Config {
baudrate: 2_000_000.Hz(),
data_mode: esp32_hal::spi::config::MODE_0,
bit_order: esp32_hal::spi::config::BitOrder::MSBFirst,
},
clkcntrl_config,
).unwrap();
let mut delay = Delay::new();
delay.delay_ms(5000u16);
let mut epd = EPD1in54::new(&mut spi, gpio5, gpio19, gpio10, gpio9, &mut delay).unwrap();
// Clear the full screen
epd.clear_frame(&mut spi);
epd.display_frame(&mut spi);
// Speeddemo
epd.set_lut(&mut spi, Some(RefreshLUT::QUICK));
let small_buffer = [Color::Black.get_byte_value(); 32]; //16x16
let number_of_runs = 1;
for i in 0..number_of_runs {
let offset = i * 8 % 150;
epd.update_partial_frame(&mut spi, &small_buffer, 25 + offset, 25 + offset, 16, 16);
epd.display_frame(&mut spi);
}
// Clear the full screen
epd.clear_frame(&mut spi);
epd.display_frame(&mut spi);
// Draw some squares
let small_buffer = [Color::Black.get_byte_value(); 3200]; //160x160
epd.update_partial_frame(&mut spi, &small_buffer, 20, 20, 160, 160);
let small_buffer = [Color::White.get_byte_value(); 800]; //80x80
epd.update_partial_frame(&mut spi, &small_buffer, 60, 60, 80, 80);
let small_buffer = [Color::Black.get_byte_value(); 8]; //8x8
epd.update_partial_frame(&mut spi, &small_buffer, 96, 96, 8, 8);
// Display updated frame
epd.display_frame(&mut spi);
delay.delay_ms(5000u16);
// Set the EPD to sleep
epd.sleep(&mut spi);
loop {}
}
For the two last points:
Current situation:
Drawable::draw()
What could be changed and improved:
update_partial_frame
For some reason, all of the color displays seem to be using their background color as the color to set the chromatic layer to when rendering in black-and-white. This means that if their background color is set to black, the whole display gets set to red. (Also, after doing that by accident, it seems to have permanently washed out my display's red color; it might be because it was trying to set a pixel to black and red at the same time?)
On top of that, a lot of them don't actually use it as the color to clear the display in clear_frame
either, just using the default background color.
As an aside, background_color
seems a bit odd in general; it's only used for clear_frame
, and doesn't actually affect the background color when rendering with embedded-graphics
. Is it really needed?
Disabling default features removes the error.
$ cargo build
Updating crates.io index
Compiling epd-waveshare v0.5.0
error[E0080]: evaluation of constant value failed
--> /home/jonathan/.cargo/registry/src/github.com-1ecc6299db9ec823/epd-waveshare-0.5.0/src/epd4in2/graphics.rs:11:18
|
11 | buffer: [u8; WIDTH as usize * HEIGHT as usize / 8],
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to compute `400_usize * 300_usize`, which would overflow
error[E0080]: evaluation of constant value failed
--> /home/jonathan/.cargo/registry/src/github.com-1ecc6299db9ec823/epd-waveshare-0.5.0/src/epd5in65f/graphics.rs:11:18
|
11 | buffer: [u8; WIDTH as usize * HEIGHT as usize / 2],
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to compute `600_usize * 448_usize`, which would overflow
error[E0080]: evaluation of constant value failed
--> /home/jonathan/.cargo/registry/src/github.com-1ecc6299db9ec823/epd-waveshare-0.5.0/src/epd7in5/graphics.rs:11:18
|
11 | buffer: [u8; WIDTH as usize * HEIGHT as usize / 8],
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to compute `640_usize * 384_usize`, which would overflow
error[E0080]: evaluation of constant value failed
--> /home/jonathan/.cargo/registry/src/github.com-1ecc6299db9ec823/epd-waveshare-0.5.0/src/epd7in5_hd/graphics.rs:11:18
|
11 | buffer: [u8; WIDTH as usize * HEIGHT as usize / 8],
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to compute `880_usize * 528_usize`, which would overflow
error[E0080]: evaluation of constant value failed
--> /home/jonathan/.cargo/registry/src/github.com-1ecc6299db9ec823/epd-waveshare-0.5.0/src/epd7in5_v2/graphics.rs:11:18
|
11 | buffer: [u8; WIDTH as usize * HEIGHT as usize / 8],
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to compute `800_usize * 480_usize`, which would overflow
For more information about this error, try `rustc --explain E0080`.
error: could not compile `epd-waveshare` due to 5 previous errors
# Cargo.toml
[dependencies]
ufmt = "0.1.0"
crc = "3.0.1"
panic-halt = "0.2.0"
embedded-graphics = "0.7.1"
epd-waveshare = "0.5.0"
[dependencies.arduino-hal]
git = "https://github.com/rahix/avr-hal"
rev = "4c9c44c314eb061ee20556ef10d45dea36e75ee4"
features = ["arduino-nano"]
[dependencies.avr-device]
version = "0.5"
$ rustup override set nightly
info: using existing install for 'nightly-x86_64-unknown-linux-gnu'
info: override toolchain for '/home/jonathan/Documents/Programming/Git/schalter-lampen' set to 'nightly-x86_64-unknown-linux-gnu'
nightly-x86_64-unknown-linux-gnu unchanged - rustc 1.69.0-nightly (246eae2fa 2023-02-21)
Dev build depends on linux-embedded-hal
which brings non-portable crates, such as gpio-cdev
, spidev
, sysfs-gpio
and serial-unix
which prevents compilation and execution of unit tests on windows.
As linux-embedded-hal
is only used for the example code, both example code build and linux-embedded-hal
dependency could be a default feature, which can be disabled on the windows platform.
There's a note in WaveshareDisplay::draw_helper
:
Lines 72 to 73 in f49b6e9
min_const_generics
was stabilised in rust 1.51, so this could probably be resolved if that's an acceptable MSRV; what's it referring to?
Is it the duplication of Display
for each model?
See #36 for more infos
Are there any tricks on the 4.2" using an STM32F3? Getting no signs of life from the display, and the program crashing once I hit the
let mut display = Display4in2::default();
line.Then you most likely don't have enough ram left over. It needs 15kB for the full default display buffer and the Display4in2::default() doesn't do much besides making a 15kB framebuffer. You could look into the examples/epd4in2_variable_size.rs example which is using a smaller buffer to update only little parts of the display.
You could also check how much ram you have left and try to reduce your usage elsewhere.
Thank you. It also looks like this command: let mut epd = EPD4in2::new(&mut spi, cs_disp, busy, dc, rst, &mut delay).expect("eink initalize error");
is crashing it as well. I think I need to figure out how to set up panics to see what's going on.
Originally posted by @David-OConnor in #47 (comment)
edit: Given that you mentioned they updated the examples to v2, and I can get the arduino example to work on V1 but not V2, maybe I need to see what V1 looks look.
by David-OConnor
From my experience, the "original" version of this crate (without my modifications) worked well with this display except for quick refresh. I did also have the issues with RAM size, though.
Given that the display protocol is write-only, errors during initialization should be limited to errors from your SPI/GPIO HAL implementation.
by mgottschlag
A few things I found while trying to get my display to work as expected:
epd7in5_v2v::EPD7in5::new(...)
hangs here since the wait_until_idle
implementation is wrong. In the example C code provided by Waveshare one can see that the driver sends a GET_STATUS
command and waits 20ms. This seems to be needed otherwise the busy pin wont update which is the root cause to the problem.
Black and White seems to have been mixed up. Setting the fill-color to black makes the display white and vice versa. Same thing goes for text colors/background.
A few things that might be important:
aarch64-linux-gnu-gcc
targeting aarch64-unknown-linux-musl
.A hacked together version of epd-waveshare can be found here and an example can be found here.
thanks..
I'm using: https://www.waveshare.com/wiki/Pico-ePaper-7.5-B
I'm getting a red screen when using epd7in5_v3
, but from what I could understand, I should be using epd7in5b_v2
, but my esp32-s2 fails to even start when including it with the same code!
Hi! First and foremost, thanks for all the work that been put in to this project!
I have an EPD 2in13 D e-paper, (Datasheet: https://www.waveshare.com/w/upload/5/5b/2.13inch_e-Paper_%28D%29_Datasheet.pdf , Commands(?): https://github.com/waveshare/e-Paper/blob/master/RaspberryPi%26JetsonNano/c/lib/e-Paper/EPD_2in13d.c), and have issues figuring out how to add support for it.
Looking in issue #26 I learned to look at the datasheet to figure out the Commands. However, It's a bit confusing as the example 2in13v2 (https://www.waveshare.com/w/upload/e/e6/2.13inch_e-Paper_Datasheet.pdf) shows the commands with hex values, but it seems omitted for 2in13d?
Do you have any pointers as how to figure out the values?
Thanks!
I recently ordered a collection of the WaveShare displays, including:
I'm happy to contribute or help test, as I plan to use these on a couple of embedded devices for my internet of streams project. I was wondering if you had any notes already on where I should be looking to help add support for the color displays.
The user has to know how EPD implements colors because tricolors have split buffers and the user has to handle it if she doesn't use Display structures.
Moreover Display structures also have to know this too (see the hacky bwrbit in the structure, or the DisplayColorRendering).
I think it should be the only responsibility of epd structures to handle this, we should present a common simple buffer format ti the user for all epds and the specific epd structures should adapt the bits they send to their specific case.
I want to use the library on a microcontroller with 16KiB SRAM, with the 400x300 pixel 4.2 inch display. The library, however, requires a full frame buffer of 400x300x1bit = 15000Byte, almost as much as the available RAM.
I would suggest the following interface to stream data into the library:
/// Iterator which streams pixels.
///
/// This type removes the need for a full screen buffer and allows usage on very memory-constrained
/// devices such as small microcontrollers.
pub trait DisplayStream {
/// Returns the next section of pixels.
fn next<'a>(&'a mut self) -> Option<&'a [u8]>;
}
to be used with a corresponding function in the WaveshareDisplay
trait:
/// Transmit a full frame to the SRAM of the EPD from a streaming iterator
fn update_frame_stream<S: DisplayStream>(
&mut self,
spi: &mut SPI,
stream: S,
) -> Result<(), SPI::Error>;
Do you think such an interface would make sense? The implementation in the driver is trivial (I'd add a stream()
function to the interface, to replace the data()
call previously used to transmit all the data to the display). The old full-buffer interface could even internally be implemented as an iterator returning a single element. However, I'd have to test whether that negatively impacts code size.
If you think that's a good idea, I'd try to clean my code up a bit to create a first draft for further review.
Got a chance recently to take a look at this and I believe the culprit might be the change made in #83 which writes bytes one at time instead of all at once as reverting this got my 7.5" HD display working again and suspect this may be the case for the V2 too.
Happy to make a PR to sort this one out but seems like we may need to support both depending on the display, don't suppose we know which screens will need each write method?
Originally posted by @whiite in #70 (comment)
Question: What is the purpose of dividing the dims by 8 when creating the buffer? eg:
pub struct Display4in2 {
buffer: [u8; WIDTH as usize * HEIGHT as usize / 8],
rotation: DisplayRotation,
}
With this in mind, how should you map pixels to the buffer, given it's not a 1:1 match? Thank you.
If you call display.set_rotation(DisplayRotation::Rotate90);
or display.set_rotation(DisplayRotation::Rotate270);
the display's dimensions (WIDTH/HEIGHT) should be swapped so that embedded-graphics
text alignment features can work properly. As things are right now, if you rotate the display 90ยฐ or 270ยฐ only left-aligned text will display properly.
This needs more consideration first.
It seems to me that the init
function for epd1in54_v2 does forget to set the lut (Look up table), which means that code does not do anything at all unless epd.set_lut is explicitly called later.
At least my Raspberry pi pico did not draw any of the data i send until I eventually tried calling set_lut.
Sadly, I don't have any experience with ePaper displays and I don't fully understand why this is needed:
The Reference code (4.2) mentions:
setting: Load LUT from OTP
SPI(0x22, 0xb1)
I guess this means init should call cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xb1])?;
somewhere?
Should I just try to get it working on my hardware and open a PR if my init does work in a way that the next display_frame-call does something? I don't fully understand what I am doing, but at least it would work then?
If anyone else tried the epd1in54_v2 and did not neet to set_lut explicitly, that would probably mean my software is buggy somewhere.
Hello,
I want to implement support for my 2.13 inch ePaper display that comes with the TTGO T5 v2.3.1.
I found the How-To to add new display support and I think this is something I could do.
However, I have a hard time understanding all the differences between the models and versioning of those displays and consequently I can't find much documentation for my screen (a datasheet).
My board has the DEPG0213BN. I found this datasheet from here but I'm unsure if this even the correct one for my display.
This is the most concrete example driver I could find.
Does anyone have a few ideas? Thanks!
this gives different results for the devices with different is_busy_low variants. this should be changed to either return false (or true) for both cases. False might be better, because when we get an error we should better just block other stuff than maybe breaking things...
Originally posted by @caemor in https://github.com/caemor/epd-waveshare/diffs
Since it is an associated type, most driver implement it as the color type the epd supports.
However since there is a separate WaveshareThreeColorDisplay trait, some driver implement it only as a black and white color and let the 3 colors handling to WaveshareThreeColorDisplay (eg epd1in54c).
We should document and enforce the right behaviour to make sure this is coherent between various implementations.
I'm adding support for the Good Display GDEY0213B74 (same as GDEQ0213B74) display that I will be using in a project. I used the epd2in13_v2
driver as a base as both seem to be based on a SSD1680 (or similar?) controller.
Among things, I found a problem with my display when sleeping: the image was retained, but at a lower contract (albeit slightly).
The original sleep code included:
// All sample code enables and disables analog/clocks...
self.set_display_update_control_2(
spi,
DisplayUpdateControl2::new()
.enable_analog()
.enable_clock()
.disable_analog()
.disable_clock(),
)?;
self.command(spi, Command::MasterActivation)?;
self.set_sleep_mode(spi, self.sleep_mode)?;
After calling Command::MasterActivation
immediately the device is sent to sleep by set_sleep_mode
, resulting in the lowered contrast image. Adding a self.wait_until_idle()
before set_sleep_mode
fixes the contrast issue with my display. Possibly (probably?) this is also the case with the Waveshare modules (which look to be Good Display devices slapped onto a PCB with and sold with nondescript names i.e. no mention of the original GD part number)?
Note. The whole DisplayUpdateControl2
and MasterActivation
sequence in sleep function seems redundant. I don't really know why this sequence is needed, it is not mentioned in the manual and the comment says it was transferred into this crate as it was part of some other sample code.. What's against just removing this code?
SPI should already handle setting the CS pin during communication, why do we have to handle it inside the library's interface mod ?
Hey @caemor @jamesmunns ,
Thanks for pointers. I'm still figuring it out. I have some weird issues when I try to test the 3.7 display using a NRF52 board. Things I've checked so far - initialization and display sequence match C/Python examples, tried different LUT provided in those examples, width/height match as well, rotation only affects that tiny area where "circle" is shown.
Have you encountered this kind of effect?
an attempt to draw a circle
I got my hands on RPi and tested waveshare Python snippet with the same display, everything worked as expected. Digging into my implementation.
Originally posted by @Alexx-G in #26 (comment)
See @peckpeck's todo from #132
/// Only for the Black/White-Displays
// TODO : 'color' is not a good name for black and white, rename it to BiColor/BWColor ?
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum Color {
/// Black color
Black,
/// White color
White,
}
Peckpecks BWColor might make the most sense for me in describing an enum with black and white, but I'm open to alternatives.
Currently (after #36) failed reads and writes are just discared.
TODO: fix all uses of let _ = ...
and unwrap_...
Is it possible to get a new release to crates.io? I'm using the 2in13 display and it would be nice to use it from crates.io instead of github.
plus it's been about a year since the last release so the embedded-graphics versions in crates.io are outdated as well.
See #33 for more info. But in short:
This seems to be about twice as slow to write to the screen as the Waveshare Python controller (specifically the July 10 2017 version, which is what I currently have hooked up to my screen), despite using the same panel settings.
Measuring some drawing times (
DATA_START_TRANSMISSION_1
+DISPLAY_REFRESH
):* Old Python driver: 24s * Buffer is 30720 bytes (`= HEIGHT * WIDTH / 8`) * Writes 4 data bytes per buffer byte * Latest Python driver: 30s * Buffer is `HEIGHT * WIDTH / 4` bytes * Writes 2 data bytes per buffer byte * This Rust driver: 53s * Buffer is `HEIGHT * WIDTH / 8` bytes * Writes 4 data bytes per buffer byte
Tested on a raspberry pi zero w by @str4d
Looking at the C code I can see that the SYSFS_GPIO_EXPORT() function does the same as the Rust function: it opens the "/sys/class/gpio/export" file and writes the pin number on it, so not sure why it's throwing the error here.
Waveshare 4.2in on RPi4
Run examples/4in2
, with let cs = Pin::new(8)
to match the Pi4
thread 'main' panicked at 'cs export: Io(Os { code: 16, kind: ResourceBusy, message: "Device or resource busy" })', src/main.rs:34:17
$ gpio read 8
1
sudo lsof /sys/class/gpio/gpio8
lsof: status error on /sys/class/gpio/gpio8: No such file or directory
Other interesting results:
pin_num
in let cs = Pin::new();
results in the program not erroring out and continuing to the end, but nothing is shown on the screen.let cs = Pin::new(8); //BCM7 CE0
// cs.export().expect("cs export");
// while !cs.is_exported() {}
// cs.set_direction(Direction::Out).expect("CS Direction");
// cs.set_value(1).expect("CS Value set to 1");
drawing is ok, and the program exits without errors, but I get a bunch of Input/output error
on the pi after that, at any keypress, until I restart the pi, and the e-ink screen is not cleared, not even after calling clear_frame()?;
, which does not error out.
Hey, thanks for the library!
I am trying to run the example in examples/epd2in13_v2.rs
on a raspberry pi 4. The display is directly connected to the pi via the displays header.
I verified the display is working with the official c example from here.
I cloned the repo and tried two ways of running the example via sudo
:
sudo env "PATH=$PATH" cargo run --example epd2in13_v2
(from a normal pi user session)
and directly as root with
cargo run --example epd2in13_v2
.
However nothing happens, no output is printed to the terminal, and the display stays blank.
Is it possible that the pins are not identical to the "default" pin configuration of the header?
I am really stuck here, any help on how to debug the issue would be much appreciated!
I have experimented with the 4.2 inch e-ink display from waveshare, and the last days I have tried to make quick refresh work. I have observed a number of deficiencies in this library, some of which I do not know how to fix:
Newer 4.2" B/W displays seem to require different LUTs for quick refresh.
As indicated by a comment below Ben Krasnow's blog post on quick refresh on this display, there are two versions of the display. I copied the LUTs from the example code for the greyscale Good Display display (does that mean that my B/W display properly supports greyscale? Yay!) and those result in proper black/white pixels, whereas the LUTs in this library currently only result in grey pixels.
Link to the example code: http://www.e-paper-display.com/download_detail/downloadsId=1022.html
My commit (the old LUTs should probably be accessible though - preferrably not behind a feature gate, but selectable at runtime): mgottschlag@a24bec5
I am unsure what the point of the "background color" provided by this library is - the documentation is lacking and I think usage the background color as-is is wrong and unusable.
My understanding of the background (or "old" frame as called by the documentation is that it allows to choose different LUTs based on what the previous image was. Note that the data is actually required for quick refresh using the LUTs in the example code above, as those completely skip pixels that do not change color!
Also, using the wrong background data might cause burn-in issues. According to the internet (I think Ben Krasnows youtube video explained something like this), the applied voltage needs to be on average 0 to prevent charging the display, which causes burn-in. I don't understand the format of the LUTs, but if they are not completely balanced (and inofficial quick refresh LUTs likely are not!), then using the same LUT over and over again causes the display to be charged (whereas only applying voltages during black/white and white/black transitions might cause the effects to cancel each other out and also greatly reduces the number of pixel changes).
At least, the library requires updates to the documentation.
The library does not provide a method to upload the "old" ("background") data.
The official quick refresh LUTs for this display depend on having the old data.
My take on this issue: mgottschlag@dbd065a
Hello,
I want to use an epd3in7 with a stm32f446 that is mounted on a nucleo dev board. I wrote the following code, that is heavily inspired from https://github.com/stm32-rs/stm32f4xx-hal/blob/master/examples/ist7920-bidi-normal-spi.rs It uses the SPI3 pins of the board instead of SPI1 as advised by waveshare wiki because there is a pin conflict on PA5 between SPI1 and the onboard led.
My code is meant to initialize the EPD on SPI3 and blink, but it does not blink. If I do comment the line initializing the EPD, the board blinks. So I guess that initializing the EPD results in a panic for some reason.
I suspected that my SPI is not working, so my code only blinks if MISO is connected to the GND, and it works: if MISO is connected to 3.3V for example, it does not blink. I tested expecting 0xff, and then it blinks when on 3.3v but not on GND, so I'd say that my SPI is OK.
Since I'm a noob at this kind of game, I'd really appreciate if someone could give me a clue about what's going wrong. I'm sorry if it's a stupid error from me, I fail to spot it.
#![no_std]
#![no_main]
use cortex_m_rt::entry;
use stm32f4xx_hal::{
pac,
spi,
gpio::GpioExt,
prelude::*,
timer::Timer,
};
#[allow(unused_imports)]
use panic_halt; // When a panic occurs, stop the microcontroller
use embedded_graphics::{
mono_font::MonoTextStyleBuilder,
prelude::*,
text::{Baseline, Text, TextStyleBuilder},
};
use epd_waveshare::{
color::*,
epd3in7::{EPD3in7,Display3in7},
prelude::*,
};
#[entry]
fn main() -> ! {
let dp = pac::Peripherals::take().unwrap();
let cp = cortex_m::peripheral::Peripherals::take().unwrap();
let gpioa = dp.GPIOA.split();
let gpiob = dp.GPIOB.split();
let rcc = dp.RCC.constrain();
let clocks = rcc.cfgr.freeze();
let mut led = gpioa.pa5.into_push_pull_output();
led.set_low();
// Configure SPI
// Inspiration: stm32f4xx-hal/examples/ist7920-bidi-normal-spi.rs
let sck = gpiob.pb3.into_alternate();
let miso = gpiob.pb4.into_push_pull_output();
let mosi = gpiob.pb5.into_alternate();
let dc = gpiob.pb14.into_push_pull_output();
let rst = gpiob.pb10.into_push_pull_output();
let cs = gpiob.pb13.into_push_pull_output();
let mut delay = Timer::syst(cp.SYST, &clocks).delay();
let mut spi = dp.SPI1.spi(
(sck, miso, mosi),
spi::Mode {
polarity: spi::Polarity::IdleLow,
phase: spi::Phase::CaptureOnFirstTransition,
},
8.MHz(),
&clocks,
);
// Configure the other pins
let busy = gpioa.pa3.into_input();
//let mut epd = EPD3in7::new(&mut spi, cs, busy, dc, rst, &mut delay, None).expect("EPD init error"); // UNCOMMENT TO LET THE CODE PANIC
/*
let mut display = Display3in7::default();
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("Hello Rust!", Point::new(5, 50), style, text_style).draw(&mut display);
// Transfer the frame data to the epd and display it
epd.update_and_display_frame( & mut spi, & display.buffer(), &mut delay).expect("Error while drawing");
*/
loop {
let mut read = [0x55];
spi.transfer(&mut read).unwrap();
if read[0] == 0xff {
led.set_high();
delay.delay_ms(200_u16);
led.set_low();
delay.delay_ms(50_u16);
}
}
}
embedded-hal 1.0 is still in beta, but is there some work in progress to make it work ?
There is some work since the SPI part has changed a lot
Other methods take a delay parameter, but not this one, this prevents me from implementing update_partial_frame from the WaveshareDisplay trait properly, because i need to wait for the idle pin
Changing this means changing a trait, would you accept a PR to change it ?
TriDisplay
was added in #76, but only epd2in13bc
was updated to use it. None of the other colored displays use it, except for epd1in83b
which was added afterwards and used it from the start.
I think the other displays should probably use it too; here's the full list:
epd1in54b
epd1in54c
epd2in13bc
epd2in7b
epd2in9bc
epd5in83b_v2
Would you be happy for me to implement this?
Since cd98033 there seems to happen the following error when trying to transfer bigger blocks of data:
Os { code: 90, kind: Other, message: "Message too long" }', libcore/result.rs:945:5
This should be connected to the change from transfering single bytes to bigger byte buffers over spi.
(https://raspberrypi.stackexchange.com/questions/65595/spi-transfer-fails-with-buffer-size-greater-than-4096)
Firt let me point that most waveshare epd are identical as goodisplay products.
Goodisplay better document their product and include the integrated circuit name in de datasheet.
This way we can know which epd has the exact same IC as which one.
In this case, I think we should just write generic driver for those ICs and instanciate them with some specific values for each epd we want to support. This would greatly reduce code size and make bug fix propagate to similar epd that share the same code.
For example 7in5b shares the exact same datasheet as 5in83b and as UC8179c IC at goodisplay. Only some data change.
I'd like to make a
// generic impl
struct UC8179c<S: UC8179cSettings> { ... }
impl<S> UC8179c<S> { ...ย }
// specific EPD
impl UC8179cSettings for Epd7in5bSettings { ... }
type Epd7in5b = UC8179c<Epd7in5bSettings>;
where the Setting
would just be a bunch of constants
This would also simplify extracting default LUT data (which format is common to a given IC) to play with them
Looking at 7b4a7f0 I think it would be better if the wait is done before the command, not after. This way, you can sleep while some work is done on the screen, and wait to the screen being ready before sending another command.
In our case, it would allow to go to sleep during the refresh of the screen, but waiting for the screen to be ready before sending a new image.
Originally posted by @TeXitoi in TeXitoi/rusty-clock#18 (comment)
163 | let bus = Image::new(&ImageRaw::new(include_bytes!("../../icons/Bus.raw"), 30),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait From<()>
is not implemented for epd_waveshare::color::Color
|
I guess it's missing some conversions?
It's defined as
impl<'a, C, BO> ImageRaw<'a, C, BO>
where
C: PixelColor + From<<C as PixelColor>::Raw>,
BO: ByteOrder,
{
I also tried creating a BinaryColor raw image, but then I cannot draw it on a "Color" display.
would it be possible to standardize into "BinaryColor" from embedded_graphics?, I could be missing lots of things, ... still new to rust.
With epd-waveshare = { git = "https://github.com/caemor/epd-waveshare" }
in Cargo.toml
This call to clear() crash with an index out of bounds
error
let mut epd7in5 = Epd7in5::new(&mut spi, cs, busy, dc, rst, &mut delay, None)
.expect("error");
let mut display = Display7in5::default();
display.clear(TriColor::White).ok();
The crash ocures here:
Line 353 in f98c121
thread 'main' panicked at 'index out of bounds: the len is 48000 but the index is 48000', /cargo/git/checkouts/epd-waveshare-201024d8b8447899/f98c121/src/graphics.rs:353:25
stack backtrace:
0: rust_begin_unwind
at /rustc/8460ca823e8367a30dda430efda790588b8c84d3/library/std/src/panicking.rs:575:5
1: core::panicking::panic_fmt
at /rustc/8460ca823e8367a30dda430efda790588b8c84d3/library/core/src/panicking.rs:64:14
2: core::panicking::panic_bounds_check
at /rustc/8460ca823e8367a30dda430efda790588b8c84d3/library/core/src/panicking.rs:159:5
3: epd_waveshare::graphics::set_pixel
at /cargo/git/checkouts/epd-waveshare-201024d8b8447899/f98c121/src/graphics.rs:353:25
4: epd_waveshare::graphics::Display<_,_,_,_,COLOR>::set_pixel
at /cargo/git/checkouts/epd-waveshare-201024d8b8447899/f98c121/src/graphics.rs:161:9
5: <epd_waveshare::graphics::Display<_,_,_,_,COLOR> as embedded_graphics_core::draw_target::DrawTarget>::draw_iter
at /cargo/git/checkouts/epd-waveshare-201024d8b8447899/f98c121/src/graphics.rs:110:13
6: embedded_graphics_core::draw_target::DrawTarget::fill_contiguous
at /cargo/registry/src/github.com-1ecc6299db9ec823/embedded-graphics-core-0.3.3/src/draw_target/mod.rs:392:9
7: embedded_graphics_core::draw_target::DrawTarget::fill_solid
at /cargo/registry/src/github.com-1ecc6299db9ec823/embedded-graphics-core-0.3.3/src/draw_target/mod.rs:408:9
8: embedded_graphics_core::draw_target::DrawTarget::clear
at /cargo/registry/src/github.com-1ecc6299db9ec823/embedded-graphics-core-0.3.3/src/draw_target/mod.rs:423:9
I created a new project copied the epd4in2 example and ran into the following error:
help: trait impl with same name found
--> /home/marcel/.cargo/registry/src/github.com-1ecc6299db9ec823/epd-waveshare-0.3.2/src/color.rs:57:1
|
57 | impl PixelColor for Color {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: perhaps two different versions of crate `embedded_graphics` are being used?
= note: required by `embedded_graphics::style::text_style::TextStyleBuilder::<C, F>::new`
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
Turned out master depends on a later version of the embedded-graphics crate.
thermometer is ๐ฆ v0.1.0 via ๐ฆ v1.42.0
โฏ cargo tree -i -p embedded-graphics:0.6.1
embedded-graphics v0.6.1
โโโ thermometer v0.1.0 (/home/marcel/github/thermometer)
thermometer is ๐ฆ v0.1.0 via ๐ฆ v1.42.0
โฏ cargo tree -i -p embedded-graphics:0.4.9
embedded-graphics v0.4.9
โโโ epd-waveshare v0.3.2
โโโ thermometer v0.1.0 (/home/marcel/github/thermometer)
Temporary workaround is basically:
embedded-graphics = "0.6.1"
epd-waveshare = { git = "https://github.com/caemor/epd-waveshare.git", rev = "79c2524c1d0980cad6e5033e7fc529a3033da774"}
I've been trying to get the Waveshare 2.7" grayscale display working and I've been having some major issues, but I think the primary blocker is that DisplayInterface::data (and write) tries to write all the data at once rather than byte by byte, which breaks on some devices.
See https://github.com/waveshare/e-Paper/blob/2a10334edcdd4e1c75eb74c7be3b6601614bef72/RaspberryPi_JetsonNano/python/lib/waveshare_epd/epd2in7.py#L164-L174 for the implementation on the 2.7". Note that the 2.7" chromatic display also uses the same code: https://github.com/waveshare/e-Paper/blob/2a10334edcdd4e1c75eb74c7be3b6601614bef72/RaspberryPi_JetsonNano/python/lib/waveshare_epd/epd2in7b.py#L111-L121.
There are some devices which seem to use a separate method to write a chunk of data at a time, but they seem to be the exception rather than the norm (https://github.com/waveshare/e-Paper/blob/2f1eeee9f5baa1753839cb1917f4e75b0c612620/RaspberryPi_JetsonNano/python/lib/waveshare_epd/epd7in5.py#L70-L74).
In my hacked up version, changing data to send bytes one at a time fixed the epd2in7. One of the issues I was seeing was that commands would hang when waiting for them to complete, in other cases it was displaying garbage, so it might fix #70, #68, and maybe others.
Test the example and update the example readme afterwards
According to this specification, delay between RESE low and RESE high should be 200us. But the DELAY
is a DelayMs<u8>
here.
https://github.com/rust-embedded/gpio-cdev
Sysfs interface for GPIO is now deprecated: rust-embedded/rust-sysfs-gpio#38
I'm using kernel 5.11 and the old way does not work any more.
Quite a few epds from Waveshare support 16 grayscale, but I cannot find any information in this lib, also looked into the source code and found all graph operations are using BinaryColor
.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.