RP2350 L Motor encoder signal not being read, please raise ticket

Hello,

I have an RP2350 XRP kit purchased from DigiKey in May. installation_verification.py completes successfully. I have had trouble with controlling the robot from day 1; today I have investigated the problem stated in the topic title, using the code below:

from XRPLib.differential_drive import DifferentialDrive
import time
d = DifferentialDrive.get_default_differential_drive()

d.reset_encoder_position()
d.set_effort(0.4, 0.4)
time.sleep(2)
d.stop()
print(d.get_left_encoder_position(), d.get_right_encoder_position())

d.reset_encoder_position()
d.set_effort(0.4, -0.4)
time.sleep(2)
d.stop()
print(d.get_left_encoder_position(), d.get_right_encoder_position())

I get the following result:

-0.0 91.76673
-0.0 -83.1636
and similar results after a) swapping physical motors L-R AND b) swapping motor connector cables from L-R. In all cases the R motor turns but the L motor does not. This behavior is consistent with earlier issues.

It looks like the motors and cables are OK, but the RP2350 is failing to read the L encoder. Do you agree?

What needs to be done to resolve this issue?

Thank you for your help.

Jon

If you inspect the connectors/headers, do any of the pins on the L shroud appear bent?

Yes, I have been inspecting the pins while making changes, they look straight and show no sign of distress. Thanks for helping.

More troubleshooting with help from Gemini. Using this code:
from machine import Pin
import time

Pin assignments for SparkFun XRP RP2350 Motor L Encoders

ENC_A_PIN = 30
ENC_B_PIN = 31

Global pulse counter and state tracking

pulse_count_a = 0
pulse_count_b = 0

def handle_encoder_a(pin):
global pulse_count_a
pulse_count_a += 1

def handle_encoder_b(pin):
global pulse_count_b
pulse_count_b += 1

Configure pins with internal pull-ups (required for open-drain Hall sensors)

enc_a = Pin(ENC_A_PIN, Pin.IN, Pin.PULL_UP)
enc_b = Pin(ENC_B_PIN, Pin.IN, Pin.PULL_UP)

Attach interrupts on falling/rising edges

enc_a.irq(trigger=Pin.IRQ_RISING | Pin.IRQ_FALLING, handler=handle_encoder_a)
enc_b.irq(trigger=Pin.IRQ_RISING | Pin.IRQ_FALLING, handler=handle_encoder_b)

print(f"Monitoring Motor L Encoders on GPIO {ENC_A_PIN} (A) and GPIO {ENC_B_PIN} (B)…")
print(“Spin the left wheel manually by hand.”)

last_a = -1
last_b = -1

while True:
val_a = enc_a.value()
val_b = enc_b.value()

print(f"RAW STATES -> Pin {ENC_A_PIN} (A): {val_a} | Pin {ENC_B_PIN} (B): {val_b} | Counts -> A: {pulse_count_a}, B: {pulse_count_b}")

time.sleep(0.25)

Result is:
RAW STATES → Pin 30 (A): 1 | Pin 31 (B): 0 | Counts → A: 895, B: 0
RAW STATES → Pin 30 (A): 1 | Pin 31 (B): 0 | Counts → A: 895, B: 0
Gemini says:
The test output isolates the problem to GPIO 31 (Motor L Encoder Channel B).

  • GPIO 30 (Channel A): Functioning normally (logic level toggled/held high at 1, counter accumulated 895 pulses).

  • GPIO 31 (Channel B): Completely dead/stuck. The state is permanently locked at 0, and count is 0.

Since you already swapped known-working motors/cables, the issue is a hard short to Ground (GND) or a damaged RP2350 GPIO pin on the board.

I’m waiting for batteries to charge, before conducting more suggested tests, and potential workaround:
Physical Troubleshooting Sequence

Step through this process with power off to identify the precise fault point on GPIO 31:

1.Disconnect Motor Connector:Power OFF.

Unplug the Motor L JST cable from the board completely so the Motor L header pins are exposed with no external cable attached. Run the MicroPython script again.

  • Verification: If Pin 31 switches from 0 to 1 (due to the internal PULL_UP), the short was inside the board’s female header socket contacts. If it stays 0, the short is on the PCB or inside the RP2350.

2.Check Resistance to Ground:Multimeter Continuity Mode.

With power disconnected, place one DMM probe on board GND and the other probe directly on the GPIO 31 pin at the Motor L header.

  • Verification: A reading near $0\,\Omega$ confirms a physical short circuit to GND on the PCB trace (e.g., solder bridge or shorted ESD protection diode). A high resistance reading indicates an internal RP2350 failure.

3.Inspect Board Solder Joints:Visual / Magnification.

Examine the JST header solder pads for Motor L and the corresponding RP2350 pin trace for GPIO 31 under a microscope or magnifying glass.

  • Verification: Check for tiny solder bridges between the GPIO 31 pin pad and adjacent ground planes or adjacent grounded pins.

GPIO Pin Damage Risk

If GPIO 31 measures near $0\,\Omega$ directly at the RP2350 IC pin even with no external connections, the internal input buffer transistor for GPIO 31 on the RP2350 silicon has shorted internally to GND (often caused by an ESD event or an over-voltage spike on the encoder line).

Software Workaround (If Pin 31 Silicon is Blown)

If GPIO 31 is permanently damaged in silicon, you can bypass it by jumpering the Channel B signal line on the PCB to an unused GPIO pin (e.g., an available expansion header pin) and updating the pin configuration in MicroPython:

Python

# Change Channel B from dead GPIO 31 to an alternate free pin (e.g., GPIO 16 or free QWIIC/expansion pin)
ENC_B_PIN = 16  

Gemini has “switches to 1” pointing at the header socket, when that result actually clears the board and points at the encoder/cable instead which is backwards. Unplugging the connector removes the cable/encoder from the circuit; only the board trace and header socket remain attached to GPIO31.

  • Pin goes HIGH after unplugging → board side is clean; the fault is in the cable or encoder itself (external).
  • Pin stays LOW after unplugging → something still connected (trace, solder joint, socket, or the GPIO silicon) is shorting it somewhere (board-side).

Do this first, before DMM/microscope work: power off, swap the Motor L and Motor R connectors, rerun the script.

  • Dead channel follows the motor → bad encoder/cable, not the board.
  • Dead channel stays on GPIO31 regardless of motor → confirms board/GPIO fault, then Steps 2–3 are worth doing.

Give that a look-see before trying the other steps

Doh! RTFM was right. Pin 031 was damaged, now physically broken. Using Motor3 for left wheel is working. Eventually I’ll replace the board. Thank you so much for your help.

No worries!