Closed pdgilbert closed 3 years ago
Hey, thanks for the detailed report and apologies for the delay. On the off chance you haven't figured out a solution yet, here's something that might help. I had a quick play around and come up with this function:
fn display(disp: &mut GraphicsMode<impl WriteOnlyDataCommand, impl DisplaySize>) -> () {
let style = PrimitiveStyleBuilder::new()
.stroke_width(1)
.stroke_color(BinaryColor::On)
.build();
Rectangle::new(Point::new(0, 0), Point::new(127, 63))
.into_styled(style)
.draw(disp)
.unwrap();
disp.flush().unwrap();
()
}
GraphicsMode
is a concrete type that provides the flush()
method - no traits required. I'm not sure where you got the _embedded_hal_serial_Write
import suggestion (IDE auto complete getting confused maybe?) but it's not required. GraphicsMode
takes some generics which I'm using impl trait
syntax for above. I did a quick test just drawing a rectangle which compiles fine.
Please note that I've just released ssd1306
version 0.6.0 which restructures some of the crate interface so the following code will only work with 0.6.0 and above. You'll also need to upgrade to embedded-graphics 0.7 which includes more breaking changes. The above function would look like this now:
fn draw<S>(display: &mut Ssd1306<impl WriteOnlyDataCommand, S, BufferedGraphicsMode<S>>)
where
S: DisplaySize,
{
let style = PrimitiveStyleBuilder::new()
.stroke_width(1)
.stroke_color(BinaryColor::On)
.build();
Rectangle::new(Point::new(0, 0), Size::new(127, 63))
.into_styled(style)
.draw(display)
.unwrap();
display.flush().unwrap();
}
I moved S: DisplaySize
out into a type parameter because it should be the same type between Ssd1306
and BufferedGraphicsMode
.
I'm a bit confused. My display()
function was called in the loop to write the data onto the screen. disp
and text_style
were initialized before and passed as arguments along with the data to display()
display(
bat_mv, bat_ma, load_ma, temp_c, values_b, &mut disp, text_style,
);
Yours seems to be doing the initialization I did before the loop but not using the data? Am I missing something? How do I call your display function and pass data to it?
With the new version I'm also having trouble finding the concrete type GraphicsMode
. Where is it exported from now?
Yours seems to be doing the initialization I did before the loop but not using the data? Am I missing something? How do I call your display function and pass data to it?
Sorry if that wasn't clear - you can add all your arguments back in. I removed them for the sake of brevity/clarity as I only wanted to demonstrate the type required for disp
.
With the new version I'm also having trouble finding the concrete type GraphicsMode. Where is it exported from now?
GraphicsMode
was renamed to BufferedGraphicsMode
to open the door to supporting immediate/other rendering modes in the future.
Sorry I should have seen some of that, but was getting confused by something else I had wrong too. Using the new crate release, the version below now works with disp.flush()
pulled into the display()
function. One minor difference is that I had to shift the Text::new()
write down by 10 so the first line is completely on the screen. Perhaps there is a better way to shift this? (Also, I do not understand why the first line is yellow while others are blue, but this is not a change.)
Beware that for bluepill
I am using PR https://github.com/stm32-rs/stm32f1xx-hal/pull/340 because the setup()
function uses traits in a simplified way that has not yet been merged into the main branch. A more complete version of the example, called battery_monitor_ads1015
, is also building (with several other examples) on several different HAL crates with my CI at https://github.com/pdgilbert/rust-integration-testing/actions but I have not run tested on hardware.
Great to hear you got it working!
One minor difference is that I had to shift the Text::new() write down by 10 so the first line is completely on the screen.
embedded-graphics 0.7 sets the text origin point to the font's baseline by default now. Take a look at the bottom of this section in the migration guide for an example on how to set the origin back to top left if you need to do that.
Also, I do not understand why the first line is yellow while others are blue, but this is not a change.
Many SSD1306 modules have a yellow strip at the top of the display, I guess for use as a status bar in MP3 players or whatnot. If you look for white or blue modules, they're usually a single colour.
Also, e-g 0.7 supports multiline text now so you don't need to use an array of heapless::String
; adding \n
where you need it should work fine if you want to simplify your code a little.
It looks like your problem is solved, so I'll close this ticket but please reopen it if you're still getting stuck!
Thanks for all your help.
I have a function with code for refreshing a display so my loop is easier to read. This extracted simplified example works
Click to expand
``` // display function for blue pill stm32f103 #![deny(unsafe_code)] #![no_std] #![no_main] #[cfg(debug_assertions)] use panic_semihosting as _; #[cfg(not(debug_assertions))] use panic_halt as _; use cortex_m_rt::entry; use core::fmt::Write; use embedded_graphics::{ fonts::{Font8x16, Text}, //Font6x8, pixelcolor::BinaryColor, prelude::*, style::{TextStyle, TextStyleBuilder}, }; use ssd1306::{prelude::*, Builder, I2CDIBuilder}; use stm32f1xx_hal::{ delay::Delay, device::I2C2, i2c::{BlockingI2c, DutyCycle, Mode, Pins}, pac::{CorePeripherals, Peripherals}, prelude::*, }; fn setup() -> (BlockingI2cbut if I move
disp.flush()
into thedisplay()
function where it really belongs then I get the compiling problemMy attempts to add the
Write
part of the trait have not been successful, I need a type argument that I have not yet guessed. But it seems strange that it is asking forserial_Write
when the device is oni2c
. What am I missing? Suggestions on how to specify this would be appreciated.