Skip to content

Commit 83d42b9

Browse files
authored
Merge pull request #1 from adafruit/master
Local merge
2 parents bb7c39a + ddbc2da commit 83d42b9

File tree

5 files changed

+158
-120
lines changed

5 files changed

+158
-120
lines changed

.travis.yml

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,31 @@
11
language: c
22
sudo: false
3-
4-
# Blacklist
5-
branches:
6-
except:
7-
- gh-pages
3+
cache:
4+
directories:
5+
- ~/arduino_ide
6+
- ~/.arduino15/packages/
7+
git:
8+
depth: false
9+
quiet: true
810

911
env:
1012
global:
1113
- PRETTYNAME="Adafruit PCA9685 PWM Servo Driver Arduino Library"
1214

15+
addons:
16+
apt:
17+
sources:
18+
- llvm-toolchain-trusty-5.0
19+
- key_url: 'http://apt.llvm.org/llvm-snapshot.gpg.key'
20+
packages:
21+
- clang-format-5.0
22+
1323
before_install:
1424
- source <(curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/install.sh)
25+
- curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/run-clang-format.py > run-clang-format.py
1526

1627
script:
28+
- python run-clang-format.py -r .
1729
- build_main_platforms
1830

1931
# Generate and deploy documentation

Adafruit_PWMServoDriver.cpp

Lines changed: 79 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -30,22 +30,22 @@
3030
#include "Adafruit_PWMServoDriver.h"
3131
#include <Wire.h>
3232

33+
//#define ENABLE_DEBUG_OUTPUT
34+
3335
/*!
3436
* @brief Instantiates a new PCA9685 PWM driver chip with the I2C address on a
3537
* TwoWire interface
3638
*/
37-
Adafruit_PWMServoDriver::Adafruit_PWMServoDriver():
38-
_i2caddr(PCA9685_I2C_ADDRESS), _i2c(&Wire) {
39-
}
39+
Adafruit_PWMServoDriver::Adafruit_PWMServoDriver()
40+
: _i2caddr(PCA9685_I2C_ADDRESS), _i2c(&Wire) {}
4041

4142
/*!
4243
* @brief Instantiates a new PCA9685 PWM driver chip with the I2C address on a
4344
* TwoWire interface
4445
* @param addr The 7-bit I2C address to locate this chip, default is 0x40
4546
*/
46-
Adafruit_PWMServoDriver::Adafruit_PWMServoDriver(const uint8_t addr):
47-
_i2caddr(addr), _i2c(&Wire) {
48-
}
47+
Adafruit_PWMServoDriver::Adafruit_PWMServoDriver(const uint8_t addr)
48+
: _i2caddr(addr), _i2c(&Wire) {}
4949

5050
/*!
5151
* @brief Instantiates a new PCA9685 PWM driver chip with the I2C address on a
@@ -54,9 +54,9 @@ Adafruit_PWMServoDriver::Adafruit_PWMServoDriver(const uint8_t addr):
5454
* @param i2c A reference to a 'TwoWire' object that we'll use to communicate
5555
* with
5656
*/
57-
Adafruit_PWMServoDriver::Adafruit_PWMServoDriver(const uint8_t addr, TwoWire& i2c) :
58-
_i2caddr(addr), _i2c(&i2c) {
59-
}
57+
Adafruit_PWMServoDriver::Adafruit_PWMServoDriver(const uint8_t addr,
58+
TwoWire &i2c)
59+
: _i2caddr(addr), _i2c(&i2c) {}
6060

