Yukon Firmware updates with latest Micropython 1.26

I would like to use some features from the latest Micropython 1.26 libraries such as I2CTarget.

Looking at the Yukon download pages there doesn’t seem to have been an updated firmware in over a year.

Can we expect an updated firmware? Is it possible to create an updated firmware ourselves?

I like the Yukon, but there doesn’t seem to be a lot of development since it was released.

There’s not been much demand for updated firmware after Wireless support was added, and there’s not been many MicroPython features that Yukon would benefit from. As such, updates tend to come when people ask, like you have now ;).

I can see the value of having I2CTarget, so I spent all of this morning updating the firmware to 1.26. Most of it was straightforward but a few things got broken and took a while to resolve.

The new firmware can be found here (you will need to be logged in to download).

I’ve done my usual board tests and the firmware seems to be working. I will hold off for a while before tagging it as an official release though in case any problems arise.

Note, for I2CTarget you will need to use I2C1 pins, which are exposed on the module slots. The I2C0 on the QwST ports is shared with internal functions of the board so cannot be changed from a host.

Firstly - thanks a lot for doing this and quickly - I really appreciate it.

I have hit a problem with Serial Bus Servo module with the new firmware (I am using the Wifi version).

Trying to do a scan of the available servos I am seeing

00: – → Output disabled
finally: Done!
Traceback (most recent call last):
File “”, line 486, in
File “/lib/pimoroni_yukon/devices/lx_servo.py”, line 247, in detect
RuntimeError: Serial Servo #2 incorrectly reported its ID as None

I am happy put some time into a simple stripped down repro of this if needed.

Are you able to verify if this error also occurs with the previous firmware? Nothing should have changed with Serial Bus Servo on the new firmware, but it is quite possible some underlying MicroPython function used by that file has changed.

Specifically something in this function: yukon/lib/pimoroni_yukon/devices/lx_servo.py at e2c5f83493c7928d29aba80c1c837c1f97c14a1f · pimoroni/yukon · GitHub

Edit: Looking at that function suggests no data is getting returned by your servo, of its not getting detected. As in, the data_buffer is None so no ID can be determined. That is populated by the handle_receive function: yukon/lib/pimoroni_yukon/devices/lx_servo.py at e2c5f83493c7928d29aba80c1c837c1f97c14a1f · pimoroni/yukon · GitHub

Also, does it occur 100% of the time or just a few times? I know I’ve had situations where the timings just happen to be off on one run, but then I re-run the exact same program and it is fine.

Fine with the previous firmware and happening all the time.

Thanks for confirming. I don’t suppose you have any equipment to be able to scope the data lines to confirm if data is making its way to/from the servo?

I’ve done some digging, and the cause of the issue is a MicroPython feature actually getting fixed between Yukon’s launch and now. rp2/machine_uart: Make it so TX is done only when no longer busy. · micropython/micropython@97af100 · GitHub

Previously when transmitting data to the servo, the txdone() function would return before the final byte had been sent, so to work around that I introduced a time delay in the LXServo code: yukon/lib/pimoroni_yukon/devices/lx_servo.py at e2c5f83493c7928d29aba80c1c837c1f97c14a1f · pimoroni/yukon · GitHub

With this newest build that time delay causes the switch from TX to RX to occur too late, resulting in the error you encountered. The solution, remove that sleep line.

I will generate a new build, but to fix things on your end, edit your lxservo.py file and replace the wait_for_send function with this:

def wait_for_send(uart):
    # As of MicroPython 1.24 txdone now waits for all data to be transmitted:
    # https://github.com/micropython/micropython/commit/97af1001ae07c573bf432b9923dcdf78055a508c

    # Wait for all the data to be sent from the buffer.
    while not uart.txdone():
        pass

Just a head’s up, you may still get times where the code gives that error back. I’ve done more runs, there can be occasions where the servos start talking before the switchover has occurred. It’s no longer the 100% as it was before though.

