Closed makerobotics closed 3 years ago
there is a delay in the servo write instruction (15ms as I could trace).
Servo.h:
#define REFRESH_INTERVAL 20000 // classic default period to refresh servos in microseconds
This is according to servo specification, and has been in the code for at least 6 years. If you take some extra time to update your code snippet to an actual MCVE, one that must compile (verifiable), and isn't full of commented lines (minimum), your chances of getting support are much better.
When planning issue reports in the future, please consider:
If I go back to a later board version, this problem is no more present.
Your use of "Later" is probably lost in translation, you mean an earlier version, but please always be specific when reporting issues.
The servo lib version is not changing anything.
This applies to a few other libraries as well, so please check first, then try, then report: There is no such thing as a "Servo lib version" for ESP8266, as the "library" is part of the ESP8266 Core. Probably it's even safer to uninstall any Servo lib from the Arduino library manager while building for the ESP8266.
Hello,
thanks for your feedback and sorry for not being so professional. It is my first time...
I now created a MCVE (had to google the meaning first). It is directly based on the official servo sketch which I only extended with some trace information:
#include <Servo.h>
#define SERVO 16
Servo myservo; // create servo object to control a servo
unsigned long timestamps[4];
int pos = 0;
void setup() {
Serial.begin(115200);
myservo.attach(SERVO); // attaches the servo on GIOxx to the servo
object
myservo.write(0);
delay(500); // wait for servo to be in position
}
void loop() {
for (pos = 0; pos <= 180; pos += 1) { // goes from 0 degrees to 180
degrees
// in steps of 1 degree
timestamps[0] = millis();
myservo.write(pos); // tell servo to go to position in
variable 'pos'
timestamps[1] = millis();
delay(5); // waits 5ms for the servo to reach the
position
timestamps[2] = millis();
Serial.print(timestamps[0]);Serial.print(" ");
Serial.print(timestamps[1]-timestamps[0]);Serial.print(" ");
Serial.print(timestamps[2]-timestamps[1]);Serial.println(" ");
}
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(5); // waits 5ms for the servo to reach the
position
}
}
Here is the trace: 571 0 5 576 15 5 596 15 5 616 15 5 636 15 5 656 15 5 676 15 5 696 15 5 716 15 5 736 15 5 756 15 5 776 15 5 796 15 5 816 15 5 836 15 5 856 15 5 876 15 5 896 15 5 916 15 5 936 15 5 956 15 5 976 15 5 996 15 5 1016 15 5 1036 15 5 1056 15 5
You can see the timestamp, the servo write (15ms) and then the delay(5ms). I agree that this timing is out of spec (refresh should be only after 20ms) but it is definitely a different behavior than before. I was sending the write instructions every 5 ms and had a fast servo movement. Now, it is limited by this 20ms.
If I use the V3.0.0 of the ESP8266, I am forced to stick to the spec (20ms is included in the servo.write instruction). If I use an older version like V2.7.3, I can also have a faster actuation as I directly leave the servo.write instruction. It is up to you to decide if it is better now (on spec) or before (faster), but for many projects like for mine, it may be a problem as it is changing the system behavior.
Thanks again for your time.
Le ven. 28 mai 2021 à 11:16, Dirk O. Kaar @.***> a écrit :
there is a delay in the servo write instruction (15ms as I could trace).
Servo.h:
define REFRESH_INTERVAL 20000 // classic default period to refresh servos in microseconds
This is according to servo specification, and has been in the code for at least 6 years. If you take some extra time to update your code snippet to an actual MCVE, one that must compile (verifiable), and isn't full of commented lines (minimum), your chances of getting support are much better.
When planning issue reports in the future, please consider:
If I go back to a later board version, this problem is no more present.
Your use of "Later" is probably lost in translation, you mean an earlier version, but please always be specific when reporting issues.
The servo lib version is not changing anything.
This applies to a few other libraries as well, so please check first, then try, then report: There is no such thing as a "Servo lib version" for ESP8266, as the "library" is part of the ESP8266 Core. Probably it's even safer to uninstall any Servo lib from the Arduino library manager while building for the ESP8266.
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/esp8266/Arduino/issues/8081#issuecomment-850276903, or unsubscribe https://github.com/notifications/unsubscribe-auth/APBLAUYUUJ6IUAIAQXRIAITTP5NNXANCNFSM45UWTNDA .
@makerobotics Please fix the code block, we can't copy & paste without editing all the line breaks by hand.
I tried to fix as I usually do but in this case: "Email replies do not support Markdown" … (so I edit my post and do the copy-paste myself)
#include <Servo.h>
#define SERVO 16
Servo myservo; // create servo object to control a servo
unsigned long timestamps[4];
int pos = 0;
void setup() {
Serial.begin(115200);
myservo.attach(SERVO); // attaches the servo on GIOxx to the servo object
myservo.write(0);
delay(500); // wait for servo to be in position
}
void loop() {
for (pos = 0; pos <= 180; pos += 1) { // goes from 0 degrees to 180 degrees in steps of 1 degree
timestamps[0] = millis();
myservo.write(pos); // tell servo to go to position in variable 'pos'
timestamps[1] = millis();
delay(5); // waits 5ms for the servo to reach the position
timestamps[2] = millis();
Serial.print(timestamps[0]);Serial.print(" ");
Serial.print(timestamps[1]-timestamps[0]);Serial.print(" ");
Serial.print(timestamps[2]-timestamps[1]);Serial.println(" ");
}
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(5); // waits 5ms for the servo to reach the position
}
}
@makerobotics You must have hit "the wrong button" :-)
Anyway: For an immediate fix, you can switch over to another waveform generator (full disclosure: I am the author of that alternative implementation).
Like so (adding enablePhaseLockedWaveform()
):
void setup() {
enablePhaseLockedWaveform();
Serial.begin(115200);
myservo.attach(SERVO); // attaches the servo on GIOxx to the servo object
myservo.write(0);
delay(500); // wait for servo to be in position
}
@earlephilhower I have only tested that the "phase locked" generator gives instant returns from servo.write
, no more, no less, and I don't really know why "pwm locked" apparently delays for up to 20ms (15 = 20 - 5). Please take it from here?
A bit more analysis for the benefit of my pending PRs, to whom it may concern. This issue remains in PR #8008 ("pwm locked"). See how compatible it is ;-)
1100 0 5
1105 1 5
1111 0 5
1116 0 5
1121 0 5
1126 0 5
1131 0 5
1136 0 5
1141 0 5
1146 0 5
1151 0 5
1156 0 5
1161 0 5
1166 0 5
1171 0 5
1176 1 5
Caveat: I haven't attached a servo, don't know if this would go up in flames...
@dok-net The servo doesn't flambé, but it does move about 3-4 times faster with your branch, Dirk.
edit: This may also explain what I saw with my PWM test routines a month ago before I disappeared: the analogWrite() ramp-up ramp-down was running a lot slower than previously.
Minor comment: my servo only goes through about 90 degrees of arc (not 180), typical for an aircraft or hobby servo.
@makerobotics your code isn't doing what you've programmed it for, at least not exactly. You're trying to update the servo every 5mS, but the period of a 50Hz servo signal is 20mS. When it's working 'correctly', the ESP is actually updating the servo position by 4 degrees every 20mS, and not by 1 degree every 5mS. You can't update the servo signal DURING the cycle, only when it starts a new cycle or else it would jitter horribly.
As I told in my previous answer, I agree on that now. Honestly, it was not clear to me. But the behaviour was charged. In previous version, my code was working fine even by calling the function every 5 ms. I can change my code accordingly, but I guess it was easier before, for someone like me without knowing the protocol. Thanks for taking care of this.
On Mon, 31 May 2021, 02:26 StanJ, @.***> wrote:
@makerobotics https://github.com/makerobotics your code isn't doing what you've programmed it for, at least not exactly. You're trying to update the servo every 5mS, but the period of a 50Hz servo signal is 20mS. When it's working 'correctly', the ESP is actually updating the servo position by 4 degrees every 20mS, and not by 1 degree every 5mS. You can't update the servo signal DURING the cycle, only when it starts a new cycle or else it would jitter horribly.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/esp8266/Arduino/issues/8081#issuecomment-851090335, or unsubscribe https://github.com/notifications/unsubscribe-auth/APBLAUYEZIDWFDCKSG372NDTQLJU3ANCNFSM45UWTNDA .
No worries, we're looking to see where the strange behavior comes in.
If you're using 'digital' servos (like the tail rotor on a helicopter) you could be running a 5mS refresh rate, but you'd have to change the refresh rate in servo.h,
#define REFRESH_INTERVAL 20000 // minimum time to refresh servos in microseconds
For modern RC systems, that refresh rate can be anything from 50Hz (ancient analog spec) up to about 333Hz maximum. 5ms is a 200Hz refresh rate, which might work depending on your servos. Some servos will chatter or jitter above ~ 100Hz, some work OK up to 333Hz.
If you add the line in setup that dok-net mentioned above, the servo function doesn't block like the default version does,
enablePhaseLockedWaveform();
so you'll get the expected motion, depending on your refresh rate: at 200Hz it'll step in 1 degree increments, and at 50Hz it'll step in 4 degree increments. The underlying issue should be corrected in the git version of the repo sometime soon, but it could be months before it's rolled into the board manager version. In the meantime, the enablePhaseLockedWaveform(); should fix you up.
Thank you all for the kind help. I could not find the documentation about enablePhaseLockedWaveform(), but I will try it soon. I also noticed a difference in the servo positions. I mounted a 180° servo, and the positions are not the same with the V3.0.0. Is it locked to 0-90° ? Unfortunately, my hardware is not available currently to compare on this level. I will investigate as soon as I have my HW back.
Find out the extreme min and max and set them in the respective call to to the servo channel. You'll know what I mean if you look at the header file.
Sorry I was probably unclear again. It seems that my servo is no more able to go to the old min and max positions with the V3.0.0 lib. Of course I can set new extreme positions, but my servo is not more able to achieve all the angles.
@makerobotics
Default min max have changed in v3.0.0:
Previous value were MIN:544 MAX:2400 (in 2.7.4 and previous version of this core)
Current values are MIN:1000 MAX:2000 (see #7023)
You can change the current defaults using uint8_t attach(int pin, uint16_t min, uint16_t max, int value);
. This method will also work with previous versions of this arduino platform.
Thanks again for your help.
@makerobotics I would like to think that in addition to @d-a-v's remark this https://github.com/connected-little-boxes/box-code/issues/8#issuecomment-880585908
provides closure to this issue. If so, would you like to promote it to solved/closed, unless there's something else unresolved?
Thanks all for your fast support. I will close the issue as there is a possibility with the attach function to bypass the problems. But I still think it is more difficult to use (even if more secure) than in the previous version. Some comments in the Arduino example would be nice (and also the attach function call).
fwiw, I just ran into this, as well. I was using 2.x ESP core and all was well with my servo project. I upgraded to 3.x and all the servo code went to 90degrees swing instead of 180. it wasted hours of my time, too. I have to disagree with this 'fix', for the record. you broke code that used to run. to push this on the apps and have APP CODE BE UPDATED was the wrong approach to this. better to create new api's or names and let people migrate GRACEFULLY over to the new version.
But the behaviour was charged. In previous version, my code was working fine even by calling the function every 5 ms. I can change my code accordingly
this is my complaint; all of a sudden things break for an application and we (apps writers) have to scramble to find out what caused it. I have to strongly disagree with how this was handled, guys. this is what temps me to LOCK DOWN all the dependances in any of my projects since too many things change under you if you dont. you should not have to do that (keeping local copies of critical system libs) but it seems that if you want your project to build and always build, you cant count on system libs staying working. how absurd is that?
These change were motivated by this comment. We had to decide between destroying hardware and a documented software breaking change. Locking down dependencies and reading breaking change list before updating them is a good practice.
I upgraded to 3.x and all the servo code went to 90degrees swing instead of 180
This however looks strange. You seem to be the first with such report. Are you using our embedded Servo library ?
Basic Infos
Platform
Settings in IDE
Problem Description
I am programming a useless box with a Wemos D1 mini. I use a servo : "myservo.write(pos); " Since the board update to V3.0.0, there is a delay in the servo write instruction (15ms as I could trace). If I go back to a later board version, this problem is no more present. The servo lib version is not changing anything.
MCVE Sketch
Time between the timestamps is 15ms as I use the V3.0.0 board.