This is a library for our Adafruit 16-channel PWM & Servo driver Pick one up today in the adafruit shop! ------> http://www.adafruit.com/products/815 These displays use I2C to communicate, 2 pins are required to interface. Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! Written by Limor Fried/Ladyada for Adafruit Industries. BSD license, check license.txt for more information All text above must be included in any redistribution
Adafruit_PWMServoDriver.cpp@4:41a00db32ae7, 2014-01-05 (annotated)
- Committer:
- bxd
- Date:
- Sun Jan 05 22:29:21 2014 +0000
- Revision:
- 4:41a00db32ae7
- Parent:
- 3:5e1fd11c4f94
updated comment about addressing.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
bxd | 0:ed0c8a6481fd | 1 | /*************************************************** |
bxd | 0:ed0c8a6481fd | 2 | This is a library for our Adafruit 16-channel PWM & Servo driver |
bxd | 0:ed0c8a6481fd | 3 | |
bxd | 0:ed0c8a6481fd | 4 | Pick one up today in the adafruit shop! |
bxd | 0:ed0c8a6481fd | 5 | ------> http://www.adafruit.com/products/815 |
bxd | 0:ed0c8a6481fd | 6 | |
bxd | 0:ed0c8a6481fd | 7 | These displays use I2C to communicate, 2 pins are required to |
bxd | 0:ed0c8a6481fd | 8 | interface. For Arduino UNOs, thats SCL -> Analog 5, SDA -> Analog 4 |
bxd | 0:ed0c8a6481fd | 9 | |
bxd | 0:ed0c8a6481fd | 10 | Adafruit invests time and resources providing this open source code, |
bxd | 0:ed0c8a6481fd | 11 | please support Adafruit and open-source hardware by purchasing |
bxd | 0:ed0c8a6481fd | 12 | products from Adafruit! |
bxd | 0:ed0c8a6481fd | 13 | |
bxd | 0:ed0c8a6481fd | 14 | Written by Limor Fried/Ladyada for Adafruit Industries. |
bxd | 0:ed0c8a6481fd | 15 | BSD license, all text above must be included in any redistribution |
bxd | 0:ed0c8a6481fd | 16 | |
bxd | 0:ed0c8a6481fd | 17 | Ported to mbed by Brian Dickman, mbed.org user bxd. |
bxd | 0:ed0c8a6481fd | 18 | ****************************************************/ |
bxd | 0:ed0c8a6481fd | 19 | |
bxd | 0:ed0c8a6481fd | 20 | #include <Adafruit_PWMServoDriver.h> |
bxd | 0:ed0c8a6481fd | 21 | |
bxd | 0:ed0c8a6481fd | 22 | Adafruit_PWMServoDriver::Adafruit_PWMServoDriver(I2C *i2c, uint8_t addr) { |
bxd | 0:ed0c8a6481fd | 23 | _i2c = i2c; |
bxd | 0:ed0c8a6481fd | 24 | |
bxd | 0:ed0c8a6481fd | 25 | // Arduino WIRE library takes address as 7-bit (unshifted), mbed takes 8 bit. |
bxd | 4:41a00db32ae7 | 26 | // in other words, use the Adafruit library default value 0x40 to talk with the breakout |
bxd | 4:41a00db32ae7 | 27 | // if you use the default resistor config. |
bxd | 0:ed0c8a6481fd | 28 | _i2caddr = addr << 1; |
bxd | 0:ed0c8a6481fd | 29 | } |
bxd | 0:ed0c8a6481fd | 30 | |
bxd | 0:ed0c8a6481fd | 31 | void Adafruit_PWMServoDriver::begin(void) { |
bxd | 0:ed0c8a6481fd | 32 | reset(); |
bxd | 0:ed0c8a6481fd | 33 | } |
bxd | 0:ed0c8a6481fd | 34 | |
bxd | 0:ed0c8a6481fd | 35 | |
bxd | 0:ed0c8a6481fd | 36 | void Adafruit_PWMServoDriver::reset(void) { |
bxd | 3:5e1fd11c4f94 | 37 | |
bxd | 3:5e1fd11c4f94 | 38 | // leave the ALL CALL address enabled (we might use that!) |
bxd | 3:5e1fd11c4f94 | 39 | // if you don't want ALL CALL, write 00 to offset 00 |
bxd | 3:5e1fd11c4f94 | 40 | write8(PCA9685_MODE1, 0x1); |
bxd | 0:ed0c8a6481fd | 41 | } |
bxd | 0:ed0c8a6481fd | 42 | |
bxd | 0:ed0c8a6481fd | 43 | void Adafruit_PWMServoDriver::setPWMFreq(float freq) { |
bxd | 0:ed0c8a6481fd | 44 | //Serial.print("Attempting to set freq "); |
bxd | 0:ed0c8a6481fd | 45 | //Serial.println(freq); |
bxd | 0:ed0c8a6481fd | 46 | |
bxd | 0:ed0c8a6481fd | 47 | float prescaleval = 25000000; |
bxd | 0:ed0c8a6481fd | 48 | prescaleval /= 4096; |
bxd | 0:ed0c8a6481fd | 49 | prescaleval /= freq; |
bxd | 0:ed0c8a6481fd | 50 | prescaleval -= 1; |
bxd | 0:ed0c8a6481fd | 51 | //printf("Estimated pre-scale: %f\r\n", prescaleval); |
bxd | 0:ed0c8a6481fd | 52 | uint8_t prescale = floor(prescaleval + 0.5); |
bxd | 0:ed0c8a6481fd | 53 | //printf("Final pre-scale: %f", prescale); |
bxd | 0:ed0c8a6481fd | 54 | |
bxd | 0:ed0c8a6481fd | 55 | uint8_t oldmode = read8(PCA9685_MODE1); |
bxd | 0:ed0c8a6481fd | 56 | uint8_t newmode = (oldmode&0x7F) | 0x10; // sleep |
bxd | 0:ed0c8a6481fd | 57 | write8(PCA9685_MODE1, newmode); // go to sleep |
bxd | 0:ed0c8a6481fd | 58 | write8(PCA9685_PRESCALE, prescale); // set the prescaler |
bxd | 0:ed0c8a6481fd | 59 | write8(PCA9685_MODE1, oldmode); |
bxd | 0:ed0c8a6481fd | 60 | wait_ms(5); |
bxd | 0:ed0c8a6481fd | 61 | write8(PCA9685_MODE1, oldmode | 0xa1); // This sets the MODE1 register to turn on auto increment. |
bxd | 0:ed0c8a6481fd | 62 | // This is why the beginTransmission below was not working. |
bxd | 0:ed0c8a6481fd | 63 | // Serial.print("Mode now 0x"); Serial.println(read8(PCA9685_MODE1), HEX); |
bxd | 0:ed0c8a6481fd | 64 | } |
bxd | 0:ed0c8a6481fd | 65 | |
bxd | 0:ed0c8a6481fd | 66 | void Adafruit_PWMServoDriver::setPWM(uint8_t num, uint16_t on, uint16_t off) { |
bxd | 0:ed0c8a6481fd | 67 | //Serial.print("Setting PWM "); Serial.print(num); Serial.print(": "); Serial.print(on); Serial.print("->"); Serial.println(off); |
bxd | 0:ed0c8a6481fd | 68 | |
bxd | 0:ed0c8a6481fd | 69 | uint8_t data[] = { LED0_ON_L+4*num, on, on >> 8, off, off >> 8 }; |
bxd | 0:ed0c8a6481fd | 70 | _i2c->write(_i2caddr, (const char *)data, 5); |
bxd | 0:ed0c8a6481fd | 71 | /* |
bxd | 0:ed0c8a6481fd | 72 | WIRE.beginTransmission(_i2caddr); |
bxd | 0:ed0c8a6481fd | 73 | WIRE.write(LED0_ON_L+4*num); |
bxd | 0:ed0c8a6481fd | 74 | WIRE.write(on); |
bxd | 0:ed0c8a6481fd | 75 | WIRE.write(on>>8); |
bxd | 0:ed0c8a6481fd | 76 | WIRE.write(off); |
bxd | 0:ed0c8a6481fd | 77 | WIRE.write(off>>8); |
bxd | 0:ed0c8a6481fd | 78 | WIRE.endTransmission(); |
bxd | 0:ed0c8a6481fd | 79 | */ |
bxd | 0:ed0c8a6481fd | 80 | } |
bxd | 0:ed0c8a6481fd | 81 | |
bxd | 0:ed0c8a6481fd | 82 | uint8_t Adafruit_PWMServoDriver::read8(uint8_t addr) { |
bxd | 0:ed0c8a6481fd | 83 | char data; |
bxd | 3:5e1fd11c4f94 | 84 | if(_i2c->write(_i2caddr, (char *)&addr, 1, true)) |
bxd | 4:41a00db32ae7 | 85 | printf("I2C ERR: no ack on write before read.\n"); |
bxd | 3:5e1fd11c4f94 | 86 | if(_i2c->read(_i2caddr, &data, 1)) |
bxd | 4:41a00db32ae7 | 87 | printf("I2C ERR: no ack on read\n"); |
bxd | 0:ed0c8a6481fd | 88 | return (uint8_t)data; |
bxd | 0:ed0c8a6481fd | 89 | } |
bxd | 0:ed0c8a6481fd | 90 | |
bxd | 0:ed0c8a6481fd | 91 | void Adafruit_PWMServoDriver::write8(uint8_t addr, uint8_t d) { |
bxd | 0:ed0c8a6481fd | 92 | char data[] = { addr, d }; |
bxd | 1:ac6c5e17c3d3 | 93 | if(_i2c->write(_i2caddr, data, 2)) |
bxd | 1:ac6c5e17c3d3 | 94 | { |
bxd | 4:41a00db32ae7 | 95 | printf("I2C ERR: No ACK on i2c write!"); |
bxd | 1:ac6c5e17c3d3 | 96 | } |
bxd | 0:ed0c8a6481fd | 97 | } |