Micropython encoder capture function sometimes takes 8 milli secs to reply

background, I have modified one of “Kevsrobots” burger bots to have 3 range sensors, left, forward and right.
This so our PI Wars team can test algorithms for escaping the maze.

At the moment it will navigate between two walls in a straight line and stop before it hits the end wall.

However, it occasionally decides to turn (say) left.

It occurred to me that this would happen if the demands are not being updated and it keeps a turn left demand on for too long a period.

I added some code to monitor how long the loop takes and on average it was 1 milli-second, with a maximum of about 8. Keeping a left demand on for 8 milli-seconds reproduces the problem.

I eventually tracked the source of the delay down to the encoder.capture() call.

I have stripped out all of the code for reading the range sensors PID etc and can reproduce the problem. See the code below.

import gc
import time
import math

from motor import Motor, pico_motor_shim
from encoder import Encoder, MMME_CPR
from pimoroni import Button, PID, NORMAL_DIR   , REVERSED_DIR

from machine import ADC, Pin

MOTOR_PINS_LEFT = pico_motor_shim.MOTOR_1          # The pins of the motor being profiled
MOTOR_PINS_RIGHT = pico_motor_shim.MOTOR_2          # The pins of the motor being profiled
ENCODER_PINS_LEFT = (16,17) #(17, 16)      # The pins of the encoder attached to the profiled motor
ENCODER_PINS_RIGHT = (15,14) #(17, 16)      # The pins of the encoder attached to the profiled motor
GEAR_RATIO = 100                         # The gear ratio of the motor
COUNTS_PER_REV = 28 * GEAR_RATIO  # The counts per revolution of the motor's output shaft

DIRECTION = NORMAL_DIR                  # The direction to spin the motor in. NORMAL_DIR (0), REVERSED_DIR (1)
SPEED_SCALE = 1.0 #5.4                       # The scaling to apply to the motor's speed to match its real-world speed

UPDATES = 100                           # How many times to update the motor per second
UPDATE_RATE = 1 / UPDATES


led = Pin(25, Pin.OUT)
# Free up hardware resources ahead of creating a new Encoder
gc.collect()

# Create a motor and set its speed scale
mLeft  = Motor(MOTOR_PINS_LEFT, direction=DIRECTION, speed_scale=SPEED_SCALE)
mRight = Motor(MOTOR_PINS_RIGHT, direction=REVERSED_DIR, speed_scale=SPEED_SCALE)

# Create an encoder, using PIO 0 and State Machine 0
encLeft  = Encoder(0, 0, ENCODER_PINS_LEFT, direction=DIRECTION, counts_per_rev=COUNTS_PER_REV, count_microsteps=True)
encRight = Encoder(1, 0, ENCODER_PINS_RIGHT, direction=DIRECTION, counts_per_rev=COUNTS_PER_REV, count_microsteps=True)

# Create the user button
user_sw = Button(pico_motor_shim.BUTTON_A)

# Enable the motor to get started
mLeft.enable()
mRight.enable()

led.on()

timeDiff = 0
iterationCount = 0
tmax = 0
tmin = 10
bmonCount = 0
tgt9 = 0
turnCount = 8
turning = 0
letsGo = True
# Continually move the motor until the user button is pressed
while (not user_sw.raw()) and letsGo == True:
           
    # Capture the state of the encoder
    timeStart = time.ticks_ms()
    captureL = encLeft.capture()
    captureR = encRight.capture()
    iterTime = time.ticks_diff(time.ticks_ms() , timeStart )

    mLeft.speed(1.0)
    mRight.speed(1.0)
    
    timeDiff += iterTime
    if iterTime > tmax:
        tmax = iterTime
    if iterTime < tmin:
        tmin = iterTime
    iterationCount +=1
    if iterTime > 5:
        tgt9+=1
    time.sleep(UPDATE_RATE)


if letsGo:
    led.on()
else:
    led.off()
# Disable the motor
mLeft.disable()
mRight.disable()

print('average : {0} min :{1} max :{2} greater than 5 msecs: {3} for {4} iterations of loop'.format(timeDiff / iterationCount

When I run this output is typically as below:
average : 0.2248866
min :0
max :8
greater than 5 msecs: 4
for 1543 iterations of loop

It has only exceeded 5 msecs for 4 out of 1543 iterations.

I am using a Pico Lipo plus motor shim and the Pimoroni version of micropython.

Any suggestions as to what to try?

I am not sure what version of micropython I am using

Steve