A good case:

A bad case:

Sadly there’s no quick fix I can do for this. The long term solution would be to write a Half-Duplex UART system for the PIO, but that will take significant time and is unlikely to get tasked to me any time soon.

Thanks for digging into this. I have retried the new firmware with the lxservo.py patch you suggested and getting the same results as you suggested - works fine sometimes, others fails with the same error.

Is this something that a try catch retry is likely to help with? Is the issue going to be mainly on initialization discovery or any setting and reading of the servo state?

A try catch retry would certainly help, in the hope timings work in your favour on a repeated try.

For that it would make sense to comment out this line from lxservo.py and call verify_id() from your own code where you have better control over repeated calls. yukon/lib/pimoroni_yukon/devices/lx_servo.py at 1658744238a6b830dffa8a1bf520813207e8c04a · pimoroni/yukon · GitHub

Though I’ve found that once a servo passes the initialisation check its timing tends to remain consistent. For example, I ran drive_servo.py and once passed that check all readings afterwards worked without issue.

Yes, the issue will occur any time you want to read data back from a servo. Just sending data will not have the issue, but then you’re also hoping the servo does what it’s told. Since that’s the same situation as you get with regular RC servos then that’s no real loss.

Hmm, this may be a workaround: class UART – duplex serial communication bus — MicroPython latest documentation

@mackemjohn Well, that was fruitful!

Changed to using IRQ to switch UART from TX to RX · pimoroni/yukon@21bbf48 · GitHub

Give that a go and see how it behaves. Switchover timings look better on my end though

Is this patch instead of or as well as the change to LXServo.py

Instead of. You should be able to revert back to the original lxservo.py that calls verify_id(). Though there is no harm in keeping it and doing the try catch repeat we talked about.

Oh, the change to wait_for_send(). Keep that.

Just wanted to report in on progress. So far things are looking pretty good but a lot more testing needed and development my end.

I have seen one instance of Servo ID reported as None in 10s of restarts, but looking pretty good.

As a result of the new firmware I am now able to have

4xBig Motor Encoder

1xSerial Servo

1x Wifi (for analysis and tuning of robot state when not connected via a USB Cable)

and Pi5 talking to Yukon over i2c via GP26/27.

Also I have the board running at 12V with a small breakout board to take the Serial Servo signals from the Yukon but feed the LX-16A servos 7.8V. This is allowing me to run 12V Motors (although I may upgrade these to Dynamixel or other Servos in the future for the wheels for better control).

Until this firmware upgrade I was struggling to get all of the modules I needed on one Yukon (I own 3 now and was expecting to have to use at least 2 of them to get the collection of modules I needed) as I was using a Proto board for UART from the Pi5 to the Yukon.

I am upgrading a 4 Wheel Diff Drive robot to a 4 Wheel Steer Robot which is why I need all of the different module combinations.

Thanks for taking the time and effort to do the Firmware upgrade and chase down the issues.

Thanks for the update. I’m glad you’ve finally been able to get Yukon working as you have been wanting!

You may be able to get better results by tweaking the number on this line. yukon/lib/pimoroni_yukon/modules/serial_servo.py at 21bbf48a9179b5e89d165718100882d8b20f12ff · pimoroni/yukon · GitHub

I chose a value that seemed to yield good results for me, but maybe 37500000 or 38500000 would be better (or even finer adjustments). If you find a more reliable value, let me know.

It’s a shame we never made a regulated serial servo module. At the time we were really unsure how much demand there would be for driving such servos, as we hadn’t made a product for them before. Glad to hear you have a workaround.

You’re most welcome. Yukon is my passion product, so if I’m always happy to help anyone get things working, even if I cannot dedicate much work time to updating firmware versions or adding new features.

Once you’re happy with how things are working with your robot, any chance you could leave a review for Yukon? It really helps others know what the board is capable of. Reviews - Write a Product Review