Currently, I am redefining the same variable (dp) multiple times to make the program work. However, this feels wrong, and I would think there would be a much better way to do this. For context, I am in a no_std environment, and compiling for avr-atmega328p (Arduino Uno), using the avr-hal-template.
#![no_std]
#![no_main]
use arduino_hal::hal::wdt;
use motor_shield::{dc::DcMotor, init_pwm, Motor};
use panic_halt as _;
#[arduino_hal::entry]
fn main() -> ! {
let dp = arduino_hal::Peripherals::take().unwrap();
let pins = arduino_hal::pins!(dp);
let dp = arduino_hal::Peripherals::take().unwrap();
let mut pwm = init_pwm(None, dp, pins).unwrap();
let mut dc_motor = DcMotor::try_new(&mut pwm, Motor::Motor1).unwrap();
let dp = arduino_hal::Peripherals::take().unwrap();
let mut watchdog = wdt::Wdt::new(dp.WDT, &dp.CPU.mcusr);
watchdog.start(wdt::Timeout::Ms4000).unwrap();
loop {
let _ = dc_motor.set_throttle(&mut pwm, 0.5);
arduino_hal::delay_ms(1000);
let _ = dc_motor.set_throttle(&mut pwm, 0.0);
arduino_hal::delay_ms(1000);
watchdog.feed();
}
}
For context, here is the init_pwm function:
pub fn init_pwm(i2c: Option<I2c>, dp: Peripherals, pins: Pins) -> Result<Pca9685<I2c>, MotorError> {
let i2c = if let Some(i2c) = i2c {
i2c
} else {
I2c::new(
dp.TWI,
pins.a4.into_pull_up_input(),
pins.a5.into_pull_up_input(),
50000,
)
};
let address = Address::from(60);
let mut pwm = Pca9685::new(i2c, address).map_err(|_| MotorError::PwmError)?;
pwm.enable().map_err(|_| MotorError::PwmError)?;
pwm.set_prescale(4).map_err(|_| MotorError::PwmError)?;
Ok(pwm)
}
The one thing I could think to do was borrow dp, but that wouldn't work because the functions don't accept references. I also cannot clone dp because it does not implement the Clone trait.
Thanks to the comment by Chayim Friedman, I finally figured out a solution. I changed the
init_pwmfunction to requireWDTinstead of the full Peripherals, as that was all it needed. I was then able to call the function with justdp.TWIinstead ofdp.