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
xm10is now in the SDK. From ademocommand 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.
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 iscdc_<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.
- Struct members sent over USB must be float only.
- The number and order of the channel names registered in JSON must exactly match the number and order of the struct's members.
- Module ID must fall in
0xF0–0xFE. 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-guiexecutable can't exercise the live-decoding path. The receiver itself needs PyQt5 to even start.selftestreports 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.