### Multi-Channel Wave PWM Pattern Source: https://context7.com/adafruit/adafruit-pwm-servo-driver-library/llms.txt Drives all 16 PWM channels in a phase-shifted wave pattern, creating a rolling effect. This example utilizes `Wire.setClock(400000)` for fast I2C communication and sets a high PWM frequency for smooth animation. The `yield()` function is necessary on ESP8266 to prevent watchdog resets. ```cpp #include #include Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(); void setup() { pwm.begin(); pwm.setOscillatorFrequency(27000000); pwm.setPWMFreq(1600); // Maximum ~1600 Hz frequency Wire.setClock(400000); // 400 kHz fast I2C for maximum update speed } void loop() { for (uint16_t i = 0; i < 4096; i += 8) { for (uint8_t ch = 0; ch < 16; ch++) { pwm.setPWM(ch, 0, (i + (4096 / 16) * ch) % 4096); } #ifdef ESP8266 yield(); // Required on ESP8266 to prevent watchdog reset #endif } } ``` -------------------------------- ### Control Servo Pulse Width and Digital Output States Source: https://context7.com/adafruit/adafruit-pwm-servo-driver-library/llms.txt Sets the PWM signal for a specific channel by defining the ON and OFF tick timings within a 4096-step cycle. Use 4096 for ON to force HIGH, and 4096 for OFF to force LOW. This example sweeps a servo and demonstrates digital HIGH/LOW output. ```cpp #include #include Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(); #define SERVO_FREQ 50 #define SERVOMIN 150 // Min pulse length (out of 4096) #define SERVOMAX 600 // Max pulse length (out of 4096) void setup() { pwm.begin(); pwm.setOscillatorFrequency(27000000); pwm.setPWMFreq(SERVO_FREQ); delay(10); } void loop() { // Sweep channel 0 servo from min to max position for (uint16_t pulselen = SERVOMIN; pulselen < SERVOMAX; pulselen++) { pwm.setPWM(0, 0, pulselen); // on=0 (start of cycle), off=pulselen } delay(500); // Sweep back max to min for (uint16_t pulselen = SERVOMAX; pulselen > SERVOMIN; pulselen--) { pwm.setPWM(0, 0, pulselen); } delay(500); // Force channel 1 fully ON (digital HIGH) pwm.setPWM(1, 4096, 0); delay(200); // Force channel 1 fully OFF (digital LOW) pwm.setPWM(1, 0, 4096); delay(200); } ``` -------------------------------- ### `begin(uint8_t prescale = 0)` — Initialize the Driver Source: https://context7.com/adafruit/adafruit-pwm-servo-driver-library/llms.txt Sets up the I2C interface, resets the chip, and configures a default PWM frequency of 1000 Hz. Returns `true` on success, `false` if the chip is not detected. Optionally accepts a raw prescale byte to configure an external clock source instead. ```APIDOC ## `begin(uint8_t prescale = 0)` — Initialize the Driver Sets up the I2C interface, resets the chip, and configures a default PWM frequency of 1000 Hz. Returns `true` on success, `false` if the chip is not detected. Optionally accepts a raw prescale byte to configure an external clock source instead. ```cpp void setup() { Serial.begin(9600); Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(); if (!pwm.begin()) { Serial.println("PCA9685 not found — check wiring!"); while (1); // Halt } Serial.println("PCA9685 initialized."); // Default PWM frequency is now 1000 Hz } ``` ``` -------------------------------- ### Initialize PCA9685 Driver and Check Connection Source: https://context7.com/adafruit/adafruit-pwm-servo-driver-library/llms.txt Initializes the I2C interface, resets the chip, and sets a default PWM frequency of 1000 Hz. Returns true on success, false if the chip is not detected. Halt execution if the chip is not found. ```cpp void setup() { Serial.begin(9600); Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(); if (!pwm.begin()) { Serial.println("PCA9685 not found — check wiring!"); while (1); // Halt } Serial.println("PCA9685 initialized."); // Default PWM frequency is now 1000 Hz } ``` -------------------------------- ### Instantiate Driver with Default I2C Address (0x40) Source: https://context7.com/adafruit/adafruit-pwm-servo-driver-library/llms.txt Use this constructor when the PCA9685 board is at its default I2C address (0x40) and connected to the default Wire I2C interface. ```cpp #include #include // Default address 0x40 on Wire Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(); ``` -------------------------------- ### Power Management with sleep() and wakeup() Source: https://context7.com/adafruit/adafruit-pwm-servo-driver-library/llms.txt Enter low-power sleep mode with sleep() and resume normal operation with wakeup(). Useful for battery-powered projects to conserve energy when PWM outputs are not needed. ```cpp #include #include Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(); void setup() { pwm.begin(); pwm.setPWMFreq(50); pwm.setPWM(0, 0, 375); // Center servo on channel 0 delay(1000); pwm.sleep(); // Enter low-power mode delay(5000); // Sleep for 5 seconds pwm.wakeup(); // Resume normal operation pwm.setPWM(0, 0, 150); // Move servo to new position } void loop() {} ``` -------------------------------- ### Simplified PWM Output with setPin() Source: https://context7.com/adafruit/adafruit-pwm-servo-driver-library/llms.txt Use setPin() for simplified PWM control with duty cycle values from 0 to 4095. Optionally invert the output for sinking current applications. ```cpp #include #include Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(); void setup() { pwm.begin(); pwm.setPWMFreq(1000); // 1 kHz for LED dimming } void loop() { // Fade LED on channel 0 from off to full brightness for (uint16_t brightness = 0; brightness <= 4095; brightness += 16) { pwm.setPin(0, brightness); // Normal (source current) pwm.setPin(1, brightness, true); // Inverted (sink current) delay(5); } // Fully on / fully off pwm.setPin(2, 4095); // Full ON delay(500); pwm.setPin(2, 0); // Full OFF delay(500); } ``` -------------------------------- ### Constructor — Default I2C Address (0x40) Source: https://context7.com/adafruit/adafruit-pwm-servo-driver-library/llms.txt Instantiates a driver object using the default PCA9685 I2C address (0x40) and the default Wire I2C interface. ```APIDOC ## Constructor — Default I2C Address (0x40) Instantiates a driver object using the default PCA9685 I2C address (0x40) and the default `Wire` I2C interface. ```cpp #include #include // Default address 0x40 on Wire Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(); ``` ``` -------------------------------- ### reset() Source: https://context7.com/adafruit/adafruit-pwm-servo-driver-library/llms.txt Sends a software reset command to the PCA9685 over I2C, returning all registers to their power-on default state and stopping all PWM outputs. ```APIDOC ## `reset()` — Software Reset Sends a software reset command to the PCA9685 over I2C, returning all registers to their power-on default state and stopping all PWM outputs. ### Request Example ```cpp #include #include Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(); void setup() { pwm.begin(); pwm.setPWM(0, 0, 500); delay(1000); pwm.reset(); // All outputs go to default (off); re-initialize as needed pwm.setPWMFreq(50); } ``` ``` -------------------------------- ### Constructor — Custom Address and I2C Bus Source: https://context7.com/adafruit/adafruit-pwm-servo-driver-library/llms.txt Instantiates a driver with an explicit address and a specific `TwoWire` bus instance, enabling use on platforms with multiple hardware I2C peripherals (e.g., `Wire1`). ```APIDOC ## Constructor — Custom Address and I2C Bus Instantiates a driver with an explicit address and a specific `TwoWire` bus instance, enabling use on platforms with multiple hardware I2C peripherals (e.g., `Wire1`). ```cpp #include #include // Use Wire1 (second I2C bus) with address 0x40 Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x40, Wire1); void setup() { Wire1.begin(); pwm.begin(); } ``` ``` -------------------------------- ### Configuring Output Driver with setOutputMode() Source: https://context7.com/adafruit/adafruit-pwm-servo-driver-library/llms.txt Set the output driver type for all channels using setOutputMode(). Use true for totem-pole (push-pull) and false for open-drain, especially for LEDs with integrated Zener diodes. ```cpp #include #include Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(); void setup() { pwm.begin(); pwm.setOutputMode(true); // Totem-pole (push-pull) for servos/MOSFETs // pwm.setOutputMode(false); // Open-drain for Zener LED drivers pwm.setPWMFreq(50); } ``` -------------------------------- ### Instantiate Driver with Custom Address and I2C Bus Source: https://context7.com/adafruit/adafruit-pwm-servo-driver-library/llms.txt Instantiate the driver with a specific I2C address and a custom TwoWire bus instance. This is useful for platforms with multiple hardware I2C peripherals, such as Wire1. ```cpp #include #include // Use Wire1 (second I2C bus) with address 0x40 Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x40, Wire1); void setup() { Wire1.begin(); pwm.begin(); } ``` -------------------------------- ### Instantiate Driver with Custom I2C Address Source: https://context7.com/adafruit/adafruit-pwm-servo-driver-library/llms.txt Instantiate the driver with a custom 7-bit I2C address. This is useful when multiple PCA9685 boards are connected to the same I2C bus. ```cpp #include #include // Board with A0 jumper soldered → address 0x41 Adafruit_PWMServoDriver pwm1 = Adafruit_PWMServoDriver(0x41); // Board with A1 jumper soldered → address 0x42 Adafruit_PWMServoDriver pwm2 = Adafruit_PWMServoDriver(0x42); ``` -------------------------------- ### setOutputMode(bool totempole) Source: https://context7.com/adafruit/adafruit-pwm-servo-driver-library/llms.txt Configures the output driver structure for all channels. Pass `true` for totem-pole (push-pull) drive — appropriate for most loads. Pass `false` for open-drain mode — required for LEDs that have integrated Zener diodes to avoid damage. ```APIDOC ## `setOutputMode(bool totempole)` — Set Output Driver Type Configures the output driver structure for all channels. Pass `true` for totem-pole (push-pull) drive — appropriate for most loads. Pass `false` for open-drain mode — required for LEDs that have integrated Zener diodes to avoid damage. ### Parameters #### Path Parameters - **totempole** (bool) - If true, sets totem-pole (push-pull) mode. If false, sets open-drain mode. ### Request Example ```cpp #include #include Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(); void setup() { pwm.begin(); pwm.setOutputMode(true); // Totem-pole (push-pull) for servos/MOSFETs // pwm.setOutputMode(false); // Open-drain for Zener LED drivers pwm.setPWMFreq(50); } ``` ``` -------------------------------- ### Software Reset with reset() Source: https://context7.com/adafruit/adafruit-pwm-servo-driver-library/llms.txt Perform a software reset of the PCA9685 chip using reset(). This returns all registers to their default state and stops all PWM outputs. Re-initialize as needed. ```cpp #include #include Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(); void setup() { pwm.begin(); pwm.setPWM(0, 0, 500); delay(1000); pwm.reset(); // All outputs go to default (off); re-initialize as needed pwm.setPWMFreq(50); } ``` -------------------------------- ### setPin(uint8_t num, uint16_t val, bool invert = false) Source: https://context7.com/adafruit/adafruit-pwm-servo-driver-library/llms.txt A convenience wrapper around `setPWM()` that accepts a single duty-cycle value from 0 (fully off) to 4095 (fully on), eliminating the need to manually manage on/off tick placement. Optionally inverts the output signal for sinking applications. ```APIDOC ## `setPin(uint8_t num, uint16_t val, bool invert = false)` — Simplified PWM Output A convenience wrapper around `setPWM()` that accepts a single duty-cycle value from 0 (fully off) to 4095 (fully on), eliminating the need to manually manage on/off tick placement. Optionally inverts the output signal for sinking applications. ### Parameters #### Path Parameters - **num** (uint8_t) - The pin number to set. - **val** (uint16_t) - The duty-cycle value from 0 to 4095. - **invert** (bool) - Optional. If true, inverts the output signal. Defaults to false. ### Request Example ```cpp #include #include Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(); void setup() { pwm.begin(); pwm.setPWMFreq(1000); // 1 kHz for LED dimming } void loop() { // Fade LED on channel 0 from off to full brightness for (uint16_t brightness = 0; brightness <= 4095; brightness += 16) { pwm.setPin(0, brightness); // Normal (source current) pwm.setPin(1, brightness, true); // Inverted (sink current) delay(5); } // Fully on / fully off pwm.setPin(2, 4095); // Full ON delay(500); pwm.setPin(2, 0); // Full OFF delay(500); } ``` ``` -------------------------------- ### Constructor — Custom I2C Address Source: https://context7.com/adafruit/adafruit-pwm-servo-driver-library/llms.txt Instantiates a driver object with a user-specified 7-bit I2C address, useful when multiple PCA9685 boards share the same bus. ```APIDOC ## Constructor — Custom I2C Address Instantiates a driver object with a user-specified 7-bit I2C address, useful when multiple PCA9685 boards share the same bus. ```cpp #include #include // Board with A0 jumper soldered → address 0x41 Adafruit_PWMServoDriver pwm1 = Adafruit_PWMServoDriver(0x41); // Board with A1 jumper soldered → address 0x42 Adafruit_PWMServoDriver pwm2 = Adafruit_PWMServoDriver(0x42); ``` ``` -------------------------------- ### Use External Clock with setExtClk() Source: https://context7.com/adafruit/adafruit-pwm-servo-driver-library/llms.txt Switches the PCA9685 to use an external clock signal applied to the EXTCLK pin. This is useful for achieving higher frequency precision than the internal oscillator allows. Ensure the external clock is connected before initializing the device. ```cpp #include #include Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(); void setup() { // Provide external clock on EXTCLK pin before calling begin() // prescale=0 in begin() means use default internal; pass nonzero to setExtClk pwm.begin(); // Initialize with internal clock first pwm.setExtClk(121); // Switch to external clock, prescale=121 → ~50 Hz at 25 MHz ext clock } ``` -------------------------------- ### Servo Control with writeMicroseconds() Source: https://context7.com/adafruit/adafruit-pwm-servo-driver-library/llms.txt Control servos by setting pulse width in microseconds using writeMicroseconds(). Standard range is 600-2400 µs. Ensure oscillator calibration for accuracy. ```cpp #include #include Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(); #define USMIN 600 // ~0° / full reverse #define USMAX 2400 // ~180° / full forward #define SERVO_FREQ 50 void setup() { pwm.begin(); pwm.setOscillatorFrequency(27000000); // Calibrated value pwm.setPWMFreq(SERVO_FREQ); delay(10); } void loop() { // Sweep channels 0–7 using microsecond control for (uint8_t servo = 0; servo < 8; servo++) { for (uint16_t us = USMIN; us <= USMAX; us++) { pwm.writeMicroseconds(servo, us); } delay(300); for (uint16_t us = USMAX; us >= USMIN; us--) { pwm.writeMicroseconds(servo, us); } delay(300); } } ``` -------------------------------- ### writeMicroseconds(uint8_t num, uint16_t Microseconds) Source: https://context7.com/adafruit/adafruit-pwm-servo-driver-library/llms.txt Sets the PWM pulse width for a channel in microseconds, mimicking the Arduino `Servo` library's `writeMicroseconds()` API. Standard servo range is approximately 600 µs (full reverse/min) to 2400 µs (full forward/max), with 1500 µs as neutral. Accuracy depends on correct oscillator calibration. ```APIDOC ## `writeMicroseconds(uint8_t num, uint16_t Microseconds)` — Servo Pulse in Microseconds Sets the PWM pulse width for a channel in microseconds, mimicking the Arduino `Servo` library's `writeMicroseconds()` API. Standard servo range is approximately 600 µs (full reverse/min) to 2400 µs (full forward/max), with 1500 µs as neutral. Accuracy depends on correct oscillator calibration. ### Parameters #### Path Parameters - **num** (uint8_t) - The channel number for the servo. - **Microseconds** (uint16_t) - The pulse width in microseconds. ### Request Example ```cpp #include #include Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(); #define USMIN 600 // ~0° / full reverse #define USMAX 2400 // ~180° / full forward #define SERVO_FREQ 50 void setup() { pwm.begin(); pwm.setOscillatorFrequency(27000000); // Calibrated value pwm.setPWMFreq(SERVO_FREQ); delay(10); } void loop() { // Sweep channels 0–7 using microsecond control for (uint8_t servo = 0; servo < 8; servo++) { for (uint16_t us = USMIN; us <= USMAX; us++) { pwm.writeMicroseconds(servo, us); } delay(300); for (uint16_t us = USMAX; us >= USMIN; us--) { pwm.writeMicroseconds(servo, us); } delay(300); } } ``` ``` -------------------------------- ### Calibrate Oscillator Frequency with setOscillatorFrequency() Source: https://context7.com/adafruit/adafruit-pwm-servo-driver-library/llms.txt Sets the internally tracked oscillator frequency for accurate PWM output. Measure your board's oscillator with an oscilloscope for best results. This calibration is crucial for `setPWMFreq()` and `writeMicroseconds()`. ```cpp #include #include Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(); void setup() { Serial.begin(9600); pwm.begin(); // Set calibrated oscillator value (measured with oscilloscope on your board) pwm.setOscillatorFrequency(27000000); // 27 MHz for this specific chip uint32_t freq = pwm.getOscillatorFrequency(); Serial.print("Oscillator frequency set to: "); Serial.print(freq); Serial.println(" Hz"); // Output: Oscillator frequency set to: 27000000 Hz pwm.setPWMFreq(50); // Now accurately targets 50 Hz for servos } ``` -------------------------------- ### Use External Clock Source: setExtClk Source: https://context7.com/adafruit/adafruit-pwm-servo-driver-library/llms.txt Switches the PCA9685 to use an external clock signal applied to the EXTCLK pin and sets the prescaler. This is useful for applications requiring precise frequency control beyond the internal oscillator's accuracy. ```APIDOC ## `setExtClk(uint8_t prescale)` — Use External Clock Source Switches the PCA9685 from its internal oscillator to an external clock signal applied to the EXTCLK pin, then sets the prescaler. Use this when precise frequency control is needed beyond the internal oscillator's accuracy. ```cpp #include #include Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(); void setup() { // Provide external clock on EXTCLK pin before calling begin() // prescale=0 in begin() means use default internal; pass nonzero to setExtClk pwm.begin(); // Initialize with internal clock first pwm.setExtClk(121); // Switch to external clock, prescale=121 → ~50 Hz at 25 MHz ext clock } ``` ``` -------------------------------- ### sleep() and wakeup() Source: https://context7.com/adafruit/adafruit-pwm-servo-driver-library/llms.txt Puts the PCA9685 into low-power sleep mode (oscillator off, all outputs frozen) or wakes it back to normal operation. Useful for battery-powered projects where the PWM outputs are not continuously needed. ```APIDOC ## `sleep()` and `wakeup()` — Power Management Puts the PCA9685 into low-power sleep mode (oscillator off, all outputs frozen) or wakes it back to normal operation. Useful for battery-powered projects where the PWM outputs are not continuously needed. ### Request Example ```cpp #include #include Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(); void setup() { pwm.begin(); pwm.setPWMFreq(50); pwm.setPWM(0, 0, 375); // Center servo on channel 0 delay(1000); pwm.sleep(); // Enter low-power mode delay(5000); // Sleep for 5 seconds pwm.wakeup(); // Resume normal operation pwm.setPWM(0, 0, 150); // Move servo to new position } void loop() {} ``` ``` -------------------------------- ### Read Prescale Register with readPrescale() Source: https://context7.com/adafruit/adafruit-pwm-servo-driver-library/llms.txt Retrieves the raw prescale byte from the PCA9685. This value, along with the oscillator frequency, determines the output PWM frequency using the formula: `freq = osc_clock / (4096 × (prescale + 1))`. Expected values depend on the target frequency and oscillator calibration. ```cpp #include #include Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(); void setup() { Serial.begin(9600); pwm.begin(); pwm.setOscillatorFrequency(25000000); // Default 25 MHz pwm.setPWMFreq(50); uint8_t prescale = pwm.readPrescale(); Serial.print("Prescale value: "); Serial.println(prescale); // Expected ~121 for 50 Hz with 25 MHz oscillator // Real freq = 25000000 / (4096 * (121 + 1)) ≈ 50.1 Hz } ``` -------------------------------- ### getPWM(uint8_t num, bool off = false) Source: https://context7.com/adafruit/adafruit-pwm-servo-driver-library/llms.txt Reads back the current PWM ON tick (default) or OFF tick from the chip's register for a specified channel. Useful for verifying the state of a channel without maintaining a shadow variable in firmware. ```APIDOC ## `getPWM(uint8_t num, bool off = false)` — Read PWM Register Value Reads back the current PWM ON tick (default) or OFF tick from the chip's register for a specified channel. Useful for verifying the state of a channel without maintaining a shadow variable in firmware. ### Parameters #### Path Parameters - **num** (uint8_t) - The channel number to read from. - **off** (bool) - If true, reads the OFF tick; otherwise, reads the ON tick. Defaults to false. ### Response #### Success Response (200) - **uint16_t** - The value of the ON or OFF tick register. ### Request Example ```cpp #include #include Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(); void setup() { Serial.begin(9600); pwm.begin(); pwm.setPWMFreq(50); // Write a known value to channel 3 pwm.setPWM(3, 0, 300); // Read it back uint16_t onVal = pwm.getPWM(3, false); // ON tick uint16_t offVal = pwm.getPWM(3, true); // OFF tick Serial.print("Channel 3 ON tick: "); Serial.println(onVal); // Expected: 0 Serial.print("Channel 3 OFF tick: "); Serial.println(offVal); // Expected: 300 } void loop() {} ``` ``` -------------------------------- ### Reading PWM Register Values with getPWM() Source: https://context7.com/adafruit/adafruit-pwm-servo-driver-library/llms.txt Read the current ON or OFF tick values from the chip's PWM register using getPWM(). Useful for verifying channel states without firmware shadow variables. ```cpp #include #include Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(); void setup() { Serial.begin(9600); pwm.begin(); pwm.setPWMFreq(50); // Write a known value to channel 3 pwm.setPWM(3, 0, 300); // Read it back uint16_t onVal = pwm.getPWM(3, false); // ON tick uint16_t offVal = pwm.getPWM(3, true); // OFF tick Serial.print("Channel 3 ON tick: "); Serial.println(onVal); // Expected: 0 Serial.print("Channel 3 OFF tick: "); Serial.println(offVal); // Expected: 300 } void loop() {} ``` -------------------------------- ### Set Global PWM Frequency for Servos or LEDs Source: https://context7.com/adafruit/adafruit-pwm-servo-driver-library/llms.txt Sets the PWM update frequency for all 16 channels. Use 50 Hz for standard analog servos or up to ~1600 Hz for LEDs. Ensure the oscillator frequency is calibrated for precision. ```cpp #include #include Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(); void setup() { pwm.begin(); pwm.setOscillatorFrequency(27000000); // Calibrated oscillator (see oscillator example) pwm.setPWMFreq(50); // 50 Hz for standard analog servos // pwm.setPWMFreq(1600); // Max ~1600 Hz for LEDs / fast switching } ``` -------------------------------- ### `setPWM(uint8_t num, uint16_t on, uint16_t off)` — Set Raw PWM On/Off Ticks Source: https://context7.com/adafruit/adafruit-pwm-servo-driver-library/llms.txt Sets the PWM signal for a single channel by specifying the exact 12-bit tick (0–4095) within the 4096-step cycle at which the output turns ON and OFF. Use `4096` as `on` to force a pin fully HIGH, and `4096` as `off` to force it fully LOW. Returns `0` on success, `1` on I2C failure. ```APIDOC ## `setPWM(uint8_t num, uint16_t on, uint16_t off)` — Set Raw PWM On/Off Ticks Sets the PWM signal for a single channel by specifying the exact 12-bit tick (0–4095) within the 4096-step cycle at which the output turns ON and OFF. Use `4096` as `on` to force a pin fully HIGH, and `4096` as `off` to force it fully LOW. Returns `0` on success, `1` on I2C failure. ```cpp #include #include Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(); #define SERVO_FREQ 50 #define SERVOMIN 150 // Min pulse length (out of 4096) #define SERVOMAX 600 // Max pulse length (out of 4096) void setup() { pwm.begin(); pwm.setOscillatorFrequency(27000000); pwm.setPWMFreq(SERVO_FREQ); delay(10); } void loop() { // Sweep channel 0 servo from min to max position for (uint16_t pulselen = SERVOMIN; pulselen < SERVOMAX; pulselen++) { pwm.setPWM(0, 0, pulselen); // on=0 (start of cycle), off=pulselen } delay(500); // Sweep back max to min for (uint16_t pulselen = SERVOMAX; pulselen > SERVOMIN; pulselen--) { pwm.setPWM(0, 0, pulselen); } delay(500); // Force channel 1 fully ON (digital HIGH) pwm.setPWM(1, 4096, 0); delay(200); // Force channel 1 fully OFF (digital LOW) pwm.setPWM(1, 0, 4096); delay(200); } ``` ``` -------------------------------- ### Oscillator Calibration: setOscillatorFrequency and getOscillatorFrequency Source: https://context7.com/adafruit/adafruit-pwm-servo-driver-library/llms.txt Calibrates the PCA9685's internal oscillator frequency for accurate PWM output. `setOscillatorFrequency` sets the tracked frequency, and `getOscillatorFrequency` retrieves it. ```APIDOC ## `setOscillatorFrequency(uint32_t freq)` and `getOscillatorFrequency()` — Oscillator Calibration Sets (or reads) the internally tracked oscillator frequency used to calculate PWM prescaler values. The PCA9685's internal oscillator nominally runs at 25 MHz but varies between ~23–27 MHz per unit. Calibrating this value ensures accurate output frequencies for `setPWMFreq()` and `writeMicroseconds()`. ```cpp #include #include Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(); void setup() { Serial.begin(9600); pwm.begin(); // Set calibrated oscillator value (measured with oscilloscope on your board) pwm.setOscillatorFrequency(27000000); // 27 MHz for this specific chip uint32_t freq = pwm.getOscillatorFrequency(); Serial.print("Oscillator frequency set to: "); Serial.print(freq); Serial.println(" Hz"); // Output: Oscillator frequency set to: 27000000 Hz pwm.setPWMFreq(50); // Now accurately targets 50 Hz for servos } ``` ``` -------------------------------- ### `setPWMFreq(float freq)` — Set Global PWM Frequency Source: https://context7.com/adafruit/adafruit-pwm-servo-driver-library/llms.txt Sets the PWM update frequency for all 16 channels simultaneously. Valid range is 1 Hz to ~1600 Hz (limited by chip prescaler). Analog servos typically require 50 Hz; LEDs can use 1000 Hz or higher. ```APIDOC ## `setPWMFreq(float freq)` — Set Global PWM Frequency Sets the PWM update frequency for all 16 channels simultaneously. Valid range is 1 Hz to ~1600 Hz (limited by chip prescaler). Analog servos typically require 50 Hz; LEDs can use 1000 Hz or higher. ```cpp #include #include Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(); void setup() { pwm.begin(); pwm.setOscillatorFrequency(27000000); // Calibrated oscillator (see oscillator example) pwm.setPWMFreq(50); // 50 Hz for standard analog servos // pwm.setPWMFreq(1600); // Max ~1600 Hz for LEDs / fast switching } ``` ``` -------------------------------- ### Read Current Prescale Register: readPrescale Source: https://context7.com/adafruit/adafruit-pwm-servo-driver-library/llms.txt Retrieves the raw prescale byte from the PCA9685's PRESCALE register. This value is used in the calculation of the actual output frequency. ```APIDOC ## `readPrescale()` — Read Current Prescale Register Returns the raw prescale byte currently written to the PCA9685's PRESCALE register. The actual output frequency is derived from: `freq = osc_clock / (4096 × (prescale + 1))`. ```cpp #include #include Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(); void setup() { Serial.begin(9600); pwm.begin(); pwm.setOscillatorFrequency(25000000); // Default 25 MHz pwm.setPWMFreq(50); uint8_t prescale = pwm.readPrescale(); Serial.print("Prescale value: "); Serial.println(prescale); // Expected ~121 for 50 Hz with 25 MHz oscillator // Real freq = 25000000 / (4096 * (121 + 1)) ≈ 50.1 Hz } ``` ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.