diff --git a/docs/development/msp/msp_messages.json b/docs/development/msp/msp_messages.json index e1b128f305d..1a0c8709fe1 100644 --- a/docs/development/msp/msp_messages.json +++ b/docs/development/msp/msp_messages.json @@ -11032,6 +11032,35 @@ "notes": "CH1-CH12 (index 0-11) are protected and will return `MSP_RESULT_ERROR`. Payload size must be 2-49 bytes. Constraint: `startChannel + channelCount <= 32`. Values persist until overwritten; no timeout. Applied as a post-RX overlay in `calculateRxChannelsAndUpdateFailsafe()` after MSP RC Override but before failsafe. Does not require `USE_RX_MSP` or MSP-RC-OVERRIDE flight mode. Does not affect failsafe detection. When MSP is the primary RX provider, channels covered by `MSP_SET_RAW_RC` are automatically skipped. Channels in the `mspOverrideChannels` bitmask are skipped when MSP RC Override mode is active. Recommended to send with `MSP_FLAG_DONT_REPLY` (flags=0x01) to save bandwidth on telemetry passthrough links. 16-bit mode requires even number of data bytes and values are clamped to 750-2250us.", "description": "Bandwidth-efficient auxiliary RC channel update. Sets CH13-CH32 with configurable resolution (2/4/8/16-bit) without affecting primary flight controls. Designed for extending channel count beyond native RC link capacity via MSP passthrough." }, + "MSP2_INAV_WIND": { + "code": 8753, + "mspv": 2, + "request": null, + "reply": { + "payload": [ + { + "name": "windSpeed", + "ctype": "uint16_t", + "desc": "Estimated horizontal wind speed (`getEstimatedHorizontalWindSpeed()`). 0 if unavailable.", + "units": "cm/s" + }, + { + "name": "windAngle", + "ctype": "uint16_t", + "desc": "Estimated wind direction in degrees (0–359, 0 = North). Derived from centidegree value divided by 100. 0 if unavailable.", + "units": "degrees" + }, + { + "name": "flags", + "ctype": "uint8_t", + "desc": "Validity flags. Bit 0: wind estimate valid (`isEstimatedWindSpeedValid()`). Remaining bits reserved.", + "units": "" + } + ] + }, + "notes": "Requires `USE_WIND_ESTIMATOR`; returns zeroes when wind estimation is not compiled in or not yet valid. Check bit 0 of `flags` before using speed/angle values.", + "description": "Retrieves the estimated horizontal wind speed and direction from the internal wind estimator." + }, "MSP2_BETAFLIGHT_BIND": { "code": 12288, "mspv": 2, diff --git a/src/main/fc/fc_msp.c b/src/main/fc/fc_msp.c index 03a24d8f5c4..4e41d28d180 100644 --- a/src/main/fc/fc_msp.c +++ b/src/main/fc/fc_msp.c @@ -131,6 +131,9 @@ #include "sensors/opflow.h" #include "sensors/temperature.h" #include "sensors/esc_sensor.h" +#ifdef USE_WIND_ESTIMATOR +#include "flight/wind_estimator.h" +#endif #include "telemetry/telemetry.h" @@ -1595,6 +1598,23 @@ static bool mspFcProcessOutCommand(uint16_t cmdMSP, sbuf_t *dst, mspPostProcessF #endif break; + case MSP2_INAV_WIND: +#ifdef USE_WIND_ESTIMATOR + { + uint16_t windAngle = 0; + uint16_t windSpeed = (uint16_t)getEstimatedHorizontalWindSpeed(&windAngle); + uint8_t windFlags = isEstimatedWindSpeedValid() ? 1 : 0; + sbufWriteU16(dst, windSpeed); + sbufWriteU16(dst, windAngle / 100); + sbufWriteU8(dst, windFlags); + } +#else + sbufWriteU16(dst, 0); + sbufWriteU16(dst, 0); + sbufWriteU8(dst, 0); +#endif + break; + case MSP2_INAV_MIXER: sbufWriteU8(dst, mixerConfig()->motorDirectionInverted); sbufWriteU8(dst, 0); diff --git a/src/main/msp/msp_protocol_v2_inav.h b/src/main/msp/msp_protocol_v2_inav.h index e50115d99ed..b38cc0e38f9 100755 --- a/src/main/msp/msp_protocol_v2_inav.h +++ b/src/main/msp/msp_protocol_v2_inav.h @@ -132,4 +132,6 @@ #define MSP2_INAV_SET_WP_INDEX 0x2221 //in message jump to waypoint N during active WP mission; payload: U8 wp_index (0-based, relative to mission start) #define MSP2_INAV_SET_CRUISE_HEADING 0x2223 //in message set heading while in Cruise/Course Hold mode; payload: I32 heading_centidegrees (0-35999) -#define MSP2_INAV_SET_AUX_RC 0x2230 \ No newline at end of file +#define MSP2_INAV_SET_AUX_RC 0x2230 + +#define MSP2_INAV_WIND 0x2231