English
English
简体中文
日本語

Arduino Quick Start

2. Devices & Examples

5. Extensions

6. Applications

Module13.2 Servo2 Arduino Tutorial

1. Preparation

2. Precautions

Pin Compatibility
Because pin configurations vary between host devices, refer to the Pin Compatibility Table in the product documentation before use and modify the example program according to the actual pin connections.

3. Example Program

  • This tutorial uses CoreS3 with Module13.2 Servo2 to control servos. Module13.2 Servo2 communicates via I2C. Modify the pin definitions in the program according to the actual circuit connections. After connecting the devices, the corresponding I2C IO pins are G12 (SDA) and G11 (SCL).
cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
#include <M5Unified.h>
#include <Wire.h>
#include "Adafruit_PWMServoDriver.h"

#define SERVO_FREQ 50  // Servo PWM frequency.

Adafruit_PWMServoDriver* pwm = nullptr;

void setup()
{
    auto cfg = M5.config();
    cfg.output_power = false;// Essential for Core2/CoreS3
    M5.begin(cfg);
    M5.Lcd.setFont(&fonts::FreeMonoBold12pt7b);

    // Get M5Bus I2C pins.
    const int8_t wireSda = M5.getPin(m5::pin_name_t::in_i2c_sda);
    const int8_t wireScl = M5.getPin(m5::pin_name_t::in_i2c_scl);

    // Find the configured SERVO2 address.
    uint8_t servo2Address = 0;
    Serial.println("Scanning SERVO2 addresses 0x40-0x47...");
    for (uint8_t address = 0x40; address <= 0x47; ++address) {
        if (M5.In_I2C.scanID(address)) {
            servo2Address = address;
            Serial.printf("Found PCA9685 at 0x%02X\n", address);
            break;
        }
    }

    if (servo2Address == 0) {
        Serial.println("PCA9685 not found on M5Bus");
        M5.Display.drawString("PCA9685 not found", 10, 80);
        while (true) {
            delay(1000);
        }
    }

    Wire.setPins(wireSda, wireScl);
    pwm = new Adafruit_PWMServoDriver(servo2Address, Wire);

    if (!pwm->begin()) {
        Serial.printf("Wire could not initialize PCA9685 at 0x%02X\n", servo2Address);
        M5.Display.drawString("Wire init failed", 10, 80);
        while (true) {
            delay(1000);
        }
    }

    // Set the PWM frequency for analog servos.
    pwm->setPWMFreq(SERVO_FREQ);

    M5.Lcd.setTextColor(TFT_GREEN, TFT_BLACK);
    M5.Lcd.drawCenterString("Module13.2 Servo2 Test", 160, 10);
}

// Set one PCA9685 channel using a pulse width in milliseconds.
void setServoPulse(uint8_t n, double pulse)
{
    double pulselength;

    // Calculate the PWM period in microseconds.
    pulselength = 1000000;
    pulselength /= SERVO_FREQ;

    // Print the period for debugging.
    Serial.print(pulselength);
    Serial.println(" us per period");

    // Convert the period to one 12-bit PWM step.
    pulselength /= 4096;
    Serial.print(pulselength);
    Serial.println(" us per bit");

    // Convert the pulse width from milliseconds to PWM steps.
    pulse *= 1000;
    pulse /= pulselength;
    Serial.println(pulse);

    // Output the requested high pulse.
    pwm->setPWM(n, 0, pulse);
}

void loop()
{
    // Drive all channels with a 0.5 ms pulse.
    for (int i = 0; i < 16; i++) {
        setServoPulse(i, 0.5);
    }
    M5.Lcd.fillRect(0, 70, 320, 20, TFT_BLACK);
    M5.Lcd.drawCenterString("Pulse width: 0.5 ms", 160, 80);
    delay(1000);

    // Drive all channels with a 2.5 ms pulse.
    for (int i = 0; i < 16; i++) {
        setServoPulse(i, 2.5);
    }
    M5.Lcd.fillRect(0, 70, 320, 20, TFT_BLACK);
    M5.Lcd.drawCenterString("Pulse width: 2.5 ms", 160, 80);
    delay(1000);
}

4. Compile and Upload

  • 1. Enter Download Mode: Press and hold the CoreS3 reset button (for about 2 seconds) until the internal green LED lights up, then release it. The device is now in download mode and ready for flashing.
Note
Different devices need to enter download mode before flashing, and the procedure may vary depending on the main controller. For details, refer to the list of device flashing tutorials at the bottom of the Arduino IDE Getting Started Guide page.
  • Select the device port, click the Compile and Upload button in the upper-left corner of Arduino IDE, and wait for the program to finish compiling and uploading to the device.

5. Servo Control

  • After power-on, the Module13.2 Servo2 module is initialized automatically, then the servos are driven repeatedly using pulse widths of 0.5ms / 2.5ms.
Note
The example code drives all 16 channels; only one channel is connected to a servo in the image below for demonstration.
Page Tools
PDF
On This Page