Record SolarXiao INA260 telemetry and repeater acceptance [skip ci]

This commit is contained in:
mikecarper committed 2026-10-21 14:35:55 -07:00
1 parent e7141400d6
commit e5c8d28d5e
3 files changed
+340

No files matched your search

+1
View File
@@ -11,6 +11,7 @@ Completed validation reports, experiments, and test guides are collected here. O
## Radio and RF
- [SolarXiao INA260 battery telemetry and carrier I2C fix, 2026-10-21](solarxiao_ina260_2026-10-21.md)
- [SolarXiao 33S HEAD bootloader, LoRa OTA and repeater acceptance, 2026-10-21](solarxiao_33s_head_bootloader_lora_ota_2026-10-21.md)
- [SX1262 channel-scanning hardware results](cad_scan_validation.md)
- [CW and CW2 validation](carrier_wave_validation.md)
@@ -0,0 +1,83 @@
<!-- meshcore-hosted-doc-link:start -->
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/test-results/solarxiao_ina260_2026-10-21/">View this page on MeshCore Docs</a>.</p>
<!-- meshcore-hosted-doc-link:end -->
# SolarXiao INA260 battery telemetry, 2026-10-21
The SolarXaio MPPT 12V LiFePO4 carrier on the Mercerwood bench now reports its
INA260 measurements in the normal MeshCore Full repeater build. With the user
reporting a 13.2 V bench supply applied to BAT, all three LoRa telemetry replies
reported **13.26 V**, with signed current readings of **-11, -8 and -8 mA**.
Three subsequent nonce-bound repeater trace tests passed at **-6 dBm**.
[Machine-readable results](solarxiao_ina260_2026-10-21.safe.json) contain the
measurements, exact firmware identity, trace evidence, cleanup and limitations.
## Discovery and correction
The original Full build contained the INA260 driver, but its carrier I2C pins
were reversed and its generic INA260 address was `0x41`. Read-only diagnostic
transactions identified this board's INA260 at **0x40**, manufacturer ID
`5449`, device ID `2270`, with **SDA=P0.09 (variant pin 30)** and
**SCL=P0.10 (variant pin 31)**. Three USB-only readings were about 0.11125 V
before the user connected the BAT supply.
The SolarXiao target now supplies these carrier pins through `PIN_BOARD_SDA`
and `PIN_BOARD_SCL`, and overrides `TELEM_INA260_ADDRESS` to `0x40`. Generic
XIAO wiring and the generic INA260 address remain unchanged. Discovery tries
the INA260's device-ID check before the INA219 driver can claim the same
address and write an incompatible configuration.
## Qualified build and live acceptance
| Item | Result |
| --- | --- |
| Source revision | [`a947f936ecd279b7b3c97b4d832c4efc9a8a696b`](https://github.com/mikecarper/MeshCore/commit/a947f936ecd279b7b3c97b4d832c4efc9a8a696b) |
| Environment and installed profile | `solarxiao_33S_repeater`, Full |
| Application version | `v1.18.0.1-halo-keymind-cascade-dev-a947f936` |
| Application body hash | `E6E4E0E7CA5DB232` |
| Application image | 579,792 bytes |
| Application SHA-256 | `0ba24397e11c0c30b0e3213ea597c536c4bc075c25fae44fc39fa43ce0e5626b` |
| Full and Reduced builds | PASS; memory, DFU and nine capability markers per package |
| Board startup tests | Six PASS, including carrier pin override and GPIO safety negative controls; ASan/UBSan |
| Warm restart | PASS; sensor discovery, identity and saved settings preserved |
| LoRa telemetry | Three replies; channel 2 has voltage, current and power |
| Repeater traces | Three PASS; exact nonce, four-byte route and one target hop |
| Trace direct RX/TX | 1 / 1 per round; zero added receive errors |
| Final core error flags | Zero |
The requested setup retained USB power, applied the supply to BAT and left
solar disconnected. This checks sensor discovery and functional readout;
it does not calibrate the INA260 against an independent voltage reference.
Channel 1 is the XIAO internal ADC reading. Channel 2 is the carrier INA260.
Reported power was 0 W in these near-zero signed-current samples; it is not
an independent power or charger-performance measurement.
The normal radio remained `910.5250244,62.5,7,5`, repeating stayed `on`, and
TX stayed `-6` dBm. RX power saving remained
`on,level=8,preamble=16,rx=39657,sleep=15975`. The telemetry controller's
temporary contact and forwarding connection were removed, the trace partner's
settings were preserved, and USB endpoints were closed.
## Scope and retained evidence
The installed application was updated through USB serial DFU. The qualified
HEAD bootloader remained at revision `b07255d4cdc601f1313e4cbe020caad3b5544821`,
manifest CRC `76EBABBF`. The earlier full LoRa OTA transfer on application
`efad0076` is documented in the
[bootloader and LoRa OTA report](solarxiao_33s_head_bootloader_lora_ota_2026-10-21.md).
This run verifies LoRa telemetry and repeater forwarding on `a947f936`; it
does not repeat a complete firmware transfer on that application.
An additional UART-pin diagnostic probe timed out after the successful INA260
reads. The original application and settings were restored before installing
the final fix. The first trace run passed all three RF traces but failed a
cleanup assertion that compared the entire changing `radio2.status` response.
The corrected check compares saved radio settings exactly and verifies radio2
remains off; the subsequent complete run passed. Its final cumulative receive
error counter was 7, with zero added during each owned trace round.
No LTC4162 charger configuration registers were written. The charger SKU is
LTC4162-FSTM as reported by the user. Charging behavior and other carrier
revisions are outside this acceptance result. The Reduced package was
build-checked only; live INA260 acceptance used the Full package.
@@ -0,0 +1,256 @@
{
"schema_version": 1,
"passed": true,
"date_utc": "2026-10-21",
"hardware": {
"carrier": "SolarXaio MPPT 12V LiFePO4",
"target": "solarxiao_33S_repeater",
"mcu": "Seeed XIAO nRF52840",
"radio": "Ebyte E22-900M33S",
"charger_sku_user_reported": "LTC4162-FSTM"
},
"firmware": {
"name": "solarxiao_33S_repeater-full-ota-v1.18.0.1-halo-keymind-cascade-dev-a947f936.zip",
"sha256": "dbe7248d3e9be11affc6e5a572f7dfba6230eda5f98d4e6e7cd98c67bc26afef",
"body_hash": "E6E4E0E7CA5DB232",
"application_sha256": "0ba24397e11c0c30b0e3213ea597c536c4bc075c25fae44fc39fa43ce0e5626b",
"application_bytes": 579792,
"source_commit": "a947f936ecd279b7b3c97b4d832c4efc9a8a696b",
"expected_version": "v1.18.0.1-halo-keymind-cascade-dev-a947f936"
},
"monitor": {
"model": "INA260",
"i2c_address": "0x40",
"manufacturer_id": "5449",
"device_id": "2270",
"sda_variant_pin": 30,
"scl_variant_pin": 31,
"sda_nrf_pin": "P0.09",
"scl_nrf_pin": "P0.10"
},
"fix": {
"carrier_i2c_pin_override": true,
"carrier_ina260_address_override": true,
"ina260_identity_checked_before_ina219": true,
"generic_ina260_default_address_unchanged": "0x41"
},
"bench_reference": {
"battery_cell_count_user_reported": 4,
"bat_supply_setpoint_v_user_reported": 13.2,
"setup_requested": "USB connected; bench supply to BAT; solar disconnected",
"voltage_accuracy_calibration_performed": false
},
"lora_telemetry": {
"passed": true,
"samples": [
{
"at_utc": "2026-10-21T21:31:12.704548+00:00",
"channel": 2,
"voltage_v": 13.26,
"current_a": -0.011,
"reported_power_w": 0.0
},
{
"at_utc": "2026-10-21T21:31:17.620520+00:00",
"channel": 2,
"voltage_v": 13.26,
"current_a": -0.008,
"reported_power_w": 0.0
},
{
"at_utc": "2026-10-21T21:31:21.414120+00:00",
"channel": 2,
"voltage_v": 13.26,
"current_a": -0.008,
"reported_power_w": 0.0
}
],
"temporary_contact_removed": true,
"temporary_forward_closed": true,
"cleanup_errors": []
},
"installation": {
"method": "USB serial application-only DFU",
"warm_restart_verified": true,
"identity_and_saved_settings_preserved": true,
"bootloader_manifest_crc": "76EBABBF",
"bootloader_changed": false,
"bootloader_source_commit": "b07255d4cdc601f1313e4cbe020caad3b5544821",
"voltage_history_after_restart": "channels=2 samples=1 retention=4d step=0.02V max=655.34V"
},
"repeater_acceptance": {
"passed": true,
"started_at": 1792618396.9636362,
"source_commit": "a947f936ecd279b7b3c97b4d832c4efc9a8a696b",
"application_body_hash": "E6E4E0E7CA5DB232",
"rounds": [
{
"index": 1,
"passed": true,
"host_send_commands": 1,
"nonce_sha256": "0637d7942ac61015940db9f0ee6b5382c69551e4a35b9301bc7122ee63217f52",
"elapsed_seconds": 0.581,
"firmware_estimate_millis": 2692,
"repeater_packet_delta": {
"recv": 1,
"sent": 1,
"direct_rx": 1,
"direct_tx": 1,
"recv_errors": 0
},
"hub_packet_delta": {
"received": 1,
"sent": 1,
"sent_flood": 0,
"sent_direct": 1,
"received_flood": 0,
"received_direct": 1,
"receive_errors": 0
},
"ignored_unowned_pushes": 1,
"exact_nonce_verified": true,
"exact_repeater_prefix_route_verified": true,
"route_bytes": 4,
"route_hops": 1,
"flags": 2,
"repeater_inbound_snr_db": 11.25,
"hub_return_snr_db": 12.25,
"reply_sha256": "32c6ae2b63caa113768712b5f0eb9731e7fabafa35a3cd3d1cc448a259d9ab35"
},
{
"index": 2,
"passed": true,
"host_send_commands": 1,
"nonce_sha256": "f7adacb94ac085dd8f3806baaa99b79480d0927ae19e7f7073c0f0fc697e38a6",
"elapsed_seconds": 0.458,
"firmware_estimate_millis": 2692,
"repeater_packet_delta": {
"recv": 1,
"sent": 1,
"direct_rx": 1,
"direct_tx": 1,
"recv_errors": 0
},
"hub_packet_delta": {
"received": 1,
"sent": 1,
"sent_flood": 0,
"sent_direct": 1,
"received_flood": 0,
"received_direct": 1,
"receive_errors": 0
},
"ignored_unowned_pushes": 1,
"exact_nonce_verified": true,
"exact_repeater_prefix_route_verified": true,
"route_bytes": 4,
"route_hops": 1,
"flags": 2,
"repeater_inbound_snr_db": 12.0,
"hub_return_snr_db": 12.25,
"reply_sha256": "b31c56b34d084c1fd32492a9b262c24d984f7b26be190889e108ac67053420dc"
},
{
"index": 3,
"passed": true,
"host_send_commands": 1,
"nonce_sha256": "a742537fad1d089d5283abeb98975c556882c9ac90bb280927b39d8d67397c94",
"elapsed_seconds": 0.55,
"firmware_estimate_millis": 2692,
"repeater_packet_delta": {
"recv": 1,
"sent": 1,
"direct_rx": 1,
"direct_tx": 1,
"recv_errors": 0
},
"hub_packet_delta": {
"received": 1,
"sent": 1,
"sent_flood": 0,
"sent_direct": 1,
"received_flood": 0,
"received_direct": 1,
"receive_errors": 0
},
"ignored_unowned_pushes": 1,
"exact_nonce_verified": true,
"exact_repeater_prefix_route_verified": true,
"route_bytes": 4,
"route_hops": 1,
"flags": 2,
"repeater_inbound_snr_db": 11.5,
"hub_return_snr_db": 12.5,
"reply_sha256": "6d3baa57a8d9a85b4c4e8850531f8a34c0aef6bd1948d935c9b8bc683175dff9"
}
],
"temporary_radio_leases_used": false,
"persistent_peer_settings_changed": false,
"final_core": {
"battery_mv": 3772,
"uptime_secs": 264,
"errors": 0,
"queue_len": 0
},
"final_packets": {
"recv": 135,
"sent": 38,
"flood_tx": 27,
"direct_tx": 11,
"flood_rx": 123,
"direct_rx": 11,
"recv_errors": 7
},
"radio": "910.5250244,62.5,7,5",
"tx_power_dbm": -6,
"repeat": "on",
"rx_power_saving": "on,level=8,preamble=16,rx=39657,sleep=15975",
"bootloader_manifest_crc": "76EBABBF",
"voltage_history": "channels=2 samples=2 retention=4d step=0.02V max=655.34V",
"trace_rounds_passed": 3,
"endpoints_closed": true,
"partner_settings_preserved": true,
"transport": {
"ports_opened": 1,
"ports_closed": 1,
"request_frames_sent": 26,
"response_frames_received": 32,
"request_bytes_sent": 305,
"response_payload_bytes": 856,
"discarded_prefix_bytes": 0,
"invalid_length_candidates": 0,
"ignored_push_frames": 0
},
"finished_at": 1792618405.1829977
},
"build_checks": {
"full": {
"passed": true,
"capability_markers_verified": 9,
"memory_and_nrf52_dfu_checks_passed": true
},
"reduced": {
"passed": true,
"capability_markers_verified": 9,
"memory_and_nrf52_dfu_checks_passed": true
}
},
"host_tests": {
"suite": "test/test_xiao_battery_safety.py",
"tests_passed": 6,
"real_board_source_compiled": true,
"asan_ubsan": true,
"carrier_pin_override_and_unsafe_gpio_negative_controls": true
},
"charger_configuration_register_writes": 0,
"qualification_notes": [
"The three USB-only raw INA260 reads were about 0.11125 V before the user applied the BAT supply.",
"An additional UART-pin diagnostic probe timed out; the exact original application and saved settings were restored before installing this fix.",
"The first trace run passed all three owned RF traces but its cleanup assertion compared the entire live radio2.status response. The final passing run compares saved radio, TX and temporary-radio values exactly and verifies radio2 remains off.",
"The final cumulative receive-error counter is 7; each of the three owned trace rounds added zero receive errors. Final core error flags are zero.",
"Channel 1 is the XIAO internal ADC reading; the carrier INA260 is channel 2 in this setup.",
"Reported INA260 power was 0 W during these signed near-zero-current samples; this is the sensor telemetry field, not an independent power or charger-performance measurement.",
"This fixed application was installed over USB. The earlier full LoRa OTA transfer was qualified on application efad0076 and is documented separately.",
"Hardware acceptance covers this SolarXiao 33S Full build and this carrier; the Reduced package was build-checked only."
]
}