Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/Mavlink.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ When `mavlink_port{1-4}_radio_type = MLRS`, INAV uses native receiver-emitted ML

Messages are organized into MAVLink datastream groups. Each group sends one message per trigger at the configured rate.

- `SYS_STATUS`: advertises detected sensors (gyro/accel/compass, baro, pitot, GPS, optical flow, rangefinder, RC, blackbox) and whether they are healthy. Includes main loop load, battery voltage/current/percentage, and logging capability.
- `SYS_STATUS`: advertises detected sensors (gyro/accel/compass, baro, pitot, GPS, optical flow, rangefinder, RC, blackbox) and whether they are healthy. Includes main loop load, battery voltage/current/percentage, and logging capability. With no battery detected, or with `FEATURE_VBAT` off, voltage is sent as `UINT16_MAX` and remaining percentage as `-1`, the MAVLink unknown values, so a ground station shows no reading instead of 0 V or a full battery.
- `RC_CHANNELS_RAW` (v1) / `RC_CHANNELS` (v2): up to 18 input channels plus RSSI mapped to MAVLink units.
- `GPS_RAW_INT`: GNSS fix quality, HDOP/VDOP, velocity, satellite count, and receiver-native ellipsoid altitude and accuracy extensions when available.
- `GLOBAL_POSITION_INT`: GPS position plus INAV altitude and velocity estimates.
Expand All @@ -145,7 +145,7 @@ Messages are organized into MAVLink datastream groups. Each group sends one mess
- `VFR_HUD`: airspeed (if a healthy pitot is available), ground speed, throttle, altitude, and climb rate.
- `HEARTBEAT`: arming state plus ArduPilot-style `custom_mode` mapping from INAV flight modes.
- `EXTENDED_SYS_STATE`: landed-state reporting.
- `BATTERY_STATUS`: per-cell voltages (cells 11-14 in `voltages_ext`), current draw, consumed mAh/Wh, and remaining percentage when available.
- `BATTERY_STATUS`: per-cell voltages (cells 11-14 in `voltages_ext`), current draw, consumed mAh/Wh, and remaining percentage when available. Without a detected battery the cell voltages stay at `UINT16_MAX` and remaining percentage at `-1`.
- `SCALED_PRESSURE`: baro pressure and temperature data.
- `SYSTEM_TIME`: boot time plus RTC Unix time when the RTC is valid.
- `STATUSTEXT`: pending OSD/system messages, changed arming-disable reasons, and flight-mode transitions. OSD/system messages carry a mapped severity (NOTICE by default, WARNING when the source OSD element is inverted, CRITICAL when it blinks); arming-disable and mode notices are always sent at NOTICE severity. Repeated OSD-derived status text is suppressed per MAVLink port; changed text is sent immediately, while unchanged notice/warning/critical messages are re-announced at progressively shorter severity-based intervals (30 s / 10 s / 5 s). Changed arming-disable reasons are broadcast to every enabled port as `Arming disabled: <reasons>`. INAV flight-mode transitions are broadcast as notices in the form `Notice: INAV: Entering <mode name>`, with explicit `Notice: INAV: Entering GCS NAV mode` / `Notice: INAV: Exiting GCS NAV mode` transitions while GCS-assisted navigation engages or ends. See [Reconnect and status re-announcement](#reconnect-and-status-re-announcement) for how these are re-sent when a peer (re)connects.
Expand Down
23 changes: 15 additions & 8 deletions src/main/mavlink/mavlink_streams.c
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,16 @@ void mavlinkSendExtendedSysState(void)
mavlinkSendMessage();
}

// Running from USB without a battery leaves the battery state at
// BATTERY_NOT_PRESENT, where voltage and remaining capacity are meaningless.
// Reporting them as 0V/0% makes a GCS or radio announce a critical battery,
// so they are reported as unknown instead. This matches the way the OSD and
// HIGH_LATENCY2 only raise a battery warning for BATTERY_WARNING/CRITICAL.
static bool mavlinkBatteryIsPresent(void)
{
return feature(FEATURE_VBAT) && getBatteryState() != BATTERY_NOT_PRESENT;
}

void mavlinkSendSystemStatus(void)
{
// Receiver is assumed to be always present
Expand Down Expand Up @@ -529,9 +539,9 @@ void mavlinkSendSystemStatus(void)
onboard_control_sensors_enabled,
onboard_control_sensors_health,
constrain(averageSystemLoadPercent * 10, 0, 1000),
feature(FEATURE_VBAT) ? getBatteryVoltage() * 10 : 0,
mavlinkBatteryIsPresent() ? getBatteryVoltage() * 10 : UINT16_MAX,
isAmperageConfigured() ? getAmperage() : -1,
feature(FEATURE_VBAT) ? calculateBatteryPercentage() : 100,
mavlinkBatteryIsPresent() ? calculateBatteryPercentage() : -1,
0,
0,
0,
Expand Down Expand Up @@ -821,7 +831,7 @@ void mavlinkSendBatteryStatus(void)
uint16_t batteryVoltagesExt[MAVLINK_MSG_BATTERY_STATUS_FIELD_VOLTAGES_EXT_LEN];
memset(batteryVoltages, UINT16_MAX, sizeof(batteryVoltages));
memset(batteryVoltagesExt, 0, sizeof(batteryVoltagesExt));
if (feature(FEATURE_VBAT)) {
if (mavlinkBatteryIsPresent()) {
uint8_t batteryCellCount = getBatteryCellCount();
if (batteryCellCount > 0) {
for (int cell = 0; cell < batteryCellCount && cell < MAVLINK_MSG_BATTERY_STATUS_FIELD_VOLTAGES_LEN + MAVLINK_MSG_BATTERY_STATUS_FIELD_VOLTAGES_EXT_LEN; cell++) {
Expand All @@ -836,9 +846,6 @@ void mavlinkSendBatteryStatus(void)
batteryVoltages[0] = getBatteryVoltage() * 10;
}
}
else {
batteryVoltages[0] = 0;
}

mavlink_msg_battery_status_pack(mavSystemId, mavComponentId, &mavSendMsg,
0,
Expand All @@ -849,7 +856,7 @@ void mavlinkSendBatteryStatus(void)
isAmperageConfigured() ? getAmperage() : -1,
isAmperageConfigured() ? getMAhDrawn() : -1,
isAmperageConfigured() ? getMWhDrawn() * 36 : -1,
feature(FEATURE_VBAT) ? calculateBatteryPercentage() : -1,
mavlinkBatteryIsPresent() ? calculateBatteryPercentage() : -1,
0,
0,
batteryVoltagesExt,
Expand Down Expand Up @@ -1041,7 +1048,7 @@ void mavlinkSendHighLatency2(timeUs_t currentTimeUs)
uint8_t epv = UINT8_MAX;
int8_t temperatureAir = 0;
int8_t climbRate = (int8_t)constrain(lrintf(getEstimatedActualVelocity(Z) / 10.0f), INT8_MIN, INT8_MAX);
int8_t battery = feature(FEATURE_VBAT) ? (int8_t)calculateBatteryPercentage() : -1;
int8_t battery = mavlinkBatteryIsPresent() ? (int8_t)calculateBatteryPercentage() : -1;

#if defined(USE_GPS)
if (sensors(SENSOR_GPS)
Expand Down