Using Servo Motors

 Using Servo with Microbit 
https://support.microbit.org/support/solutions/articles/19000101864-using-a-servo-with-the-micro-bit


Using Continuous Rotation Servo with Microbit
https://youtu.be/h6McLLdBoCM


Arduino:


#include <Servo.h>

Servo myservo; // create Servo object to control a servo
// twelve Servo objects can be created on most boards

int pos = 0; // variable to store the servo position

void setup() {
myservo.attach(9); // attaches the servo on pin 9 to the Servo object
}

void loop() {
for (pos = 0; pos <= 180; pos += 1) { // goes from 0 degrees to 180 degrees
// in steps of 1 degree
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15 ms for the servo to reach the position
}
for (pos = 180; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15 ms for the servo to reach the position
}
}
----------------------------

Wiring the PCA9685 to an ESP32

Wiring the PCA9685 16-Channel Servo Driver to an ESP32 requires two distinct circuits: one for the logic (the I2C communication between the ESP32 and the driver) and one for the power (to drive the servos).

CRITICAL WARNING: Do not attempt to power your servos directly from the ESP32's 5V or 3.3V pins. Servos draw significant current, and doing so will cause the ESP32 to brown out, reset continually, or potentially suffer permanent damage.

1. Logic Connections (ESP32 to PCA9685)

This circuit powers the PCA9685 chip itself and establishes the I2C communication lines so the ESP32 can send commands.

The ESP32 is a 3.3V logic device. While the PCA9685 is 5V-safe, it is best practice to power the logic side of the PCA9685 with 3.3V to match the ESP32's I2C logic levels.

  • ESP32 3V3 $\rightarrow$ PCA9685 VCC (Powers the chip logic)

  • ESP32 GND $\rightarrow$ PCA9685 GND (Common ground reference)

  • ESP32 GPIO 21 $\rightarrow$ PCA9685 SDA (I2C Data Line - Default on ESP32)

  • ESP32 GPIO 22 $\rightarrow$ PCA9685 SCL (I2C Clock Line - Default on ESP32)

Optional Pin:

  • OE (Output Enable): By default, the PCA9685 is enabled. You can optionally connect this to an ESP32 GPIO pin. Pulling this pin HIGH instantly disables all PWM outputs (useful for an emergency stop). Pulling it LOW enables them. If unused, leave it disconnected.

2. Servo Power Connections (External Supply to PCA9685)

This circuit provides the "muscle" to drive the servos. You must use an external DC power supply. The voltage required depends on your specific servos (typically 5V or 6V for hobby servos like the SG90 or MG996R). Ensure the power supply can handle the peak current of all your servos moving simultaneously (e.g., a 5V/2A or 5V/10A power supply).

You should connect this power source to the Blue Terminal Block at the top of the PCA9685 board, as it includes reverse-polarity protection.

  • External Power Supply Positive (+) $\rightarrow$ PCA9685 V+ (Terminal Block)

  • External Power Supply Ground (-) $\rightarrow$ PCA9685 GND (Terminal Block)

The Most Important Connection: Common Ground

For the control signals (PWM) to work, the external power supply and the ESP32 must share a common ground reference.

  • ESP32 GND $\rightarrow$ PCA9685 GND (Side Header)

  • External Supply Ground $\rightarrow$ PCA9685 GND (Terminal Block)

(Note: The GND pins on the PCA9685 side headers and the GND on the terminal block are internally connected on the board. As long as the ESP32 and the external supply both connect to a GND on the PCA9685, the common ground is established.)

3. Connecting the Servos

The PCA9685 has 16 numbered columns of pins (0 to 15). Each column corresponds to one channel and has three pins:

  1. PWM / Signal (Top row, usually yellow or white wire on the servo)

  2. V+ (Middle row, usually red wire on the servo)

  3. GND (Bottom row, usually brown or black wire on the servo)

Plug your servos directly into these columns, ensuring the ground wire aligns with the bottom row.

Summary Wiring Diagram

[External 5V/6V Power Supply]
     (+) ---------------------> [PCA9685 Terminal Block V+]
     (-) ---------------------> [PCA9685 Terminal Block GND]

[ESP32]
    3V3 ----------------------> [PCA9685 Side Header VCC]
    GND ----------------------> [PCA9685 Side Header GND]
GPIO 21 (SDA) ----------------> [PCA9685 Side Header SDA]
GPIO 22 (SCL) ----------------> [PCA9685 Side Header SCL]

[Servos 0-15]
  Signal ---------------------> [PCA9685 Top Row (PWM)]
   Power ---------------------> [PCA9685 Middle Row (V+)]
  Ground ---------------------> [PCA9685 Bottom Row (GND)]
----------------------------------------------------
// for ESP32:

#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>

// Initialize the PCA9685 at the default I2C address (0x40)
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();

// Calibrate these values for your specific servos
#define SERVOMIN 150 // Minimum pulse length count (out of 4096)
#define SERVOMAX 600 // Maximum pulse length count (out of 4096)

// Define our servo channels
#define SERVO_1 0
#define SERVO_2 1
#define SERVO_3 2
#define SERVO_4 3

void setup() {
// ESP32 users typically use 115200 baud instead of 9600
Serial.begin(115200);
Serial.println("ESP32 + PCA9685 4-Servo Control");

// Initialize I2C specifically for the ESP32's default pins (SDA=21, SCL=22)
Wire.begin(21, 22);
pwm.begin();
// Set oscillator frequency and PWM frequency (50 Hz is standard for analog servos)
pwm.setOscillatorFrequency(27000000);
pwm.setPWMFreq(50);
delay(10);
}

// Helper function to easily move servos by degree rather than calculating pulses manually
void setServoAngle(uint8_t channel, uint8_t angle) {
// Constrain the angle to prevent sending out-of-bounds commands
angle = constrain(angle, 0, 180);
// Map the 0-180 degree range to our calibrated minimum and maximum pulse ticks
uint16_t pulse = map(angle, 0, 180, SERVOMIN, SERVOMAX);
// Send the command to the board
pwm.setPWM(channel, 0, pulse);
}

void loop() {
Serial.println("Moving all servos to 0 degrees...");
setServoAngle(SERVO_1, 0);
setServoAngle(SERVO_2, 0);
setServoAngle(SERVO_3, 0);
setServoAngle(SERVO_4, 0);
delay(1500);

Serial.println("Moving servos to different positions...");
setServoAngle(SERVO_1, 45);
setServoAngle(SERVO_2, 90);
setServoAngle(SERVO_3, 135);
setServoAngle(SERVO_4, 180);
delay(1500);

Serial.println("Sweeping Servo 1 smoothly...");
for (int pos = 45; pos <= 135; pos++) {
setServoAngle(SERVO_1, pos);
delay(15); // Short delay makes the movement smooth
}
delay(1000);
}

No comments:

Post a Comment