This is a library for the PCA9685 ported from the Adafruit Ardiuno library.
PCA9685Lib.cpp@2:ec40a85eba51, 2015-02-14 (annotated)
- 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?
User | Revision | Line number | New 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 | */ |