|
1 |
| -/*************************************************** |
2 |
| - This is a library for our Adafruit 16-channel PWM & Servo driver |
3 |
| -
|
4 |
| - Pick one up today in the adafruit shop! |
5 |
| - ------> http://www.adafruit.com/products/815 |
6 |
| -
|
7 |
| - These displays use I2C to communicate, 2 pins are required to |
8 |
| - interface. |
9 |
| -
|
10 |
| - Adafruit invests time and resources providing this open source code, |
11 |
| - please support Adafruit and open-source hardware by purchasing |
12 |
| - products from Adafruit! |
13 |
| -
|
14 |
| - Written by Limor Fried/Ladyada for Adafruit Industries. |
15 |
| - BSD license, all text above must be included in any redistribution |
16 |
| - ****************************************************/ |
| 1 | +/*! |
| 2 | + * @file Adafruit_PWMServoDriver.cpp |
| 3 | + * |
| 4 | + * @mainpage Adafruit 16-channel PWM & Servo driver |
| 5 | + * |
| 6 | + * @section intro_sec Introduction |
| 7 | + * |
| 8 | + * This is a library for the 16-channel PWM & Servo driver. |
| 9 | + * |
| 10 | + * Designed specifically to work with the Adafruit PWM & Servo driver. |
| 11 | + * |
| 12 | + * Pick one up today in the adafruit shop! |
| 13 | + * ------> https://www.adafruit.com/product/815 |
| 14 | + * |
| 15 | + * These displays use I2C to communicate, 2 pins are required to interface. |
| 16 | + * |
| 17 | + * Adafruit invests time and resources providing this open source code, |
| 18 | + * please support Adafruit andopen-source hardware by purchasing products |
| 19 | + * from Adafruit! |
| 20 | + * |
| 21 | + * @section author Author |
| 22 | + * |
| 23 | + * Limor Fried/Ladyada (Adafruit Industries). |
| 24 | + * |
| 25 | + * @section license License |
| 26 | + * |
| 27 | + * BSD license, all text above must be included in any redistribution |
| 28 | + */ |
17 | 29 |
|
18 | 30 | #include "Adafruit_PWMServoDriver.h"
|
19 | 31 | #include <Wire.h>
|
20 | 32 |
|
21 |
| -// Set to true to print some debug messages, or false to disable them. |
22 |
| -//#define ENABLE_DEBUG_OUTPUT |
23 |
| - |
24 |
| - |
25 |
| -/**************************************************************************/ |
26 |
| -/*! |
27 |
| - @brief Instantiates a new PCA9685 PWM driver chip with the I2C address on the Wire interface. On Due we use Wire1 since its the interface on the 'default' I2C pins. |
28 |
| - @param addr The 7-bit I2C address to locate this chip, default is 0x40 |
29 |
| -*/ |
30 |
| -/**************************************************************************/ |
31 |
| -Adafruit_PWMServoDriver::Adafruit_PWMServoDriver(uint8_t addr) { |
32 |
| - _i2caddr = addr; |
33 |
| - |
34 |
| -#if defined(ARDUINO_SAM_DUE) |
35 |
| - _i2c = &Wire1; |
36 |
| -#else |
37 |
| - _i2c = &Wire; |
38 |
| -#endif |
39 |
| -} |
40 |
| - |
41 |
| -/**************************************************************************/ |
42 |
| -/*! |
43 |
| - @brief Instantiates a new PCA9685 PWM driver chip with the I2C address on a TwoWire interface |
44 |
| - @param i2c A pointer to a 'Wire' compatible object that we'll use to communicate with |
45 |
| - @param addr The 7-bit I2C address to locate this chip, default is 0x40 |
46 |
| -*/ |
47 |
| -/**************************************************************************/ |
| 33 | +/*! |
| 34 | + * @brief Instantiates a new PCA9685 PWM driver chip with the I2C address on a |
| 35 | + * TwoWire interface |
| 36 | + * @param i2c A pointer to a 'Wire' compatible object that we'll use to |
| 37 | + * communicate with |
| 38 | + * @param addr The 7-bit I2C address to locate this chip, default is 0x40 |
| 39 | + */ |
48 | 40 | Adafruit_PWMServoDriver::Adafruit_PWMServoDriver(TwoWire *i2c, uint8_t addr) {
|
49 | 41 | _i2c = i2c;
|
50 | 42 | _i2caddr = addr;
|
51 | 43 | }
|
52 | 44 |
|
53 |
| -/**************************************************************************/ |
54 |
| -/*! |
55 |
| - @brief Setups the I2C interface and hardware |
56 |
| -*/ |
57 |
| -/**************************************************************************/ |
| 45 | +/*! |
| 46 | + * @brief Setups the I2C interface and hardware |
| 47 | + */ |
58 | 48 | void Adafruit_PWMServoDriver::begin(void) {
|
59 | 49 | _i2c->begin();
|
60 | 50 | reset();
|
61 | 51 | // set a default frequency
|
62 | 52 | setPWMFreq(1000);
|
63 | 53 | }
|
64 | 54 |
|
65 |
| - |
66 |
| -/**************************************************************************/ |
67 |
| -/*! |
68 |
| - @brief Sends a reset command to the PCA9685 chip over I2C |
69 |
| -*/ |
70 |
| -/**************************************************************************/ |
| 55 | +/*! |
| 56 | + * @brief Sends a reset command to the PCA9685 chip over I2C |
| 57 | + */ |
71 | 58 | void Adafruit_PWMServoDriver::reset(void) {
|
72 | 59 | write8(PCA9685_MODE1, 0x80);
|
73 | 60 | delay(10);
|
74 | 61 | }
|
75 | 62 |
|
76 |
| -/**************************************************************************/ |
77 |
| -/*! |
78 |
| - @brief Sets the PWM frequency for the entire chip, up to ~1.6 KHz |
79 |
| - @param freq Floating point frequency that we will attempt to match |
80 |
| -*/ |
81 |
| -/**************************************************************************/ |
| 63 | +/*! |
| 64 | + * @brief Sets the PWM frequency for the entire chip, up to ~1.6 KHz |
| 65 | + * @param freq Floating point frequency that we will attempt to match |
| 66 | + */ |
82 | 67 | void Adafruit_PWMServoDriver::setPWMFreq(float freq) {
|
83 | 68 | #ifdef ENABLE_DEBUG_OUTPUT
|
84 | 69 | Serial.print("Attempting to set freq ");
|
85 | 70 | Serial.println(freq);
|
86 | 71 | #endif
|
87 | 72 |
|
88 |
| - freq *= 0.9; // Correct for overshoot in the frequency setting (see issue #11). |
| 73 | + freq *= |
| 74 | + 0.9; // Correct for overshoot in the frequency setting (see issue #11). |
89 | 75 | float prescaleval = 25000000;
|
90 | 76 | prescaleval /= 4096;
|
91 | 77 | prescaleval /= freq;
|
92 | 78 | prescaleval -= 1;
|
93 | 79 |
|
94 | 80 | #ifdef ENABLE_DEBUG_OUTPUT
|
95 |
| - Serial.print("Estimated pre-scale: "); Serial.println(prescaleval); |
| 81 | + Serial.print("Estimated pre-scale: "); |
| 82 | + Serial.println(prescaleval); |
96 | 83 | #endif
|
97 | 84 |
|
98 | 85 | uint8_t prescale = floor(prescaleval + 0.5);
|
99 | 86 | #ifdef ENABLE_DEBUG_OUTPUT
|
100 |
| - Serial.print("Final pre-scale: "); Serial.println(prescale); |
| 87 | + Serial.print("Final pre-scale: "); |
| 88 | + Serial.println(prescale); |
101 | 89 | #endif
|
102 |
| - |
| 90 | + |
103 | 91 | uint8_t oldmode = read8(PCA9685_MODE1);
|
104 |
| - uint8_t newmode = (oldmode&0x7F) | 0x10; // sleep |
105 |
| - write8(PCA9685_MODE1, newmode); // go to sleep |
106 |
| - write8(PCA9685_PRESCALE, prescale); // set the prescaler |
| 92 | + uint8_t newmode = (oldmode & 0x7F) | 0x10; // sleep |
| 93 | + write8(PCA9685_MODE1, newmode); // go to sleep |
| 94 | + write8(PCA9685_PRESCALE, prescale); // set the prescaler |
107 | 95 | write8(PCA9685_MODE1, oldmode);
|
108 | 96 | delay(5);
|
109 |
| - write8(PCA9685_MODE1, oldmode | 0xa0); // This sets the MODE1 register to turn on auto increment. |
| 97 | + write8(PCA9685_MODE1, |
| 98 | + oldmode | |
| 99 | + 0xa0); // This sets the MODE1 register to turn on auto increment. |
110 | 100 |
|
111 | 101 | #ifdef ENABLE_DEBUG_OUTPUT
|
112 |
| - Serial.print("Mode now 0x"); Serial.println(read8(PCA9685_MODE1), HEX); |
| 102 | + Serial.print("Mode now 0x"); |
| 103 | + Serial.println(read8(PCA9685_MODE1), HEX); |
113 | 104 | #endif
|
114 | 105 | }
|
115 | 106 |
|
116 |
| -/**************************************************************************/ |
117 |
| -/*! |
118 |
| - @brief Sets the PWM output of one of the PCA9685 pins |
119 |
| - @param num One of the PWM output pins, from 0 to 15 |
120 |
| - @param on At what point in the 4096-part cycle to turn the PWM output ON |
121 |
| - @param off At what point in the 4096-part cycle to turn the PWM output OFF |
122 |
| -*/ |
123 |
| -/**************************************************************************/ |
| 107 | +/*! |
| 108 | + * @brief Sets the PWM output of one of the PCA9685 pins |
| 109 | + * @param num One of the PWM output pins, from 0 to 15 |
| 110 | + * @param on At what point in the 4096-part cycle to turn the PWM output ON |
| 111 | + * @param off At what point in the 4096-part cycle to turn the PWM output OFF |
| 112 | + */ |
124 | 113 | void Adafruit_PWMServoDriver::setPWM(uint8_t num, uint16_t on, uint16_t off) {
|
125 | 114 | #ifdef ENABLE_DEBUG_OUTPUT
|
126 |
| - Serial.print("Setting PWM "); Serial.print(num); Serial.print(": "); Serial.print(on); Serial.print("->"); Serial.println(off); |
| 115 | + Serial.print("Setting PWM "); |
| 116 | + Serial.print(num); |
| 117 | + Serial.print(": "); |
| 118 | + Serial.print(on); |
| 119 | + Serial.print("->"); |
| 120 | + Serial.println(off); |
127 | 121 | #endif
|
128 | 122 |
|
129 | 123 | _i2c->beginTransmission(_i2caddr);
|
130 |
| - _i2c->write(LED0_ON_L+4*num); |
| 124 | + _i2c->write(LED0_ON_L + 4 * num); |
131 | 125 | _i2c->write(on);
|
132 |
| - _i2c->write(on>>8); |
| 126 | + _i2c->write(on >> 8); |
133 | 127 | _i2c->write(off);
|
134 |
| - _i2c->write(off>>8); |
| 128 | + _i2c->write(off >> 8); |
135 | 129 | _i2c->endTransmission();
|
136 | 130 | }
|
137 | 131 |
|
138 |
| -/**************************************************************************/ |
139 |
| -/*! |
140 |
| - @brief Helper to set pin PWM output. Sets pin without having to deal with on/off tick placement and properly handles a zero value as completely off and 4095 as completely on. Optional invert parameter supports inverting the pulse for sinking to ground. |
141 |
| - @param num One of the PWM output pins, from 0 to 15 |
142 |
| - @param val The number of ticks out of 4096 to be active, should be a value from 0 to 4095 inclusive. |
143 |
| - @param invert If true, inverts the output, defaults to 'false' |
144 |
| -*/ |
145 |
| -/**************************************************************************/ |
146 |
| -void Adafruit_PWMServoDriver::setPin(uint8_t num, uint16_t val, bool invert) |
147 |
| -{ |
| 132 | +/*! |
| 133 | + * @brief Helper to set pin PWM output. Sets pin without having to deal with |
| 134 | + * on/off tick placement and properly handles a zero value as completely off and |
| 135 | + * 4095 as completely on. Optional invert parameter supports inverting the |
| 136 | + * pulse for sinking to ground. |
| 137 | + * @param num One of the PWM output pins, from 0 to 15 |
| 138 | + * @param val The number of ticks out of 4096 to be active, should be a value |
| 139 | + * from 0 to 4095 inclusive. |
| 140 | + * @param invert If true, inverts the output, defaults to 'false' |
| 141 | + */ |
| 142 | +void Adafruit_PWMServoDriver::setPin(uint8_t num, uint16_t val, bool invert) { |
148 | 143 | // Clamp value between 0 and 4095 inclusive.
|
149 | 144 | val = min(val, (uint16_t)4095);
|
150 | 145 | if (invert) {
|
151 | 146 | if (val == 0) {
|
152 | 147 | // Special value for signal fully on.
|
153 | 148 | setPWM(num, 4096, 0);
|
154 |
| - } |
155 |
| - else if (val == 4095) { |
| 149 | + } else if (val == 4095) { |
156 | 150 | // Special value for signal fully off.
|
157 | 151 | setPWM(num, 0, 4096);
|
| 152 | + } else { |
| 153 | + setPWM(num, 0, 4095 - val); |
158 | 154 | }
|
159 |
| - else { |
160 |
| - setPWM(num, 0, 4095-val); |
161 |
| - } |
162 |
| - } |
163 |
| - else { |
| 155 | + } else { |
164 | 156 | if (val == 4095) {
|
165 | 157 | // Special value for signal fully on.
|
166 | 158 | setPWM(num, 4096, 0);
|
167 |
| - } |
168 |
| - else if (val == 0) { |
| 159 | + } else if (val == 0) { |
169 | 160 | // Special value for signal fully off.
|
170 | 161 | setPWM(num, 0, 4096);
|
171 |
| - } |
172 |
| - else { |
| 162 | + } else { |
173 | 163 | setPWM(num, 0, val);
|
174 | 164 | }
|
175 | 165 | }
|
176 | 166 | }
|
177 | 167 |
|
178 |
| -/*******************************************************************************************/ |
179 |
| - |
180 | 168 | uint8_t Adafruit_PWMServoDriver::read8(uint8_t addr) {
|
181 | 169 | _i2c->beginTransmission(_i2caddr);
|
182 | 170 | _i2c->write(addr);
|
|
0 commit comments