-
Hello, I am working on a project where I would like to move ten MG90S servos from a webpage with ten respective buttons (left or right). I tested them separately using REPL and they were perfectly working, but then then when I built the webpage (which calls a simple API) and started clicking on the buttons, after a few clicks the servos started to move randomly. At the beginning I thought it was wiring, so I checked it, then power, so switched to external power supply, or the wifi messing up with the PWMs, so I disabled everything and I narrowed the problem down to the following code, where the problem persists: import time
from machine import Pin,PWM
class Servo():
def __init__(self, pin):
self.pwm = PWM(Pin(pin))
self.pwm.freq(50)
# Don't move
self.pwm.duty(0)
def left(self):
print('Left')
self.pwm.duty(106)
time.sleep(0.5)
def right(self):
print('Right')
self.pwm.duty(114)
time.sleep(0.5)
servo_pins = [14,12,23,22,27,25,21,26,19,18]
servos = []
for servo_pin in servo_pins:
servos.append(Servo(servo_pin))
print('Running...')
while True:
for servo in servos:
servo.left()
for servo in servos:
servo.right() Example output:
I have done search for similar discussions both on the archive forum and here but could not find much. What am I missing? MicroPython v1.22.2, Board ESP32 / WROOM (https://micropython.org/download/ESP32_GENE) |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 7 replies
-
The loop will run much faster than the servos can respond. Add a delay: while True:
for servo in servos:
servo.left()
time.sleep_ms(700)
for servo in servos:
servo.right()
time.sleep_ms(700) |
Beta Was this translation helpful? Give feedback.
-
So, I think I found out where the issue was: basically, power consumption. However, what I experienced is a bit more complex, so I am writing it down here for future reference. The ESP32 MicroPython docs say that, to move a servo, you can just connect it to the board pins. Which works fine. So, since in my project my ten servos would never move simultaneously, I thought "ok, so I am going to do the same thing but on ten different pins". What I did not consider is that the when a servo receives a PWM signal telling it to move to a given position, and that signal persists, the servo does consume power to stay hold still in that position. And if in that position the servo is in a slightly stall state (e.g. because there is something blocking its movement, even just the last bit of it) then power consumption spikes up a lot (full stall is reported to be about 700 mA!). So long story short I could reproduce the issue with just two servos by holding one of them still with my hand (and they went crazy). I don't know if there is something else involved, as electrical issues possibly including ground connections, although the circuitry is pretty simple (just jumper wires and a common ground). I was able to work around the issue by completely disabling the PWM output to the servos while not moving them. I could not use the duty cycle because of the (other) issue with PWMs I outlined in my previous post, but I achieved the goal by setting the pins as an input pins. The following code works, but sometimes I still see some servos moving in a way that does not seem fully "right" to me. I don't know how to reproduce it though, and for now it's ok for me so I'm keeping it this way, also because I'm not expert in electronics and I don't know how I could improve that part. Thank you both @GitHubsSilverBullet and @peterhinch for your help in pinpointing the main problem! class Servo():
def __init__(self, pin):
self.pin = pin
self.pwm = PWM(Pin(pin))
self.pwm.deinit()
Pin(self.pin, Pin.IN)
def left(self):
print('Left')
self.pwm.init(freq=50, duty=105)
time.sleep(0.2)
self.pwm.deinit()
Pin(self.pin, Pin.IN)
def right(self):
print('Right')
self.pwm.init(freq=50, duty=115)
time.sleep(0.2)
self.pwm.deinit()
Pin(self.pin, Pin.IN) |
Beta Was this translation helpful? Give feedback.
-
A servo is a closed loop system: if you supply a constant pulse width it will move to that position. If any thing tries to move the motor from that position, the feedback loop will apply torque to the motor to try to restore its position. This consumes power. If you stop supplying pulses the servo loop becomes inoperative, and stops consuming power. The spindle will not resist applied torque (although the effect of the internal gearbox will probably cause it to stay put). |
Beta Was this translation helpful? Give feedback.
So, I think I found out where the issue was: basically, power consumption. However, what I experienced is a bit more complex, so I am writing it down here for future reference.
The ESP32 MicroPython docs say that, to move a servo, you can just connect it to the board pins. Which works fine. So, since in my project my ten servos would never move simultaneously, I thought "ok, so I am going to do the same thing but on ten different pins".
What I did not consider is that the when a servo receives a PWM signal telling it to move to a given position, and that signal persists, the servo does consume power to stay hold still in that position. And if in that position the servo is in a slightly st…