|
| 1 | +/**************************************************************************************************************************** |
| 2 | + ESP32_New_ISR_MultiServos.ino |
| 3 | + For ESP32, ESP32_S2, ESP32_S3, ESP32_C3 boards with ESP32 core v2.0.0+ |
| 4 | + Written by Khoi Hoang |
| 5 | +
|
| 6 | + Built by Khoi Hoang https://github.com/khoih-prog/ESP32_New_ISR_Servo |
| 7 | + Licensed under MIT license |
| 8 | +
|
| 9 | + The ESP32, ESP32_S2, ESP32_S3, ESP32_C3 have two timer groups, TIMER_GROUP_0 and TIMER_GROUP_1 |
| 10 | + 1) each group of ESP32, ESP32_S2, ESP32_S3 has two general purpose hardware timers, TIMER_0 and TIMER_1 |
| 11 | + 2) each group of ESP32_C3 has ony one general purpose hardware timer, TIMER_0 |
| 12 | + |
| 13 | + All the timers are based on 64-bit counters (except 54-bit counter for ESP32_S3 counter) and 16 bit prescalers. |
| 14 | + The timer counters can be configured to count up or down and support automatic reload and software reload. |
| 15 | + They can also generate alarms when they reach a specific value, defined by the software. |
| 16 | + The value of the counter can be read by the software program. |
| 17 | +
|
| 18 | + Now these new 16 ISR-based PWM servo contro uses only 1 hardware timer. |
| 19 | + The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers |
| 20 | + Therefore, their executions are not blocked by bad-behaving functions / tasks. |
| 21 | + This important feature is absolutely necessary for mission-critical tasks. |
| 22 | +*****************************************************************************************************************************/ |
| 23 | + |
| 24 | +/**************************************************************************************************************************** |
| 25 | + This example will demonstrate the nearly perfect accuracy compared to software timers by printing the actual elapsed millisecs. |
| 26 | + Being ISR-based timers, their executions are not blocked by bad-behaving functions / tasks, such as connecting to WiFi, Internet |
| 27 | + and Blynk services. You can also have many (up to 16) timers to use. |
| 28 | + This non-being-blocked important feature is absolutely necessary for mission-critical tasks. |
| 29 | + You'll see blynkTimer is blocked while connecting to WiFi / Internet / Blynk, and elapsed time is very unaccurate |
| 30 | + In this super simple example, you don't see much different after Blynk is connected, because of no competing task is |
| 31 | + written |
| 32 | +
|
| 33 | + From ESP32 Servo Example Using Arduino ESP32 Servo Library |
| 34 | + John K. Bennett |
| 35 | + March, 2017 |
| 36 | +
|
| 37 | + Different servos require different pulse widths to vary servo angle, but the range is |
| 38 | + an approximately 500-2500 microsecond pulse every 20ms (50Hz). In general, hobbyist servos |
| 39 | + sweep 180 degrees, so the lowest number in the published range for a particular servo |
| 40 | + represents an angle of 0 degrees, the middle of the range represents 90 degrees, and the top |
| 41 | + of the range represents 180 degrees. So for example, if the range is 1000us to 2000us, |
| 42 | + 1000us would equal an angle of 0, 1500us would equal 90 degrees, and 2000us would equal 1800 |
| 43 | + degrees. |
| 44 | +
|
| 45 | + Circuit: |
| 46 | + Servo motors have three wires: power, ground, and signal. The power wire is typically red, |
| 47 | + the ground wire is typically black or brown, and the signal wire is typically yellow, |
| 48 | + orange or white. Since the ESP32 can supply limited current at only 3.3V, and servos draw |
| 49 | + considerable power, we will connect servo power to the VBat pin of the ESP32 (located |
| 50 | + near the USB connector). THIS IS ONLY APPROPRIATE FOR SMALL SERVOS. |
| 51 | +
|
| 52 | + We could also connect servo power to a separate external |
| 53 | + power source (as long as we connect all of the grounds (ESP32, servo, and external power). |
| 54 | + In this example, we just connect ESP32 ground to servo ground. The servo signal pins |
| 55 | + connect to any available GPIO pins on the ESP32 (in this example, we use pins |
| 56 | + 22, 19, 23, & 18). |
| 57 | +
|
| 58 | + In this example, we assume four Tower Pro SG90 small servos. |
| 59 | + The published min and max for this servo are 500 and 2400, respectively. |
| 60 | + These values actually drive the servos a little past 0 and 180, so |
| 61 | + if you are particular, adjust the min and max values to match your needs. |
| 62 | + Experimentally, 550 and 2350 are pretty close to 0 and 180. |
| 63 | +*****************************************************************************************************************************/ |
| 64 | + |
| 65 | +#if !defined(ESP32) |
| 66 | + #error This code is intended to run on the ESP32 platform! Please check your Tools->Board setting. |
| 67 | +#endif |
| 68 | + |
| 69 | +#define TIMER_INTERRUPT_DEBUG 0 |
| 70 | +#define ISR_SERVO_DEBUG 1 |
| 71 | + |
| 72 | +// For ESP32_C3, select ESP32 timer number (0-1) |
| 73 | +// For ESP32 and ESP32_S2, select ESP32 timer number (0-3) |
| 74 | +#if defined( ARDUINO_ESP32C3_DEV ) |
| 75 | + #define USE_ESP32_TIMER_NO 1 |
| 76 | +#else |
| 77 | + #define USE_ESP32_TIMER_NO 3 |
| 78 | +#endif |
| 79 | + |
| 80 | +// To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error |
| 81 | +#include "ESP32_New_ISR_Servo.h" |
| 82 | + |
| 83 | +//See file .../hardware/espressif/esp32/variants/(esp32|doitESP32devkitV1)/pins_arduino.h |
| 84 | +#if !defined(LED_BUILTIN) |
| 85 | + #define LED_BUILTIN 2 // Pin D2 mapped to pin GPIO2/ADC12 of ESP32, control on-board LED |
| 86 | +#endif |
| 87 | + |
| 88 | +#define PIN_LED 2 // Pin D2 mapped to pin GPIO2/ADC12 of ESP32, control on-board LED |
| 89 | + |
| 90 | +#define PIN_D0 0 // Pin D0 mapped to pin GPIO0/BOOT/ADC11/TOUCH1 of ESP32 |
| 91 | +#define PIN_D1 1 // Pin D1 mapped to pin GPIO1/TX0 of ESP32 |
| 92 | +#define PIN_D2 2 // Pin D2 mapped to pin GPIO2/ADC12/TOUCH2 of ESP32 |
| 93 | +#define PIN_D3 3 // Pin D3 mapped to pin GPIO3/RX0 of ESP32 |
| 94 | +#define PIN_D4 4 // Pin D4 mapped to pin GPIO4/ADC10/TOUCH0 of ESP32 |
| 95 | +#define PIN_D5 5 // Pin D5 mapped to pin GPIO5/SPISS/VSPI_SS of ESP32 |
| 96 | +#define PIN_D6 6 // Pin D6 mapped to pin GPIO6/FLASH_SCK of ESP32 |
| 97 | +#define PIN_D7 7 // Pin D7 mapped to pin GPIO7/FLASH_D0 of ESP32 |
| 98 | +#define PIN_D8 8 // Pin D8 mapped to pin GPIO8/FLASH_D1 of ESP32 |
| 99 | +#define PIN_D9 9 // Pin D9 mapped to pin GPIO9/FLASH_D2 of ESP32 |
| 100 | + |
| 101 | +// Published values for SG90 servos; adjust if needed |
| 102 | +#define MIN_MICROS 800 //544 |
| 103 | +#define MAX_MICROS 2450 |
| 104 | + |
| 105 | +int servoIndex1 = -1; |
| 106 | +int servoIndex2 = -1; |
| 107 | + |
| 108 | +void setup() |
| 109 | +{ |
| 110 | + Serial.begin(115200); |
| 111 | + while (!Serial); |
| 112 | + |
| 113 | + delay(500); |
| 114 | + |
| 115 | + Serial.print(F("\nStarting ESP32_New_ISR_MultiServos on ")); Serial.println(ARDUINO_BOARD); |
| 116 | + Serial.println(ESP32_NEW_ISR_SERVO_VERSION); |
| 117 | + |
| 118 | + //Select ESP32 timer USE_ESP32_TIMER_NO |
| 119 | + ESP32_ISR_Servos.useTimer(USE_ESP32_TIMER_NO); |
| 120 | + |
| 121 | + servoIndex1 = ESP32_ISR_Servos.setupServo(PIN_D2, MIN_MICROS, MAX_MICROS); |
| 122 | + servoIndex2 = ESP32_ISR_Servos.setupServo(PIN_D3, MIN_MICROS, MAX_MICROS); |
| 123 | + |
| 124 | + if (servoIndex1 != -1) |
| 125 | + Serial.println(F("Setup Servo1 OK")); |
| 126 | + else |
| 127 | + Serial.println(F("Setup Servo1 failed")); |
| 128 | + |
| 129 | + if (servoIndex2 != -1) |
| 130 | + Serial.println(F("Setup Servo2 OK")); |
| 131 | + else |
| 132 | + Serial.println(F("Setup Servo2 failed")); |
| 133 | +} |
| 134 | + |
| 135 | +void loop() |
| 136 | +{ |
| 137 | + int position; |
| 138 | + |
| 139 | + if ( ( servoIndex1 != -1) && ( servoIndex2 != -1) ) |
| 140 | + { |
| 141 | + for (position = 0; position <= 180; position++) |
| 142 | + { |
| 143 | + // goes from 0 degrees to 180 degrees |
| 144 | + // in steps of 1 degree |
| 145 | + |
| 146 | + if (position % 30 == 0) |
| 147 | + { |
| 148 | + Serial.print(F("Servo1 pos = ")); Serial.print(position); |
| 149 | + Serial.print(F(", Servo2 pos = ")); Serial.println(180 - position); |
| 150 | + } |
| 151 | + |
| 152 | + ESP32_ISR_Servos.setPosition(servoIndex1, position); |
| 153 | + ESP32_ISR_Servos.setPosition(servoIndex2, 180 - position); |
| 154 | + // waits 30ms for the servo to reach the position |
| 155 | + delay(30); |
| 156 | + } |
| 157 | + |
| 158 | + delay(5000); |
| 159 | + |
| 160 | + for (position = 180; position >= 0; position--) |
| 161 | + { |
| 162 | + // goes from 180 degrees to 0 degrees |
| 163 | + if (position % 30 == 0) |
| 164 | + { |
| 165 | + Serial.print(F("Servo1 pos = ")); Serial.print(position); |
| 166 | + Serial.print(F(", Servo2 pos = ")); Serial.println(180 - position); |
| 167 | + } |
| 168 | + |
| 169 | + ESP32_ISR_Servos.setPosition(servoIndex1, position); |
| 170 | + ESP32_ISR_Servos.setPosition(servoIndex2, 180 - position); |
| 171 | + // waits 30ms for the servo to reach the position |
| 172 | + delay(30); |
| 173 | + } |
| 174 | + |
| 175 | + delay(5000); |
| 176 | + } |
| 177 | +} |
0 commit comments