PCA9685 library
Dependents: s-rov-firmware DISCO-F746NG_rtos_test
pca9685.cpp
- Committer:
- YJ_Kim
- Date:
- 2017-01-26
- Revision:
- 2:5c8802f876f8
- Parent:
- 1:7e071acc57b1
File content as of revision 2:5c8802f876f8:
#include "mbed.h" #include "pca9685.h" PCA9685::PCA9685(uint8_t i2c_addr, I2C* i2c_object, float freq): PCA9685_ADDR(i2c_addr << 1), frequency(freq), i2c(i2c_object) {} void PCA9685::reset(void){ write_8(PCA9685_MODE1, 0x00); // reset the device } void PCA9685::init(void){ reset(); set_pwm_frequency(frequency); } void PCA9685::set_pwm_frequency(float freq){ freq *= 0.9; // Correct for overshoot in the frequency setting (see issue #11). float prescaleval = 25000000; prescaleval /= 4096; prescaleval /= freq; prescaleval -= 1; char prescale = floor(prescaleval + 0.5); char oldmode = read_8(PCA9685_MODE1); char newmode = (oldmode&0x7F) | 0x10; // sleep write_8(PCA9685_MODE1, newmode); //go to sleep write_8(PCA9685_PRESCALE, prescale); // set the prescaler write_8(PCA9685_MODE1, oldmode); wait(0.5); write_8(PCA9685_MODE1, oldmode | 0xa1); } void PCA9685::set_servo_angle(uint8_t num, float angle){ if(angle > 180.0) angle = 180.0; if(angle < 0.0) angle = 0.0; // 0 ~ 180 degree to 1 ~ 2ms set_pwm_duty(num, (frequency*angle/180.0 + frequency)*0.1 ); } void PCA9685::set_pwm_output(uint8_t num, uint16_t on, uint16_t off){ char cmd[5]; cmd[0] = PCA9685_LED0_ON_L + 4*num; cmd[1] = on % 256; cmd[2] = on / 256; cmd[3] = off % 256; cmd[4] = off / 256; i2c->write(PCA9685_ADDR, cmd, 5); } void PCA9685::set_pwm_duty(uint8_t num, float duty){ if(duty > 100.0) duty = 100.0; if(duty < 0.0) duty = 0.0; uint16_t on = 0x0000; uint16_t off = (uint16_t)(duty * 40.95); set_pwm_output(num, on, off); } void PCA9685::write_8(uint8_t reg, uint8_t msg){ char cmd[2]; cmd[0] = reg; cmd[1] = msg; i2c->write(PCA9685_ADDR, cmd, 2); } char PCA9685::read_8(uint8_t reg){ char cmd = reg; i2c->write(PCA9685_ADDR, &cmd, 1); i2c->read(PCA9685_ADDR, &cmd, 1); return cmd; }