Skip to content

Commit fa51b6f

Browse files
authored
Merge pull request #46 from hoffmannjan/master
sleep wake + EXTCLK
2 parents b2cabf0 + f8545f2 commit fa51b6f

File tree

2 files changed

+74
-6
lines changed

2 files changed

+74
-6
lines changed

Adafruit_PWMServoDriver.cpp

Lines changed: 68 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,22 +44,76 @@ Adafruit_PWMServoDriver::Adafruit_PWMServoDriver(TwoWire *i2c, uint8_t addr) {
4444

4545
/*!
4646
* @brief Setups the I2C interface and hardware
47+
* @param prescale
48+
* Sets External Clock (Optional)
49+
*
4750
*/
48-
void Adafruit_PWMServoDriver::begin(void) {
51+
void Adafruit_PWMServoDriver::begin(uint8_t prescale) {
4952
_i2c->begin();
5053
reset();
51-
// set a default frequency
52-
setPWMFreq(1000);
54+
if (prescale) {
55+
setExtClk(prescale);
56+
} else {
57+
// set a default frequency
58+
setPWMFreq(1000);
59+
}
5360
}
5461

5562
/*!
5663
* @brief Sends a reset command to the PCA9685 chip over I2C
5764
*/
58-
void Adafruit_PWMServoDriver::reset(void) {
65+
void Adafruit_PWMServoDriver::reset() {
5966
write8(PCA9685_MODE1, 0x80);
6067
delay(10);
6168
}
6269

70+
/*!
71+
* @brief Puts board into sleep mode
72+
*/
73+
void Adafruit_PWMServoDriver::sleep() {
74+
uint8_t awake = read8(PCA9685_MODE1);
75+
uint8_t sleep = awake | 0x10; // set sleep bit high
76+
write8(PCA9685_MODE1, sleep);
77+
delay(5); // wait until cycle ends for sleep to be active
78+
}
79+
80+
/*!
81+
* @brief Wakes board from sleep
82+
*/
83+
void Adafruit_PWMServoDriver::wakeup() {
84+
uint8_t sleep = read8(PCA9685_MODE1);
85+
uint8_t wakeup = sleep & ~0x10; // set sleep bit low
86+
write8(PCA9685_MODE1, wakeup);
87+
}
88+
89+
/**************************************************************************/
90+
/*!
91+
@brief Sets EXTCLK pin to use the external clock
92+
@param prescale Configures the prescale value to be used by the external
93+
clock
94+
*/
95+
/**************************************************************************/
96+
void Adafruit_PWMServoDriver::setExtClk(uint8_t prescale) {
97+
uint8_t oldmode = read8(PCA9685_MODE1);
98+
uint8_t newmode = (oldmode & 0x7F) | 0x10; // sleep
99+
write8(PCA9685_MODE1, newmode); // go to sleep, turn off internal oscillator
100+
101+
// This sets both the SLEEP and EXTCLK bits of the MODE1 register to switch to
102+
// use the external clock.
103+
write8(PCA9685_MODE1, (newmode |= 0x40));
104+
105+
write8(PCA9685_PRESCALE, prescale); // set the prescaler
106+
107+
delay(5);
108+
write8(PCA9685_MODE1,
109+
(newmode & ~(0x10)) | 0xa0); // clear the SLEEP bit to start
110+
111+
#ifdef ENABLE_DEBUG_OUTPUT
112+
Serial.print("Mode now 0x");
113+
Serial.println(read8(PCA9685_MODE1), HEX);
114+
#endif
115+
}
116+
63117
/*!
64118
* @brief Sets the PWM frequency for the entire chip, up to ~1.6 KHz
65119
* @param freq Floating point frequency that we will attempt to match
@@ -104,6 +158,16 @@ void Adafruit_PWMServoDriver::setPWMFreq(float freq) {
104158
#endif
105159
}
106160

161+
/*!
162+
* @brief Gets the PWM output of one of the PCA9685 pins
163+
* @param num One of the PWM output pins, from 0 to 15
164+
* @return requested PWM output value
165+
*/
166+
uint8_t Adafruit_PWMServoDriver::getPWM(uint8_t num) {
167+
_i2c->requestFrom((uint8_t)_i2caddr, LED0_ON_L + 4 * num, (uint8_t)4);
168+
return _i2c->read();
169+
}
170+
107171
/*!
108172
* @brief Sets the PWM output of one of the PCA9685 pins
109173
* @param num One of the PWM output pins, from 0 to 15

Adafruit_PWMServoDriver.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,13 @@
4949
class Adafruit_PWMServoDriver {
5050
public:
5151
Adafruit_PWMServoDriver(TwoWire *I2C = &Wire, uint8_t addr = 0x40);
52-
void begin(void);
53-
void reset(void);
52+
void begin(uint8_t prescale = 0);
53+
void reset();
54+
void sleep();
55+
void wakeup();
56+
void setExtClk(uint8_t prescale);
5457
void setPWMFreq(float freq);
58+
uint8_t getPWM(uint8_t num);
5559
void setPWM(uint8_t num, uint16_t on, uint16_t off);
5660
void setPin(uint8_t num, uint16_t val, bool invert=false);
5761

0 commit comments

Comments
 (0)