feat: 更新ESP32Servo库

This commit is contained in:
王立帮
2025-04-29 21:38:30 +08:00
parent 231fd8463f
commit 29e0873289
19 changed files with 3649 additions and 854 deletions

View File

@@ -37,14 +37,24 @@
*/
// Include the ESP32 Arduino Servo Library instead of the original Arduino Servo Library
#include <ESP32_Servo.h>
#include <ESP32Servo.h>
Servo myservo; // create servo object to control a servo
// Possible PWM GPIO pins on the ESP32: 0(used by on-board button),2,4,5(used by on-board LED),12-19,21-23,25-27,32-33
// Possible PWM GPIO pins on the ESP32-S2: 0(used by on-board button),1-17,18(used by on-board LED),19-21,26,33-42
// Possible PWM GPIO pins on the ESP32-S3: 0(used by on-board button),1-21,35-45,47,48(used by on-board LED)
// Possible PWM GPIO pins on the ESP32-C3: 0(used by on-board button),1-7,8(used by on-board LED),9-10,18-21
int servoPin = 18; // GPIO pin used to connect the servo control (digital out)
// Possible ADC pins on the ESP32: 0,2,4,12-15,32-39; 34-39 are recommended for analog input
// Possible ADC pins on the ESP32-S2: 1-20 are recommended for analog input
#if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3)
int potPin = 10; // GPIO pin used to connect the potentiometer (analog in)
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
int potPin = 4; // GPIO pin used to connect the potentiometer (analog in)
#else
int potPin = 34; // GPIO pin used to connect the potentiometer (analog in)
#endif
int ADC_Max = 4096; // This is the default ADC max value on the ESP32 (12 bit ADC width);
// this width can be set (in low-level oode) from 9-12 bits, for a
// a range of max values of 512-4096
@@ -53,6 +63,12 @@ int val; // variable to read the value from the analog pin
void setup()
{
// Allow allocation of all timers
ESP32PWM::allocateTimer(0);
ESP32PWM::allocateTimer(1);
ESP32PWM::allocateTimer(2);
ESP32PWM::allocateTimer(3);
myservo.setPeriodHertz(50);// Standard 50hz servo
myservo.attach(servoPin, 500, 2400); // attaches the servo on pin 18 to the servo object
// using SG90 servo min/max of 500us and 2400us
// for MG995 large servo, use 1000us and 2000us,

View File

@@ -33,74 +33,130 @@
* Experimentally, 550 and 2350 are pretty close to 0 and 180.
*/
#include <ESP32_Servo.h>
#include <ESP32Servo.h>
// create four servo objects
Servo servo1;
Servo servo2;
Servo servo3;
Servo servo4;
Servo servo2;
Servo servo3;
Servo servo4;
Servo servo5;
// Published values for SG90 servos; adjust if needed
int minUs = 500;
int maxUs = 2400;
int minUs = 1000;
int maxUs = 2000;
// These are all GPIO pins on the ESP32
// Recommended pins include 2,4,12-19,21-23,25-27,32-33
int servo1Pin = 18;
int servo2Pin = 19;
int servo3Pin = 22;
int servo4Pin = 23;
// Recommended pins include 2,4,12-19,21-23,25-27,32-33
// for the ESP32-S2 the GPIO pins are 1-21,26,33-42
// for the ESP32-S3 the GPIO pins are 1-21,35-45,47-48
// for the ESP32-C3 the GPIO pins are 1-10,18-21
#if defined(CONFIG_IDF_TARGET_ESP32C3)
int servo1Pin = 7;
int servo2Pin = 6;
int servo3Pin = 5;
int servo4Pin = 4;
int servo5Pin = 3;
#else
int servo1Pin = 15;
int servo2Pin = 16;
int servo3Pin = 14;
#if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3)
int servo4Pin = 13;
#else
int servo4Pin = 32;
#endif
int servo5Pin = 4;
#endif
int pos = 0; // position in degrees
ESP32PWM pwm;
void setup() {
// Allow allocation of all timers
ESP32PWM::allocateTimer(0);
ESP32PWM::allocateTimer(1);
ESP32PWM::allocateTimer(2);
ESP32PWM::allocateTimer(3);
Serial.begin(115200);
servo1.setPeriodHertz(50); // Standard 50hz servo
servo2.setPeriodHertz(50); // Standard 50hz servo
servo3.setPeriodHertz(330); // Standard 50hz servo
servo4.setPeriodHertz(200); // Standard 50hz servo
//servo5.setPeriodHertz(50); // Standard 50hz servo
void setup()
{
servo1.attach(servo1Pin, minUs, maxUs);
servo2.attach(servo2Pin, minUs, maxUs);
servo3.attach(servo3Pin, minUs, maxUs);
servo4.attach(servo4Pin, minUs, maxUs);
}
void loop() {
for (pos = 0; pos <= 180; pos += 1) { // sweep from 0 degrees to 180 degrees
// in steps of 1 degree
servo1.write(pos);
delay(20); // waits 20ms for the servo to reach the position
}
for (pos = 180; pos >= 0; pos -= 1) { // sweep from 180 degrees to 0 degrees
servo1.write(pos);
delay(20);
}
servo1.attach(servo1Pin, minUs, maxUs);
servo2.attach(servo2Pin, minUs, maxUs);
#if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C3)
pwm.attachPin(37, 10000);//10khz
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
pwm.attachPin(7, 10000);//10khz
#else
pwm.attachPin(27, 10000);//10khz
#endif
servo3.attach(servo3Pin, minUs, maxUs);
servo4.attach(servo4Pin, minUs, maxUs);
for (pos = 0; pos <= 180; pos += 1) { // sweep from 0 degrees to 180 degrees
// in steps of 1 degree
servo2.write(pos);
delay(20); // waits 20ms for the servo to reach the position
}
for (pos = 180; pos >= 0; pos -= 1) { // sweep from 180 degrees to 0 degrees
servo2.write(pos);
delay(20);
}
//servo5.attach(servo5Pin, minUs, maxUs);
for (pos = 0; pos <= 180; pos += 1) { // sweep from 0 degrees to 180 degrees
// in steps of 1 degree
servo3.write(pos);
delay(20); // waits 20ms for the servo to reach the position
}
for (pos = 180; pos >= 0; pos -= 1) { // sweep from 180 degrees to 0 degrees
servo3.write(pos);
delay(20);
}
for (pos = 0; pos <= 180; pos += 1) { // sweep from 0 degrees to 180 degrees
// in steps of 1 degree
servo4.write(pos);
delay(20); // waits 20ms for the servo to reach the position
}
for (pos = 180; pos >= 0; pos -= 1) { // sweep from 180 degrees to 0 degrees
servo4.write(pos);
delay(20);
}
for (pos = 0; pos <= 180; pos += 1) { // sweep from 0 degrees to 180 degrees
// in steps of 1 degree
servo1.write(pos);
delay(1); // waits 20ms for the servo to reach the position
}
for (pos = 180; pos >= 0; pos -= 1) { // sweep from 180 degrees to 0 degrees
servo1.write(pos);
delay(1);
}
for (pos = 0; pos <= 180; pos += 1) { // sweep from 0 degrees to 180 degrees
// in steps of 1 degree
servo2.write(pos);
delay(1); // waits 20ms for the servo to reach the position
}
for (pos = 180; pos >= 0; pos -= 1) { // sweep from 180 degrees to 0 degrees
servo2.write(pos);
delay(1);
}
for (pos = 0; pos <= 180; pos += 1) { // sweep from 0 degrees to 180 degrees
// in steps of 1 degree
servo3.write(pos);
delay(1); // waits 20ms for the servo to reach the position
}
for (pos = 180; pos >= 0; pos -= 1) { // sweep from 180 degrees to 0 degrees
servo3.write(pos);
delay(1);
}
for (pos = 0; pos <= 180; pos += 1) { // sweep from 0 degrees to 180 degrees
// in steps of 1 degree
servo4.write(pos);
delay(1); // waits 20ms for the servo to reach the position
}
for (pos = 180; pos >= 0; pos -= 1) { // sweep from 180 degrees to 0 degrees
servo4.write(pos);
delay(1);
}
for (pos = 0; pos <= 180; pos += 1) { // sweep from 0 degrees to 180 degrees
// in steps of 1 degree
servo5.write(pos);
delay(1); // waits 20ms for the servo to reach the position
}
for (pos = 180; pos >= 0; pos -= 1) { // sweep from 180 degrees to 0 degrees
servo5.write(pos);
delay(1);
}
servo1.detach();
servo2.detach();;
servo3.detach();
servo4.detach();
pwm.detachPin(27);
delay(5000);
}

View File

@@ -1,109 +0,0 @@
/*
* ESP32 Servo Example
* John K. Bennett
* March, 2017
*
* This sketch uses low-level ESP32 PWM functionality to sweep 4 servos in sequence.
* It does NOT use the ESP32_Servo library for Arduino.
*
* The ESP32 supports 16 hardware LED PWM channels that are intended
* to be used for LED brightness control. The low level ESP32 code allows us to set the
* PWM frequency and bit-depth, and then control them by setting bits in the relevant control
* register. The core files esp32-hal-ledc.* provides helper functions to make this set up
* straightforward.
*
* Different servos require different pulse widths to vary servo angle, but the range is
* an approximately 500-2500 microsecond pulse every 20ms (50Hz). In general, hobbyist servos
* sweep 180 degrees, so the lowest number in the published range for a particular servo
* represents an angle of 0 degrees, the middle of the range represents 90 degrees, and the top
* of the range represents 180 degrees. So for example, if the range is 1000us to 2000us,
* 1000us would equal an angle of 0, 1500us would equal 90 degrees, and 2000us would equal 1800
* degrees.
*
* The ESP32 PWM timers allow us to set the timer width (max 20 bits). Thus
* the timer "tick" length is (pulse_period/2**timer_width), and the equation for pulse_high_width
* (the portion of cycle (20ms in our case) that the signal is high) becomes:
*
* pulse_high_width = count * tick_length
* = count * (pulse_period/2**timer_width)
*
* and count = (pulse_high_width / (pulse_period/2**timer_width))
*
* For example, if we want a 1500us pulse_high_width, we set pulse_period to 20ms (20000us)
* (this value is set in the ledcSetup call), and count (used in the ledcWrite call) to
* 1500/(20000/65655), or 4924. This is the value we write to the timer in the ledcWrite call.
*
* As a concrete example, suppose we want to repeatedly sweep four Tower Pro SG90 servos
* from 0 to 180 degrees. The published pulse width range for the SG90 is 500-2400us. Thus,
* we should vary the count used in ledcWrite from 1638 to 7864.
*
* Circuit:
* Servo motors have three wires: power, ground, and signal. The power wire is typically red,
* the ground wire is typically black or brown, and the signal wire is typically yellow,
* orange or white. Since the ESP32 can supply limited current at only 3.3V, and servos draw
* considerable power, we will connect servo power to the VBat pin of the ESP32 (located
* near the USB connector). THIS IS ONLY APPROPRIATE FOR SMALL SERVOS.
*
* We could also connect servo power to a separate external
* power source (as long as we connect all of the grounds (ESP32, servo, and external power).
* In this example, we just connect ESP32 ground to servo ground. The servo signal pins
* connect to any available GPIO pins on the ESP32 (in this example, we use pins
* 22, 19, 23, & 18).
*
* In this example, we assume four Tower Pro SG90 small servos.
* The published min and max for this servo are 500 and 2400, respectively.
* These values actually drive the servos a little past 0 and 180, so
* if you are particular, adjust the min and max values to match your needs.
* Experimentally, 550us and 2350us are pretty close to 0 and 180.
*
* This code was inspired by a post on Hackaday by Elliot Williams.
*/
// Values for TowerPro SG90 small servos; adjust if needed
#define COUNT_LOW 1638
#define COUNT_HIGH 7864
#define TIMER_WIDTH 16
#include "esp32-hal-ledc.h"
void setup() {
ledcSetup(1, 50, TIMER_WIDTH); // channel 1, 50 Hz, 16-bit width
ledcAttachPin(22, 1); // GPIO 22 assigned to channel 1
ledcSetup(2, 50, TIMER_WIDTH); // channel 2, 50 Hz, 16-bit width
ledcAttachPin(19, 2); // GPIO 19 assigned to channel 2
ledcSetup(3, 50, TIMER_WIDTH); // channel 3, 50 Hz, 16-bit width
ledcAttachPin(23, 3); // GPIO 23 assigned to channel 3
ledcSetup(4, 50, TIMER_WIDTH); // channel 4, 50 Hz, 16-bit width
ledcAttachPin(18, 4); // GPIO 18 assigned to channel 4
}
void loop() {
for (int i=COUNT_LOW ; i < COUNT_HIGH ; i=i+100)
{
ledcWrite(1, i); // sweep servo 1
delay(200);
}
for (int i=COUNT_LOW ; i < COUNT_HIGH ; i=i+100)
{
ledcWrite(2, i); // sweep servo 2
delay(200);
}
for (int i=COUNT_LOW ; i < COUNT_HIGH ; i=i+100)
{
ledcWrite(3, i); // sweep the servo
delay(200);
}
for (int i=COUNT_LOW ; i < COUNT_HIGH ; i=i+100)
{
ledcWrite(4, i); // sweep the servo
delay(200);
}
}

View File

@@ -0,0 +1,36 @@
#include <ESP32Servo.h>
int APin = 13;
ESP32PWM pwm;
int freq = 1000;
void setup() {
// Allow allocation of all timers
ESP32PWM::allocateTimer(0);
ESP32PWM::allocateTimer(1);
ESP32PWM::allocateTimer(2);
ESP32PWM::allocateTimer(3);
Serial.begin(115200);
pwm.attachPin(APin, freq, 10); // 1KHz 10 bits
}
void loop() {
// fade the LED on thisPin from off to brightest:
for (float brightness = 0; brightness <= 0.5; brightness += 0.001) {
// Write a unit vector value from 0.0 to 1.0
pwm.writeScaled(brightness);
delay(2);
}
//delay(1000);
// fade the LED on thisPin from brithstest to off:
for (float brightness = 0.5; brightness >= 0; brightness -= 0.001) {
freq += 10;
// Adjust the frequency on the fly with a specific brightness
// Frequency is in herts and duty cycle is a unit vector 0.0 to 1.0
pwm.adjustFrequency(freq, brightness); // update the time base of the PWM
delay(2);
}
// pause between LEDs:
delay(1000);
freq = 1000;
pwm.adjustFrequency(freq, 0.0); // reset the time base
}

View File

@@ -36,31 +36,47 @@
* if you are particular, adjust the min and max values to match your needs.
*/
#include <ESP32_Servo.h>
#include <ESP32Servo.h>
Servo myservo; // create servo object to control a servo
// 16 servo objects can be created on the ESP32
// 16 servo objects can be created on the ESP32
int pos = 0; // variable to store the servo position
// Recommended PWM GPIO pins on the ESP32 include 2,4,12-19,21-23,25-27,32-33
// Possible PWM GPIO pins on the ESP32-S2: 0(used by on-board button),1-17,18(used by on-board LED),19-21,26,33-42
// Possible PWM GPIO pins on the ESP32-S3: 0(used by on-board button),1-21,35-45,47,48(used by on-board LED)
// Possible PWM GPIO pins on the ESP32-C3: 0(used by on-board button),1-7,8(used by on-board LED),9-10,18-21
#if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3)
int servoPin = 17;
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
int servoPin = 7;
#else
int servoPin = 18;
#endif
void setup() {
myservo.attach(servoPin); // attaches the servo on pin 18 to the servo object
// using default min/max of 1000us and 2000us
// different servos may require different min/max settings
// for an accurate 0 to 180 sweep
// Allow allocation of all timers
ESP32PWM::allocateTimer(0);
ESP32PWM::allocateTimer(1);
ESP32PWM::allocateTimer(2);
ESP32PWM::allocateTimer(3);
myservo.setPeriodHertz(50); // standard 50 hz servo
myservo.attach(servoPin, 1000, 2000); // attaches the servo on pin 18 to the servo object
// using default min/max of 1000us and 2000us
// different servos may require different min/max settings
// for an accurate 0 to 180 sweep
}
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 15ms 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 15ms for the servo to reach the position
}
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 15ms 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 15ms for the servo to reach the position
}
}

