Skip to main content

Pca9685

Struct Pca9685 

Source
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>

Source

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_ADDRESS with 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.

Source

pub fn with_frequency(self, hz: u32) -> Self

Sets the PWM frequency every channel shares, 24 to 1526 Hz.

The prescaler can only approximate a frequency; frequency reports the one the part will run at.

§Arguments
  • hz - the update rate; 50 Hz for hobby servos.
§Returns

The driver.

Source

pub fn with_oscillator(self, hz: u32) -> Self

Sets the clock the prescaler divides, for a board that drives EXTCLK.

§Arguments
§Returns

The driver.

Source

pub fn with_outputs(self, outputs: Outputs) -> Self

Sets how the outputs are wired.

§Arguments
  • outputs - the MODE2 settings.
§Returns

The driver.

Source

pub fn prescale(&self) -> u8

Returns the prescale value the driver writes for its frequency.

Source

pub fn frequency(&self) -> f32

Returns the frequency the part will run at, after the prescaler rounds.

Source

pub fn release(self) -> (I2C, D)

Gives back the bus and the delay.

§Returns

The bus and delay the driver was built from.

Source§

impl<I2C: I2c, D: DelayNs> Pca9685<I2C, D>

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Trait Implementations§

Source§

impl<I2C, D> Actuator for Pca9685<I2C, D>
where I2C: I2c + Send, I2C::Error: Debug, D: DelayNs + Send,

Source§

type Command = Output

The command accepted by a single application, for example a setpoint.
Source§

async fn apply(&mut self, command: Output) -> Result<()>

Applies a command to the actuator. Read more
§

fn map_command<F, C>(self, convert: F) -> MapCommand<Self, F, C>
where Self: Sized, F: FnMut(C) -> Self::Command,

Wraps this actuator so every command passes through convert first. Read more
Source§

impl<I2C: Debug, D: Debug> Debug for Pca9685<I2C, D>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<I2C, D> Freeze for Pca9685<I2C, D>
where I2C: Freeze, D: Freeze,

§

impl<I2C, D> RefUnwindSafe for Pca9685<I2C, D>

§

impl<I2C, D> Send for Pca9685<I2C, D>
where I2C: Send, D: Send,

§

impl<I2C, D> Sync for Pca9685<I2C, D>
where I2C: Sync, D: Sync,

§

impl<I2C, D> Unpin for Pca9685<I2C, D>
where I2C: Unpin, D: Unpin,

§

impl<I2C, D> UnsafeUnpin for Pca9685<I2C, D>
where I2C: UnsafeUnpin, D: UnsafeUnpin,

§

impl<I2C, D> UnwindSafe for Pca9685<I2C, D>
where I2C: UnwindSafe, D: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.