Bug Report: Onboard LSM6DS3 IMU Fails to Initialize After Interrupted DFU Sessions on XIAO nRF52840 Sense (Qbead Hardware) — Resolved by Full Power Cycle
Summary
The onboard LSM6DS3(TR-C) IMU on two independent Qbead units (Seeed XIAO nRF52840 Sense) stopped initializing after a period of unstable DFU mode / firmware upload activity. LSM6DS3::begin() consistently returned a non-zero (failure) status code, and a direct WHO_AM_I register read (address 0x0F) returned 0x00 instead of a valid chip identifier, with accelerometer output flat at 0.00 on all axes. The issue was reproduced identically across two separate toolchains (PlatformIO and the official Arduino IDE + Seeeduino package) and two separate physical boards, which initially pointed toward a possible hardware defect. This conclusion was incorrect. A full battery drain followed by re-flashing the exact same, previously-failing firmware resolved the issue on both affected units. This confirms the root cause was some transient MCU/peripheral state corruption requiring a true power-off cycle to clear — not a hardware defect, library bug, or toolchain issue.
Environment
| Component |
Detail |
| Board |
Seeed Studio XIAO nRF52840 Sense |
| Onboard sensor |
LSM6DS3 / LSM6DS3TR-C, expected I2C address 0x6A |
| Toolchain A |
PlatformIO on VS Code, platform Seeed-Studio/platform-seeedboards, board id seeed-xiao-afruitnrf52-nrf52840, framework arduino |
| Toolchain B |
Arduino IDE, board package Seeeduino:nrf52 v1.1.13, FQBN Seeeduino:nrf52:xiaonRF52840 |
| Sensor library |
seeed-studio/Seeed Arduino LSM6DS3, tested at both 2.0.5 and 2.0.7 |
| Firmware under test |
Qbead's own Qbead.h; IMU-reader example, Dynamical Decoupling simple example, minimal standalone I2C diagnostic sketches |
| Host system |
Windows, Lenovo Legion Pro 5 |
| Units tested |
2 physically separate, previously untouched XIAO nRF52840 Sense boards |
Reproducibility
Consistently reproducible prior to the fix, across:
- Board 1/2 + PlatformIO
- Board 1/2 + Arduino IDE
- Library version
2.0.5 and 2.0.7 (no behavioral difference)
- Both the full Qbead firmware, inc. some of its examples, and minimal standalone diagnostic sketches
Consistently resolved on both boards after a full battery drain + re-power + re-flash of the same firmware that had previously failed (see Resolution).
Symptoms (Prior to Fix)
Qbead::begin() printed [ERROR]{IMU} IMU failed to initialize.
- Standalone diagnostic sketch:
myIMU.begin() returned 1 (non-zero = failure).
- Direct WHO_AM_I register read (
0x0F) returned 0x00, not a valid chip ID.
readFloatAccelX/Y/Z() returned a flat 0.00 on all axes continuously, unchanged by physical movement.
- No I2C bus hang using the intended
Wire object — the transaction completed cleanly but returned invalid/zeroed data.
- NeoPixel driver and BLE advertising (Bluefruit) continued to initialize and run correctly; only the IMU path was affected.
Impact
- Any Qbead feature depending on IMU data was non-functional: Bloch-sphere orientation rendering, tap detection, BLE-notified accelerometer/tap characteristics.
- Confirmed to have worked correctly earlier in the same session, on one device, (LED tracked physical rotation) before regressing during a period of repeated bootloader entry/exit and USB instability. Thus rendering the device's interactivity dead.
Root Cause
Transient corruption of MCU or IMU peripheral state, caused by an unstable/interrupted upload session, that persisted across normal resets and firmware flashes and was only cleared by a genuine full power-off cycle.
Given the board's onboard battery and, to my knowledge, no method to manually instruct a full power-cycle meant that all reset attempts (single reset, double-tap-to-DFU-mode, re-flashing, even multi-minute unplug periods) never actually achieved a true cold restart, and therefore never had the chance to clear whatever internal state was left in a bad configuration.
A likely contributing sequence, based on the debugging timeline:
- Repeated USB port enumeration and at least one interrupted/marginal DFU session (correlated with use of an unstable side-mounted USB-A port on the host laptop; see USB Port Note below) occurred around the time the IMU stopped initializing. In general many DFU-mode / reset button instructions and firmware upload attempts were attempted in a relatively short time period.
- This is possibly consistent with some documented nRF52-series behavior: Nordic Semiconductor's errata documentation confirms that certain peripheral register states are not cleared by watchdog, CPU lockup, soft, or pin resets on this chip family. This goes a little far into the weeds of the hardware specifics, hence I did not verify this assertion extensively or used it to resolve the issue.
- Only forcing a full discharge of the onboard battery (via sustained maximum-brightness LED load) achieved a true power-on reset, which resolved the issue on both independently-tested units upon the first re-flashing of the same firmware after the battery had drained (LED's gone off).
This rules out a broken hardware issue. Especially given the exact same behaviour occurred on two factory new Qbeads. This is further supported by the brief correct behaviour of the IMU tracking physical rotation after a serial monitor triggered the already flashed firmware on one of the devices. This was before any successful firmware upload was performed.
Resolution
- Force a full battery discharge: flash a minimal sketch that sets all NeoPixels to maximum brightness/full white and leaves them on continuously, and let the board run until the LEDs went dark on their own (battery depleted below operating voltage).
- Allow the board to rest, fully unpowered, for a period of time.
- Reconnect USB power and re-flash the exact same firmware that had previously failed (no code changes).
- IMU initialized successfully on both affected boards; accelerometer readings responded correctly to physical movement.
No firmware, library, or configuration changes were required — the fix was exclusively a full power cycle.
USB Port Note (Related Finding)
Earlier upload/connectivity instability (frequent COM port drops, PermissionError 13, semaphore timeouts) correlated with use of a side-mounted USB-A port on the host laptop (Lenovo Legion Pro 5). Lenovo's own published specifications confirm side and rear USB-A ports on this model line are wired as distinct ports, differing in USB generation/controller rather than being interchangeable. Switching to a rear USB port resolved the connectivity instability. This is the most likely trigger for the interrupted/marginal upload session that is suspected to have caused the transient IMU state corruption described above, though the exact causal mechanism remains unconfirmed at the register/peripheral level.
Debugging Steps Performed (Condensed)
- Resolved PlatformIO/Windows upload tooling issues (USB COM port instability, expected COM port reassignment after upload/reset).
- Observed regression to
[ERROR]{IMU} IMU failed to initialize following a period of repeated bootloader entry/exit and USB instability, later correlated with an unstable side USB port.
- Built minimal standalone I2C diagnostic sketches to isolate the IMU from BLE/NeoPixel code.
- Ruled out a missing IMU power-enable gate (not relevant to this board variant).
- Read the WHO_AM_I register directly, obtaining
0x00.
- Tested library version sensitivity (
2.0.5 vs 2.0.7, full cache clear) — no change.
- Cross-validated under the official Arduino IDE + Seeeduino board package, independent of PlatformIO — identical failure.
- Cross-validated on a second, independent, previously untouched board — identical failure.
- Attempted a full power-cycle via forced battery drain (maximum-brightness LED load).
- Re-flashed the same, previously-failing firmware after the drain-and-rest period — IMU initialized correctly on both boards.
Suggested Follow-Up
- Potentially document this failure mode and its resolution for other Qbead users/maintainers in a Troubleshooting addition of the installation README. Since the underlying trigger (interrupted DFU session leaving peripheral state corrupted until a true power cycle) is plausible to occur for other users; it may present itself after interrupted DFU uploads due to different root causes.
- Consider whether a firmware-level workaround exists. Such as an explicit peripheral reset sequence at boot to make the IMU initialization path resilient to this class of corruption without requiring a full battery drain.
Status
Resolved. Root cause: transient peripheral/MCU state corruption requiring a full power cycle to clear, likely triggered by an unstable/interrupted DFU upload session. Fixed via full battery discharge and reflash, with no code changes, on both affected units.
Bug Report: Onboard LSM6DS3 IMU Fails to Initialize After Interrupted DFU Sessions on XIAO nRF52840 Sense (Qbead Hardware) — Resolved by Full Power Cycle
Summary
The onboard LSM6DS3(TR-C) IMU on two independent Qbead units (Seeed XIAO nRF52840 Sense) stopped initializing after a period of unstable DFU mode / firmware upload activity.
LSM6DS3::begin()consistently returned a non-zero (failure) status code, and a direct WHO_AM_I register read (address0x0F) returned0x00instead of a valid chip identifier, with accelerometer output flat at0.00on all axes. The issue was reproduced identically across two separate toolchains (PlatformIO and the official Arduino IDE + Seeeduino package) and two separate physical boards, which initially pointed toward a possible hardware defect. This conclusion was incorrect. A full battery drain followed by re-flashing the exact same, previously-failing firmware resolved the issue on both affected units. This confirms the root cause was some transient MCU/peripheral state corruption requiring a true power-off cycle to clear — not a hardware defect, library bug, or toolchain issue.Environment
0x6ASeeed-Studio/platform-seeedboards, board idseeed-xiao-afruitnrf52-nrf52840, frameworkarduinoSeeeduino:nrf52v1.1.13, FQBNSeeeduino:nrf52:xiaonRF52840seeed-studio/Seeed Arduino LSM6DS3, tested at both2.0.5and2.0.7Qbead.h; IMU-reader example, Dynamical Decoupling simple example, minimal standalone I2C diagnostic sketchesReproducibility
Consistently reproducible prior to the fix, across:
2.0.5and2.0.7(no behavioral difference)Consistently resolved on both boards after a full battery drain + re-power + re-flash of the same firmware that had previously failed (see Resolution).
Symptoms (Prior to Fix)
Qbead::begin()printed[ERROR]{IMU} IMU failed to initialize.myIMU.begin()returned1(non-zero = failure).0x0F) returned0x00, not a valid chip ID.readFloatAccelX/Y/Z()returned a flat0.00on all axes continuously, unchanged by physical movement.Wireobject — the transaction completed cleanly but returned invalid/zeroed data.Impact
Root Cause
Transient corruption of MCU or IMU peripheral state, caused by an unstable/interrupted upload session, that persisted across normal resets and firmware flashes and was only cleared by a genuine full power-off cycle.
Given the board's onboard battery and, to my knowledge, no method to manually instruct a full power-cycle meant that all reset attempts (single reset, double-tap-to-DFU-mode, re-flashing, even multi-minute unplug periods) never actually achieved a true cold restart, and therefore never had the chance to clear whatever internal state was left in a bad configuration.
A likely contributing sequence, based on the debugging timeline:
This rules out a broken hardware issue. Especially given the exact same behaviour occurred on two factory new Qbeads. This is further supported by the brief correct behaviour of the IMU tracking physical rotation after a serial monitor triggered the already flashed firmware on one of the devices. This was before any successful firmware upload was performed.
Resolution
No firmware, library, or configuration changes were required — the fix was exclusively a full power cycle.
USB Port Note (Related Finding)
Earlier upload/connectivity instability (frequent COM port drops,
PermissionError 13, semaphore timeouts) correlated with use of a side-mounted USB-A port on the host laptop (Lenovo Legion Pro 5). Lenovo's own published specifications confirm side and rear USB-A ports on this model line are wired as distinct ports, differing in USB generation/controller rather than being interchangeable. Switching to a rear USB port resolved the connectivity instability. This is the most likely trigger for the interrupted/marginal upload session that is suspected to have caused the transient IMU state corruption described above, though the exact causal mechanism remains unconfirmed at the register/peripheral level.Debugging Steps Performed (Condensed)
[ERROR]{IMU} IMU failed to initializefollowing a period of repeated bootloader entry/exit and USB instability, later correlated with an unstable side USB port.0x00.2.0.5vs2.0.7, full cache clear) — no change.Suggested Follow-Up
Status
Resolved. Root cause: transient peripheral/MCU state corruption requiring a full power cycle to clear, likely triggered by an unstable/interrupted DFU upload session. Fixed via full battery discharge and reflash, with no code changes, on both affected units.