6161
/*!
6262
* @brief Setups the I2C interface and hardware
@@ -72,6 +72,8 @@ void Adafruit_PWMServoDriver::begin(uint8_t prescale) {
7272
// set a default frequency
7373
setPWMFreq(1000);
7474
}
75+
// set the default internal frequency
76+
setOscillatorFrequency(FREQUENCY_OSCILLATOR);
7577
}
7678

7779
/*!
@@ -146,21 +148,17 @@ void Adafruit_PWMServoDriver::setPWMFreq(float freq) {
146148
Serial.println(freq);
147149
#endif
148150
// Range output modulation frequency is dependant on oscillator
149-
if (freq < 1) freq = 1;
150-
if (freq > 3500) freq = 3500; // Datasheet limit is 3052=50MHz/(4*4096)
151-
/*
152-
freq *= 0.9; // Correct for overshoot in the frequency setting (see issue #11)
153-
float prescaleval = FREQUENCY_OSCILLATOR;
154-
*/
155-
uint32_t prescaleval = FREQUENCY_CALIBRATED;
156-
prescaleval /= freq; // required output modulation frequency
157-
// rounding to nearest number is equal to adding 0,5 and floor to nearest number
158-
prescaleval += 2048;
159-
prescaleval /= 4096;
160-
prescaleval -= 1;
161-
if (prescaleval < PCA9685_PRESCALE_MIN) prescaleval = PCA9685_PRESCALE_MIN;
162-
if (prescaleval > PCA9685_PRESCALE_MAX) prescaleval = PCA9685_PRESCALE_MAX;
163-
uint8_t prescale = (uint8_t) prescaleval;
151+
if (freq < 1)
152+
freq = 1;
153+
if (freq > 3500)
154+
freq = 3500; // Datasheet limit is 3052=50MHz/(4*4096)
155+
156+
float prescaleval = ((_oscillator_freq / (freq * 4096.0)) + 0.5) - 1;
157+
if (prescaleval < PCA9685_PRESCALE_MIN)
158+
prescaleval = PCA9685_PRESCALE_MIN;
159+
if (prescaleval > PCA9685_PRESCALE_MAX)
160+
prescaleval = PCA9685_PRESCALE_MAX;
161+
uint8_t prescale = (uint8_t)prescaleval;
164162

165163
#ifdef ENABLE_DEBUG_OUTPUT
166164
Serial.print("Final pre-scale: ");
@@ -183,22 +181,21 @@ void Adafruit_PWMServoDriver::setPWMFreq(float freq) {
183181
}
184182

