I'm trying to control a robot that has Nema stepper motors, UART to communicate with the host and an SSD1306 I2C display.
I'd like the wheels to run as stable and smooth as possible, so I found this code: https://github.com/jeffmer/micropython- ... stepper.py
The idea is that a timer is used to execute a stepper callback which is executed at a very high frequency and then the callback decided whether to send a pulse to a stepper diver board.
Every second I also read current and voltage from an INA219 board using I2C, display results on a display and also send them to UART.
The problem is that every second the motors "stutter" so it seems like LCD/UART code has a priority over the timer.
My limited understanding was that the timer would pause everything else going on, execute, and then return control to the main loop, but it seems like as long as the main loop is busy the timer is not called or delayed.
Here is a snippet of the code:
Code: Select all
m1 = Stepper(18, 19)
m2 = Stepper(20, 21)
motors_en = Pin(22, Pin.OUT)
motors_en.high()
def step_cb(t):
global m1, m2
m1.do_step()
m2.do_step()
tim = Timer()
tim.init(freq=10000, mode=Timer.PERIODIC, callback=step_cb)
def update_power():
global screen, uart
voltage = ina.bus_voltage
current = ina.current
# screen.battery_status(voltage, current) # screen is a wrapper around SSD1306 library using I2C
# send('P:' + str(voltage) + ',' + str(current)) # just sends data over UART
report_deadline = utime.ticks_add(utime.ticks_ms(), 200)
while True:
if uart.any() > 0:
c = uart.read(1)
if c == b'\n' and len(buffer) > 0:
on_command(buffer.decode('utf-8'))
buffer = b''
elif len(buffer) > 0 or (len(buffer) == 0 and c == b'C'):
buffer += c
if utime.ticks_diff(report_deadline, utime.ticks_ms()) < 0:
report_deadline = utime.ticks_add(utime.ticks_ms(), 1000)
update_power()
Or restructure the code in a way that allows for "step_cb" callback to be always executed on schedule?
Cheers,
Leonti