Scriptone Scriptone

【Rust】Making LEDs Breathe with Raspberry Pi and Rust

Overview

We’ll build a simple LED blinking circuit and use Rust to control the LED in a complex manner, creating a smooth breathing effect where the LED fades in and out.

Components

The components are as follows:

  • LED x1
  • 220Ω resistor x2
  • Jumper wires x2

Circuit

The configuration is a simple setup that just connects an LED and resistor to create a circuit. For details, please check the 4.1.3. Circuit section on this linked page.

Code

Please add rppal and ctrlc using cargo beforehand. Write the following in main.rs and cross-compile for Raspberry Pi.

use rppal::gpio::{Gpio, OutputPin};
use rppal::pwm::{Channel, Polarity, Pwm};
use std::error::Error;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::thread;
use std::time::Duration;

const LED_PIN: u8 = 18;
const PWM_FREQUENCY: f64 = 1000.0;

fn main() -> Result<(), Box<dyn Error>> {
    println!("Starting Breathing LED...");
    println!("Press Ctrl+C to quit");

    let running = Arc::new(AtomicBool::new(true));
    let r = running.clone();

    ctrlc::set_handler(move || {
        println!("\nExiting...");
        r.store(false, Ordering::SeqCst);
    })?;

    let gpio = Gpio::new()?;
    let mut led = gpio.get(LED_PIN)?.into_output();

    println!("Starting software PWM on GPIO pin {}", LED_PIN);

    let mut brightness = 0.0;
    let mut increasing = true;
    let step = 0.01;
    let delay = Duration::from_millis(10);

    while running.load(Ordering::SeqCst) {
        led.set_pwm_frequency(PWM_FREQUENCY, brightness)?;

        if increasing {
            brightness += step;
            if brightness >= 1.0 {
                brightness = 1.0;
                increasing = false;
            }
        } else {
            brightness -= step;
            if brightness <= 0.0 {
                brightness = 0.0;
                increasing = true;
            }
        }

        thread::sleep(delay);
    }

    led.clear_pwm()?;
    led.set_low();
    println!("Breathing LED stopped");

    Ok(())
}

This mechanism varies the brightness between 0.00 and 1.00. The initial value is 0.0. It increments by 0.01 until the brightness reaches 1.00, then it starts decrementing the brightness by 0.01. When it reaches 0, it switches back to incrementing. By repeating this process, the LED blinks smoothly like breathing.

Operation

Summary

While the circuit itself is very simple, by being creative with Rust code, we can add complex functionality despite having a simple circuit. This is one effective example of combining software and hardware. Because the circuit is simple, the effects of the software are easy to understand, making it an interesting subject for learning control. It might be fun to experiment with different blinking patterns.

Related Posts