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@3:5e1fd11c4f94, 2014-01-05 (annotated)
- Committer:
- bxd
- Date:
- Sun Jan 05 22:26:12 2014 +0000
- Revision:
- 3:5e1fd11c4f94
- Parent:
- 2:237e7b9d17c8
- Child:
- 4:41a00db32ae7
Fixed horrible bug in read8, left ALL CALL enabled on reset.
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 | 0:ed0c8a6481fd | 26 | _i2caddr = addr << 1; |
bxd | 0:ed0c8a6481fd | 27 | } |
bxd | 0:ed0c8a6481fd | 28 | |
bxd | 0:ed0c8a6481fd | 29 | void Adafruit_PWMServoDriver::begin(void) { |
bxd | 0:ed0c8a6481fd | 30 | reset(); |
bxd | 0:ed0c8a6481fd | 31 | } |
bxd | 0:ed0c8a6481fd | 32 | |
bxd | 0:ed0c8a6481fd | 33 | |
bxd | 0:ed0c8a6481fd | 34 | void Adafruit_PWMServoDriver::reset(void) { |
bxd | 3:5e1fd11c4f94 | 35 | |
bxd | 3:5e1fd11c4f94 | 36 | // leave the ALL CALL address enabled (we might use that!) |
bxd | 3:5e1fd11c4f94 | 37 | // if you don't want ALL CALL, write 00 to offset 00 |
bxd | 3:5e1fd11c4f94 | 38 | write8(PCA9685_MODE1, 0x1); |
bxd | 0:ed0c8a6481fd | 39 | } |
bxd | 0:ed0c8a6481fd | 40 | |
bxd | 0:ed0c8a6481fd | 41 | void Adafruit_PWMServoDriver::setPWMFreq(float freq) { |
bxd | 0:ed0c8a6481fd | 42 | //Serial.print("Attempting to set freq "); |
bxd | 0:ed0c8a6481fd | 43 | //Serial.println(freq); |
bxd | 0:ed0c8a6481fd | 44 | |
bxd | 0:ed0c8a6481fd | 45 | float prescaleval = 25000000; |
bxd | 0:ed0c8a6481fd | 46 | prescaleval /= 4096; |
bxd | 0:ed0c8a6481fd | 47 | prescaleval /= freq; |
bxd | 0:ed0c8a6481fd | 48 | prescaleval -= 1; |
bxd | 0:ed0c8a6481fd | 49 | //printf("Estimated pre-scale: %f\r\n", prescaleval); |
bxd | 0:ed0c8a6481fd | 50 | uint8_t prescale = floor(prescaleval + 0.5); |
bxd | 0:ed0c8a6481fd | 51 | //printf("Final pre-scale: %f", prescale); |
bxd | 0:ed0c8a6481fd | 52 | |
bxd | 0:ed0c8a6481fd | 53 | uint8_t oldmode = read8(PCA9685_MODE1); |
bxd | 0:ed0c8a6481fd | 54 | uint8_t newmode = (oldmode&0x7F) | 0x10; // sleep |
bxd | 0:ed0c8a6481fd | 55 | write8(PCA9685_MODE1, newmode); // go to sleep |
bxd | 0:ed0c8a6481fd | 56 | write8(PCA9685_PRESCALE, prescale); // set the prescaler |
bxd | 0:ed0c8a6481fd | 57 | write8(PCA9685_MODE1, oldmode); |
bxd | 0:ed0c8a6481fd | 58 | wait_ms(5); |
bxd | 0:ed0c8a6481fd | 59 | write8(PCA9685_MODE1, oldmode | 0xa1); // This sets the MODE1 register to turn on auto increment. |
bxd | 0:ed0c8a6481fd | 60 | // This is why the beginTransmission below was not working. |
bxd | 0:ed0c8a6481fd | 61 | // Serial.print("Mode now 0x"); Serial.println(read8(PCA9685_MODE1), HEX); |
bxd | 0:ed0c8a6481fd | 62 | } |
bxd | 0:ed0c8a6481fd | 63 | |
bxd | 0:ed0c8a6481fd | 64 | void Adafruit_PWMServoDriver::setPWM(uint8_t num, uint16_t on, uint16_t off) { |
bxd | 0:ed0c8a6481fd | 65 | //Serial.print("Setting PWM "); Serial.print(num); Serial.print(": "); Serial.print(on); Serial.print("->"); Serial.println(off); |
bxd | 0:ed0c8a6481fd | 66 | |
bxd | 0:ed0c8a6481fd | 67 | uint8_t data[] = { LED0_ON_L+4*num, on, on >> 8, off, off >> 8 }; |
bxd | 0:ed0c8a6481fd | 68 | _i2c->write(_i2caddr, (const char *)data, 5); |
bxd | 0:ed0c8a6481fd | 69 | /* |
bxd | 0:ed0c8a6481fd | 70 | WIRE.beginTransmission(_i2caddr); |
bxd | 0:ed0c8a6481fd | 71 | WIRE.write(LED0_ON_L+4*num); |
bxd | 0:ed0c8a6481fd | 72 | WIRE.write(on); |
bxd | 0:ed0c8a6481fd | 73 | WIRE.write(on>>8); |
bxd | 0:ed0c8a6481fd | 74 | WIRE.write(off); |
bxd | 0:ed0c8a6481fd | 75 | WIRE.write(off>>8); |
bxd | 0:ed0c8a6481fd | 76 | WIRE.endTransmission(); |
bxd | 0:ed0c8a6481fd | 77 | */ |
bxd | 0:ed0c8a6481fd | 78 | } |
bxd | 0:ed0c8a6481fd | 79 | |
bxd | 0:ed0c8a6481fd | 80 | uint8_t Adafruit_PWMServoDriver::read8(uint8_t addr) { |
bxd | 0:ed0c8a6481fd | 81 | char data; |
bxd | 3:5e1fd11c4f94 | 82 | if(_i2c->write(_i2caddr, (char *)&addr, 1, true)) |
bxd | 3:5e1fd11c4f94 | 83 | printf("no ack on write before read.\n"); |
bxd | 3:5e1fd11c4f94 | 84 | if(_i2c->read(_i2caddr, &data, 1)) |
bxd | 3:5e1fd11c4f94 | 85 | printf("no ack on read\n"); |
bxd | 0:ed0c8a6481fd | 86 | return (uint8_t)data; |
bxd | 0:ed0c8a6481fd | 87 | } |
bxd | 0:ed0c8a6481fd | 88 | |
bxd | 0:ed0c8a6481fd | 89 | void Adafruit_PWMServoDriver::write8(uint8_t addr, uint8_t d) { |
bxd | 0:ed0c8a6481fd | 90 | char data[] = { addr, d }; |
bxd | 1:ac6c5e17c3d3 | 91 | if(_i2c->write(_i2caddr, data, 2)) |
bxd | 1:ac6c5e17c3d3 | 92 | { |
bxd | 3:5e1fd11c4f94 | 93 | printf("No ACK on i2c write!"); |
bxd | 1:ac6c5e17c3d3 | 94 | } |
bxd | 0:ed0c8a6481fd | 95 | } |