View File

@@ -0,0 +1,25 @@
/*
*/
#include <ESP32Servo.h>
int pin = 2;
void setup() {
// Allow allocation of all timers
ESP32PWM::allocateTimer(0);
ESP32PWM::allocateTimer(1);
ESP32PWM::allocateTimer(2);
ESP32PWM::allocateTimer(3);
Serial.begin(115200);
}
void loop() {
tone(pin, 4186, // C
500); // half a second
tone(pin, 5274, // E
500); // half a second
delay(500);
}

View File

@@ -0,0 +1,87 @@
/*
Mega analogWrite() test
This sketch fades LEDs up and down one at a time on digital pins 2 through 13.
This sketch was written for the Arduino Mega, and will not work on previous boards.
The circuit:
* LEDs attached from pins 2 through 13 to ground. or for ESP32-S2 pins 1-17,19-21,26,33-42
created 8 Feb 2009
by Tom Igoe
This example code is in the public domain.
*/
// These constants won't change. They're used to give names
// to the pins used:
#if defined(ARDUINO_ESP32S2_DEV) || defined(ARDUINO_ESP32S3_DEV)
const int lowestPin = 1;
const int highestPin = 42;
#elif defined(ARDUINO_ESP32C3_DEV)
const int lowestPin = 1;
const int highestPin = 19;
#else
const int lowestPin = 2;
const int highestPin = 33;
#endif
#include <ESP32Servo.h>
Servo myservo;
void setup() {
Serial.begin(115200);
// Allow allocation of all timers
ESP32PWM::allocateTimer(0);
ESP32PWM::allocateTimer(1);
ESP32PWM::allocateTimer(2);
ESP32PWM::allocateTimer(3);
}
void loop() {
if (!myservo.attached()) {
myservo.setPeriodHertz(50); // standard 50 hz servo
myservo.attach(33, 1000, 2000); // Attach the servo after it has been detatched
}
myservo.write(0);
// iterate over the pins:
for (int thisPin = lowestPin; thisPin <= highestPin; thisPin++) {
if (ESP32PWM::hasPwm(thisPin) && // Is it possible for this pin to PWM
(ESP32PWM::channelsRemaining() > 0 || // New channels availible to allocate
pwmFactory(thisPin) != NULL || // already allocated this pin in the factory
thisPin == 25 || // one of the 2 DAC outputs, no timer needed
thisPin == 26)) { // one of the 2 DAC outputs, no timer needed
if (pwmFactory(thisPin) == NULL) { // check if its the first time for the pin or its a DAC
#if defined(ARDUINO_ESP32S2_DEV)
if (thisPin == 17 || // one of the 2 DAC outputs, no timer needed
thisPin == 18)
#elif defined(ARDUINO_ESP32C3_DEV) || defined(ARDUINO_ESP32S3_DEV)
if (1 == 0) // no DAC outputs for these chips
#else
if (thisPin == 25 || // one of the 2 DAC outputs, no timer needed
thisPin == 26)
#endif
{
Serial.println("DAC to pin " + String(thisPin));
} else
Serial.println("Writing to pin " + String(thisPin));
pinMode(thisPin, OUTPUT);
}
// fade the LED on thisPin from off to brightest:
for (int brightness = 0; brightness < 255; brightness++) {
analogWrite(thisPin, brightness);
delay(1);
myservo.write(brightness);
}
// fade the LED on thisPin from brithstest to off:
for (int brightness = 255; brightness >= 0; brightness--) {
analogWrite(thisPin, brightness);
myservo.write(brightness);
delay(1);
}
}
}
myservo.detach(); // Turn the servo off for a while
delay(2000);
}