Author
Topic: LED Array (RP2040) (Read 71 Times)
Role
Posts: 7
Points: 0

To open the LED Array example, click on the navigation menu button on the top left side of the screen. Then, click on 'open example' as shown below.

Once the 'Pick Example Code To Load' window opens, select 'Blink LEDS(RP-2040)' as shown below.

Now, the LEDArray project will open up. To flash the code onto your board, follow the instructions in Section 3 of the Making Your First Project tutorial.

 

Breakdown of main.rs:

1. Attribute Macros and Imports

Attribute Macros

    #![no_std]
    #![no_main]
  • #![no_std] removes the standard library to make the code suitable for bare-metal (embedded) programming.

  • #![no_main] tells Rust that we are defining our own entry point instead of using the standard main() function.

Low-Level and HAL Imports

    use panic_halt as _;
    use embedded_hal::{
        digital::{OutputPin, InputPin},
        spi,
        delay::DelayNs,
    };
  • panic_halt as _; ensures that if the program panics, execution halts.

  • embedded_hal::digital::OutputPin: Used for setting GPIO pins as outputs.

  • embedded_hal::digital::InputPin: Allows reading the state of input pins (though not used in this example).

  • embedded_hal::spi: Provides SPI communication support.

  • embedded_hal::delay::DelayNs: Enables time delay functionality.

Board-Specific Imports

    use adafruit_feather_rp2040::entry;
    use adafruit_feather_rp2040::{
        hal::{
            clocks::{init_clocks_and_plls, Clock},
            pac,
            watchdog::Watchdog,
            Sio,
            gpio::{FunctionUart, FunctionSpi, FunctionI2C},
            uart,
            I2C,
            pio::PIOExt,
            timer::Timer,
        },
        Pins, XOSC_CRYSTAL_FREQ,
    };
  • entry: Marks the program’s entry point.

  • hal: Hardware Abstraction Layer for the Raspberry Pi RP2040 chip.

  • init_clocks_and_plls(): Configures system clocks.

  • Watchdog: Provides system reset functionality to prevent crashes.

  • Sio: Manages Single-Cycle IO (GPIO control).

  • pio::PIOExt: Enables Programmable IO (PIO) for controlling WS2812 LEDs.

  • timer::Timer: Used to introduce timing delays.

Imports for External Devices

    use ws2812_pio::Ws2812;
    use smart_leds::{brightness, SmartLedsWrite, RGB8};
  • ws2812_pio::Ws2812: Enables WS2812 (NeoPixel) LED communication via PIO.

  • smart_leds: Provides LED control functions like brightness adjustment.

2. Main Function(Entry Point)

    #[entry]
    fn main() -> ! {
  • #[entry] marks the function as the program's entry point.

  • fn main() -> ! indicates that the function never returns (infinite loop).

Peripheral and Clock Initialization

    let mut pac = pac::Peripherals::take().unwrap();
    let core = pac::CorePeripherals::take().unwrap();
    let mut watchdog = Watchdog::new(pac.WATCHDOG);
  • pac::Peripherals::take() retrieves access to microcontroller peripherals.

  • pac::CorePeripherals::take() grants access to core peripherals.

  • Watchdog::new() initializes the watchdog timer to prevent system hangs.

    let clocks = init_clocks_and_plls(
        XOSC_CRYSTAL_FREQ,
        pac.XOSC,
        pac.CLOCKS,
        pac.PLL_SYS,
        pac.PLL_USB,
        &mut pac.RESETS,
        &mut watchdog,
    ).ok().unwrap();
  • Configures the system clock using the external crystal frequency.

3. GPIO and Timer Setup

    let sio = Sio::new(pac.SIO);
    let pins = Pins::new(
        pac.IO_BANK0,
        pac.PADS_BANK0,
        sio.gpio_bank0,
        &mut pac.RESETS,
    );
  • Sio::new(pac.SIO): Initializes the Single-Cycle IO system.

  • Pins::new(): Configures GPIO pins.

    let timer = Timer::new(pac.TIMER, &mut pac.RESETS, &clocks);
  • Timer::new(): Initializes a timer for delays.

Power Enable Pin Setup

    let mut pwr_pin = pins.d10.into_push_pull_output();
    pwr_pin.set_high().unwrap();
  • pins.d10.into_push_pull_output(): Configures pin 10 as an output to power external devices.

  • pwr_pin.set_high().unwrap(): Turns on power to the NeoPixel matrix.

4. Neopixel Setup

    let (mut pio, sm0, _, _, _) = pac.PIO0.split(&mut pac.RESETS);
    let mut neopixels = Ws2812::new(
        pins.d5.into_function(),
        &mut pio,
        sm0,
        clocks.peripheral_clock.freq(),
        timer.count_down(),
    );
  • pac.PIO0.split(&mut pac.RESETS): Initializes PIO for controlling the NeoPixel matrix.

  • Ws2812::new(): Configures the LED driver on pin D5.

5. LED Animation Loop

    let mut n: u8 = 128;
    let mut timer = timer;
    loop {
  • let mut n: u8 = 128;: Initializes a counter for the color cycle.

  • loop {: Infinite loop to continuously update the LED colors.

Generating the Gradient Colors

    let mut colors: [RGB8; 64] = [RGB8::default(); 64];
    for (i, color) in colors.iter_mut().enumerate() {
        *color = wheel((n + i as u8) % 255);
    }
  • let mut colors: [RGB8; 64]: Creates an array to store colors for all 64 LEDs.

  • wheel((n + i as u8) % 255): Computes a color from a wheel function.

Updating the LED Matrix

    neopixels.write(brightness(colors.iter().cloned(), 32)).unwrap();
  • neopixels.write(): Sends color data to the NeoPixel matrix.

  • brightness(colors.iter().cloned(), 32): Reduces LED brightness to 12.5% (32/255).

Incrementing the Color Cycle and Delaying the Animation

    n = n.wrapping_add(1);
    timer.delay_ms(25);
    }
  • n.wrapping_add(1): Cycles through colors smoothly without overflow issues.

  • timer.delay_ms(25): Adds a small delay between frames for a smooth animation.

6. Color Wheel Function

    fn wheel(mut wheel_pos: u8) -> RGB8 {
        wheel_pos = 255 - wheel_pos;
        if wheel_pos < 85 {
            (255 - (wheel_pos * 3), 0, wheel_pos * 3).into()
        } else if wheel_pos < 170 {
            wheel_pos -= 85;
            (0, wheel_pos * 3, 255 - (wheel_pos * 3)).into()
        } else {
            wheel_pos -= 170;
            (wheel_pos * 3, 255 - (wheel_pos * 3), 0).into()
        }
    }
  • Converts a value 0..=255 into an RGB color, smoothly transitioning between:

    • Red → Green → Blue → Red.

  • Uses three conditional branches to set RGB values for different color segments.


This Topic Is Closed!