Skip to content

Commit afbdf1f

Browse files
committed
Handle out-of-range/overflow in prescale calculation.
1 parent 9dd0d3c commit afbdf1f

File tree

2 files changed

+24
-10
lines changed

2 files changed

+24
-10
lines changed

Adafruit_PWMServoDriver.cpp

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -120,19 +120,23 @@ void Adafruit_PWMServoDriver::setPWMFreq(float freq) {
120120
Serial.print("Attempting to set freq ");
121121
Serial.println(freq);
122122
#endif
123-
124-
freq *= 0.9; // Correct for overshoot in the frequency setting (see issue #11).
125-
float prescaleval = 25000000;
123+
// Range output modulation frequency is dependant on oscillator
124+
if (freq < 1) freq = 1;
125+
if (freq > 3500) freq = 3500; // Datasheet limit is 3052=50MHz/(4*4096)
126+
/*
127+
freq *= 0.9; // Correct for overshoot in the frequency setting (see issue #11)
128+
float prescaleval = FREQUENCY_OSCILLATOR;
129+
*/
130+
uint32_t prescaleval = FREQUENCY_CALIBRATED;
131+
prescaleval /= freq; // required output modulation frequency
132+
// rounding to nearest number is equal to adding 0,5 and floor to nearest number
133+
prescaleval += 2048;
126134
prescaleval /= 4096;
127-
prescaleval /= freq;
128135
prescaleval -= 1;
136+
if (prescaleval < PCA9685_PRESCALE_MIN) prescaleval = PCA9685_PRESCALE_MIN;
137+
if (prescaleval > PCA9685_PRESCALE_MAX) prescaleval = PCA9685_PRESCALE_MAX;
138+
uint8_t prescale = (uint8_t) prescaleval;
129139

130-
#ifdef ENABLE_DEBUG_OUTPUT
131-
Serial.print("Estimated pre-scale: ");
132-
Serial.println(prescaleval);
133-
#endif
134-
135-
uint8_t prescale = floor(prescaleval + 0.5);
136140
#ifdef ENABLE_DEBUG_OUTPUT
137141
Serial.print("Final pre-scale: ");
138142
Serial.println(prescale);
@@ -178,6 +182,15 @@ void Adafruit_PWMServoDriver::setOutputMode(bool totempole) {
178182
#endif
179183
}
180184

185+
/*!
186+
* @brief Reads set Prescale from PCA9685
187+
* @param void
188+
*/
189+
uint8_t Adafruit_PWMServoDriver::readPrescale(void)
190+
{
191+
return read8(PCA9685_PRESCALE);
192+
}
193+
181194
/*!
182195
* @brief Gets the PWM output of one of the PCA9685 pins
183196
* @param num One of the PWM output pins, from 0 to 15

Adafruit_PWMServoDriver.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ class Adafruit_PWMServoDriver {
8686
uint8_t getPWM(uint8_t num);
8787
void setPWM(uint8_t num, uint16_t on, uint16_t off);
8888
void setPin(uint8_t num, uint16_t val, bool invert=false);
89+
uint8_t readPrescale(void);
8990

9091
private:
9192
uint8_t _i2caddr;

0 commit comments

Comments
 (0)