185183
/*!
186-
* @brief Sets the output mode of the PCA9685 to either
187-
* open drain or push pull / totempole.
184+
* @brief Sets the output mode of the PCA9685 to either
185+
* open drain or push pull / totempole.
188186
* Warning: LEDs with integrated zener diodes should
189-
* only be driven in open drain mode.
190-
* @param totempole Totempole if true, open drain if false.
187+
* only be driven in open drain mode.
188+
* @param totempole Totempole if true, open drain if false.
191189
*/
192-
void Adafruit_PWMServoDriver::setOutputMode(bool totempole) {
193-
uint8_t oldmode = read8(PCA9685_MODE2);
190+
void Adafruit_PWMServoDriver::setOutputMode(bool totempole) {
191+
uint8_t oldmode = read8(PCA9685_MODE2);
194192
uint8_t newmode;
195193
if (totempole) {
196194
newmode = oldmode | MODE2_OUTDRV;
197-
}
198-
else {
195+
} else {
199196
newmode = oldmode & ~MODE2_OUTDRV;
200197
}
201-
write8(PCA9685_MODE2, newmode);
198+
write8(PCA9685_MODE2, newmode);
202199
#ifdef ENABLE_DEBUG_OUTPUT
203200
Serial.print("Setting output mode: ");
204201
Serial.print(totempole ? "totempole" : "open drain");
@@ -211,8 +208,7 @@ void Adafruit_PWMServoDriver::setOutputMode(bool totempole) {
211208
* @brief Reads set Prescale from PCA9685
212209
* @return prescale value
213210
*/
214-
uint8_t Adafruit_PWMServoDriver::readPrescale(void)
215-
{
211+
uint8_t Adafruit_PWMServoDriver::readPrescale(void) {
216212
return read8(PCA9685_PRESCALE);
217213
}
218214

@@ -288,55 +284,74 @@ void Adafruit_PWMServoDriver::setPin(uint8_t num, uint16_t val, bool invert) {
288284
}
289285

290286
/*!
291-
* @brief Sets the PWM output of one of the PCA9685 pins based on the input microseconds, output is not precise
287+
* @brief Sets the PWM output of one of the PCA9685 pins based on the input
288+
* microseconds, output is not precise
292289
* @param num One of the PWM output pins, from 0 to 15
293290
* @param Microseconds The number of Microseconds to turn the PWM output ON
294291
*/
295-
void Adafruit_PWMServoDriver::writeMicroseconds(uint8_t num, uint16_t Microseconds) {
296-
#ifdef ENABLE_DEBUG_OUTPUT
292+
void Adafruit_PWMServoDriver::writeMicroseconds(uint8_t num,
293+
uint16_t Microseconds) {
294+
#ifdef ENABLE_DEBUG_OUTPUT
297295
Serial.print("Setting PWM Via Microseconds on output");
298296
Serial.print(num);
299297
Serial.print(": ");
300298
Serial.print(Microseconds);
301299
Serial.println("->");
302-
#endif
300+
#endif
303301

304302
double pulse = Microseconds;
305303
double pulselength;
306-
pulselength = 1000000; // 1,000,000 us per second
304+
pulselength = 1000000; // 1,000,000 us per second
305+
306+
// Read prescale
307+
uint16_t prescale = Adafruit_PWMServoDriver::readPrescale();
308+
309+
#ifdef ENABLE_DEBUG_OUTPUT
310+
Serial.print(prescale);
311+
Serial.println(" PCA9685 chip prescale");
312+
#endif
307313

308-
// Read prescale and convert to frequency
309-
double prescale = Adafruit_PWMServoDriver::readPrescale();
314+
// Calculate the pulse for PWM based on Equation 1 from the datasheet section
315+
// 7.3.5
310316
prescale += 1;
311-
uint32_t freq = 25000000; // Chip frequency is 25MHz
312-
freq /= prescale;
313-
freq /= 4096; // 12 bits of resolution
314-
315-
#ifdef ENABLE_DEBUG_OUTPUT
316-
Serial.print(freq); Serial.println(" Calculated PCA9685 chip PWM Frequency");
317-
#endif
318-
319-
pulselength /= freq; // us per period from PCA9685 chip PWM Frequency using prescale reverse frequency calc
320-
321-
#ifdef ENABLE_DEBUG_OUTPUT
322-
Serial.print(pulselength); Serial.println(" us per period");
323-
#endif
324-
325-
pulselength /= 4096; // 12 bits of resolution
326-
327-
#ifdef ENABLE_DEBUG_OUTPUT
328-
Serial.print(pulselength); Serial.println(" us per bit");
329-
#endif
317+
pulselength *= prescale;
318+
pulselength /= _oscillator_freq;
319+
320+
#ifdef ENABLE_DEBUG_OUTPUT
321+
Serial.print(pulselength);
322+
Serial.println(" us per bit");
323+
#endif
330324

331325
pulse /= pulselength;
332326

333-
#ifdef ENABLE_DEBUG_OUTPUT
334-
Serial.print(pulse);Serial.println(" pulse for PWM");
335-
#endif
327+
#ifdef ENABLE_DEBUG_OUTPUT
328+
Serial.print(pulse);
329+
Serial.println(" pulse for PWM");
330+
#endif
336331

337332
Adafruit_PWMServoDriver::setPWM(num, 0, pulse);
338333
}
339334

335+
/*!
336+
* @brief Getter for the internally tracked oscillator used for freq
337+
* calculations
338+
* @returns The frequency the PCA9685 thinks it is running at (it cannot
339+
* introspect)
340+
*/
341+
uint32_t Adafruit_PWMServoDriver::getOscillatorFrequency(void) {
342+
return _oscillator_freq;
343+
}
344+
345+
/*!
346+
* @brief Setter for the internally tracked oscillator used for freq
347+
* calculations
348+
* @param freq The frequency the PCA9685 should use for frequency calculations
349+
*/
350+
void Adafruit_PWMServoDriver::setOscillatorFrequency(uint32_t freq) {
351+
_oscillator_freq = freq;
352+
}
353+
354+
/******************* Low level I2C interface */
340355
uint8_t Adafruit_PWMServoDriver::read8(uint8_t addr) {
341356
_i2c->beginTransmission(_i2caddr);
342357
_i2c->write(addr);

Adafruit_PWMServoDriver.h

Lines changed: 47 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
*
44
* This is a library for our Adafruit 16-channel PWM & Servo driver.
55
*
6-
* Designed specifically to work with the Adafruit 16-channel PWM & Servo driver.
6+
* Designed specifically to work with the Adafruit 16-channel PWM & Servo
7+
* driver.
78
*
89
* Pick one up today in the adafruit shop!
910
* ------> https://www.adafruit.com/product/815
@@ -26,57 +27,56 @@
2627
#include <Wire.h>
2728

2829
// REGISTER ADDRESSES
29-
#define PCA9685_MODE1 0x00 /**< Mode Register 1 */
30-
#define PCA9685_MODE2 0x01 /**< Mode Register 2 */
31-
#define PCA9685_SUBADR1 0x02 /**< I2C-bus subaddress 1 */
32-
#define PCA9685_SUBADR2 0x03 /**< I2C-bus subaddress 2 */
33-
#define PCA9685_SUBADR3 0x04 /**< I2C-bus subaddress 3 */
34-
#define PCA9685_ALLCALLADR 0x05 /**< LED All Call I2C-bus address */
35-
#define PCA9685_LED0_ON_L 0x06 /**< LED0 output and brightness control byte 0 */
36-
#define PCA9685_LED0_ON_H 0x07 /**< LED0 output and brightness control byte 1 */
37-
#define PCA9685_LED0_OFF_L 0x08 /**< LED0 output and brightness control byte 2 */
38-
#define PCA9685_LED0_OFF_H 0x09 /**< LED0 output and brightness control byte 3 */
30+
#define PCA9685_MODE1 0x00 /**< Mode Register 1 */
31+
#define PCA9685_MODE2 0x01 /**< Mode Register 2 */
32+
#define PCA9685_SUBADR1 0x02 /**< I2C-bus subaddress 1 */
33+
#define PCA9685_SUBADR2 0x03 /**< I2C-bus subaddress 2 */
34+
#define PCA9685_SUBADR3 0x04 /**< I2C-bus subaddress 3 */
35+
#define PCA9685_ALLCALLADR 0x05 /**< LED All Call I2C-bus address */
36+
#define PCA9685_LED0_ON_L 0x06 /**< LED0 on tick, low byte*/
37+
#define PCA9685_LED0_ON_H 0x07 /**< LED0 on tick, high byte*/
38+
#define PCA9685_LED0_OFF_L 0x08 /**< LED0 off tick, low byte */
39+
#define PCA9685_LED0_OFF_H 0x09 /**< LED0 off tick, high byte */
3940
// etc all 16: LED15_OFF_H 0x45
40-
#define PCA9685_ALLLED_ON_L 0xFA /**< load all the LEDn_ON registers, byte 0 */
41-
#define PCA9685_ALLLED_ON_H 0xFB /**< load all the LEDn_ON registers, byte 1 */
42-
#define PCA9685_ALLLED_OFF_L 0xFC /**< load all the LEDn_OFF registers, byte 0 */
43-
#define PCA9685_ALLLED_OFF_H 0xFD /**< load all the LEDn_OFF registers, byte 1 */
44-
#define PCA9685_PRESCALE 0xFE /**< Prescaler for PWM output frequency */
45-
#define PCA9685_TESTMODE 0xFF /**< defines the test mode to be entered */
41+
#define PCA9685_ALLLED_ON_L 0xFA /**< load all the LEDn_ON registers, low */
42+
#define PCA9685_ALLLED_ON_H 0xFB /**< load all the LEDn_ON registers, high */
43+
#define PCA9685_ALLLED_OFF_L 0xFC /**< load all the LEDn_OFF registers, low */
44+
#define PCA9685_ALLLED_OFF_H 0xFD /**< load all the LEDn_OFF registers,high */
45+
#define PCA9685_PRESCALE 0xFE /**< Prescaler for PWM output frequency */
46+
#define PCA9685_TESTMODE 0xFF /**< defines the test mode to be entered */
4647

4748
// MODE1 bits
48-
#define MODE1_ALLCAL 0x01 /**< respond to LED All Call I2C-bus address */
49-
#define MODE1_SUB3 0x02 /**< respond to I2C-bus subaddress 3 */
50-
#define MODE1_SUB2 0x04 /**< respond to I2C-bus subaddress 2 */
51-
#define MODE1_SUB1 0x08 /**< respond to I2C-bus subaddress 1 */
52-
#define MODE1_SLEEP 0x10 /**< Low power mode. Oscillator off */
53-
#define MODE1_AI 0x20 /**< Auto-Increment enabled */
54-
#define MODE1_EXTCLK 0x40 /**< Use EXTCLK pin clock */
55-
#define MODE1_RESTART 0x80 /**< Restart enabled */
49+
#define MODE1_ALLCAL 0x01 /**< respond to LED All Call I2C-bus address */
50+
#define MODE1_SUB3 0x02 /**< respond to I2C-bus subaddress 3 */
51+
#define MODE1_SUB2 0x04 /**< respond to I2C-bus subaddress 2 */
52+
#define MODE1_SUB1 0x08 /**< respond to I2C-bus subaddress 1 */
53+
#define MODE1_SLEEP 0x10 /**< Low power mode. Oscillator off */
54+
#define MODE1_AI 0x20 /**< Auto-Increment enabled */
55+
#define MODE1_EXTCLK 0x40 /**< Use EXTCLK pin clock */
56+
#define MODE1_RESTART 0x80 /**< Restart enabled */
5657
// MODE2 bits
57-
#define MODE2_OUTNE_0 0x01 /**< Active LOW output enable input */
58-
#define MODE2_OUTNE_1 0x02 /**< Active LOW output enable input - high impedience */
59-
#define MODE2_OUTDRV 0x04 /**< totem pole structure vs open-drain */
60-
#define MODE2_OCH 0x08 /**< Outputs change on ACK vs STOP */
61-
#define MODE2_INVRT 0x10 /**< Output logic state inverted */
58+
#define MODE2_OUTNE_0 0x01 /**< Active LOW output enable input */
59+
#define MODE2_OUTNE_1 \
60+
0x02 /**< Active LOW output enable input - high impedience */
61+
#define MODE2_OUTDRV 0x04 /**< totem pole structure vs open-drain */
62+
#define MODE2_OCH 0x08 /**< Outputs change on ACK vs STOP */
63+
#define MODE2_INVRT 0x10 /**< Output logic state inverted */
6264

63-
#define PCA9685_I2C_ADDRESS 0x40 /**< Default PCA9685 I2C Slave Address */
65+
#define PCA9685_I2C_ADDRESS 0x40 /**< Default PCA9685 I2C Slave Address */
66+
#define FREQUENCY_OSCILLATOR 25000000 /**< Int. osc. frequency in datasheet */
6467

65-
#define FREQUENCY_OSCILLATOR 25000000 /**< Oscillator frequency cf satasheet */
66-
#define FREQUENCY_CALIBRATED 26075000 /**< Oscillator frequency measured at 104.3% */
67-
#define FREQUENCY_LEGACY 27777778 /**< Oscillator frequency using freq /= 0,9 */
68-
69-
#define PCA9685_PRESCALE_MIN 3 /**< minimum prescale value */
68+
#define PCA9685_PRESCALE_MIN 3 /**< minimum prescale value */
7069
#define PCA9685_PRESCALE_MAX 255 /**< maximum prescale value */
7170

72-
/*!
73-
* @brief Class that stores state and functions for interacting with PCA9685 PWM chip
71+
/*!
72+
* @brief Class that stores state and functions for interacting with PCA9685
73+
* PWM chip
7474
*/
7575
class Adafruit_PWMServoDriver {
76-
public:
76+
public:
7777
Adafruit_PWMServoDriver();
7878
Adafruit_PWMServoDriver(const uint8_t addr);
79-
Adafruit_PWMServoDriver(const uint8_t addr, TwoWire& i2c);
79+
Adafruit_PWMServoDriver(const uint8_t addr, TwoWire &i2c);
8080
void begin(uint8_t prescale = 0);
8181
void reset();
8282
void sleep();
@@ -87,14 +87,18 @@ class Adafruit_PWMServoDriver {
8787
void setOutputMode(bool totempole);
8888
uint8_t getPWM(uint8_t num);
8989
void setPWM(uint8_t num, uint16_t on, uint16_t off);
90-
void setPin(uint8_t num, uint16_t val, bool invert=false);
90+
void setPin(uint8_t num, uint16_t val, bool invert = false);
9191
uint8_t readPrescale(void);
9292
void writeMicroseconds(uint8_t num, uint16_t Microseconds);
9393

94-
private:
94+
void setOscillatorFrequency(uint32_t freq);
95+
uint32_t getOscillatorFrequency(void);
96+
97+
private:
9598
uint8_t _i2caddr;
96-
TwoWire* _i2c;
99+
TwoWire *_i2c;
97100

101+
uint32_t _oscillator_freq;
98102
uint8_t read8(uint8_t addr);
99103
void write8(uint8_t addr, uint8_t d);
100104
};

0 commit comments

Comments
 (0)