0

I have this, using rp2040_hal:

use defmt_rtt as _;
use embedded_hal::timer::CountDown;
use rp2040_hal::pio::StateMachineIndex;
use rp2040_hal::prelude::_rphal_pio_PIOExt;
use rp2040_hal::{gpio::PinId, timer::Timer, Clock};
use rp_pico::hal::clocks::ClocksManager;
use rp_pico::hal::pac::Peripherals;
use smart_leds::RGB8;
use ws2812_pio::{self, Ws2812};

pub struct LedControl<C, I, SM>
where
    C: CountDown,
    I: PinId + rp2040_hal::gpio::bank0::BankPinId,
    SM: StateMachineIndex,
{
    leds: [RGB8; 100],
    num_of_leds: usize,
    ws: Ws2812<rp2040_hal::pac::PIO0, SM, C, I>,
}
impl<C, I, SM> LedControl<C, I, SM>
where
    C: CountDown,
    I: PinId + rp2040_hal::gpio::bank0::BankPinId,
    SM: StateMachineIndex,
{
    pub fn new(pins: rp2040_hal::gpio::Pins, clk: &ClocksManager, timer: &Timer, num: usize) {
        let mut pc = Peripherals::take().unwrap();
        let (mut pio, sm0, _, _, _) = pc.PIO0.split(&mut pc.RESETS);
        let strip = Ws2812::new(
            pins.gpio4.into_mode(),
            &mut pio,
            sm0,
            clk.peripheral_clock.freq(),
            timer.count_down(),
        );
        LedControl {
            num_of_leds: num,
            ws: strip,
            leds: [(0, 0, 0).into(); 100],
        };
    }

    pub fn modifyPixel(&mut self, rgb: &(u8, u8, u8), idx: &usize) {
        self.leds[idx.clone()] = (*rgb).into()
    }

    pub fn pixels(&mut self) -> [RGB8; 100] {
        return self.leds.clone();
    }

    pub fn test_ws(&mut self) {
        self.ws.write(self.leds.iter().copied()).unwarp();
    }
}

with cargo.toml:

[package]
edition = "2021"
name = "rp2040-project-WS3823"
version = "0.1.0"

[dependencies]
cortex-m = "0.7"
cortex-m-rt = "0.7"
embedded-hal = { version = "0.2.5", features = ["unproven"] }

defmt = "0.3"
defmt-rtt = "0.4.0"
panic-probe = { version = "0.3", features = ["print-defmt"] }

# We're using a Pico by default on this template
rp-pico = "0.6.0"

# but you can use any BSP. Uncomment this to use the pro_micro_rp2040 BSP instead
# sparkfun-pro-micro-rp2040 = "0.3"

# If you're not going to use a Board Support Package you'll need these:
rp2040-hal = { version = "0.7.0", features = ["rt"] }
# rp2040-boot2 = "0.2"
smart-leds = "0.3.0"
ws2812-pio = "0.5.0"
fugit = "0.3.6"

# cargo build/run
[profile.dev]
codegen-units = 1
debug = 2
debug-assertions = true
incremental = false
opt-level = 3
overflow-checks = true

# cargo build/run --release
[profile.release]
codegen-units = 1
debug = 2
debug-assertions = false
incremental = false
lto = 'fat'
opt-level = 3
overflow-checks = false

# do not optimize proc-macro crates = faster builds from scratch
[profile.dev.build-override]
codegen-units = 8
debug = false
debug-assertions = false
opt-level = 0
overflow-checks = false

[profile.release.build-override]
codegen-units = 8
debug = false
debug-assertions = false
opt-level = 0
overflow-checks = false

# cargo test
[profile.test]
codegen-units = 1
debug = 2
debug-assertions = true
incremental = false
opt-level = 3
overflow-checks = true

# cargo test --release
[profile.bench]
codegen-units = 1
debug = 2
debug-assertions = false
incremental = false
lto = 'fat'
opt-level = 3

the error is:

self.ws.write(self.leds.iter().copied()).unwarp();
   |    ^^^^^ method not found in `Ws2812<rp2040_hal::rp2040_pac::PIO0, SM, C, I>`

