I tried to make a servo sweep with a certain interval. But I'm not sure why it's not working properly. I tried to follow the example given by Adafuit website [Ditch the delay() | Multi-tasking the Arduino - Part 1 | Adafruit Learning System ], but they used lines of code such as:
if ((millis() - lastUpdate) > updateInterval) {
lastUpdate = millis();
pos += increment;
servo.write(pos);
Serial.println(pos);
if (pos > 180 || pos < 0) { //reverse direction
increment = -increment;
}
}
While mine:
if ((millis() - lastUpdate) > updateInterval) {
lastUpdate = millis();
pos += increment;
servo.writeMicroseconds(pos);
Serial.println(pos);
if (pos > 500 || pos < 2500) { //Minimum angle (500PWM: 0°), Maximum angle (2500PWM: 180°)
//reverse direction
increment = -increment;
}
}
The difference between mine and Adafruit's is that I used servo.writeMicroseconds(), while they used servo.write(). The reason I want to use the function of servo.writeMicroseconds() is because I want a higher resolution than servo.write(). I checked the serial monitor, but it gives an output of 0 and 1. Can someone point out what is wrong with my code? I'd highly appreciate it if someone solved this.
Here is my full code (I used the ESP32 Dev Module):
#include <ESP32Servo.h>
Servo servo;
int pos, increment, updateInterval;
unsigned long long lastUpdate;
void setup() {
Serial.begin(115200);
ESP32PWM::allocateTimer(0);
ESP32PWM::allocateTimer(1);
ESP32PWM::allocateTimer(2);
ESP32PWM::allocateTimer(3);
servo.setPeriodHertz(330); // Standard 50hz servo_1
servo.attach(19, 500, 2500);
}
void loop() {
if ((millis() - lastUpdate) > updateInterval) {
lastUpdate = millis();
pos += increment;
servo.writeMicroseconds(pos);
Serial.println(pos);
if (pos > 500 || pos < 2500) {
increment = -increment;
}
}
}
LarryD
October 27, 2022, 2:45am
2
Where did you define the value of updateInterval ?
This will always be true.
I think I forgot to put in the defined value.
updateInterval = 1;
LarryD
October 27, 2022, 2:55am
5
quantum2_0:
updateInterval = 1;
So every 1 microsecond you will be updating the servo with a new value ?
I think I should use interval, not updateInterval. The interval is constant, so... it will not be updating the servo with a new value.
const int interval = 1;
LarryD
October 27, 2022, 3:05am
7
500 to 2500 is 2000 individual positions.
Each position takes 1 us; 2000us is 2ms
Therefore, your are expecting the servo to go from 500 to 2500 in 2ms, do we see a problem here ?
500us to 2500us is the pulse width of the servo control signal. The interval between each 1us step is 1ms, so it will take 2000mS to go the full range.
The major problem is the if statement, it will always be true, so you are always switching between increment and -increment.
There are several problems with the coding itself that I've noticed:
1.) Pos is not initially defined
Solution:
int pos = 500;
2.) Increment is also not initially defined
Solution:
const int increment = 1;
3.) interval [ ̶u̶p̶d̶a̶t̶e̶I̶n̶t̶e̶r̶v̶a̶l̶] is also not initially defined
Solution:
const int interval = 1;
4.) [An aspect of the major issue] The if statement is always true
Solution:
Use toggle
void loop() {
if ((millis() - lastUpdate) > interval) {
lastUpdate = millis();
if (pos >= 500 && toggle == true) {
pos += increment;
servo.writeMicroseconds(pos);
Serial.println(pos);
if (pos == 2500) {
toggle = false;
}
}
}
else if (pos <= 2500 && toggle == false) {
pos -= increment;
servo.writeMicroseconds(pos);
Serial.println(pos);
if (pos == 500) {
toggle = true;
}
}
}
But now the servo motor moves slowly counter-clockwise and moves a bit faster when clockwise
I would try commenting out the statements to print the value of pos. At 115200 baud there should not be a problem with filling the serial buffer, but if that happened the larger numbers would be more likely to cause it and slow down the code.
alto777
October 27, 2022, 12:21pm
12
This switches direction when pos goes over 180, or under 0:
if (pos > 180 || pos < 0) { //reverse direction
increment = -increment;
}
This always switches direction:
if (pos > 500 || pos < 2500) { //Minimum angle (500PWM: 0°), Maximum angle (2500PWM: 180°)
//reverse direction
increment = -increment;
It seems like what you want is
if (pos > 2500 || pos < 500) { //Minimum angle (500PWM: 0°), Maximum angle (2500PWM: 180°)
//reverse direction
increment = -increment;
to match the pattern of the code you are modifying.
a7
I followed Mr. Johnwasser's coding and now it's working! Now I can control two servos without a headache. Here is the link for references: [How to accomplish a SERVO sweep Forward and Reverse both with millis? - #7 by johnwasser ]. I've made minor changes to the coding itself, and when I think of it, mine using toggle is a little bit cumbersome
#include <ESP32Servo.h>
Servo servo;
const byte ServoPin = 19;
const unsigned StepPeriod = 1;
const int StepIncrement = 1;
void setup() {
Serial.begin(115200);
ESP32PWM::allocateTimer(0);
ESP32PWM::allocateTimer(1);
ESP32PWM::allocateTimer(2);
ESP32PWM::allocateTimer(3);
servo.setPeriodHertz(330);
servo.attach(ServoPin, 500, 2500);
}
void loop() {
static int pos = 500;
static int increment = StepIncrement;
static unsigned long startMillis = 0;
unsigned long currentMillis = millis();
if (currentMillis - startMillis >= StepPeriod) {
startMillis = currentMillis;
pos += increment;
if (pos > 2500) {
pos = 2500;
increment = -StepIncrement;
}
if (pos < 500) {
pos = 500;
increment = StepIncrement;
}
Serial.println(pos);
servo.writeMicroseconds(pos);
}
}
Here's a sneak peek at my little J.A.R.V.I.S
system
Closed
April 25, 2023, 9:15pm
15
This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.