This is a library for the PCA9685 ported from the Adafruit Ardiuno library.

Committer:
rvasquez6089
Date:
Sat Feb 14 19:35:08 2015 +0000
Revision:
2:ec40a85eba51
Parent:
0:1ecf26e0cf3c
Added Documentation and SetMode2 Register function

Who changed what in which revision?

UserRevisionLine numberNew contents of line
rvasquez6089 0:1ecf26e0cf3c 1
rvasquez6089 0:1ecf26e0cf3c 2
rvasquez6089 0:1ecf26e0cf3c 3 #include "PCA9685Lib.h"
rvasquez6089 0:1ecf26e0cf3c 4
rvasquez6089 0:1ecf26e0cf3c 5
rvasquez6089 0:1ecf26e0cf3c 6 void LEDarr::operator=(uint16_t duty)
rvasquez6089 0:1ecf26e0cf3c 7 {
rvasquez6089 0:1ecf26e0cf3c 8 PCALib->setDuty(LEDnum, duty);
rvasquez6089 0:1ecf26e0cf3c 9 }
rvasquez6089 0:1ecf26e0cf3c 10
rvasquez6089 0:1ecf26e0cf3c 11 PCA9685Lib::PCA9685Lib(I2C i2cobj, int addr) : _i2caddr(addr) , i2c(i2cobj)
rvasquez6089 0:1ecf26e0cf3c 12 {
rvasquez6089 0:1ecf26e0cf3c 13 for(int i = 0; i<16 ; i++)
rvasquez6089 0:1ecf26e0cf3c 14 {
rvasquez6089 0:1ecf26e0cf3c 15 LED[i].PCALib = this;
rvasquez6089 0:1ecf26e0cf3c 16 LED[i].LEDnum = i;
rvasquez6089 0:1ecf26e0cf3c 17 }
rvasquez6089 0:1ecf26e0cf3c 18 }
rvasquez6089 0:1ecf26e0cf3c 19
rvasquez6089 0:1ecf26e0cf3c 20 void PCA9685Lib::i2c_probe(void)
rvasquez6089 0:1ecf26e0cf3c 21 {
rvasquez6089 0:1ecf26e0cf3c 22 printf("Searching for I2C devices...\n");
rvasquez6089 0:1ecf26e0cf3c 23
rvasquez6089 0:1ecf26e0cf3c 24 int count = 0;
rvasquez6089 0:1ecf26e0cf3c 25 for (int address=4; address<256; address+=2) {
rvasquez6089 0:1ecf26e0cf3c 26 if (!i2c.write(address, NULL, 0)) { // 0 returned is ok
rvasquez6089 0:1ecf26e0cf3c 27 printf(" - I2C device found at address 0x%02X\r\n", address);
rvasquez6089 0:1ecf26e0cf3c 28 count++;
rvasquez6089 0:1ecf26e0cf3c 29 }
rvasquez6089 0:1ecf26e0cf3c 30 }
rvasquez6089 0:1ecf26e0cf3c 31 printf("%d devices found\r\n", count);
rvasquez6089 0:1ecf26e0cf3c 32 }
rvasquez6089 0:1ecf26e0cf3c 33
rvasquez6089 0:1ecf26e0cf3c 34 void PCA9685Lib::begin(void) {
rvasquez6089 0:1ecf26e0cf3c 35 reset();
rvasquez6089 0:1ecf26e0cf3c 36 }
rvasquez6089 0:1ecf26e0cf3c 37
rvasquez6089 0:1ecf26e0cf3c 38 void PCA9685Lib::setI2Cfreq(int freq) {
rvasquez6089 0:1ecf26e0cf3c 39 i2c.frequency(freq);
rvasquez6089 0:1ecf26e0cf3c 40 }
rvasquez6089 0:1ecf26e0cf3c 41
rvasquez6089 0:1ecf26e0cf3c 42 void PCA9685Lib::reset(void) {
rvasquez6089 0:1ecf26e0cf3c 43 write8(PCA9685_MODE1, 0x0);
rvasquez6089 0:1ecf26e0cf3c 44 }
rvasquez6089 0:1ecf26e0cf3c 45
rvasquez6089 0:1ecf26e0cf3c 46 void PCA9685Lib::setPrescale(uint8_t prescale) {
rvasquez6089 0:1ecf26e0cf3c 47 uint8_t oldmode = read8(PCA9685_MODE1);
rvasquez6089 0:1ecf26e0cf3c 48 uint8_t newmode = (oldmode&0x7F) | 0x10; // sleep
rvasquez6089 0:1ecf26e0cf3c 49 write8(PCA9685_MODE1, newmode); // go to sleep
rvasquez6089 0:1ecf26e0cf3c 50 wait_ms(5);
rvasquez6089 0:1ecf26e0cf3c 51 write8(PCA9685_PRESCALE, prescale); // set the prescaler
rvasquez6089 0:1ecf26e0cf3c 52 write8(PCA9685_MODE1, oldmode);
rvasquez6089 0:1ecf26e0cf3c 53 wait_ms(5);
rvasquez6089 0:1ecf26e0cf3c 54 write8(PCA9685_MODE1, oldmode | 0xa1);
rvasquez6089 0:1ecf26e0cf3c 55 }
rvasquez6089 0:1ecf26e0cf3c 56
rvasquez6089 0:1ecf26e0cf3c 57 void PCA9685Lib::setPWMFreq(float freq) {
rvasquez6089 0:1ecf26e0cf3c 58 //Serial.print("Attempting to set freq ");
rvasquez6089 0:1ecf26e0cf3c 59 //Serial.println(freq);
rvasquez6089 0:1ecf26e0cf3c 60 float prescaleval = 25000000;
rvasquez6089 0:1ecf26e0cf3c 61 prescaleval /= 4096;
rvasquez6089 0:1ecf26e0cf3c 62 prescaleval /= freq;
rvasquez6089 0:1ecf26e0cf3c 63 //Serial.print("Estimated pre-scale: "); Serial.println(prescaleval);
rvasquez6089 0:1ecf26e0cf3c 64 uint8_t prescale = floor(prescaleval + 0.5) - 1;
rvasquez6089 0:1ecf26e0cf3c 65 //Serial.print("Final pre-scale: "); Serial.println(prescale);
rvasquez6089 0:1ecf26e0cf3c 66 setPrescale(prescale);
rvasquez6089 0:1ecf26e0cf3c 67 }
rvasquez6089 0:1ecf26e0cf3c 68
rvasquez6089 2:ec40a85eba51 69 void PCA9685Lib::setMode2(uint8_t val)
rvasquez6089 2:ec40a85eba51 70 {
rvasquez6089 2:ec40a85eba51 71 write8(PCA9685_MODE2, val);
rvasquez6089 2:ec40a85eba51 72 }
rvasquez6089 2:ec40a85eba51 73
rvasquez6089 0:1ecf26e0cf3c 74 void PCA9685Lib::setPWM(uint8_t num, uint16_t on, uint16_t off) {
rvasquez6089 0:1ecf26e0cf3c 75 // hmm doesnt work, whyso? ( Not in AI mode. See line 54 above. ( Works now!! :D )
rvasquez6089 0:1ecf26e0cf3c 76
rvasquez6089 0:1ecf26e0cf3c 77 char cmd[5];
rvasquez6089 0:1ecf26e0cf3c 78 cmd[0] = LED0_ON_L + 4 * num;
rvasquez6089 0:1ecf26e0cf3c 79 cmd[1] = on;
rvasquez6089 0:1ecf26e0cf3c 80 cmd[2] = on >> 8;
rvasquez6089 0:1ecf26e0cf3c 81 cmd[3] = off;
rvasquez6089 0:1ecf26e0cf3c 82 cmd[4] = off >> 8;
rvasquez6089 0:1ecf26e0cf3c 83 i2c.write(_i2caddr, cmd, 5);
rvasquez6089 0:1ecf26e0cf3c 84
rvasquez6089 0:1ecf26e0cf3c 85 /*write8(LED0_ON_L+4*num, on);
rvasquez6089 0:1ecf26e0cf3c 86 write8(LED0_ON_H+4*num, on >> 8);
rvasquez6089 0:1ecf26e0cf3c 87 write8(LED0_OFF_L+4*num, off);
rvasquez6089 0:1ecf26e0cf3c 88 write8(LED0_OFF_H+4*num, off >> 8);*/
rvasquez6089 0:1ecf26e0cf3c 89 }
rvasquez6089 0:1ecf26e0cf3c 90
rvasquez6089 0:1ecf26e0cf3c 91 // Set pwm duty in us order
rvasquez6089 0:1ecf26e0cf3c 92 void PCA9685Lib::setDuty(uint8_t num, uint16_t duty) {
rvasquez6089 0:1ecf26e0cf3c 93 float pulselength = 10000; // 10,000 us per second
rvasquez6089 0:1ecf26e0cf3c 94 duty = 4094 * duty / pulselength;
rvasquez6089 0:1ecf26e0cf3c 95 setPWM(num, 0, duty);
rvasquez6089 0:1ecf26e0cf3c 96 }
rvasquez6089 0:1ecf26e0cf3c 97
rvasquez6089 0:1ecf26e0cf3c 98 uint8_t PCA9685Lib::read8(char addr) {
rvasquez6089 0:1ecf26e0cf3c 99 i2c.write(_i2caddr, &addr, 1);
rvasquez6089 0:1ecf26e0cf3c 100 char rtn;
rvasquez6089 0:1ecf26e0cf3c 101 i2c.read(_i2caddr, &rtn, 1);
rvasquez6089 0:1ecf26e0cf3c 102 return rtn;
rvasquez6089 0:1ecf26e0cf3c 103 }
rvasquez6089 0:1ecf26e0cf3c 104
rvasquez6089 0:1ecf26e0cf3c 105 void PCA9685Lib::write8(char addr, char d) {
rvasquez6089 0:1ecf26e0cf3c 106 char cmd[2];
rvasquez6089 0:1ecf26e0cf3c 107 cmd[0] = addr;
rvasquez6089 0:1ecf26e0cf3c 108 cmd[1] = d;
rvasquez6089 0:1ecf26e0cf3c 109 i2c.write(_i2caddr, cmd, 2);
rvasquez6089 0:1ecf26e0cf3c 110 }
rvasquez6089 0:1ecf26e0cf3c 111
rvasquez6089 0:1ecf26e0cf3c 112
rvasquez6089 2:ec40a85eba51 113 /*
rvasquez6089 2:ec40a85eba51 114 This is a library for our Adafruit 16-channel PWM & Servo driver
rvasquez6089 2:ec40a85eba51 115
rvasquez6089 2:ec40a85eba51 116 Pick one up today in the adafruit shop!
rvasquez6089 2:ec40a85eba51 117 ------> http://www.adafruit.com/products/815
rvasquez6089 2:ec40a85eba51 118
rvasquez6089 2:ec40a85eba51 119 These displays use I2C to communicate, 2 pins are required to
rvasquez6089 2:ec40a85eba51 120 interface. For Arduino UNOs, thats SCL -> Analog 5, SDA -> Analog 4
rvasquez6089 2:ec40a85eba51 121
rvasquez6089 2:ec40a85eba51 122 Adafruit invests time and resources providing this open source code,
rvasquez6089 2:ec40a85eba51 123 please support Adafruit and open-source hardware by purchasing
rvasquez6089 2:ec40a85eba51 124 products from Adafruit!
rvasquez6089 2:ec40a85eba51 125
rvasquez6089 2:ec40a85eba51 126 Written by Limor Fried/Ladyada for Adafruit Industries.
rvasquez6089 2:ec40a85eba51 127 BSD license, all text above must be included in any redistribution
rvasquez6089 2:ec40a85eba51 128 ****************************************************/
rvasquez6089 2:ec40a85eba51 129
rvasquez6089 2:ec40a85eba51 130 /*****************************
rvasquez6089 2:ec40a85eba51 131 This program was ported from https://github.com/adafruit/Adafruit-PWM-Servo-Driver-Library.
rvasquez6089 2:ec40a85eba51 132
rvasquez6089 2:ec40a85eba51 133 */