pub struct Pca9685<I2C, D> { /* private fields */ }Expand description
A PCA9685 on an I2C bus, driving up to sixteen PWM outputs.
init follows the datasheet’s prescale procedure: the
oscillator is put to sleep, because the prescale register only takes a write
while it is, the prescale for the requested frequency is written, the output
wiring is set, the oscillator is woken, the 500 us it needs to stabilize pass,
and the restart bit is written so any channel loaded before the sleep resumes.
Register auto-increment stays on so a channel’s four bytes load in one transfer.
As an [Actuator] the command is an Output; a servo is
Pwm::servo on its channel, and [Actuator::map_command] turns an angle or
a bool into one.
§Examples
A pan-tilt camera mount’s servo, driven through a PCA9685 that is not plugged in yet: the board is set up for the 50 Hz a hobby servo wants, and channel 0 is sent to the center of its travel, a 1.5 ms pulse. The simulated part keeps what it was told, so the program can read it back.
use pamoja_actuators::pca9685::{
channel_register, frequency_for_prescale, register, sim, Output, Pca9685, Pwm,
DEFAULT_I2C_ADDRESS, INTERNAL_OSC_HZ,
};
use pamoja_core::Actuator;
use pamoja_hal::i2c::I2c;
use pamoja_hal::script::{block_on, DelayLog};
const PART: u8 = DEFAULT_I2C_ADDRESS;
let mut board = Pca9685::new(sim::part(PART), PART, DelayLog::new()).with_frequency(50);
let center = Pwm::servo(1_500, 50);
block_on(board.apply(Output { channel: 0, pwm: center }))?;
// The part runs at 50 Hz, to the nearest step its prescale allows, and channel 0 holds
// the pulse.
let (mut part, delay) = board.release();
let prescale = part.register(register::PRE_SCALE);
assert!((frequency_for_prescale(prescale, INTERNAL_OSC_HZ) - 50.0).abs() < 0.5);
let mut held = [0u8; 4];
part.write_read(PART, &[channel_register(0)], &mut held).expect("the part answers");
assert_eq!(Pwm::from_bytes(&held), center);
assert_eq!(delay.total_micros(), 500, "the oscillator's start-up time");Implementations§
Source§impl<I2C, D> Pca9685<I2C, D>
impl<I2C, D> Pca9685<I2C, D>
Sourcepub fn new(bus: I2C, address: u8, delay: D) -> Self
pub fn new(bus: I2C, address: u8, delay: D) -> Self
Wraps an I2C bus and the part’s address.
§Arguments
bus- the I2C bus the part is on.address- the address the A5 to A0 pins select;DEFAULT_I2C_ADDRESSwith all six low.delay- the timer that paces the oscillator start-up.
§Returns
The driver, at the part’s default 200 Hz on its internal oscillator with totem-pole outputs.
Sourcepub fn with_frequency(self, hz: u32) -> Self
pub fn with_frequency(self, hz: u32) -> Self
Sourcepub fn with_oscillator(self, hz: u32) -> Self
pub fn with_oscillator(self, hz: u32) -> Self
Sets the clock the prescaler divides, for a board that drives EXTCLK.
§Arguments
hz- the oscillator frequency; the internal one isINTERNAL_OSC_HZ.
§Returns
The driver.
Sourcepub fn with_outputs(self, outputs: Outputs) -> Self
pub fn with_outputs(self, outputs: Outputs) -> Self
Source§impl<I2C: I2c, D: DelayNs> Pca9685<I2C, D>
impl<I2C: I2c, D: DelayNs> Pca9685<I2C, D>
Sourcepub fn init(&mut self) -> Result<(), DriverError<I2C::Error>>
pub fn init(&mut self) -> Result<(), DriverError<I2C::Error>>
Sets the prescale and output wiring and starts the oscillator.
§Errors
Returns DriverError::Bus if the bus fails.
Sourcepub fn set_channel(
&mut self,
channel: u8,
pwm: Pwm,
) -> Result<(), DriverError<I2C::Error>>
pub fn set_channel( &mut self, channel: u8, pwm: Pwm, ) -> Result<(), DriverError<I2C::Error>>
Loads one channel’s on and off counts.
Initializes the part first if init has not run.
§Arguments
channel- the output, 0 to 15.pwm- the counts to load.
§Errors
Returns DriverError::Command for a channel the part does not have, and
DriverError::Bus if the bus fails.
Sourcepub fn channel(&mut self, channel: u8) -> Result<Pwm, DriverError<I2C::Error>>
pub fn channel(&mut self, channel: u8) -> Result<Pwm, DriverError<I2C::Error>>
Reads one channel’s on and off counts back from the part.
The four registers are read one at a time, so the read works whether or not MODE1’s auto-increment bit is set, and it changes nothing on the part: a program that restarts can ask a running part what it holds.
§Arguments
channel- the output, 0 to 15.
§Returns
The setting the channel holds, full-on and full-off flags included.
§Errors
Returns DriverError::Command for a channel the part does not have, and
DriverError::Bus if the bus fails.
Sourcepub fn set_all(&mut self, pwm: Pwm) -> Result<(), DriverError<I2C::Error>>
pub fn set_all(&mut self, pwm: Pwm) -> Result<(), DriverError<I2C::Error>>
Loads every channel with the same on and off counts in one transfer.
§Arguments
pwm- the counts to load.
§Errors
Returns DriverError::Bus if the bus fails.
Sourcepub fn sleep(&mut self) -> Result<(), DriverError<I2C::Error>>
pub fn sleep(&mut self) -> Result<(), DriverError<I2C::Error>>
Stops the oscillator; the channel registers keep their values.
§Errors
Returns DriverError::Bus if the bus fails.
Sourcepub fn wake(&mut self) -> Result<(), DriverError<I2C::Error>>
pub fn wake(&mut self) -> Result<(), DriverError<I2C::Error>>
Restarts the oscillator and every channel that was running before sleep.
§Errors
Returns DriverError::Bus if the bus fails.
Sourcepub fn software_reset(&mut self) -> Result<(), DriverError<I2C::Error>>
pub fn software_reset(&mut self) -> Result<(), DriverError<I2C::Error>>
Resets every PCA9685 on the bus to its power-up state.
This is the general-call software reset the datasheet defines; it reaches every part on the bus that honors it, not only this one.
§Errors
Returns DriverError::Bus if the bus fails.