From d7e0ec9236bb68a689ce618f4a39c147581b2e31 Mon Sep 17 00:00:00 2001 From: Walt Sorensen Date: Tue, 29 Oct 2019 10:03:08 -0600 Subject: [PATCH 01/11] Simplify and improve the writeMicroseconds() calculations Checked the calculations by hand Use Datasheet 7.3.5 Equation 1 for frequency from prescale https://cdn-shop.adafruit.com/datasheets/PCA9685.pdf Frequency = (ClockFrequency/(PreScale+1))*(1/BitRate) and from the rest of the calculation us per period = PulseLength/Frequency us per bit = us per period/BitRate we can combine to get us per bit = (PulseLength/((ClockFrequency/(PreScale+1))*(1/BitRate)))*(1/BitRate) This can be simplified to (PulseLength (PreScale + 1))/ClockFrequency this formula was implemented in proposed code checked by setting chip frequency to 60Hz read prescale = 105 us per bit = 4.069 with 25Mhz (a PWM frequency of about 57.3hz) Choosing the FREQUENCY_CALIBRATED constant listed at 104.3% higher or 26.075MHz we get us per bit = 4.1035 or a PWM frequency of about 60.056Hz much closer to the set 60Hz Overall this change makes less calculation steps, and uses fewer variables. The change should be faster and more accurate to the intended results. --- Adafruit_PWMServoDriver.cpp | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/Adafruit_PWMServoDriver.cpp b/Adafruit_PWMServoDriver.cpp index 4c614fe..b84f141 100755 --- a/Adafruit_PWMServoDriver.cpp +++ b/Adafruit_PWMServoDriver.cpp @@ -296,24 +296,14 @@ void Adafruit_PWMServoDriver::writeMicroseconds(uint8_t num, uint16_t Microsecon double pulselength; pulselength = 1000000; // 1,000,000 us per second - // Read prescale and convert to frequency + // Read prescale double prescale = Adafruit_PWMServoDriver::readPrescale(); - prescale += 1; - uint32_t freq = 25000000; // Chip frequency is 25MHz - freq /= prescale; - freq /= 4096; // 12 bits of resolution - - #ifdef ENABLE_DEBUG_OUTPUT - Serial.print(freq); Serial.println(" Calculated PCA9685 chip PWM Frequency"); - #endif - - pulselength /= freq; // us per period from PCA9685 chip PWM Frequency using prescale reverse frequency calc + Serial.print(prescale); Serial.println(" PCA9685 chip prescale"); - #ifdef ENABLE_DEBUG_OUTPUT - Serial.print(pulselength); Serial.println(" us per period"); - #endif - - pulselength /= 4096; // 12 bits of resolution + // Calculate the pulse for PWM based on Equation 1 from the datasheet section 7.3.5 + prescale += 1; + pulselength *= prescale; + pulselength /= FREQUENCY_CALIBRATED; #ifdef ENABLE_DEBUG_OUTPUT Serial.print(pulselength); Serial.println(" us per bit"); From 942f457cb43ed847824e56bbe8ed97246d60f866 Mon Sep 17 00:00:00 2001 From: Walt Sorensen Date: Tue, 29 Oct 2019 10:13:10 -0600 Subject: [PATCH 02/11] Wrap print statement in #ifdef ENABLE_DEBUG_OUTPUT debug statements should be Wrapped in `#ifdef ENABLE_DEBUG_OUTPUT` --- Adafruit_PWMServoDriver.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Adafruit_PWMServoDriver.cpp b/Adafruit_PWMServoDriver.cpp index b84f141..bb31329 100755 --- a/Adafruit_PWMServoDriver.cpp +++ b/Adafruit_PWMServoDriver.cpp @@ -298,7 +298,10 @@ void Adafruit_PWMServoDriver::writeMicroseconds(uint8_t num, uint16_t Microsecon // Read prescale double prescale = Adafruit_PWMServoDriver::readPrescale(); + + #ifdef ENABLE_DEBUG_OUTPUT Serial.print(prescale); Serial.println(" PCA9685 chip prescale"); + #endif // Calculate the pulse for PWM based on Equation 1 from the datasheet section 7.3.5 prescale += 1; From 33ec0da54b4bbee46b9f428497502a877e79de07 Mon Sep 17 00:00:00 2001 From: Walt Sorensen Date: Tue, 29 Oct 2019 12:29:38 -0600 Subject: [PATCH 03/11] Change prescale from double to uint16_t Prescale values are integers 3 to 255 with a maximum of 255+1 for the calculations. --- Adafruit_PWMServoDriver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Adafruit_PWMServoDriver.cpp b/Adafruit_PWMServoDriver.cpp index bb31329..f3170ac 100755 --- a/Adafruit_PWMServoDriver.cpp +++ b/Adafruit_PWMServoDriver.cpp @@ -297,7 +297,7 @@ void Adafruit_PWMServoDriver::writeMicroseconds(uint8_t num, uint16_t Microsecon pulselength = 1000000; // 1,000,000 us per second // Read prescale - double prescale = Adafruit_PWMServoDriver::readPrescale(); + uint16_t prescale = Adafruit_PWMServoDriver::readPrescale(); #ifdef ENABLE_DEBUG_OUTPUT Serial.print(prescale); Serial.println(" PCA9685 chip prescale"); From d1f63cc9f463e69ebc38d3283d51f6f7798ab437 Mon Sep 17 00:00:00 2001 From: Lady Ada Date: Sun, 3 Nov 2019 13:15:49 -0500 Subject: [PATCH 04/11] add set/get oscillator functions --- Adafruit_PWMServoDriver.cpp | 28 +++++++++++++++++----------- Adafruit_PWMServoDriver.h | 9 +++++---- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/Adafruit_PWMServoDriver.cpp b/Adafruit_PWMServoDriver.cpp index f3170ac..eacbc08 100755 --- a/Adafruit_PWMServoDriver.cpp +++ b/Adafruit_PWMServoDriver.cpp @@ -30,6 +30,8 @@ #include "Adafruit_PWMServoDriver.h" #include +//#define ENABLE_DEBUG_OUTPUT + /*! * @brief Instantiates a new PCA9685 PWM driver chip with the I2C address on a * TwoWire interface @@ -72,6 +74,8 @@ void Adafruit_PWMServoDriver::begin(uint8_t prescale) { // set a default frequency setPWMFreq(1000); } + // set the default internal frequency + setOscillatorFrequency(FREQUENCY_OSCILLATOR); } /*! @@ -139,16 +143,9 @@ void Adafruit_PWMServoDriver::setPWMFreq(float freq) { // Range output modulation frequency is dependant on oscillator if (freq < 1) freq = 1; if (freq > 3500) freq = 3500; // Datasheet limit is 3052=50MHz/(4*4096) - /* - freq *= 0.9; // Correct for overshoot in the frequency setting (see issue #11) - float prescaleval = FREQUENCY_OSCILLATOR; - */ - uint32_t prescaleval = FREQUENCY_CALIBRATED; - prescaleval /= freq; // required output modulation frequency - // rounding to nearest number is equal to adding 0,5 and floor to nearest number - prescaleval += 2048; - prescaleval /= 4096; - prescaleval -= 1; + + + float prescaleval = ((_oscillator_freq / (freq * 4096.0)) + 0.5) - 1; if (prescaleval < PCA9685_PRESCALE_MIN) prescaleval = PCA9685_PRESCALE_MIN; if (prescaleval > PCA9685_PRESCALE_MAX) prescaleval = PCA9685_PRESCALE_MAX; uint8_t prescale = (uint8_t) prescaleval; @@ -306,7 +303,7 @@ void Adafruit_PWMServoDriver::writeMicroseconds(uint8_t num, uint16_t Microsecon // Calculate the pulse for PWM based on Equation 1 from the datasheet section 7.3.5 prescale += 1; pulselength *= prescale; - pulselength /= FREQUENCY_CALIBRATED; + pulselength /= _oscillator_freq; #ifdef ENABLE_DEBUG_OUTPUT Serial.print(pulselength); Serial.println(" us per bit"); @@ -321,6 +318,15 @@ void Adafruit_PWMServoDriver::writeMicroseconds(uint8_t num, uint16_t Microsecon Adafruit_PWMServoDriver::setPWM(num, 0, pulse); } +uint32_t Adafruit_PWMServoDriver::getOscillatorFrequency(void) { + return _oscillator_freq; +} + +void Adafruit_PWMServoDriver::setOscillatorFrequency(uint32_t freq) { + _oscillator_freq = freq; +} + +/******************* Low level I2C interface */ uint8_t Adafruit_PWMServoDriver::read8(uint8_t addr) { _i2c->beginTransmission(_i2caddr); _i2c->write(addr); diff --git a/Adafruit_PWMServoDriver.h b/Adafruit_PWMServoDriver.h index 0fecb28..cb88119 100644 --- a/Adafruit_PWMServoDriver.h +++ b/Adafruit_PWMServoDriver.h @@ -61,10 +61,7 @@ #define MODE2_INVRT 0x10 /**< Output logic state inverted */ #define PCA9685_I2C_ADDRESS 0x40 /**< Default PCA9685 I2C Slave Address */ - -#define FREQUENCY_OSCILLATOR 25000000 /**< Oscillator frequency cf satasheet */ -#define FREQUENCY_CALIBRATED 26075000 /**< Oscillator frequency measured at 104.3% */ -#define FREQUENCY_LEGACY 27777778 /**< Oscillator frequency using freq /= 0,9 */ +#define FREQUENCY_OSCILLATOR 25000000 /**< Oscillator frequency in datasheet */ #define PCA9685_PRESCALE_MIN 3 /**< minimum prescale value */ #define PCA9685_PRESCALE_MAX 255 /**< maximum prescale value */ @@ -90,10 +87,14 @@ class Adafruit_PWMServoDriver { uint8_t readPrescale(void); void writeMicroseconds(uint8_t num, uint16_t Microseconds); + void setOscillatorFrequency(uint32_t freq); + uint32_t getOscillatorFrequency(void); + private: uint8_t _i2caddr; TwoWire* _i2c; + uint32_t _oscillator_freq; uint8_t read8(uint8_t addr); void write8(uint8_t addr, uint8_t d); }; From ded0d046f56339ae6eaa3c2c47c004c3740b4ece Mon Sep 17 00:00:00 2001 From: Lady Ada Date: Sun, 3 Nov 2019 13:17:46 -0500 Subject: [PATCH 05/11] add setosc example --- examples/pwmtest/pwmtest.ino | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/examples/pwmtest/pwmtest.ino b/examples/pwmtest/pwmtest.ino index be9e79c..3c2c4b6 100644 --- a/examples/pwmtest/pwmtest.ino +++ b/examples/pwmtest/pwmtest.ino @@ -31,6 +31,10 @@ void setup() { Serial.println("16 channel PWM test!"); pwm.begin(); + // In theory the internal oscillator is 25MHz but it really isn't + // that precise. You can 'calibrate' by tweaking this number till + // you get the frequency you're expecting! + pwm.setOscillatorFrequency(27000000); // The int.osc. is closer to 27MHz pwm.setPWMFreq(1600); // This is the maximum PWM frequency // if you want to really speed stuff up, you can go into 'fast 400khz I2C' mode From 40fa21645e23be6344e0364f6dbce9b597c56453 Mon Sep 17 00:00:00 2001 From: Lady Ada Date: Sun, 3 Nov 2019 13:22:31 -0500 Subject: [PATCH 06/11] updated servodemo --- examples/servo/servo.ino | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/examples/servo/servo.ino b/examples/servo/servo.ino index a9ba63d..4141baf 100644 --- a/examples/servo/servo.ino +++ b/examples/servo/servo.ino @@ -33,9 +33,9 @@ Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(); // have! #define SERVOMIN 150 // This is the 'minimum' pulse length count (out of 4096) #define SERVOMAX 600 // This is the 'maximum' pulse length count (out of 4096) -#define USMIN 611 // This is the rounded 'minimum' microsecond length based on the minimum pulse of 150 -#define USMAX 2441 // This is the rounded 'maximum' microsecond length based on the maximum pulse of 600 -#define FREQ 60 // Analog servos run at ~60 Hz updates +#define USMIN 600 // This is the rounded 'minimum' microsecond length based on the minimum pulse of 150 +#define USMAX 2400 // This is the rounded 'maximum' microsecond length based on the maximum pulse of 600 +#define SERVO_FREQ 60 // Analog servos run at ~60 Hz updates // our servo # counter uint8_t servonum = 0; @@ -45,8 +45,11 @@ void setup() { Serial.println("8 channel Servo test!"); pwm.begin(); - - pwm.setPWMFreq(FREQ); // Analog servos run at ~60 Hz updates + // In theory the internal oscillator is 25MHz but it really isn't + // that precise. You can 'calibrate' by tweaking this number till + // you get the frequency you're expecting! + pwm.setOscillatorFrequency(27000000); // The int.osc. is closer to 27MHz + pwm.setPWMFreq(SERVO_FREQ); // Analog servos run at ~60 Hz updates delay(10); } @@ -57,7 +60,7 @@ void setServoPulse(uint8_t n, double pulse) { double pulselength; pulselength = 1000000; // 1,000,000 us per second - pulselength /= FREQ; // Analog servos run at ~60 Hz updates + pulselength /= SERVO_FREQ; // Analog servos run at ~60 Hz updates Serial.print(pulselength); Serial.println(" us per period"); pulselength /= 4096; // 12 bits of resolution Serial.print(pulselength); Serial.println(" us per bit"); @@ -94,6 +97,6 @@ void loop() { delay(500); - servonum ++; + servonum++; if (servonum > 7) servonum = 0; // Testing the first 8 servo channels -} +} \ No newline at end of file From 71164df4bc6b27efd6e25a745f78d8cc7ecf7b8b Mon Sep 17 00:00:00 2001 From: Lady Ada Date: Sun, 3 Nov 2019 13:23:57 -0500 Subject: [PATCH 07/11] add caching and clang --- .travis.yml | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 20276cd..0511636 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,19 +1,31 @@ language: c sudo: false - -# Blacklist -branches: - except: - - gh-pages +cache: + directories: + - ~/arduino_ide + - ~/.arduino15/packages/ +git: + depth: false + quiet: true env: global: - PRETTYNAME="Adafruit PCA9685 PWM Servo Driver Arduino Library" +addons: + apt: + sources: + - llvm-toolchain-trusty-5.0 + - key_url: 'http://apt.llvm.org/llvm-snapshot.gpg.key' + packages: + - clang-format-5.0 + before_install: - source <(curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/install.sh) + - curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/run-clang-format.py > run-clang-format.py script: + - python run-clang-format.py -r . - build_main_platforms # Generate and deploy documentation From dd088c46ca046e9ad4123a1705002b3871ce9358 Mon Sep 17 00:00:00 2001 From: Lady Ada Date: Sun, 3 Nov 2019 13:37:06 -0500 Subject: [PATCH 08/11] clang --- Adafruit_PWMServoDriver.cpp | 106 +++++++++++++++++++++--------------- Adafruit_PWMServoDriver.h | 92 +++++++++++++++++-------------- 2 files changed, 113 insertions(+), 85 deletions(-) diff --git a/Adafruit_PWMServoDriver.cpp b/Adafruit_PWMServoDriver.cpp index eacbc08..e972fdf 100755 --- a/Adafruit_PWMServoDriver.cpp +++ b/Adafruit_PWMServoDriver.cpp @@ -36,18 +36,16 @@ * @brief Instantiates a new PCA9685 PWM driver chip with the I2C address on a * TwoWire interface */ -Adafruit_PWMServoDriver::Adafruit_PWMServoDriver(): - _i2caddr(PCA9685_I2C_ADDRESS), _i2c(&Wire) { -} +Adafruit_PWMServoDriver::Adafruit_PWMServoDriver() + : _i2caddr(PCA9685_I2C_ADDRESS), _i2c(&Wire) {} /*! * @brief Instantiates a new PCA9685 PWM driver chip with the I2C address on a * TwoWire interface * @param addr The 7-bit I2C address to locate this chip, default is 0x40 */ -Adafruit_PWMServoDriver::Adafruit_PWMServoDriver(const uint8_t addr): - _i2caddr(addr), _i2c(&Wire) { -} +Adafruit_PWMServoDriver::Adafruit_PWMServoDriver(const uint8_t addr) + : _i2caddr(addr), _i2c(&Wire) {} /*! * @brief Instantiates a new PCA9685 PWM driver chip with the I2C address on a @@ -56,9 +54,9 @@ Adafruit_PWMServoDriver::Adafruit_PWMServoDriver(const uint8_t addr): * @param i2c A reference to a 'TwoWire' object that we'll use to communicate * with */ -Adafruit_PWMServoDriver::Adafruit_PWMServoDriver(const uint8_t addr, TwoWire& i2c) : - _i2caddr(addr), _i2c(&i2c) { -} +Adafruit_PWMServoDriver::Adafruit_PWMServoDriver(const uint8_t addr, + TwoWire &i2c) + : _i2caddr(addr), _i2c(&i2c) {} /*! * @brief Setups the I2C interface and hardware @@ -141,14 +139,17 @@ void Adafruit_PWMServoDriver::setPWMFreq(float freq) { Serial.println(freq); #endif // Range output modulation frequency is dependant on oscillator - if (freq < 1) freq = 1; - if (freq > 3500) freq = 3500; // Datasheet limit is 3052=50MHz/(4*4096) - + if (freq < 1) + freq = 1; + if (freq > 3500) + freq = 3500; // Datasheet limit is 3052=50MHz/(4*4096) float prescaleval = ((_oscillator_freq / (freq * 4096.0)) + 0.5) - 1; - if (prescaleval < PCA9685_PRESCALE_MIN) prescaleval = PCA9685_PRESCALE_MIN; - if (prescaleval > PCA9685_PRESCALE_MAX) prescaleval = PCA9685_PRESCALE_MAX; - uint8_t prescale = (uint8_t) prescaleval; + if (prescaleval < PCA9685_PRESCALE_MIN) + prescaleval = PCA9685_PRESCALE_MIN; + if (prescaleval > PCA9685_PRESCALE_MAX) + prescaleval = PCA9685_PRESCALE_MAX; + uint8_t prescale = (uint8_t)prescaleval; #ifdef ENABLE_DEBUG_OUTPUT Serial.print("Final pre-scale: "); @@ -157,12 +158,12 @@ void Adafruit_PWMServoDriver::setPWMFreq(float freq) { uint8_t oldmode = read8(PCA9685_MODE1); uint8_t newmode = (oldmode & ~MODE1_RESTART) | MODE1_SLEEP; // sleep - write8(PCA9685_MODE1, newmode); // go to sleep - write8(PCA9685_PRESCALE, prescale); // set the prescaler + write8(PCA9685_MODE1, newmode); // go to sleep + write8(PCA9685_PRESCALE, prescale); // set the prescaler write8(PCA9685_MODE1, oldmode); delay(5); // This sets the MODE1 register to turn on auto increment. - write8(PCA9685_MODE1, oldmode | MODE1_RESTART | MODE1_AI); + write8(PCA9685_MODE1, oldmode | MODE1_RESTART | MODE1_AI); #ifdef ENABLE_DEBUG_OUTPUT Serial.print("Mode now 0x"); @@ -171,22 +172,21 @@ void Adafruit_PWMServoDriver::setPWMFreq(float freq) { } /*! - * @brief Sets the output mode of the PCA9685 to either - * open drain or push pull / totempole. + * @brief Sets the output mode of the PCA9685 to either + * open drain or push pull / totempole. * Warning: LEDs with integrated zener diodes should - * only be driven in open drain mode. - * @param totempole Totempole if true, open drain if false. + * only be driven in open drain mode. + * @param totempole Totempole if true, open drain if false. */ -void Adafruit_PWMServoDriver::setOutputMode(bool totempole) { - uint8_t oldmode = read8(PCA9685_MODE2); +void Adafruit_PWMServoDriver::setOutputMode(bool totempole) { + uint8_t oldmode = read8(PCA9685_MODE2); uint8_t newmode; if (totempole) { newmode = oldmode | MODE2_OUTDRV; - } - else { + } else { newmode = oldmode & ~MODE2_OUTDRV; } - write8(PCA9685_MODE2, newmode); + write8(PCA9685_MODE2, newmode); #ifdef ENABLE_DEBUG_OUTPUT Serial.print("Setting output mode: "); Serial.print(totempole ? "totempole" : "open drain"); @@ -199,8 +199,7 @@ void Adafruit_PWMServoDriver::setOutputMode(bool totempole) { * @brief Reads set Prescale from PCA9685 * @return prescale value */ -uint8_t Adafruit_PWMServoDriver::readPrescale(void) -{ +uint8_t Adafruit_PWMServoDriver::readPrescale(void) { return read8(PCA9685_PRESCALE); } @@ -276,52 +275,69 @@ void Adafruit_PWMServoDriver::setPin(uint8_t num, uint16_t val, bool invert) { } /*! - * @brief Sets the PWM output of one of the PCA9685 pins based on the input microseconds, output is not precise + * @brief Sets the PWM output of one of the PCA9685 pins based on the input + * microseconds, output is not precise * @param num One of the PWM output pins, from 0 to 15 * @param Microseconds The number of Microseconds to turn the PWM output ON */ -void Adafruit_PWMServoDriver::writeMicroseconds(uint8_t num, uint16_t Microseconds) { - #ifdef ENABLE_DEBUG_OUTPUT +void Adafruit_PWMServoDriver::writeMicroseconds(uint8_t num, + uint16_t Microseconds) { +#ifdef ENABLE_DEBUG_OUTPUT Serial.print("Setting PWM Via Microseconds on output"); Serial.print(num); Serial.print(": "); Serial.print(Microseconds); Serial.println("->"); - #endif +#endif double pulse = Microseconds; double pulselength; - pulselength = 1000000; // 1,000,000 us per second + pulselength = 1000000; // 1,000,000 us per second // Read prescale uint16_t prescale = Adafruit_PWMServoDriver::readPrescale(); - #ifdef ENABLE_DEBUG_OUTPUT - Serial.print(prescale); Serial.println(" PCA9685 chip prescale"); - #endif +#ifdef ENABLE_DEBUG_OUTPUT + Serial.print(prescale); + Serial.println(" PCA9685 chip prescale"); +#endif - // Calculate the pulse for PWM based on Equation 1 from the datasheet section 7.3.5 + // Calculate the pulse for PWM based on Equation 1 from the datasheet section + // 7.3.5 prescale += 1; - pulselength *= prescale; + pulselength *= prescale; pulselength /= _oscillator_freq; - #ifdef ENABLE_DEBUG_OUTPUT - Serial.print(pulselength); Serial.println(" us per bit"); - #endif +#ifdef ENABLE_DEBUG_OUTPUT + Serial.print(pulselength); + Serial.println(" us per bit"); +#endif pulse /= pulselength; - #ifdef ENABLE_DEBUG_OUTPUT - Serial.print(pulse);Serial.println(" pulse for PWM"); - #endif +#ifdef ENABLE_DEBUG_OUTPUT + Serial.print(pulse); + Serial.println(" pulse for PWM"); +#endif Adafruit_PWMServoDriver::setPWM(num, 0, pulse); } +/*! + * @brief Getter for the internally tracked oscillator used for freq + * calculations + * @returns The frequency the PCA9685 thinks it is running at (it cannot + * introspect) + */ uint32_t Adafruit_PWMServoDriver::getOscillatorFrequency(void) { return _oscillator_freq; } +/*! + * @brief Setter for the internally tracked oscillator used for freq + * calculations + * @param freq The frequency the PCA9685 should use for frequency calculations + */ void Adafruit_PWMServoDriver::setOscillatorFrequency(uint32_t freq) { _oscillator_freq = freq; } diff --git a/Adafruit_PWMServoDriver.h b/Adafruit_PWMServoDriver.h index cb88119..2e48fae 100644 --- a/Adafruit_PWMServoDriver.h +++ b/Adafruit_PWMServoDriver.h @@ -3,7 +3,8 @@ * * This is a library for our Adafruit 16-channel PWM & Servo driver. * - * Designed specifically to work with the Adafruit 16-channel PWM & Servo driver. + * Designed specifically to work with the Adafruit 16-channel PWM & Servo + * driver. * * Pick one up today in the adafruit shop! * ------> https://www.adafruit.com/product/815 @@ -26,54 +27,65 @@ #include // REGISTER ADDRESSES -#define PCA9685_MODE1 0x00 /**< Mode Register 1 */ -#define PCA9685_MODE2 0x01 /**< Mode Register 2 */ -#define PCA9685_SUBADR1 0x02 /**< I2C-bus subaddress 1 */ -#define PCA9685_SUBADR2 0x03 /**< I2C-bus subaddress 2 */ -#define PCA9685_SUBADR3 0x04 /**< I2C-bus subaddress 3 */ -#define PCA9685_ALLCALLADR 0x05 /**< LED All Call I2C-bus address */ -#define PCA9685_LED0_ON_L 0x06 /**< LED0 output and brightness control byte 0 */ -#define PCA9685_LED0_ON_H 0x07 /**< LED0 output and brightness control byte 1 */ -#define PCA9685_LED0_OFF_L 0x08 /**< LED0 output and brightness control byte 2 */ -#define PCA9685_LED0_OFF_H 0x09 /**< LED0 output and brightness control byte 3 */ +#define PCA9685_MODE1 0x00 /**< Mode Register 1 */ +#define PCA9685_MODE2 0x01 /**< Mode Register 2 */ +#define PCA9685_SUBADR1 0x02 /**< I2C-bus subaddress 1 */ +#define PCA9685_SUBADR2 0x03 /**< I2C-bus subaddress 2 */ +#define PCA9685_SUBADR3 0x04 /**< I2C-bus subaddress 3 */ +#define PCA9685_ALLCALLADR 0x05 /**< LED All Call I2C-bus address */ +#define PCA9685_LED0_ON_L 0x06 /**< LED0 output and brightness control byte 0 \ + */ +#define PCA9685_LED0_ON_H 0x07 /**< LED0 output and brightness control byte 1 \ + */ +#define PCA9685_LED0_OFF_L \ + 0x08 /**< LED0 output and brightness control byte 2 */ +#define PCA9685_LED0_OFF_H \ + 0x09 /**< LED0 output and brightness control byte 3 */ // etc all 16: LED15_OFF_H 0x45 -#define PCA9685_ALLLED_ON_L 0xFA /**< load all the LEDn_ON registers, byte 0 */ -#define PCA9685_ALLLED_ON_H 0xFB /**< load all the LEDn_ON registers, byte 1 */ -#define PCA9685_ALLLED_OFF_L 0xFC /**< load all the LEDn_OFF registers, byte 0 */ -#define PCA9685_ALLLED_OFF_H 0xFD /**< load all the LEDn_OFF registers, byte 1 */ -#define PCA9685_PRESCALE 0xFE /**< Prescaler for PWM output frequency */ -#define PCA9685_TESTMODE 0xFF /**< defines the test mode to be entered */ +#define PCA9685_ALLLED_ON_L 0xFA /**< load all the LEDn_ON registers, byte 0 \ + */ +#define PCA9685_ALLLED_ON_H 0xFB /**< load all the LEDn_ON registers, byte 1 \ + */ +#define PCA9685_ALLLED_OFF_L \ + 0xFC /**< load all the LEDn_OFF registers, byte 0 */ +#define PCA9685_ALLLED_OFF_H \ + 0xFD /**< load all the LEDn_OFF registers, byte 1 */ +#define PCA9685_PRESCALE 0xFE /**< Prescaler for PWM output frequency */ +#define PCA9685_TESTMODE 0xFF /**< defines the test mode to be entered */ // MODE1 bits -#define MODE1_ALLCAL 0x01 /**< respond to LED All Call I2C-bus address */ -#define MODE1_SUB3 0x02 /**< respond to I2C-bus subaddress 3 */ -#define MODE1_SUB2 0x04 /**< respond to I2C-bus subaddress 2 */ -#define MODE1_SUB1 0x08 /**< respond to I2C-bus subaddress 1 */ -#define MODE1_SLEEP 0x10 /**< Low power mode. Oscillator off */ -#define MODE1_AI 0x20 /**< Auto-Increment enabled */ -#define MODE1_EXTCLK 0x40 /**< Use EXTCLK pin clock */ -#define MODE1_RESTART 0x80 /**< Restart enabled */ +#define MODE1_ALLCAL 0x01 /**< respond to LED All Call I2C-bus address */ +#define MODE1_SUB3 0x02 /**< respond to I2C-bus subaddress 3 */ +#define MODE1_SUB2 0x04 /**< respond to I2C-bus subaddress 2 */ +#define MODE1_SUB1 0x08 /**< respond to I2C-bus subaddress 1 */ +#define MODE1_SLEEP 0x10 /**< Low power mode. Oscillator off */ +#define MODE1_AI 0x20 /**< Auto-Increment enabled */ +#define MODE1_EXTCLK 0x40 /**< Use EXTCLK pin clock */ +#define MODE1_RESTART 0x80 /**< Restart enabled */ // MODE2 bits -#define MODE2_OUTNE_0 0x01 /**< Active LOW output enable input */ -#define MODE2_OUTNE_1 0x02 /**< Active LOW output enable input - high impedience */ -#define MODE2_OUTDRV 0x04 /**< totem pole structure vs open-drain */ -#define MODE2_OCH 0x08 /**< Outputs change on ACK vs STOP */ -#define MODE2_INVRT 0x10 /**< Output logic state inverted */ +#define MODE2_OUTNE_0 0x01 /**< Active LOW output enable input */ +#define MODE2_OUTNE_1 \ + 0x02 /**< Active LOW output enable input - high impedience */ +#define MODE2_OUTDRV 0x04 /**< totem pole structure vs open-drain */ +#define MODE2_OCH 0x08 /**< Outputs change on ACK vs STOP */ +#define MODE2_INVRT 0x10 /**< Output logic state inverted */ -#define PCA9685_I2C_ADDRESS 0x40 /**< Default PCA9685 I2C Slave Address */ -#define FREQUENCY_OSCILLATOR 25000000 /**< Oscillator frequency in datasheet */ +#define PCA9685_I2C_ADDRESS 0x40 /**< Default PCA9685 I2C Slave Address */ +#define FREQUENCY_OSCILLATOR 25000000 /**< Oscillator frequency in datasheet \ + */ -#define PCA9685_PRESCALE_MIN 3 /**< minimum prescale value */ +#define PCA9685_PRESCALE_MIN 3 /**< minimum prescale value */ #define PCA9685_PRESCALE_MAX 255 /**< maximum prescale value */ -/*! - * @brief Class that stores state and functions for interacting with PCA9685 PWM chip +/*! + * @brief Class that stores state and functions for interacting with PCA9685 + * PWM chip */ class Adafruit_PWMServoDriver { - public: +public: Adafruit_PWMServoDriver(); Adafruit_PWMServoDriver(const uint8_t addr); - Adafruit_PWMServoDriver(const uint8_t addr, TwoWire& i2c); + Adafruit_PWMServoDriver(const uint8_t addr, TwoWire &i2c); void begin(uint8_t prescale = 0); void reset(); void sleep(); @@ -83,16 +95,16 @@ class Adafruit_PWMServoDriver { void setOutputMode(bool totempole); uint8_t getPWM(uint8_t num); void setPWM(uint8_t num, uint16_t on, uint16_t off); - void setPin(uint8_t num, uint16_t val, bool invert=false); + void setPin(uint8_t num, uint16_t val, bool invert = false); uint8_t readPrescale(void); void writeMicroseconds(uint8_t num, uint16_t Microseconds); void setOscillatorFrequency(uint32_t freq); uint32_t getOscillatorFrequency(void); - private: +private: uint8_t _i2caddr; - TwoWire* _i2c; + TwoWire *_i2c; uint32_t _oscillator_freq; uint8_t read8(uint8_t addr); From 60c00ea06d1534a6dab4a68ea914db5a8aa8e3a5 Mon Sep 17 00:00:00 2001 From: Lady Ada Date: Sun, 3 Nov 2019 13:45:18 -0500 Subject: [PATCH 09/11] handclang --- Adafruit_PWMServoDriver.h | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/Adafruit_PWMServoDriver.h b/Adafruit_PWMServoDriver.h index 2e48fae..e5f7354 100644 --- a/Adafruit_PWMServoDriver.h +++ b/Adafruit_PWMServoDriver.h @@ -33,23 +33,15 @@ #define PCA9685_SUBADR2 0x03 /**< I2C-bus subaddress 2 */ #define PCA9685_SUBADR3 0x04 /**< I2C-bus subaddress 3 */ #define PCA9685_ALLCALLADR 0x05 /**< LED All Call I2C-bus address */ -#define PCA9685_LED0_ON_L 0x06 /**< LED0 output and brightness control byte 0 \ - */ -#define PCA9685_LED0_ON_H 0x07 /**< LED0 output and brightness control byte 1 \ - */ -#define PCA9685_LED0_OFF_L \ - 0x08 /**< LED0 output and brightness control byte 2 */ -#define PCA9685_LED0_OFF_H \ - 0x09 /**< LED0 output and brightness control byte 3 */ +#define PCA9685_LED0_ON_L 0x06 /**< LED0 output & brightness control byte 0 */ +#define PCA9685_LED0_ON_H 0x07 /**< LED0 output & brightness control byte 1 */ +#define PCA9685_LED0_OFF_L 0x08 /**< LED0 output & brightness control byte 2 */ +#define PCA9685_LED0_OFF_H 0x09 /**< LED0 output & brightness control byte 3 */ // etc all 16: LED15_OFF_H 0x45 -#define PCA9685_ALLLED_ON_L 0xFA /**< load all the LEDn_ON registers, byte 0 \ - */ -#define PCA9685_ALLLED_ON_H 0xFB /**< load all the LEDn_ON registers, byte 1 \ - */ -#define PCA9685_ALLLED_OFF_L \ - 0xFC /**< load all the LEDn_OFF registers, byte 0 */ -#define PCA9685_ALLLED_OFF_H \ - 0xFD /**< load all the LEDn_OFF registers, byte 1 */ +#define PCA9685_ALLLED_ON_L 0xFA /**< load all the LEDn_ON registers, low */ +#define PCA9685_ALLLED_ON_H 0xFB /**< load all the LEDn_ON registers, high */ +#define PCA9685_ALLLED_OFF_L 0xFC /**< load all the LEDn_OFF registers, low */ +#define PCA9685_ALLLED_OFF_H 0xFD /**< load all the LEDn_OFF registers, high */ #define PCA9685_PRESCALE 0xFE /**< Prescaler for PWM output frequency */ #define PCA9685_TESTMODE 0xFF /**< defines the test mode to be entered */ @@ -71,8 +63,7 @@ #define MODE2_INVRT 0x10 /**< Output logic state inverted */ #define PCA9685_I2C_ADDRESS 0x40 /**< Default PCA9685 I2C Slave Address */ -#define FREQUENCY_OSCILLATOR 25000000 /**< Oscillator frequency in datasheet \ - */ +#define FREQUENCY_OSCILLATOR 25000000 /**< Int. osc. frequency in datasheet */ #define PCA9685_PRESCALE_MIN 3 /**< minimum prescale value */ #define PCA9685_PRESCALE_MAX 255 /**< maximum prescale value */ From dea0ea7d373e6a89f25780ac03e45331eec120d5 Mon Sep 17 00:00:00 2001 From: Lady Ada Date: Sun, 3 Nov 2019 13:50:29 -0500 Subject: [PATCH 10/11] moreclang --- Adafruit_PWMServoDriver.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Adafruit_PWMServoDriver.h b/Adafruit_PWMServoDriver.h index e5f7354..3605e7a 100644 --- a/Adafruit_PWMServoDriver.h +++ b/Adafruit_PWMServoDriver.h @@ -33,15 +33,15 @@ #define PCA9685_SUBADR2 0x03 /**< I2C-bus subaddress 2 */ #define PCA9685_SUBADR3 0x04 /**< I2C-bus subaddress 3 */ #define PCA9685_ALLCALLADR 0x05 /**< LED All Call I2C-bus address */ -#define PCA9685_LED0_ON_L 0x06 /**< LED0 output & brightness control byte 0 */ -#define PCA9685_LED0_ON_H 0x07 /**< LED0 output & brightness control byte 1 */ -#define PCA9685_LED0_OFF_L 0x08 /**< LED0 output & brightness control byte 2 */ -#define PCA9685_LED0_OFF_H 0x09 /**< LED0 output & brightness control byte 3 */ +#define PCA9685_LED0_ON_L 0x06 /**< LED0 on tick, low byte*/ +#define PCA9685_LED0_ON_H 0x07 /**< LED0 on tick, high byte*/ +#define PCA9685_LED0_OFF_L 0x08 /**< LED0 off tick, low byte */ +#define PCA9685_LED0_OFF_H 0x09 /**< LED0 off tick, high byte */ // etc all 16: LED15_OFF_H 0x45 -#define PCA9685_ALLLED_ON_L 0xFA /**< load all the LEDn_ON registers, low */ -#define PCA9685_ALLLED_ON_H 0xFB /**< load all the LEDn_ON registers, high */ +#define PCA9685_ALLLED_ON_L 0xFA /**< load all the LEDn_ON registers, low */ +#define PCA9685_ALLLED_ON_H 0xFB /**< load all the LEDn_ON registers, high */ #define PCA9685_ALLLED_OFF_L 0xFC /**< load all the LEDn_OFF registers, low */ -#define PCA9685_ALLLED_OFF_H 0xFD /**< load all the LEDn_OFF registers, high */ +#define PCA9685_ALLLED_OFF_H 0xFD /**< load all the LEDn_OFF registers,high */ #define PCA9685_PRESCALE 0xFE /**< Prescaler for PWM output frequency */ #define PCA9685_TESTMODE 0xFF /**< defines the test mode to be entered */ From 16705a539bfe829ad518f6f69ffcbb3a1c087181 Mon Sep 17 00:00:00 2001 From: Lady Ada Date: Sun, 3 Nov 2019 13:55:22 -0500 Subject: [PATCH 11/11] clang2 --- Adafruit_PWMServoDriver.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Adafruit_PWMServoDriver.h b/Adafruit_PWMServoDriver.h index 3605e7a..e0857d8 100644 --- a/Adafruit_PWMServoDriver.h +++ b/Adafruit_PWMServoDriver.h @@ -42,8 +42,8 @@ #define PCA9685_ALLLED_ON_H 0xFB /**< load all the LEDn_ON registers, high */ #define PCA9685_ALLLED_OFF_L 0xFC /**< load all the LEDn_OFF registers, low */ #define PCA9685_ALLLED_OFF_H 0xFD /**< load all the LEDn_OFF registers,high */ -#define PCA9685_PRESCALE 0xFE /**< Prescaler for PWM output frequency */ -#define PCA9685_TESTMODE 0xFF /**< defines the test mode to be entered */ +#define PCA9685_PRESCALE 0xFE /**< Prescaler for PWM output frequency */ +#define PCA9685_TESTMODE 0xFF /**< defines the test mode to be entered */ // MODE1 bits #define MODE1_ALLCAL 0x01 /**< respond to LED All Call I2C-bus address */