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.
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.
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.
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.
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.