madhephaestus / ESP32Servo

Arduino-compatible servo library for the ESP32
138 stars 53 forks source link

.write sometimes won't work #25

Closed Alex-Scheff closed 2 years ago

Alex-Scheff commented 2 years ago

I'm working on an engine controller. A servo controls the throttle plate. It works pretty well with only one exception: Sometimes when doing a ''blip'' (opening up the plate for 100ms) it just won't do it. It's random, sometimes it works, sometimes it doesn't. A workaround for that is to detach and immediately reattach the servo before doing the blip. Do you have an idea why it might do that?

The servo related code snippets: `// Servo Init

ESP32PWM::allocateTimer(0); ESP32PWM::allocateTimer(1); ESP32PWM::allocateTimer(2); ESP32PWM::allocateTimer(3); throttleServo.setPeriodHertz(330); if(throttleServo.attach(servoPinThrottle, 900, 2100)){ Serial.println("ThrottleServo attached successfully"); } else { Serial.println("No connection to ThrottleServo, this is BAD"); Serial.println("Engine can't start, ignition is cut!"); digitalWrite(ignitionCutRelaisPin, HIGH); Serial.println("Infinite loop starting now..."); for(;;); } throttleServo.write(servoMinDegree); delay(5);`

`void handleThrottleServo(){ // Get's called every time in Loop

switch(throttleMode){ case 1: // Low Power Linear Mode servoMapOben = servoMaxDegree + 40; break; case 2: // Mid Power Linear Mode servoMapOben = servoMaxDegree + 20; break; case 3: // High Power Linear Mode servoMapOben = servoMaxDegree; break; } if(waterTempAfterIntercooler < coolantTempSetValue){ // Wenn Kühlmitteltemperatur unter 30 Grad Leerlaufdrehzahl erhöhen servoMapUnten = servoMinDegree - 15; // Muss später getestet werden und eventuell etwas höher gesetzt werden } else { servoMapUnten = servoMinDegree; } servoDegree = map(smoothedPotValue, linearPotLowValue, linearPotHighValue, servoMapUnten, servoMapOben); if(launchControlActive){ int8_t rpmDif = drehzahlSpeedRaw - drehzahlFront; // Die zwei werden nie genau gleich sein, ein Fehlerbereich muss vernachlässigt werden dürfen. Wie hoch? Die 0 muss später angepasst werden. Lenkwinkel notwendig? if(rpmDif > 10){ // Wenn rpmDif größer Null ist dann dreht die Hinterachse durch lcVal--; } else if(rpmDif <= -11){ lcVal = 0; } servoDegree =+ lcVal; } throttleServo.write(servoDegree); }`

`void throttleBlipFunction(){ // Get's called every time I'm trying to downshift

if(!throttleBlipActive){ throttleServo.detach(); throttleServo.attach(servoPinThrottle, 900, 2100); throttleServo.write(servoMaxDegree); //Serial.println("Throttle Blip aktiv"); switch(gear){ // Zeiten später nach Tests anpassen case 2: timeDelayThrottleBlip = 200; break; case 3: timeDelayThrottleBlip = 180; break; case 4: timeDelayThrottleBlip = 160; break; case 5: timeDelayThrottleBlip = 140; break; case 6: timeDelayThrottleBlip = 120; break; } startTimeThrottleBlip = millis(); throttleBlipActive = true; } else if(millis() >= startTimeThrottleBlip + timeDelayThrottleBlip){ throttleBlipActive = false; } }`

madhephaestus commented 2 years ago

can you verify the blip never fires with a scope? Also its a tight timing for a hobby servo, depending on the time in the cycle of the PWM cycle you could be in between the pulses when you set the new PWM. New values arent loaded until the next cycle, so that can be 30 ms away. You might be asking the servo to respond without enough control pulses? How many pulses does your servo need before it passes the runt rejection? (that will be a per servo difference) For an application this tight riming you might want to look into a 333 or 300 hz servo, they can be driven much faster than standard hobby servos, but are a bit more rare.

Alex-Scheff commented 2 years ago

Unfortunately I don't have a scope to measure the pulses. I'm using an 330Hz Servo, so ist should be fast in responding to the inputs. Any way to speed up the cycle speed? 30ms delay is quite a lot.

madhephaestus commented 2 years ago

It looks like that code already has it set now that I read it.

I think it's time to invest in an o-scope, Intermittent code is highly unlikely, but over aggressive runt rejection in the servo might behave like this. Can you use your phone as high speed camera to see if it twitches even a little?

You could also make a diagnostic tool out of a second esp32 and a little screen. Have the esp measure the time the pulse is high to the screen every ms, and use your phones slow mo mode to see the servo and screen in frame. Then you should see the pulse be read by second esp, and the servo move or not move in the same vid.

Debugging servos is tough, mostly because they have a microcontroller inside making its own decisions. The esp32 supports encoders, and I wrote a threaded motor controller in RBE1001lib. Then you can use a generic motor with encoder and can get much tighter control.

On Tue, May 24, 2022, 3:48 AM Alex-Scheff @.***> wrote:

Unfortunately I don't have a scope to measure the pulses. I'm using an 330Hz Servo, so ist should be fast in responding to the inputs. Any way to speed up the cycle speed? 30ms delay is quite a lot.

— Reply to this email directly, view it on GitHub https://github.com/madhephaestus/ESP32Servo/issues/25#issuecomment-1135528518, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAJSKRX43B5DTME3YTBDXBLVLSCVBANCNFSM5WWI26TQ . You are receiving this because you commented.Message ID: @.***>

Alex-Scheff commented 2 years ago

Void handleThrottleServo(); won't get called if the blip function is active, so the handle function can't overwrite the blip function. Furthermore the servo I'm using is very fast and when the blip wont work there is just no movement at all, no twitching. I'll post a video when I'm back home.

Alex-Scheff commented 2 years ago

Working Blip: https://youtu.be/D0A0Q7E0AcE

Not working Blip: https://youtu.be/Ziu_hf0HACs

madhephaestus commented 2 years ago

can you confirm with a print statement that the servo is being told to move but is not moving?

Alex-Scheff commented 2 years ago

Yes, I use .print to debug most of my code. The function gets called every time and the Servo is told to move every time

madhephaestus commented 2 years ago

get rid of the extra detach and attach and add 'servoMaxDegree' to the print statement.

There is a lot of stateful code that can effect things. I am not able to reproduce your error, so i need a clear example of it not working to suspect the underlying library. Can you include the print statements in the background of the video of it not working? I would also be interested to see if the core is resetting (which could be seen in print statements). Also be sure to set the print terminal speeds to 115200, so you can see the core startup print statements.

madhephaestus commented 2 years ago

this seems more like user code, no demonstration of a fault in the library was found