Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactored setting prescale, add setPrescale #65

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 25 additions & 20 deletions Adafruit_PWMServoDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,29 +104,41 @@ void Adafruit_PWMServoDriver::wakeup() {
}

/*!
* @brief Sets EXTCLK pin to use the external clock
* @brief Sets prescaler for PWM output frequency
* @param prescale
* Configures the prescale value to be used by the external clock
* Defines the frequency at which the outputs modulate
* @param extclk
* Sets EXTCLK pin to use the external clock
*/
void Adafruit_PWMServoDriver::setExtClk(uint8_t prescale) {
uint8_t oldmode = read8(PCA9685_MODE1);
uint8_t newmode = (oldmode & ~MODE1_RESTART) | MODE1_SLEEP; // sleep
write8(PCA9685_MODE1, newmode); // go to sleep, turn off internal oscillator
void Adafruit_PWMServoDriver::setPrescale(uint8_t prescale, bool extclk) {
if (prescale < PCA9685_PRESCALE_MIN)
return;
// if (prescale > PCA9685_PRESCALE_MAX) return;

uint8_t newmode1 = read8(PCA9685_MODE1);
newmode1 = (newmode1 & ~MODE1_RESTART) | MODE1_SLEEP; // sleep
write8(PCA9685_MODE1, newmode1); // go to sleep, turn off internal oscillator

// This sets both the SLEEP and EXTCLK bits of the MODE1 register to switch to
// use the external clock.
write8(PCA9685_MODE1, (newmode |= MODE1_EXTCLK));
if (extclk) {
write8(PCA9685_MODE1, (newmode1 |= MODE1_EXTCLK));
}

write8(PCA9685_PRESCALE, prescale); // set the prescaler

delay(5);
// clear the SLEEP bit to start
write8(PCA9685_MODE1, (newmode & ~MODE1_SLEEP) | MODE1_RESTART | MODE1_AI);
write8(PCA9685_MODE1, (newmode1 & ~MODE1_SLEEP) | MODE1_RESTART | MODE1_AI);
}

#ifdef ENABLE_DEBUG_OUTPUT
Serial.print("Mode now 0x");
Serial.println(read8(PCA9685_MODE1), HEX);
#endif
/*!
* @brief Sets EXTCLK pin to use the external clock
* @param prescale
* Configures the prescale value to be used by the external clock
*/
void Adafruit_PWMServoDriver::setExtClk(uint8_t prescale) {
setPrescale(prescale, true);
}

/*!
Expand Down Expand Up @@ -156,14 +168,7 @@ void Adafruit_PWMServoDriver::setPWMFreq(float freq) {
Serial.println(prescale);
#endif

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, oldmode);
delay(5);
// This sets the MODE1 register to turn on auto increment.
write8(PCA9685_MODE1, oldmode | MODE1_RESTART | MODE1_AI);
setPrescale(prescale);

#ifdef ENABLE_DEBUG_OUTPUT
Serial.print("Mode now 0x");
Expand Down
1 change: 1 addition & 0 deletions Adafruit_PWMServoDriver.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ class Adafruit_PWMServoDriver {
void reset();
void sleep();
void wakeup();
void setPrescale(uint8_t prescale, bool extclk = false);
void setExtClk(uint8_t prescale);
void setPWMFreq(float freq);
void setOutputMode(bool totempole);
Expand Down
2 changes: 2 additions & 0 deletions examples/pwmtest/pwmtest.ino
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ void setup() {
// 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
// or as alternative set the prescale manual: freq = oscillator-Hz / 4096*(prescale+1)
// pwm.setPrescale(0x1e); // PCA9685 sets itself default to 0x1e, approx 200Hz

// if you want to really speed stuff up, you can go into 'fast 400khz I2C' mode
// some i2c devices dont like this so much so if you're sharing the bus, watch
Expand Down
1 change: 1 addition & 0 deletions keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ begin KEYWORD2
reset KEYWORD2
sleep KEYWORD2
wakeup KEYWORD2
setPrescale KEYWORD2
setExtClk KEYWORD2
setPWMFreq KEYWORD2
setOutputMode KEYWORD2
Expand Down