How to set up GPIO event listeners on a Raspberry Pi using Rust

38 Views Asked by At

I am using rppal crate to interact with the GPIO pins on a Raspberry Pi.

What I am trying to do is set up listeners on pins, and do something in the event of falling or rising edge events.

use rppal::gpio::{Gpio, OutputPin, InputPin, Trigger};
use std::{error::Error, sync::{Arc, Mutex}, thread, time::{Duration, Instant}};
use ctrlc;


const CAMERA_SENSOR_GPIO: u8 = 25;
const STOPPER_SENSOR_GPIO: u8 = 26;
const ACTIVATE_ROBOT_ARM_GPIO: u8 = 24;
const ACTIVATE_TRAFFIC_STOPPER_GPIO: u8 = 23;

struct GPIOManager {
    output_pins: Vec<Arc<Mutex<OutputPin>>>
}

impl GPIOManager {
    // Constructor for the GPIOManager class
    fn new() -> Result<Self, Box<dyn Error>> {
        let setup_start = Instant::now();

        let gpio = Gpio::new()?;
        let mut output_pins = Vec::new();

        // Initialize pins
        let camera_sensor = Arc::new(Mutex::new(gpio.get(CAMERA_SENSOR_GPIO)?.into_input_pullup()));
        let stopper_sensor = Arc::new(Mutex::new(gpio.get(STOPPER_SENSOR_GPIO)?.into_input_pullup()));
        let activate_robot_arm = Arc::new(Mutex::new(gpio.get(ACTIVATE_ROBOT_ARM_GPIO)?.into_output()));
        let activate_traffic_stopper = Arc::new(Mutex::new(gpio.get(ACTIVATE_TRAFFIC_STOPPER_GPIO)?.into_output()));

        // Store references to the pins for cleanup
        output_pins.push(activate_robot_arm.clone());
        output_pins.push(activate_traffic_stopper.clone());

        // Setup event handlers
        Self::setup_falling_edge_event_handler(camera_sensor.clone(), activate_robot_arm.clone());
        Self::setup_falling_edge_event_handler(stopper_sensor.clone(), activate_traffic_stopper.clone());
        Self::setup_rising_edge_event_handler(stopper_sensor.clone(), activate_traffic_stopper.clone());

        let setup_duration = setup_start.elapsed();
        println!("\nGPIO setup time: {:.6} seconds", setup_duration.as_secs_f64());

        Ok(GPIOManager { output_pins })
    }

    // Function to set up a FallingEdge event handler for a pin
    fn setup_falling_edge_event_handler(sensor: Arc<Mutex<InputPin>>, actuator: Arc<Mutex<OutputPin>>) {
        println!("Falling Edge Event!");
        let actuator_clone = actuator.clone();
        let mut sensor_guard = sensor.lock().unwrap();
        sensor_guard.set_async_interrupt(Trigger::FallingEdge, move |_| {
            let mut actuator_guard = actuator_clone.lock().unwrap();
            println!("Setting something to LOW");
            actuator_guard.set_low(); // Remove .unwrap() here
        }).unwrap();
    }

    // Function to set up a RisingEdge event handler for a pin
    fn setup_rising_edge_event_handler(sensor: Arc<Mutex<InputPin>>, actuator: Arc<Mutex<OutputPin>>) {
        println!("Rising Edge Event!");
        let actuator_clone = actuator.clone();
        let mut sensor_guard = sensor.lock().unwrap();
        sensor_guard.set_async_interrupt(Trigger::RisingEdge, move |_| {
            let mut actuator_guard = actuator_clone.lock().unwrap();
            println!("Setting something to HIGH");
            actuator_guard.set_high(); // Remove .unwrap() here
        }).unwrap();
    }

    // Function to reset all pins back to HIGH
    fn cleanup(&self) {
        for pin in &self.output_pins {
            let mut pin_guard = pin.lock().unwrap();
            pin_guard.set_high(); // Remove .unwrap() here
        }
        println!("GPIO pins reset!");
    }
}


fn main() -> Result<(), Box<dyn Error>> {
    let gpio_manager = Arc::new(Mutex::new(GPIOManager::new()?));
    let gpio_manager_clone = gpio_manager.clone();

    ctrlc::set_handler(move || {
        let gpio_manager = gpio_manager_clone.lock().unwrap();
        gpio_manager.cleanup();
        std::process::exit(0); // Exit the program
    }).expect("Error setting Ctrl-C handler");

    loop {
        thread::sleep(Duration::from_secs(1));
    }
}

And this is the output when you try to run this:

Falling Edge Event!
Falling Edge Event!
Rising Edge Event!

GPIO setup time: 0.001778 seconds
^CGPIO pins reset!

The problem is that none of the event listeners are actually working.

Does anyone know where is my mistake and how to fix it?

0

There are 0 best solutions below