which make since because this is a generic reference, not an implementation, but how do I tell the compiler that I am using the implementation? ('strip' in the c-tor)

I am using the template for the pico pi: https://github.com/rp-rs/rp2040-project-template.git

4
  • 1
    The write function comes from the SmartLedsWrite trait. You have to bring it into scope with use smart_leds_trait::SmartLedsWrite; to use the write function Commented Dec 24, 2022 at 23:35
  • @susitsm Should be an answer instead? Commented Dec 25, 2022 at 9:59
  • 1
    I don't have time to write a full answer and test it since it's Christmas. Feel free to do so @Finomnis Commented Dec 25, 2022 at 11:56
  • @susitsm how would you go about this? I tried several ways, nothing works, I know I am an old Java dev, but this is frying my brain :-) Commented Dec 25, 2022 at 13:14

1 Answer 1

1

There are two problems in your code:

  • SmartLedsWrite, which provides write(), is not in scope
  • SmartLedsWrite requires your timer to be specifically of type rp2040_hal::timer::CountDown, not of impl embedded_hal::timer::CountDown, as can be seen here.

The write() function is part of the SmartLedsWrite trait.

To use a trait in Rust, it has to be in scope.

You can bring it in scope by modifying the following line in your code:

use smart_leds::RGB8;

to:

use smart_leds::{SmartLedsWrite, RGB8};

Fixing the CountDown requires introducing a lifetime on your LedControl object and replacing the generic with an actual type.

This code compiles (not sure if it works, don't have the required hardware in front of me):

use defmt_rtt as _;
use rp2040_hal::pio::StateMachineIndex;
use rp2040_hal::prelude::_rphal_pio_PIOExt;
use rp2040_hal::timer::CountDown;
use rp2040_hal::{gpio::PinId, timer::Timer, Clock};
use rp_pico::hal::clocks::ClocksManager;
use rp_pico::hal::pac::Peripherals;
use smart_leds::{SmartLedsWrite, RGB8};
use ws2812_pio::{self, Ws2812};

pub struct LedControl<'t, I, SM>
where
    I: PinId + rp2040_hal::gpio::bank0::BankPinId,
    SM: StateMachineIndex,
{
    leds: [RGB8; 100],
    num_of_leds: usize,
    ws: Ws2812<rp2040_hal::pac::PIO0, SM, CountDown<'t>, I>,
}
impl<'t, I, SM> LedControl<'t, I, SM>
where
    I: PinId + rp2040_hal::gpio::bank0::BankPinId,
    SM: StateMachineIndex,
{
    pub fn new(pins: rp2040_hal::gpio::Pins, clk: &ClocksManager, timer: &Timer, num: usize) {
        let mut pc = Peripherals::take().unwrap();
        let (mut pio, sm0, _, _, _) = pc.PIO0.split(&mut pc.RESETS);
        let strip = Ws2812::new(
            pins.gpio4.into_mode(),
            &mut pio,
            sm0,
            clk.peripheral_clock.freq(),
            timer.count_down(),
        );
        LedControl {
            num_of_leds: num,
            ws: strip,
            leds: [(0, 0, 0).into(); 100],
        };
    }

    pub fn modifyPixel(&mut self, rgb: &(u8, u8, u8), idx: &usize) {
        self.leds[idx.clone()] = (*rgb).into()
    }

    pub fn pixels(&mut self) -> [RGB8; 100] {
        return self.leds.clone();
    }

    pub fn test_ws(&mut self) {
        self.ws.write(self.leds.iter().copied()).unwrap();
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

still getting the same error: error[E0599]: no method named write found for struct Ws2812 in the current scope --> src\fast_led\led_manager.rs:53:17 | 53 | self.ws.write(self.leds.iter().copied()).unwarp(); | ^^^^^ method not found in Ws2812<rp2040_hal::rp2040_pac::PIO0, SM, C, I> warning: unused import: SmartLedsWrite --> src\fast_led\led_manager.rs:8:18 | 8 | use smart_leds::{SmartLedsWrite, RGB8}; | ^^^^^^^^^^^^^^
Ok give me some moments to actually reproduce your problem.
@MrG Found a second problem. It compiles for me now.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.