Library for interfacing with the NXP PCA9685 PWM controller over an I2C connection. Designed with the Adafruit breakout board (of the same name) in mind.
Dependents: Hexapod_Library main_robot_gant_v22
Documentation is lacking - not currently ready for public use, sorry.
Revision 4:3bcda7deb098, committed 2016-05-10
- Comitter:
- el13cj
- Date:
- Tue May 10 12:14:55 2016 +0000
- Parent:
- 3:a3410f2f061d
- Commit message:
- About to add directions;
Changed in this revision
PCA9685.cpp | Show annotated file Show diff for this revision Revisions of this file |
--- a/PCA9685.cpp Thu Apr 14 16:00:40 2016 +0000 +++ b/PCA9685.cpp Tue May 10 12:14:55 2016 +0000 @@ -7,35 +7,40 @@ #include "definitions.h" -PCA9685::PCA9685(uint8_t i2c_address, I2C i2c_object, float frequency) : i2c_addr(i2c_address), freq(frequency), i2c(i2c_object) +PCA9685::PCA9685(uint8_t i2c_address, I2C i2c_object, float frequency) : + + i2c_addr(i2c_address), + freq(frequency), + i2c(i2c_object) + { - //int two = 1 + 1; } -void PCA9685::init(void) { - +void PCA9685::init(void) +{ + reset(); - + uint8_t prescale = (uint8_t) (OSC_CLOCK / (4096 * PWM_SCALER * freq)) - 1; - + write_8(MODE1, 0x21); //0010 0001 : AI ENABLED write_8(MODE2, 0x07); //0000 0111 : NOT INVRT, CHANGE ON STOP, TOTEM POLE, \OE = 1, LEDn = HIGH IMP - + set_prescale(prescale); - - - + } -void PCA9685::reset(void) { - +void PCA9685::reset(void) +{ + write_8(MODE1,0x00); - + } -void PCA9685::set_prescale(uint8_t prescale) { - +void PCA9685::set_prescale(uint8_t prescale) +{ + uint8_t oldmode = read_8(MODE1); uint8_t newmode = (oldmode&0x7F) | 0x10; // set the sleep bit @@ -45,15 +50,16 @@ write_8(MODE1, oldmode); wait_ms(5); write_8(MODE1, oldmode | 0xa1); // wake up the device - + } //NB REQUIRES AUTO-INCREMENT MODE ENABLED //0 <= pwm_output <= 15 //0 <= (count_on || count_off) <= 4095 -void PCA9685::set_pwm_output(int pwm_output, uint16_t count_on, uint16_t count_off) { - +void PCA9685::set_pwm_output(int pwm_output, uint16_t count_on, uint16_t count_off) +{ + char msg[5]; msg[0] = LED0_ON_L + (4 * pwm_output); @@ -63,17 +69,18 @@ msg[4] = count_off >> 8; i2c.write(i2c_addr, msg, 5); - + } -void PCA9685::set_pwm_output_on_0(int pwm_output, uint16_t count_off) { - +void PCA9685::set_pwm_output_on_0(int pwm_output, uint16_t count_off) +{ + char msg[3]; - + msg[0] = LED0_ON_L + 2 + (4 * pwm_output); msg[1] = count_off; msg[2] = count_off >> 8; - + i2c.write(i2c_addr,msg,3); } @@ -81,70 +88,80 @@ //NB REQUIRES AUTO-INCREMENT MODE ENABLED //0 <= pwm_output <= 15 -void PCA9685::set_pwm_duty(int pwm_output, float duty_cycle) { - - if (duty_cycle > 1.0) { duty_cycle = 1.0; } - if (duty_cycle < 0.0) { duty_cycle = 0.0; } - +void PCA9685::set_pwm_duty(int pwm_output, float duty_cycle) +{ + + if (duty_cycle > 1.0) { + duty_cycle = 1.0; + } + if (duty_cycle < 0.0) { + duty_cycle = 0.0; + } + uint16_t count_off = (uint16_t) (duty_cycle * 4095); uint16_t count_on = 0x0000; - + set_pwm_output(pwm_output, count_on, count_off); - + } //NB REQUIRES AUTO-INCREMENT MODE ENABLED //0 <= pwm_output <= 15 -void PCA9685::set_pwm_pw(int pwm_output, float pulse_width_us) { - +void PCA9685::set_pwm_pw(int pwm_output, float pulse_width_us) +{ + float period_us = (1e6/freq); - + float duty = pulse_width_us/period_us; - + set_pwm_duty(pwm_output, duty); - + } - + -void PCA9685::update(void) { - +void PCA9685::update(void) +{ + i2c.stop(); } - + -void PCA9685::write_8(uint8_t reg, uint8_t msg) { - +void PCA9685::write_8(uint8_t reg, uint8_t msg) +{ + char send[2]; //Store the address and data in an array send[0] = reg; send[1] = msg; i2c.write(i2c_addr, send, 2); - + } -uint8_t PCA9685::read_8(uint8_t reg) { - +uint8_t PCA9685::read_8(uint8_t reg) +{ + char send[1] ; send[0] = reg; i2c.write(i2c_addr, send, 1); char recieve[1]; i2c.read(i2c_addr, recieve, 1); return recieve[0]; - -} + +} -int PCA9685::convert_pwm_value(float pulse_width_us, float period_us) { +int PCA9685::convert_pwm_value(float pulse_width_us, float period_us) +{ int result; float interim; - + interim = ((pulse_width_us / period_us) * 4095); //scale the pulse width to a 12-bit scale result = (int) interim; //round the value to the nearest integer - + return result; - -} + +} #endif \ No newline at end of file