Skip to content

XM10 Extension Module SDK v2.8.0

Release date: 2026-09-10 | Target boards: Rev 1.1 · Rev 2.0 | New: PC data tool xm10


At a glance

This release fills out the PC side far more than the firmware.

  • The PC data tool xm10 is now in the SDK. From a demo command that runs the whole pipeline with no board attached, to a live graph window, lossless logging, and CSV export — all from one script.
  • Total Data (0x20)'s 197 channels can now be decoded correctly on the PC. Until now the values came out mixed up and wrong.
  • Channel names you register now show up on the PC screen. Until now they only showed as ch0, ch1…
  • Example 35 was fixed. It registered channel names but never actually sent the values behind them.
  • The firmware itself barely changed. Everything in this document that affects behavior is all there is.

The star of this release — the PC data tool xm10

It lives in the SDK's Extension_Module/PythonDecoder/ folder. It wasn't there through v2.7.0 — starting this release it ships inside the SDK. For the full guide see PC data tool guide; below is just enough to get a feel for it.

Here's the first thing to try — and you don't need a board nearby for it.

cd Extension_Module/PythonDecoder
pip install pyserial pyqt5 pyqtgraph numpy
python xm10.py demo

It streams prepared data through the whole path once, and tells you at the end whether each item passed.

Command What it does
xm10.py demo Demonstrate the whole pipeline with no board attached
xm10.py ports List connected ports, flag ones that look like XM10
xm10.py recv Live graph window (--cli for console only)
xm10.py soak --minutes 30 Receive for a set time and check nothing was dropped
xm10.py export FILE --csv DIR Turn a saved .xmlog into CSV
xm10.py selftest Check the tool itself, no board needed

If you need a standalone executable, build_exe.py builds one. The version with the graph window is about 55.6 MB; --no-gui (console only, no graphs) is about 23.0 MB. After building, run selftest and demo on that executable once to confirm it actually works.

.xmlog — saving what arrives, exactly as it arrived

  • What arrives is saved to a file before it gets interpreted, byte for byte. Turning it into CSV can be done anytime afterward with export.
  • Channels the screen doesn't even draw (the system channel, 0x20) still go into the file in full.
  • If data goes missing partway through, that gap is recorded right in the file, so you can tell later where it happened.
  • Even if the file gets cut short (a crash, etc.), everything up to that point still reads back fine.
  • The graph window has a "Save .xmlog" checkbox, on by default. It saves to the same folder as the CSV.
  • File names: CSV is cdc_phai_<timestamp>.csv, xmlog is cdc_<timestamp>.xmlog.

Total Data (0x20)'s 197 channels now decode correctly on the PC

XM10 has already been sending these 197 channels at 1 kHz, but until now the PC side read them all as floats. In reality it's a mix of integers and floats, so the values came out corrupted.

This time xm10 was fixed to read each channel in its real format.

  • If you use a receiver you wrote yourself, keep this in mind: the data is 365 bytes, but what reaches the PC is 368 bytes — 3 zero-padding bytes get tacked on to round up to a 4-byte length unit.
  • Exported CSV columns are titled with the real channel name, like leftHipAngle. No more counting columns by number to find the one you want.

Your custom channels now get names

Firmware has always been sending the channel names you register with XM_SetUsbCustomMeta() — the receiving programs from before did not use them and showed ch0, ch1… instead. From now on xm10 uses the name.

  • Registered names appear in graph titles and CSV column headers.
  • This path doesn't carry the value's type, though, so the PC assumes float32 and says so on screen and in the CSV summary (⚠ type unknown — assuming float32).

Fixed — Example 35 MultiLayer Transparent Control

It registered 7 channel names (Gravity / DOB / Impedance / Total / Angle / Velocity / Mode, all in Nm·deg·deg/s) but never once called the function that actually sends the values. On the PC it looked like channels that had a name but would never receive data. Fixed on both Rev 2.0 and Rev 1.1.

The other examples that send data over USB do not have this problem.


4 things to keep in mind when using this

Already noted in places like example 09, but worth repeating now that channel names show up on their own.

  1. Struct members sent over USB must be float only.
  2. The number and order of the channel names registered in JSON must exactly match the number and order of the struct's members.
  3. Module ID must fall in 0xF0–0xFE.
  4. XM_SetUsbCustomMeta() keeps only one registration per connection. Call it more than once and the later call just overwrites the earlier one. Do not register channels one by one — gather them into a single call.

Example count

Rev 2.0 46, Rev 1.1 42 — same as v2.7.0.


Not yet done — please read

  • Not yet confirmed on a real XM10 board. This release's PC tool was checked only with prepared data and its own self-checks, and has not been tested against an actual XM10 board. Let us know if anything looks off once you try it.
  • The type of a channel's values (float, integer, and so on) does not reach the PC yet. Right now the board only sends the name — that's exactly why the PC always assumes float32, as noted above.
  • The --no-gui executable can't exercise the live-decoding path. The receiver itself needs PyQt5 to even start. selftest reports this on screen.

Two folders are renamed in the Rev 1.1 SDK

Two folder names change inside the Rev 1.1 SDK. Rev 2.0 already changed in v2.7.0; Rev 1.1 now matches.

Was Now
XM_FW/IOIF/ XM_FW/phoundation-ioif/
XM_FW/AGR_MW/ XM_FW/phoundation-mw/

If you use the SDK as shipped, there is nothing to do — the bundled CMakeLists.txt and .cproject already point at the new paths. Only change your own build scripts or project settings if you wrote the old paths there by hand. Includes that name only the file, like #include "ioif_agrb_uart.h", are not affected.


Compatibility

Item Notes
Existing firmware code Rebuild only. No public API removed or renamed
PC data tool Bundled with the SDK starting this release. Needs separate Python packages (pyserial pyqt5 pyqtgraph numpy)
Rev 1.1 Includes the Example 35 fix; nothing else in the firmware changed. The two folders above are renamed
Total Data / channel names Shared by Rev 1.1 and Rev 2.0

Downloads

File For
Rev2.0.zip Rev 2.0 board SDK (46 examples, includes PythonDecoder/)
Rev1.1.zip Rev 1.1 board SDK (42 examples, includes PythonDecoder/)
AGR_Bootloader.bin XM10 bootloader — same file as v2.6.0 (unchanged in this release)
SUIT_H10_Binary_20260820.zip KIT H10 firmware — same file as v2.6.0
SUIT_ContentsFiles_20260820.zip H10 content files — same file as v2.6.0

The three bootloader/H10 files are the v2.6.0 ones re-uploaded as-is. Only the XM10 side changed in this release; those are unchanged.

Extract to a short path (e.g. C:\xm10\). A deep path can hit the Windows path-length limit and break the build — that is a path-length problem, not a code problem.