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?