1
0
Fork 0
mirror of https://github.com/iNavFlight/inav.git synced 2025-07-14 20:10:15 +03:00

Merge branch 'master' into abo_mission_restart_option

This commit is contained in:
breadoven 2021-10-29 10:05:10 +01:00 committed by GitHub
commit e18173f8bd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
316 changed files with 6245 additions and 5101 deletions

View file

@ -37,7 +37,7 @@ else()
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/${TOOLCHAIN}-checks.cmake")
endif()
project(INAV VERSION 3.1.0)
project(INAV VERSION 4.0.0)
enable_language(ASM)

View file

@ -1,17 +0,0 @@
#Notes
## Expected acc/mag/gyro behavior
Observations of a flight-tested flip32 board in the configurator's 'raw sensor data' tab.
lift front of board (i.e. pitch back)
gyro y increases (green)
acc x increases (blue)
acc z decreases (red)
mag x decreases (blue)
lift left of boar (i.e. roll right)
gyro x increases (blue)
acc y increases (green)
mag y decreases (green)
mag z increases (red)

View file

@ -1,11 +1,13 @@
# INAV - navigation capable flight controller
## F3 based flight controllers
> STM32 F3 flight controllers like Omnibus F3 or SP Racing F3 are deprecated and soon they will reach the end of support in INAV. If you are still using F3 boards, please migrate to F4 or F7.
![INAV](http://static.rcgroups.net/forums/attachments/6/1/0/3/7/6/a9088858-102-inav.png)
![Travis CI status](https://travis-ci.org/iNavFlight/inav.svg?branch=master)
# INAV Community
* [INAV Discord Server](https://discord.gg/peg2hhbYwN)
* [INAV Official on Facebook](https://www.facebook.com/groups/INAVOfficial)
* [RC Groups Support](https://www.rcgroups.com/forums/showthread.php?2495732-Cleanflight-iNav-(navigation-rewrite)-project)
* [INAV Official on Telegram](https://t.me/INAVFlight)
## Features
@ -16,9 +18,9 @@
* Fully configurable mixer that allows to run any hardware you want: multirotor, fixed wing, rovers, boats and other experimental devices
* Multiple sensor support: GPS, Pitot tube, sonar, lidar, temperature, ESC with BlHeli_32 telemetry
* SmartAudio and IRC Tramp VTX support
* DSHOT and Multishot ESCs
* Blackbox flight recorder logging
* On Screen Display (OSD) - both character and pixel style
* DJI OSD integration: all elements, system messages and warnings
* Telemetry: SmartPort, FPort, MAVlink, LTM
* Multi-color RGB LED Strip support
* Advanced gyro filtering: Matrix Filter and RPM filter
@ -52,9 +54,6 @@ See: https://github.com/iNavFlight/inav/blob/master/docs/Installation.md
* [Wing Tuning Masterclass](docs/INAV_Wing_Tuning_Masterclass.pdf)
* [Official documentation](https://github.com/iNavFlight/inav/tree/master/docs)
* [Official Wiki](https://github.com/iNavFlight/inav/wiki)
* [INAV Official on Telegram](https://t.me/INAVFlight)
* [INAV Official on Facebook](https://www.facebook.com/groups/INAVOfficial)
* [RC Groups Support](https://www.rcgroups.com/forums/showthread.php?2495732-Cleanflight-iNav-(navigation-rewrite)-project)
* [Video series by Painless360](https://www.youtube.com/playlist?list=PLYsWjANuAm4qdXEGFSeUhOZ10-H8YTSnH)
* [Video series by Paweł Spychalski](https://www.youtube.com/playlist?list=PLOUQ8o2_nCLloACrA6f1_daCjhqY2x0fB)

View file

@ -2,13 +2,13 @@ include(gcc)
set(arm_none_eabi_triplet "arm-none-eabi")
# Keep version in sync with the distribution files below
set(arm_none_eabi_gcc_version "9.3.1")
set(arm_none_eabi_base_url "https://developer.arm.com/-/media/Files/downloads/gnu-rm/9-2020q2/gcc-arm-none-eabi-9-2020-q2-update")
set(arm_none_eabi_gcc_version "10.2.1")
set(arm_none_eabi_base_url "https://developer.arm.com/-/media/Files/downloads/gnu-rm/10-2020q4/gcc-arm-none-eabi-10-2020-q4-major")
# suffix and checksum
set(arm_none_eabi_win32 "win32.zip" 184b3397414485f224e7ba950989aab6)
set(arm_none_eabi_linux_amd64 "x86_64-linux.tar.bz2" 2b9eeccc33470f9d3cda26983b9d2dc6)
set(arm_none_eabi_linux_aarch64 "aarch64-linux.tar.bz2" 000b0888cbe7b171e2225b29be1c327c)
set(arm_none_eabi_gcc_macos "mac.tar.bz2" 75a171beac35453fd2f0f48b3cb239c3)
set(arm_none_eabi_win32 "win32.zip" 5ee6542a2af847934177bc8fa1294c0d)
set(arm_none_eabi_linux_amd64 "x86_64-linux.tar.bz2" 8312c4c91799885f222f663fc81f9a31)
set(arm_none_eabi_linux_aarch64 "aarch64-linux.tar.bz2" 1c3b8944c026d50362eef1f01f329a8e)
set(arm_none_eabi_gcc_macos "mac.tar.bz2" e588d21be5a0cc9caa60938d2422b058)
function(arm_none_eabi_gcc_distname var)
string(REPLACE "/" ";" url_parts ${arm_none_eabi_base_url})

View file

@ -33,7 +33,7 @@ function(enable_settings exe name)
add_custom_command(
OUTPUT ${output}
COMMAND
${CMAKE_COMMAND} -E env CFLAGS="${cflags}" TARGET=${name} PATH=$ENV{PATH} SETTINGS_CXX=${args_SETTINGS_CXX}
${CMAKE_COMMAND} -E env CFLAGS="${cflags}" TARGET=${name} PATH="$ENV{PATH}" SETTINGS_CXX=${args_SETTINGS_CXX}
${RUBY_EXECUTABLE} ${SETTINGS_GENERATOR} ${MAIN_DIR} ${SETTINGS_FILE} -o "${dir}"
DEPENDS ${SETTINGS_GENERATOR} ${SETTINGS_FILE}
)

View file

@ -189,7 +189,7 @@ endfunction()
function(add_hex_target name exe hex)
add_custom_target(${name} ALL
cmake -E env PATH=$ENV{PATH}
cmake -E env PATH="$ENV{PATH}"
# TODO: Overriding the start address with --set-start 0x08000000
# seems to be required due to some incorrect assumptions about .hex
# files in the configurator. Verify wether that's the case and fix
@ -201,7 +201,7 @@ endfunction()
function(add_bin_target name exe bin)
add_custom_target(${name}
cmake -E env PATH=$ENV{PATH}
cmake -E env PATH="$ENV{PATH}"
${CMAKE_OBJCOPY} -Obinary $<TARGET_FILE:${exe}> ${bin}
BYPRODUCTS ${bin}
)

View file

@ -19,6 +19,8 @@ main_sources(STM32F3_SRC
target/system_stm32f30x.c
config/config_streamer_stm32f3.c
config/config_streamer_ram.c
config/config_streamer_extflash.c
drivers/adc_stm32f30x.c
drivers/bus_i2c_stm32f30x.c

View file

@ -36,6 +36,8 @@ main_sources(STM32F4_SRC
target/system_stm32f4xx.c
config/config_streamer_stm32f4.c
config/config_streamer_ram.c
config/config_streamer_extflash.c
drivers/adc_stm32f4xx.c
drivers/adc_stm32f4xx.c
@ -124,6 +126,7 @@ exclude_basenames(STM32F411_OR_F427_STDPERIPH_SRC ${STM32F411_OR_F427_STDPERIPH_
set(STM32F411_COMPILE_DEFINITIONS
STM32F411xE
MCU_FLASH_SIZE=512
OPTIMIZATION -Os
)
function(target_stm32f411xe name)
@ -132,9 +135,9 @@ function(target_stm32f411xe name)
STARTUP startup_stm32f411xe.s
SOURCES ${STM32F411_OR_F427_STDPERIPH_SRC}
COMPILE_DEFINITIONS ${STM32F411_COMPILE_DEFINITIONS}
LINKER_SCRIPT stm32_flash_f411xe
LINKER_SCRIPT stm32_flash_f411xe
SVD STM32F411
${ARGN}
${ARGN}
)
endfunction()

View file

@ -61,6 +61,8 @@ main_sources(STM32F7_SRC
target/system_stm32f7xx.c
config/config_streamer_stm32f7.c
config/config_streamer_ram.c
config/config_streamer_extflash.c
drivers/adc_stm32f7xx.c
drivers/bus_i2c_hal.c

View file

@ -142,6 +142,8 @@ main_sources(STM32H7_SRC
target/system_stm32h7xx.c
config/config_streamer_stm32h7.c
config/config_streamer_ram.c
config/config_streamer_extflash.c
drivers/adc_stm32h7xx.c
drivers/bus_i2c_hal.c
@ -217,4 +219,4 @@ macro(define_target_stm32h7 subfamily size)
endfunction()
endmacro()
define_target_stm32h7(43 i)
define_target_stm32h7(43 i)

View file

@ -30,7 +30,7 @@ These boards are well tested with INAV and are known to be of good quality and r
It's possible to find more supported and tested boards [here](https://github.com/iNavFlight/inav/wiki/Welcome-to-INAV,-useful-links-and-products)
### Boards documentation
See the [docs](https://github.com/iNavFlight/inav/tree/master/docs) folder for additional information regards to many targets in INAV, to example help in finding pinout and features. _Feel free to help improve the docs._
See the [docs/boards](https://github.com/iNavFlight/inav/tree/master/docs/boards) folder for additional information regards to many targets in INAV, to example help in finding pinout and features. _Feel free to help improve the docs._
### Boards based on F4/F7 CPUs
@ -38,7 +38,7 @@ These boards are powerful and in general support everything INAV is capable of.
### Boards based on F3 CPUs
Boards based on F3 boards will be supported for as long as practical, sometimes with reduced features due to lack of resources. No new features will be added so F3 boards are not recommended for new builds.
Boards based on STM32F3 MCUs are no longer supported by latest INAV version. Last release is 2.6.1.
### Boards based on F1 CPUs
@ -46,4 +46,4 @@ Boards based on STM32F1 CPUs are no longer supported by latest INAV version. Las
### Not recommended for new setups
F1 and F3 boards are no longer recommended. Users should choose a board from the supported F4 or F7 devices available in the latest release.
F1 and F3 boards are no longer recommended. Users should choose a board from the supported F4 or F7 devices available in the latest release.

View file

@ -34,10 +34,12 @@ The stick positions are combined to activate different functions:
| Trim Acc Forwards | HIGH | CENTER | HIGH | CENTER |
| Trim Acc Backwards | HIGH | CENTER | LOW | CENTER |
| Save current waypoint mission | LOW | CENTER | HIGH | LOW |
| Load/unload current waypoint mission | LOW | CENTER | HIGH | HIGH |
| Load current waypoint mission | LOW | CENTER | HIGH | HIGH |
| Unload waypoint mission | LOW | CENTER | LOW | HIGH |
| Save setting | LOW | LOW | LOW | HIGH |
| Enter OSD Menu (CMS) | CENTER | LOW | HIGH | CENTER |
For graphical stick position in all transmitter modes, check out [this page](https://www.mrd-rc.com/tutorials-tools-and-testing/inav-flight/inav-stick-commands-for-all-transmitter-modes/).
![Stick Positions](assets/images/StickPositions.png)
## Yaw control

View file

@ -9,12 +9,13 @@ Failsafe is a state the flight controller is meant to enter when the radio recei
If the failsafe happens while the flight controller is disarmed, it only prevent arming. If it happens while armed, the failsafe policy configured in `failsafe_procedure` is engaged. The available procedures are:
* __DROP:__ Just kill the motors and disarm (crash the craft).
* __SET-THR:__ Enable auto-level mode (for multirotor) or enter preconfigured roll/pitch/yaw spiral down (for airplanes) and set the throttle to a predefined value (`failsafe_throttle`) for a predefined time (`failsafe_off_delay`). This is meant to get the craft to a safe-ish landing (or more realistically, a controlled crash), it doesn't require any extra sensor other than gyros and accelerometers.
* __RTH:__ (Return To Home) One of the key features of inav, it automatically navigates the craft back to the home position and (optionally) lands it. Similarly to all other automated navigation methods, it requires GPS for any type of craft, plus compass and barometer for multicopters.
* __LAND:__ (replaces **SET-THR** from INAV V3.1.0) Performs an Emergency Landing. Enables auto-level mode (for multirotor) or enters a preconfigured roll/pitch/yaw spiral down (for airplanes). If altitude sensors are working an actively controlled descent is performed using the Emergency Landing descent speed (`nav_emerg_landing_speed`). If altitude sensors are unavailable descent is performed with the throttle set to a predefined value (`failsafe_throttle`). The descent can be limited to a predefined time (`failsafe_off_delay`) after which the craft disarms. This is meant to get the craft to a safe-ish landing (or more realistically, a controlled crash), Other than using altitude sensors for an actively controlled descent it doesn't require any extra sensors other than gyros and accelerometers.
* __SET-THR:__ (Pre INAV V3.1.0) Same as **LAND** except it doesn't use an Emergency Landing but is limited instead to just setting the throttle to a predefined value (`failsafe_throttle`) to perform a descent. It doesn't require any extra sensors other than gyros and accelerometers.
* __RTH:__ (Return To Home) One of the key features of INAV, it automatically navigates the craft back to the home position and (optionally) lands it. Similarly to all other automated navigation methods, it requires GPS for any type of craft, plus compass and barometer for multicopters.
* __NONE:__ Do nothing. This is meant to let the craft perform a fully automated flight (eg. waypoint flight) outside of radio range. Highly unsafe when used with manual flight.
Note that:
* Should the failsafe disarm the flight controller (**DROP**, **SET-THR** after `failsafe_off_delay` or **RTH** with `nav_disarm_on_landing` ON), the flight controller will be disarmed and re-arming will be locked until the signal from the receiver is restored for 30 seconds AND the arming switch is in the OFF position (when an arm switch is in use).
* Should the failsafe disarm the flight controller (**DROP**, **LAND/SET-THR** after `failsafe_off_delay` or **RTH** with `nav_disarm_on_landing` ON), the flight controller will be disarmed and re-arming will be locked until the signal from the receiver is restored for 30 seconds AND the arming switch is in the OFF position (when an arm switch is in use).
* Prior to starting failsafe it is checked if the throttle position has been below `min_throttle` for the last `failsafe_throttle_low_delay` seconds. If it was, the craft is assumed to be on the ground and is simply disarmed. This feature can be disabled completely by setting `failsafe_throttle_low_delay` to zero, which may be necessary to do if the craft may fly long with zero throttle (eg. gliders).
@ -22,9 +23,9 @@ Note that:
* If the craft is landed but armed, the failsafe may make the motors and props spin again and even make the craft take off (in case of **RTH** failsafe). Take expecially care of this when using `MOTOR_STOP` feature. **Props will spin up without warning**. Have a look at the `failsafe_throttle_low_delay` setting explained above to learn when this could happen.
* If any required navigation sensor becomes unavailable during a Return to Home (eg. loss of GPS fix), an emergency landing similar to **SET-THR** but with barometer support will be performed after a short timeout. An emergency landing would also be performed right when the failsafe is triggered if any required sensor is reported as unavailable.
* If any required navigation sensor becomes unavailable during a Return to Home (eg. loss of GPS fix), an emergency landing, as used by the **LAND** procedure, will be performed after a short timeout. An emergency landing would also be performed right when the failsafe is triggered if any required sensor is reported as unavailable.
* **SET-THR** doesn't control the descend in any other way than setting a fixed throttle. Thus, appropriate testing must be performed to find the right throttle value. Consider that a constant throttle setting will yield different thrusts depending on battery voltage, so when you evaluate the throttle value do it with a loaded battery. Failure to do so may cause a flyaway.
* The **SET-THR** procedure doesn't control descent in any way other than setting a fixed throttle. This is also the case for the **LAND** procedure when altitude sensors are unavailable. Thus, appropriate testing must be performed to find the right throttle value. Consider that a constant throttle setting will yield different thrusts depending on battery voltage, so when you evaluate the throttle value do it with a loaded battery. Failure to do so may cause a flyaway.
* When the failsafe mode is aborted (RC signal restored/failsafe switch set to OFF), the current stick positions will be enforced immediately. Be ready to react quickly.
@ -48,7 +49,7 @@ Failsafe delays are configured in 0.1 second units. Distances are in centimeters
#### `failsafe_procedure`
Selects the failsafe procedure. Valid procedures are **DROP**, **SET-THR**, **RTH** and **NONE**. See above for a description of each one.
Selects the failsafe procedure. Valid procedures are **DROP**, **LAND/SET-THR**, **RTH** and **NONE**. See above for a description of each one.
#### `failsafe_delay`
@ -122,25 +123,29 @@ Enables landing when home position is reached. If OFF the craft will hover indef
Instructs the flight controller to disarm the craft when landing is detected
### Parameters relevant to **SET-THR** failsafe procedure
### Parameters relevant to **LAND/SET-THR** failsafe procedure
#### `failsafe_off_delay`
Delay after failsafe activates before motors finally turn off. This is the amount of time 'failsafe_throttle' is active. If you fly at higher altitudes you may need more time to descend safely. Set to zero to keep `failsafe_throttle` active indefinitely.
#### `nav_emerg_landing_speed`
(**LAND** only) Actively controlled descent speed when altitude sensors are available. If altitude sensors aren't available landing descent falls back to using the fixed thottle setting `failsafe_throttle` so ensure this is also set correctly.
#### `failsafe_throttle`
Throttle level used for landing. Specify a value that causes the aircraft to descend at about 1M/sec. Default is set to 1000 which should correspond to throttle off.
#### `failsafe_fw_roll_angle`
This parameter defines amount of roll angle (in 1/10 deg units) to execute on failsafe. Negative = LEFT
This parameter defines the amount of roll angle (in 1/10 deg units) to execute on failsafe. Negative = LEFT
#### `failsafe_fw_pitch_angle`
This parameter defines amount of pitch angle (in 1/10 deg units) to execute on `SET-THR` failsafe for an airplane. Negative = CLIMB
This parameter defines the amount of pitch angle (in 1/10 deg units) to execute on failsafe for an airplane. Negative = CLIMB
#### `failsafe_fw_yaw_rate`
This parameter defines amount of yaw rate (in deg per second units) to execute on `SET-THR` failsafe for an airplane. Negative = LEFT
This parameter defines the amount of yaw rate (in deg per second units) to execute on failsafe for an airplane. Negative = LEFT

View file

@ -28,7 +28,6 @@ The following adjustments can be made in flight as well as on the ground.
* Throttle Expo
* Pitch, Roll, Yaw Rates
* Pitch, Roll, Yaw PIDs
* Rate profile
* Manual rates
* FW cruise_throttle, pitch2thr, min_throttle_down_pitch_angle
* Board alignment
@ -62,7 +61,7 @@ Hint: With OpenTX transmitters you can combine two momentary OFF-ON switches to
The CLI command `adjrange` is used to configure adjustment ranges.
12 adjustment ranges can be defined.
20 adjustment ranges can be defined.
4 adjustments can be made at the same time, each simultaneous adjustment requires an adjustment slot.
Show the current ranges using:
@ -77,12 +76,12 @@ Configure a range using:
| Argument | Value | Meaning |
| -------- | ----- |-------- |
| Index | 0 - 11 | Select the adjustment range to configure |
| Index | 0 - 19 | Select the adjustment range to configure |
| Slot | 0 - 3 | Select the adjustment slot to use |
| Range Channel | 0 based index, AUX1 = 0, AUX2 = 1 | The AUX channel to use to select an adjustment for a switch/pot |
| Range Start | 900 - 2100. Steps of 25, e.g. 900, 925, 950... | Start of range |
| Range End | 900 - 2100 | End of range |
| Adjustment function | 0 - 11 | See Adjustment function table |
| Adjustment function | 0 - 56 | See Adjustment function table |
| Adjustment channel | 0 based index, AUX1 = 0, AUX2 = 1 | The channel that is controlled by a 3 Position switch/Pot |
Range Start/End values should match the values sent by your receiver.
@ -100,8 +99,8 @@ this reason ensure that you define enough ranges to cover the range channel's us
### Adjustment function
| Value | Adjustment | Notes |
| ----- | ---------- |------ |
| Value | Adjustment |
| ----- | ---------- |
| 0 | None |
| 1 | RC RATE |
| 2 | RC_EXPO |
@ -111,47 +110,54 @@ this reason ensure that you define enough ranges to cover the range channel's us
| 6 | PITCH_ROLL_P |
| 7 | PITCH_ROLL_I |
| 8 | PITCH_ROLL_D |
| 9 | YAW_P |
| 10 | YAW_I |
| 11 | YAW_D_FF |
| 12 | RATE_PROFILE | Switch between 3 rate profiles using a 3 position switch. |
| 13 | PITCH_RATE |
| 14 | ROLL_RATE |
| 15 | PITCH_P |
| 16 | PITCH_I |
| 17 | PITCH_D_FF |
| 18 | ROLL_P |
| 19 | ROLL_I |
| 20 | ROLL_D_FF |
| 21 | RC_YAW_EXPO |
| 22 | MANUAL_RC_EXPO |
| 23 | MANUAL_RC_YAW_EXPO |
| 24 | MANUAL_PITCH_ROLL_RATE |
| 25 | MANUAL_ROLL_RATE |
| 26 | MANUAL_PITCH_RATE |
| 27 | MANUAL_YAW_RATE |
| 28 | NAV_FW_CRUISE_THROTTLE |
| 29 | NAV_FW_PITCH2THR |
| 30 | ROLL_BOARD_ALIGNMENT |
| 31 | PITCH_BOARD_ALIGNMENT |
| 32 | LEVEL_P |
| 33 | LEVEL_I |
| 34 | LEVEL_D |
| 35 | POS_XY_P |
| 36 | POS_XY_I |
| 37 | POS_XY_D |
| 38 | POS_Z_P |
| 39 | POS_Z_I |
| 40 | POS_Z_D |
| 41 | HEADING_P |
| 42 | VEL_XY_P |
| 43 | VEL_XY_I |
| 44 | VEL_XY_D |
| 45 | VEL_Z_P |
| 46 | VEL_Z_I |
| 47 | VEL_Z_D |
| 48 | FW_MIN_THROTTLE_DOWN_PITCH_ANGLE |
| 49 | ADJUSTMENT_VTX_POWER_LEVEL |
| 9 | PITCH_ROLL_FF |
| 10 | PITCH_P |
| 11 | PITCH_I |
| 12 | PITCH_D |
| 13 | PITCH_FF |
| 14 | ROLL_P |
| 15 | ROLL_I |
| 16 | ROLL_D |
| 17 | ROL_FF |
| 18 | YAW_P |
| 19 | YAW_I |
| 20 | YAW_D |
| 21 | YAW_FF
| 22 | Unused |
| 23 | PITCH_RATE |
| 24 | ROLL_RATE |
| 25 | RC_YAW_EXPO |
| 26 | MANUAL_RC_EXPO |
| 27 | MANUAL_RC_YAW_EXPO |
| 28 | MANUAL_PITCH_ROLL_RATE |
| 29 | MANUAL_ROLL_RATE |
| 30 | MANUAL_PITCH_RATE |
| 31 | MANUAL_YAW_RATE |
| 32 | NAV_FW_CRUISE_THROTTLE |
| 33 | NAV_FW_PITCH2THR |
| 34 | ROLL_BOARD_ALIGNMENT |
| 35 | PITCH_BOARD_ALIGNMENT |
| 36 | LEVEL_P |
| 37 | LEVEL_I |
| 38 | LEVEL_D |
| 39 | POS_XY_P |
| 40 | POS_XY_I |
| 41 | POS_XY_D |
| 42 | POS_Z_P |
| 43 | POS_Z_I |
| 44 | POS_Z_D |
| 45 | HEADING_P |
| 46 | VEL_XY_P |
| 47 | VEL_XY_I |
| 48 | VEL_XY_D |
| 49 | VEL_Z_P |
| 50 | VEL_Z_I |
| 51 | VEL_Z_D |
| 52 | FW_MIN_THROTTLE_DOWN_PITCH_ANGLE |
| 53 | ADJUSTMENT_VTX_POWER_LEVEL |
| 54 | TPA |
| 55 | TPA_BREAKPOINT |
| 56 | NAV_FW_CONTROL_SMOOTHNESS |
## Examples
@ -193,9 +199,9 @@ range.
adjrange 3 2 1 900 1150 6 3
adjrange 4 2 1 1150 1300 7 3
adjrange 5 2 1 1300 1500 8 3
adjrange 6 2 1 1500 1700 9 3
adjrange 7 2 1 1700 1850 10 3
adjrange 8 2 1 1850 2100 11 3
adjrange 6 2 1 1500 1700 18 3
adjrange 7 2 1 1700 1850 19 3
adjrange 8 2 1 1850 2100 20 3
```
explained:
@ -210,38 +216,19 @@ explained:
(1) in the range 1300-1500 then use adjustment Pitch/Roll D (8) when aux 4
(3) is in the appropriate position.
* configure adjrange 6 to use adjustment slot 3 (2) so that when aux2
(1) in the range 1500-1700 then use adjustment Yaw P (9) when aux 4
(1) in the range 1500-1700 then use adjustment Yaw P (18) when aux 4
(3) is in the appropriate position.
* configure adjrange 7 to use adjustment slot 3 (2) so that when aux2
(1) in the range 1700-1850 then use adjustment Yaw I (10) when aux 4
(1) in the range 1700-1850 then use adjustment Yaw I (19) when aux 4
(3) is in the appropriate position.
* configure adjrange 8 to use adjustment slot 3 (2) so that when aux2
(1) in the range 1850-2100 then use adjustment Yaw D (11) when aux 4
(1) in the range 1850-2100 then use adjustment Yaw D (20) when aux 4
(3) is in the appropriate position.
### Example 4 - Use a single 3 position switch to change between 3 different rate profiles
adjrange 11 3 3 900 2100 12 3
explained:
* configure adjrange 11 to use adjustment slot 4 (3) so that when aux4
(3) in the range 900-2100 then use adjustment Rate Profile (12) when aux 4
(3) is in the appropriate position.
When the switch is low, rate profile 0 is selcted.
When the switch is medium, rate profile 1 is selcted.
When the switch is high, rate profile 2 is selcted.
### Configurator examples
The following 5 images show valid configurations. In all cases the entire usable range for the Range Channel is used.
![Configurator example 1](Screenshots/adjustments-rate-profile-selection-via-3pos.png)
---
![Configurator example 2](Screenshots/adjustments-pitch-and-roll-rate-adjustment-via-3pos.png)
---
@ -263,4 +250,4 @@ The following examples shows __incorrect__ configurations - the entire usable ra
In the following example, the incorrect configuraton (above) has been corrected by adding a range that makes 'No changes'.
![Configurator example 7](Screenshots/adjustments-incorrect-config-2-corrected.png)
![Configurator example 7](Screenshots/adjustments-incorrect-config-2-corrected.png)

View file

@ -2,7 +2,7 @@
A profile is a set of configuration settings.
Currently three profiles are supported. The default profile is profile `0`.
Currently three profiles are supported. The default profile is profile `1`.
## Changing profiles
@ -10,9 +10,9 @@ Profiles can be selected using a GUI or the following stick combinations:
| Profile | Throttle | Yaw | Pitch | Roll |
| ------- | -------- | ----- | ------ | ------ |
| 0 | Down | Left | Middle | Left |
| 1 | Down | Left | Up | Middle |
| 2 | Down | Left | Middle | Right |
| 1 | Down | Left | Middle | Left |
| 2 | Down | Left | Up | Middle |
| 3 | Down | Left | Middle | Right |
The CLI `profile` command can also be used:
@ -20,45 +20,127 @@ The CLI `profile` command can also be used:
profile <index>
```
# Rate Profiles
INAV supports rate profiles in addition to regular profiles.
Rate profiles contain settings that adjust how your craft behaves based on control input.
Three rate profiles are supported.
Rate profiles can be selected while flying using the inflight adjustments feature.
Each normal profile has a setting called 'default_rate_profile`. When a profile is activated the
corresponding rate profile is also activated.
Profile 0 has a default rate profile of 0.
Profile 1 has a default rate profile of 1.
Profile 2 has a default rate profile of 2.
The defaults are set this way so that it's simple to configure a profile and a rate profile at the same.
The current rate profile can be shown or set using the CLI `rateprofile` command:
```
rateprofile <index>
```
The values contained within a rate profile can be seen by using the CLI `dump rates` command.
The values contained within a profile can be seen by using the CLI `dump profile` command.
e.g
```
# dump rates
# dump profile
# rateprofile
rateprofile 0
# profile
profile 1
set rc_expo = 65
set mc_p_pitch = 40
set mc_i_pitch = 30
set mc_d_pitch = 23
set mc_cd_pitch = 60
set mc_p_roll = 40
set mc_i_roll = 30
set mc_d_roll = 23
set mc_cd_roll = 60
set mc_p_yaw = 85
set mc_i_yaw = 45
set mc_d_yaw = 0
set mc_cd_yaw = 60
set mc_p_level = 20
set mc_i_level = 15
set mc_d_level = 75
set fw_p_pitch = 5
set fw_i_pitch = 7
set fw_d_pitch = 0
set fw_ff_pitch = 50
set fw_p_roll = 5
set fw_i_roll = 7
set fw_d_roll = 0
set fw_ff_roll = 50
set fw_p_yaw = 6
set fw_i_yaw = 10
set fw_d_yaw = 0
set fw_ff_yaw = 60
set fw_p_level = 20
set fw_i_level = 5
set fw_d_level = 75
set max_angle_inclination_rll = 300
set max_angle_inclination_pit = 300
set dterm_lpf_hz = 110
set dterm_lpf_type = PT2
set dterm_lpf2_hz = 0
set dterm_lpf2_type = PT1
set yaw_lpf_hz = 0
set fw_iterm_throw_limit = 165
set fw_loiter_direction = RIGHT
set fw_reference_airspeed = 1500.000
set fw_turn_assist_yaw_gain = 1.000
set fw_turn_assist_pitch_gain = 1.000
set fw_iterm_limit_stick_position = 0.500
set fw_yaw_iterm_freeze_bank_angle = 0
set pidsum_limit = 500
set pidsum_limit_yaw = 350
set iterm_windup = 50
set rate_accel_limit_roll_pitch = 0
set rate_accel_limit_yaw = 10000
set heading_hold_rate_limit = 90
set nav_mc_pos_z_p = 50
set nav_mc_vel_z_p = 100
set nav_mc_vel_z_i = 50
set nav_mc_vel_z_d = 10
set nav_mc_pos_xy_p = 65
set nav_mc_vel_xy_p = 40
set nav_mc_vel_xy_i = 15
set nav_mc_vel_xy_d = 100
set nav_mc_vel_xy_ff = 40
set nav_mc_heading_p = 60
set nav_mc_vel_xy_dterm_lpf_hz = 2.000
set nav_mc_vel_xy_dterm_attenuation = 90
set nav_mc_vel_xy_dterm_attenuation_start = 10
set nav_mc_vel_xy_dterm_attenuation_end = 60
set nav_fw_pos_z_p = 40
set nav_fw_pos_z_i = 5
set nav_fw_pos_z_d = 10
set nav_fw_pos_xy_p = 75
set nav_fw_pos_xy_i = 5
set nav_fw_pos_xy_d = 8
set nav_fw_heading_p = 60
set nav_fw_pos_hdg_p = 30
set nav_fw_pos_hdg_i = 2
set nav_fw_pos_hdg_d = 0
set nav_fw_pos_hdg_pidsum_limit = 350
set mc_iterm_relax = RP
set mc_iterm_relax_cutoff = 15
set d_boost_min = 0.500
set d_boost_max = 1.250
set d_boost_max_at_acceleration = 7500.000
set d_boost_gyro_delta_lpf_hz = 80
set antigravity_gain = 1.000
set antigravity_accelerator = 1.000
set antigravity_cutoff_lpf_hz = 15
set pid_type = AUTO
set mc_cd_lpf_hz = 30
set fw_level_pitch_trim = 0.000
set smith_predictor_strength = 0.500
set smith_predictor_delay = 0.000
set smith_predictor_lpf_hz = 50
set fw_level_pitch_gain = 5.000
set thr_mid = 50
set thr_expo = 0
set roll_pitch_rate = 0
set yaw_rate = 0
set tpa_rate = 0
set tpa_breakpoint = 1500
set fw_tpa_time_constant = 0
set rc_expo = 70
set rc_yaw_expo = 20
set roll_rate = 20
set pitch_rate = 20
set yaw_rate = 20
set manual_rc_expo = 70
set manual_rc_yaw_expo = 20
set manual_roll_rate = 100
set manual_pitch_rate = 100
set manual_yaw_rate = 100
set fpv_mix_degrees = 0
set rate_dynamics_center_sensitivity = 100
set rate_dynamics_end_sensitivity = 100
set rate_dynamics_center_correction = 10
set rate_dynamics_end_correction = 10
set rate_dynamics_center_weight = 0
set rate_dynamics_end_weight = 0
```

View file

@ -74,7 +74,8 @@ IPF can be edited using INAV Configurator user interface, of via CLI
| 38 | RC_CHANNEL_OVERRIDE | Overrides channel set by `Operand A` to value of `Operand B` |
| 39 | SET_HEADING_TARGET | Sets heading-hold target to `Operand A`, in degrees. Value wraps-around. |
| 40 | MOD | Divide `Operand A` by `Operand B` and returns the remainder |
| 41 | LOITER_RADIUS_OVERRIDE | Sets the loiter radius to `Operand A` [`0` : `100000`] in cm. If the value is lower than the loiter radius set in the **Advanced Tuning**, that will be used. |
| 42 | SET_PROFILE | Sets the active config profile (PIDFF/Rates/Filters/etc) to `Operand A`. `Operand A` must be a valid profile number, currently from 1 to 3. If not, the profile will not change |
### Operands
@ -125,8 +126,10 @@ IPF can be edited using INAV Configurator user interface, of via CLI
| 30 | ACTIVE_WAYPOINT_ACTION | See ACTIVE_WAYPOINT_ACTION paragraph |
| 31 | 3D HOME_DISTANCE | in `meters`, calculated from HOME_DISTANCE and ALTITUDE using Pythagorean theorem |
| 32 | CROSSFIRE LQ | Crossfire Link quality as returned by the CRSF protocol |
| 33 | CROSSFIRE SNR | Crossfire SNR as returned by the CRSF protocol |
| 34 | GPS_VALID | boolean `0`/`1`. True when the GPS has a valid 3D Fix |
| 33 | CROSSFIRE SNR | Crossfire SNR as returned by the CRSF protocol |
| 34 | GPS_VALID | boolean `0`/`1`. True when the GPS has a valid 3D Fix |
| 35 | LOITER_RADIUS | The current loiter radius in cm. |
| 36 | ACTIVE_PROFILE | integer for the active config profile `[1..MAX_PROFILE_COUNT]` |
#### ACTIVE_WAYPOINT_ACTION

View file

@ -14,19 +14,17 @@ Current support of rangefinders in INAV is very limited. They are used only to:
Following rangefinders are supported:
* HC-SR04 - ***DO NOT USE*** HC-SR04 while most popular is not suited to use in noise reach environments (like multirotors). It is proven that this sonar rangefinder start to report random values already at 1.5m above solid concrete surface. Reported altitude is valid up to only 75cm above concrete. ***DO NOT USE***
* US-100 in trigger-echo mode - Can be used as direct replacement of _HC-SR04_ when `rangefinder_hardware` is set to _HCSR04_. Useful up to 2m over concrete and correctly reporting _out of range_ when out of range
* SRF10 - experimental
* INAV_I2C - is a simple [DIY rangefinder interface with Arduino Pro Mini 3.3V](https://github.com/iNavFlight/inav-rangefinder). Can be used to connect when flight controller has no Trigger-Echo ports.
* VL53L0X - simple laser rangefinder usable up to 75cm
* UIB - experimental
* MSP - experimental
* TOF10120 - small & lightweight laser range sensor, usable up to 200cm
## Connections
Target dependent in case of Trigger/Echo solutions like `HC-SR04` and `US-100`.
I2C solutions like `VL53L0X` or `INAV_I2C` can be connected to I2C port and used as any other I2C device.
#### Constraints
Target dependent in case of Trigger/Echo solutions like `HC-SR04` and `US-100`. No constrains for I2C like `VL53L0X` or `INAV_I2C`.
iNav does not support `HC-SR04` and `US-100`. No constrains for I2C like `VL53L0X` or `INAV_I2C`.

View file

@ -452,6 +452,16 @@ If the remaining battery capacity goes below this threshold the beeper will emit
---
### beeper_pwm_mode
Allows disabling PWM mode for beeper on some targets. Switch from ON to OFF if the external beeper sound is weak. Do not switch from OFF to ON without checking if the board supports PWM beeper mode
| Default | Min | Max |
| --- | --- | --- |
| OFF | | |
---
### blackbox_device
Selection of where to write blackbox data
@ -562,16 +572,6 @@ ADC , VIRTUAL, NONE. The virtual current sensor, once calibrated, estimates the
---
### d_boost_factor
_// TODO_
| Default | Min | Max |
| --- | --- | --- |
| 1.25 | 1 | 3 |
---
### d_boost_gyro_delta_lpf_hz
_// TODO_
@ -582,6 +582,16 @@ _// TODO_
---
### d_boost_max
_// TODO_
| Default | Min | Max |
| --- | --- | --- |
| 1.25 | 1 | 3 |
---
### d_boost_max_at_acceleration
_// TODO_
@ -592,6 +602,16 @@ _// TODO_
---
### d_boost_min
_// TODO_
| Default | Min | Max |
| --- | --- | --- |
| 0.5 | 0 | 1 |
---
### deadband
These are values (in us) by how much RC input can be different before it's considered valid. For transmitters with jitter on outputs, this value can be increased. Defaults are zero, but can be increased up to 10 or so if rc inputs twitch while idle.
@ -734,11 +754,11 @@ Cutoff frequency for stage 2 D-term low pass filter
### dterm_lpf2_type
Defines the type of stage 1 D-term LPF filter. Possible values: `PT1`, `BIQUAD`. `PT1` offers faster filter response while `BIQUAD` better attenuation.
Defines the type of stage 1 D-term LPF filter. Possible values: `PT1`, `BIQUAD`, `PT2`, `PT3`.
| Default | Min | Max |
| --- | --- | --- |
| BIQUAD | | |
| PT1 | | |
---
@ -748,17 +768,17 @@ Dterm low pass filter cutoff frequency. Default setting is very conservative and
| Default | Min | Max |
| --- | --- | --- |
| 40 | 0 | 500 |
| 110 | 0 | 500 |
---
### dterm_lpf_type
Defines the type of stage 1 D-term LPF filter. Possible values: `PT1`, `BIQUAD`. `PT1` offers faster filter response while `BIQUAD` better attenuation.
Defines the type of stage 1 D-term LPF filter. Possible values: `PT1`, `BIQUAD`, `PT2`, `PT3`.
| Default | Min | Max |
| --- | --- | --- |
| BIQUAD | | |
| PT2 | | |
---
@ -768,17 +788,17 @@ Enable/disable dynamic gyro notch also known as Matrix Filter
| Default | Min | Max |
| --- | --- | --- |
| OFF | | |
| ON | | |
---
### dynamic_gyro_notch_min_hz
Minimum frequency for dynamic notches. Default value of `150` works best with 5" multirors. Should be lowered with increased size of propellers. Values around `100` work fine on 7" drones. 10" can go down to `60` - `70`
Minimum frequency for dynamic notches. Default value of `150` works best with 5" multirotors. Should be lowered with increased size of propellers. Values around `100` work fine on 7" drones. 10" can go down to `60` - `70`
| Default | Min | Max |
| --- | --- | --- |
| 150 | 30 | 1000 |
| 50 | 30 | 1000 |
---
@ -792,16 +812,6 @@ Q factor for dynamic notches
---
### dynamic_gyro_notch_range
Range for dynamic gyro notches. `MEDIUM` for 5", `HIGH` for 3" and `MEDIUM`/`LOW` for 7" and bigger propellers
| Default | Min | Max |
| --- | --- | --- |
| MEDIUM | | |
---
### eleres_freq
_// TODO_
@ -894,7 +904,7 @@ Time in deciseconds to wait before activating failsafe when signal is lost. See
### failsafe_fw_pitch_angle
Amount of dive/climb when `SET-THR` failsafe is active on a fixed-wing machine. In 1/10 deg (deci-degrees). Negative values = climb
Amount of dive/climb when `LAND` (or old `SET-THR`) failsafe is active on a fixed-wing machine. In 1/10 deg (deci-degrees). Negative values = climb
| Default | Min | Max |
| --- | --- | --- |
@ -904,7 +914,7 @@ Amount of dive/climb when `SET-THR` failsafe is active on a fixed-wing machine.
### failsafe_fw_roll_angle
Amount of banking when `SET-THR` failsafe is active on a fixed-wing machine. In 1/10 deg (deci-degrees). Negative values = left roll
Amount of banking when `LAND` (or old `SET-THR`) failsafe is active on a fixed-wing machine. In 1/10 deg (deci-degrees). Negative values = left roll
| Default | Min | Max |
| --- | --- | --- |
@ -914,7 +924,7 @@ Amount of banking when `SET-THR` failsafe is active on a fixed-wing machine. In
### failsafe_fw_yaw_rate
Requested yaw rate to execute when `SET-THR` failsafe is active on a fixed-wing machine. In deg/s. Negative values = left turn
Requested yaw rate to execute when `LAND` (or old `SET-THR`) failsafe is active on a fixed-wing machine. In deg/s. Negative values = left turn
| Default | Min | Max |
| --- | --- | --- |
@ -998,7 +1008,7 @@ What failsafe procedure to initiate in Stage 2. See [Failsafe documentation](Fai
| Default | Min | Max |
| --- | --- | --- |
| SET-THR | | |
| LAND | | |
---
@ -1158,13 +1168,13 @@ The target percentage of maximum mixer output used for determining the rates in
| Default | Min | Max |
| --- | --- | --- |
| 90 | 50 | 100 |
| 80 | 50 | 100 |
---
### fw_autotune_min_stick
Minimum stick input [%] to consider overshoot/undershoot detection
Minimum stick input [%], after applying deadband and expo, to start recording the plane's response to stick input.
| Default | Min | Max |
| --- | --- | --- |
@ -1522,36 +1532,6 @@ Enable use of Galileo satellites. This is at the expense of other regional const
---
### gyro_abg_alpha
Alpha factor for Gyro Alpha-Beta-Gamma filter
| Default | Min | Max |
| --- | --- | --- |
| 0 | 0 | 1 |
---
### gyro_abg_boost
Boost factor for Gyro Alpha-Beta-Gamma filter
| Default | Min | Max |
| --- | --- | --- |
| 0.35 | 0 | 2 |
---
### gyro_abg_half_life
Sample half-life for Gyro Alpha-Beta-Gamma filter
| Default | Min | Max |
| --- | --- | --- |
| 0.5 | 0 | 10 |
---
### gyro_anti_aliasing_lpf_hz
Gyro processing anti-aliasing filter cutoff frequency. In normal operation this filter setting should never be changed. In Hz
@ -1658,7 +1638,7 @@ _// TODO_
| Default | Min | Max |
| --- | --- | --- |
| 0 | 0 | 1 |
| 0 | 0 | 2 |
---
@ -1928,7 +1908,7 @@ Inertial Measurement Unit KP Gain for accelerometer measurements
| Default | Min | Max |
| --- | --- | --- |
| 2500 | | 65535 |
| 1000 | | 65535 |
---
@ -1938,7 +1918,7 @@ Inertial Measurement Unit KP Gain for compass measurements
| Default | Min | Max |
| --- | --- | --- |
| 10000 | | 65535 |
| 5000 | | 65535 |
---
@ -2458,7 +2438,7 @@ Exposition value used for the PITCH/ROLL axes by the `MANUAL` flight mode [0-100
| Default | Min | Max |
| --- | --- | --- |
| 70 | 0 | 100 |
| 35 | 0 | 100 |
---
@ -2832,26 +2812,6 @@ When powering up, gyro bias is calculated. If the model is shaking/moving during
---
### motor_accel_time
Minimum time for the motor(s) to accelerate from 0 to 100% throttle (ms) [0-1000]
| Default | Min | Max |
| --- | --- | --- |
| 0 | 0 | 1000 |
---
### motor_decel_time
Minimum time for the motor(s) to deccelerate from 100 to 0% throttle (ms) [0-1000]
| Default | Min | Max |
| --- | --- | --- |
| 0 | 0 | 1000 |
---
### motor_direction_inverted
Use if you need to inverse yaw motor direction.
@ -2924,7 +2884,7 @@ Maximum climb/descent rate that UAV is allowed to reach during navigation modes.
### nav_auto_speed
Maximum velocity firmware is allowed in full auto modes (RTH, WP) [cm/s] [Multirotor only]
Speed in fully autonomous modes (RTH, WP) [cm/s]. Used for WP mode when no specific WP speed set. [Multirotor only]
| Default | Min | Max |
| --- | --- | --- |
@ -3424,7 +3384,7 @@ Maximum climb/descent rate firmware is allowed when processing pilot input for A
### nav_manual_speed
Maximum velocity firmware is allowed when processing pilot input for POSHOLD/CRUISE control mode [cm/s] [Multirotor only]
Maximum speed allowed when processing pilot input for POSHOLD/CRUISE control mode [cm/s] [Multirotor only]
| Default | Min | Max |
| --- | --- | --- |
@ -3442,6 +3402,16 @@ Max allowed altitude (above Home Point) that applies to all NAV modes (including
---
### nav_max_auto_speed
Maximum speed allowed in fully autonomous modes (RTH, WP) [cm/s] [Multirotor only]
| Default | Min | Max |
| --- | --- | --- |
| 1000 | 10 | 2000 |
---
### nav_max_terrain_follow_alt
Max allowed above the ground altitude for terrain following mode
@ -4132,6 +4102,16 @@ Value above which to make the OSD distance from home indicator blink (meters)
---
### osd_esc_rpm_precision
Number of characters used to display the RPM value.
| Default | Min | Max |
| --- | --- | --- |
| 3 | 3 | 6 |
---
### osd_esc_temp_alarm_max
Temperature above which the IMU temperature OSD element will start blinking (decidegrees centigrade)
@ -4552,6 +4532,16 @@ Display minimum voltage of the `BATTERY` or the average per `CELL` in the OSD st
---
### osd_stats_page_auto_swap_time
Auto swap display time interval between disarm stats pages (seconds). Reverts to manual control when Roll stick used to change pages. Disabled when set to 0.
| Default | Min | Max |
| --- | --- | --- |
| 3 | 0 | 10 |
---
### osd_telemetry
To enable OSD telemetry for antenna tracker. Possible values are `OFF`, `ON` and `TEST`
@ -4782,6 +4772,66 @@ Limits acceleration of YAW rotation speed that can be requested by stick input.
---
### rate_dynamics_center_correction
The center stick correction for Rate Dynamics
| Default | Min | Max |
| --- | --- | --- |
| 10 | 10 | 95 |
---
### rate_dynamics_center_sensitivity
The center stick sensitivity for Rate Dynamics
| Default | Min | Max |
| --- | --- | --- |
| 100 | 25 | 175 |
---
### rate_dynamics_center_weight
The center stick weight for Rate Dynamics
| Default | Min | Max |
| --- | --- | --- |
| 0 | 0 | 95 |
---
### rate_dynamics_end_correction
The end stick correction for Rate Dynamics
| Default | Min | Max |
| --- | --- | --- |
| 10 | 10 | 95 |
---
### rate_dynamics_end_sensitivity
The end stick sensitivity for Rate Dynamics
| Default | Min | Max |
| --- | --- | --- |
| 100 | 25 | 175 |
---
### rate_dynamics_end_weight
The end stick weight for Rate Dynamics
| Default | Min | Max |
| --- | --- | --- |
| 0 | 0 | 95 |
---
### rc_expo
Exposition value used for the PITCH/ROLL axes by all the stabilized flights modes (all but `MANUAL`)
@ -5128,7 +5178,7 @@ Enable Kalman filter on the gyro data
| Default | Min | Max |
| --- | --- | --- |
| OFF | | |
| ON | | |
---
@ -5654,7 +5704,7 @@ These are values (in us) by how much RC input can be different before it's consi
### yaw_lpf_hz
Yaw low pass filter cutoff frequency. Should be disabled (set to `0`) on small multirotors (7 inches and below)
Yaw P term low pass filter cutoff frequency. Should be disabled (set to `0`) on small multirotors (7 inches and below)
| Default | Min | Max |
| --- | --- | --- |

View file

@ -121,6 +121,7 @@ The following sensors are transmitted
* **0430** : if `frsky_pitch_roll = ON` set this will be pitch degrees*10
* **0440** : if `frsky_pitch_roll = ON` set this will be roll degrees*10
* **0450** : 'Flight Path Vector' or 'Course over ground' in degrees*10
* **0460** : Azimuth in degrees*10
### Compatible SmartPort/INAV telemetry flight status
To quickly and easily monitor these SmartPort sensors and flight modes, install [OpenTX Telemetry Widget](https://github.com/iNavFlight/OpenTX-Telemetry-Widget) to your Taranis Q X7, X9D, X9D+ or X9E transmitter.

BIN
docs/assets/betafpvf722.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 221 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1,012 KiB

After

Width:  |  Height:  |  Size: 666 KiB

Before After
Before After

View file

@ -2,23 +2,23 @@
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="2478.5964mm"
height="1400.9835mm"
viewBox="0 0 8782.4284 4964.1146"
id="svg2"
version="1.1"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
inkscape:version="1.1 (c4e8f9ed74, 2021-05-24)"
sodipodi:docname="StickPositions.svg"
inkscape:export-filename="C:\Users\teckel.SSCORP\Downloads\StickPositions.png"
inkscape:export-filename="StickPositions.png"
inkscape:export-xdpi="74.996788"
inkscape:export-ydpi="74.996788">
inkscape:export-ydpi="74.996788"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs
id="defs4" />
<sodipodi:namedview
@ -29,15 +29,15 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.13995495"
inkscape:cx="3633.6202"
inkscape:cy="2120.4595"
inkscape:cx="6594.9793"
inkscape:cy="3265.3365"
inkscape:document-units="px"
inkscape:current-layer="g4157"
showgrid="false"
inkscape:window-width="2560"
inkscape:window-height="1377"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-width="1920"
inkscape:window-height="1010"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
fit-margin-top="1"
fit-margin-left="1"
@ -49,7 +49,8 @@
inkscape:guide-bbox="true"
inkscape:snap-object-midpoints="true"
inkscape:snap-others="false"
inkscape:object-nodes="true" />
inkscape:object-nodes="true"
inkscape:pagecheckerboard="0" />
<metadata
id="metadata7">
<rdf:RDF>
@ -58,7 +59,7 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
@ -160,7 +161,7 @@
x="533.55804"
style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="font-size:286.5987854px;line-height:1.25;text-align:end;text-anchor:end"
style="font-size:286.599px;line-height:1.25;text-align:end;text-anchor:end"
id="tspan4711"
y="-1909.1018"
x="533.55804"
@ -205,7 +206,7 @@
x="533.55804"
y="-1488.6938"
id="tspan4763"
style="font-size:286.5987854px;line-height:1.25;text-align:end;text-anchor:end">Profile 2</tspan></text>
style="font-size:286.599px;line-height:1.25;text-align:end;text-anchor:end">Profile 2</tspan></text>
<rect
ry="0"
y="-1317.7664"
@ -242,7 +243,7 @@
x="533.55804"
style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="font-size:286.5987854px;line-height:1.25;text-align:end;text-anchor:end"
style="font-size:286.599px;line-height:1.25;text-align:end;text-anchor:end"
id="tspan4815"
y="-1068.2856"
x="533.55804"
@ -287,7 +288,7 @@
x="533.55811"
y="583.57056"
id="tspan4867"
style="font-size:286.5987854px;line-height:1.25;text-align:end;text-anchor:end">Calibrate Gyro</tspan></text>
style="font-size:286.599px;line-height:1.25;text-align:end;text-anchor:end">Calibrate Gyro</tspan></text>
<rect
style="display:inline;opacity:1;fill:none;fill-opacity:1;stroke:#808080;stroke-width:11.05660725;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4875"
@ -328,7 +329,7 @@
x="533.55811"
y="1003.9787"
id="tspan4919"
style="font-size:286.5987854px;line-height:1.25;text-align:end;text-anchor:end">Calibrate Acc</tspan></text>
style="font-size:286.599px;line-height:1.25;text-align:end;text-anchor:end">Calibrate Acc</tspan></text>
<rect
ry="0"
y="1171.4286"
@ -365,7 +366,7 @@
x="536.28436"
style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="font-size:286.5987854px;line-height:1.25;text-align:end;text-anchor:end"
style="font-size:286.599px;line-height:1.25;text-align:end;text-anchor:end"
id="tspan4971"
y="1420.9093"
x="536.2843"
@ -408,7 +409,7 @@
x="5680.7969"
style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="font-size:286.5987854px;line-height:1.25;text-align:end;text-anchor:end"
style="font-size:286.599px;line-height:1.25;text-align:end;text-anchor:end"
id="tspan5651"
y="-1527.5551"
x="5680.7969"
@ -453,7 +454,7 @@
x="5680.7969"
y="-1107.1469"
id="tspan5703"
style="font-size:286.5987854px;line-height:1.25;text-align:end;text-anchor:end">Trim Acc Left</tspan></text>
style="font-size:286.599px;line-height:1.25;text-align:end;text-anchor:end">Trim Acc Left</tspan></text>
<rect
style="display:inline;opacity:1;fill:none;fill-opacity:1;stroke:#808080;stroke-width:11.05660725;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect5711"
@ -492,7 +493,7 @@
x="5680.7969"
y="-686.73877"
id="tspan5755"
style="font-size:286.5987854px;line-height:1.25;text-align:end;text-anchor:end">Trim Acc Right</tspan></text>
style="font-size:286.599px;line-height:1.25;text-align:end;text-anchor:end">Trim Acc Right</tspan></text>
<rect
ry="0"
y="-489.01691"
@ -527,7 +528,7 @@
x="5680.7969"
style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="font-size:286.5987854px;line-height:1.25;text-align:end;text-anchor:end"
style="font-size:286.599px;line-height:1.25;text-align:end;text-anchor:end"
id="tspan5807"
y="-266.3306"
x="5680.7969"
@ -570,7 +571,7 @@
x="5680.7969"
y="154.07762"
id="tspan5859"
style="font-size:286.5987854px;line-height:1.25;text-align:end;text-anchor:end">Trim Acc Backwards</tspan></text>
style="font-size:286.599px;line-height:1.25;text-align:end;text-anchor:end">Trim Acc Backwards</tspan></text>
<rect
ry="0"
y="351.79944"
@ -607,7 +608,7 @@
x="5680.7969"
style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="font-size:286.5987854px;line-height:1.25;text-align:end;text-anchor:end"
style="font-size:286.599px;line-height:1.25;text-align:end;text-anchor:end"
id="tspan5911"
y="574.48572"
x="5680.7969"
@ -626,6 +627,20 @@
id="path5923"
d="m 5992.6852,1082.4789 c 0,10.5728 -14.6765,19.1438 -32.7809,19.1438 -18.1044,0 -32.7809,-8.571 -32.7809,-19.1438 0,-10.5729 14.6765,-163.59574 32.7809,-163.59574 18.1044,0 32.7809,153.02284 32.7809,163.59574 z"
style="display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:8.07780743;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<rect
ry="0"
y="1145.4941"
x="5811.6289"
height="288.94339"
width="288.94339"
id="rect5919-7"
style="display:inline;fill:none;fill-opacity:1;stroke:#808080;stroke-width:11.0566;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
sodipodi:nodetypes="sssss"
inkscape:connector-curvature="0"
id="path5923-5"
d="m 5988.8813,1455.7655 c 0,10.5728 -14.6765,19.1438 -32.7809,19.1438 -18.1044,0 -32.7809,-8.571 -32.7809,-19.1438 0,-10.5729 14.6765,-163.5957 32.7809,-163.5957 18.1044,0 32.7809,153.0228 32.7809,163.5957 z"
style="display:inline;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:8.07781;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<rect
style="display:inline;opacity:1;fill:none;fill-opacity:1;stroke:#808080;stroke-width:11.05660725;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect5941"
@ -648,54 +663,81 @@
x="5680.7969"
style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="font-size:286.5987854px;line-height:1.25;text-align:end;text-anchor:end"
style="font-size:286.599px;line-height:1.25;text-align:end;text-anchor:end"
id="tspan5963"
y="994.89398"
x="5680.7969"
sodipodi:role="line">Load waypoint mission</tspan></text>
<text
id="text5961-3"
y="1369.7102"
x="5681.5464"
style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="font-size:286.599px;line-height:1.25;text-align:end;text-anchor:end"
id="tspan5963-6"
y="1369.7102"
x="5681.5464"
sodipodi:role="line">Unload waypoint mission</tspan></text>
<rect
style="display:inline;opacity:1;fill:none;fill-opacity:1;stroke:#808080;stroke-width:11.05660725;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
style="display:inline;opacity:1;fill:none;fill-opacity:1;stroke:#808080;stroke-width:11.0566;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect5971"
width="288.94339"
height="288.94339"
x="5815.4326"
y="1192.6158"
y="1526.3658"
ry="0" />
<path
sodipodi:nodetypes="sssss"
inkscape:connector-curvature="0"
id="path5977"
d="m 5863.6503,1478.825 c -7.4762,7.4762 -23.9146,3.1589 -36.7164,-9.6428 -12.8017,-12.8018 -17.119,-29.2402 -9.6428,-36.7164 7.4761,-7.4761 126.0574,-105.3017 138.8592,-92.5 12.8017,12.8018 -85.0239,131.3831 -92.5,138.8592 z"
style="display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:8.07780743;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 5863.6503,1812.575 c -7.4762,7.4762 -23.9146,3.1589 -36.7164,-9.6428 -12.8017,-12.8018 -17.119,-29.2402 -9.6428,-36.7164 7.4761,-7.4761 126.0574,-105.3017 138.8592,-92.5 12.8017,12.8018 -85.0239,131.3831 -92.5,138.8592 z"
style="display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:8.07781;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:transform-center-y="73.935654"
inkscape:transform-center-x="73.935653" />
<rect
ry="0"
y="1192.6158"
y="1526.3658"
x="6221.147"
height="288.94339"
width="288.94339"
id="rect5993"
style="display:inline;opacity:1;fill:none;fill-opacity:1;stroke:#808080;stroke-width:11.05660725;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
style="display:inline;opacity:1;fill:none;fill-opacity:1;stroke:#808080;stroke-width:11.0566;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
sodipodi:nodetypes="sssss"
inkscape:connector-curvature="0"
id="path6001"
d="m 6460.9887,1478.825 c 7.4761,7.4762 23.9146,3.1589 36.7163,-9.6428 12.8017,-12.8018 17.119,-29.2402 9.6428,-36.7164 -7.4761,-7.4761 -126.0574,-105.3017 -138.8591,-92.5 -12.8018,12.8018 85.0238,131.3831 92.5,138.8592 z"
style="display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:8.07780743;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 6460.9887,1812.575 c 7.4761,7.4762 23.9146,3.1589 36.7163,-9.6428 12.8017,-12.8018 17.119,-29.2402 9.6428,-36.7164 -7.4761,-7.4761 -126.0574,-105.3017 -138.8591,-92.5 -12.8018,12.8018 85.0238,131.3831 92.5,138.8592 z"
style="display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:8.07781;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:transform-center-y="73.935654"
inkscape:transform-center-x="-73.935657" />
<rect
ry="0"
y="1140.2471"
x="6228.9062"
height="288.94339"
width="288.94339"
id="rect5993-3"
style="display:inline;fill:none;fill-opacity:1;stroke:#808080;stroke-width:11.0566;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
sodipodi:nodetypes="sssss"
inkscape:connector-curvature="0"
id="path6001-5"
d="m 6468.7482,1426.4562 c 7.4761,7.4762 23.9146,3.1589 36.7163,-9.6428 12.8017,-12.8018 17.119,-29.2402 9.6428,-36.7164 -7.4761,-7.4761 -126.0574,-105.3017 -138.8591,-92.5 -12.8018,12.8018 85.0238,131.3831 92.5,138.8592 z"
style="display:inline;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:8.07781;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:transform-center-y="73.935654"
inkscape:transform-center-x="-73.935657" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="5680.7969"
y="1415.3022"
x="5714.6821"
y="1775.6128"
id="text6013"><tspan
sodipodi:role="line"
x="5680.7969"
y="1415.3022"
x="5714.6821"
y="1775.6128"
id="tspan6015"
style="font-size:286.5987854px;line-height:1.25;text-align:end;text-anchor:end">Save Setting</tspan></text>
style="font-size:286.599px;line-height:1.25;text-align:end;text-anchor:end">Save Setting</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
@ -706,7 +748,7 @@
x="5690.6709"
y="-1955.0773"
id="tspan4219"
style="font-size:286.5987854px;line-height:1.25;text-align:end;text-anchor:end">Enter OSD Menu (CMS)</tspan></text>
style="font-size:286.599px;line-height:1.25;text-align:end;text-anchor:end">Enter OSD Menu (CMS)</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
@ -717,7 +759,7 @@
x="2179.2812"
y="-2663.0625"
id="tspan7909"
style="font-size:352.85842896px;line-height:1.25;text-align:center;text-anchor:middle">Mode 2 Stick Functions</tspan></text>
style="font-size:352.858px;line-height:1.25;text-align:center;text-anchor:middle">Mode 2 Stick Functions</tspan></text>
<rect
style="display:inline;opacity:1;fill:none;fill-opacity:1;stroke:#808080;stroke-width:11.05660725;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect927"
@ -752,7 +794,7 @@
x="533.55811"
y="-673.06989"
id="tspan935"
style="font-size:286.5987854px;line-height:1.25;text-align:end;text-anchor:end">Battery profile 1</tspan></text>
style="font-size:286.599px;line-height:1.25;text-align:end;text-anchor:end">Battery profile 1</tspan></text>
<rect
style="display:inline;opacity:1;fill:none;fill-opacity:1;stroke:#808080;stroke-width:11.05660725;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect943"
@ -773,7 +815,7 @@
x="533.55804"
style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="font-size:286.5987854px;line-height:1.25;text-align:end;text-anchor:end"
style="font-size:286.599px;line-height:1.25;text-align:end;text-anchor:end"
id="tspan947"
y="-252.66168"
x="533.55811"
@ -802,7 +844,7 @@
x="533.55811"
y="167.74652"
id="tspan959"
style="font-size:286.5987854px;line-height:1.25;text-align:end;text-anchor:end">Battery profile 3</tspan></text>
style="font-size:286.599px;line-height:1.25;text-align:end;text-anchor:end">Battery profile 3</tspan></text>
<path
sodipodi:nodetypes="sssss"
inkscape:connector-curvature="0"

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Before After
Before After

View file

@ -71,7 +71,7 @@ Airplanes
Buzzer is supported with additional switching MOSFET transistor when connected to PWM Output #9.
![Buzzer](assets/images/anyfcf7_buzzer_pwm9.png)
![Buzzer](../assets/images/anyfcf7_buzzer_pwm9.png)
## SD Card Detection
@ -83,4 +83,4 @@ Buzzer is supported with additional switching MOSFET transistor when connected t
# AnyFC F7 Pro from Banggood
This board is not yet officially supported. It _should_ work but INAV devs did not tested it yet. Use on your own responsibility
This board is not yet officially supported. It _should_ work but INAV devs did not tested it yet. Use on your own responsibility

12
docs/boards/BetFPVF722.md Normal file
View file

@ -0,0 +1,12 @@
# BetaFPVF722
## I2C bus for magnetometer
BetFPVF722 does not have I2C pads broken out. I2C is shared with UART3
* TX3 - SCL
* RX3 - SDA
> I2C and UART3 can not be used at the same time! Connect the serial receiver to a different serial port when I2C device like MAG is used.
![BetaFPVF722 I2C](../assets/betafpvf722.png)

View file

0
docs/Board - KroozX.md → docs/boards/KroozX.md Executable file → Normal file
View file

View file

@ -1,7 +1,5 @@
# Board - [MATEKSYS F405-Wing](https://inavflight.com/shop/p/MATEKF405WING)
![Matek F405 Wing](https://quadmeup.com/wp-content/uploads/2018/12/DSC_0007.jpg)
## Specification:
* STM32F405 CPU
@ -22,4 +20,4 @@
## Where to buy:
* [Banggood](https://inavflight.com/shop/p/MATEKF405WING)
* [Banggood](https://inavflight.com/shop/p/MATEKF405WING)

0
docs/Board - NOX.md → docs/boards/NOX.md Executable file → Normal file
View file

View file

@ -155,14 +155,14 @@ This board allows for single **SoftwareSerial** port on small soldering pads loc
Please note that this is *not* the motor PWM5/PWM6 pins, but small surface mount pads CH5/CH6.
### Omnibus F4 Pro SoftwareSerial Connections
![Omnibus F4 Pro SoftwareSerial Connections](assets/images/omnibusf4pro_ss.jpg)
![Omnibus F4 Pro SoftwareSerial Connections](../assets/images/omnibusf4pro_ss.jpg)
| Pad | SoftwareSerial Role |
| ---- | ---- |
| CH5 | RX |
| CH6 | TX |
![Omnibus F4 Pro SmartPort using SoftwareSerial](assets/images/omnibusf4pro_ss.png)
![Omnibus F4 Pro SmartPort using SoftwareSerial](../assets/images/omnibusf4pro_ss.png)
### Omnibus F4 v3/v4/v5 SoftwareSerial Connections
@ -181,22 +181,22 @@ Following diagrams applies to _Pro_ version with integrated current meter and JS
## Board layout
![Omnibus F4 Pro Board Layout](assets/images/omnibusf4pro.png)
![Omnibus F4 Pro Board Layout](../assets/images/omnibusf4pro.png)
## Flying wing motor and servos
![Omnibus F4 Pro Flying Wing Setup](assets/images/omnibusf4pro_flyingwing_setup.png)
![Omnibus F4 Pro Flying Wing Setup](../assets/images/omnibusf4pro_flyingwing_setup.png)
## RX setup
![Omnibus F4 Pro RX Setup](assets/images/omnibusf4pro_rx.png)
![Omnibus F4 Pro RX Setup](../assets/images/omnibusf4pro_rx.png)
## FPV setup
![Omnibus F4 Pro FPV Setup](assets/images/omnibusf4pro_fpv_setup.png)
![Omnibus F4 Pro FPV Setup](../assets/images/omnibusf4pro_fpv_setup.png)
## GPS setup
![Omnibus F4 Pro GPS Setup](assets/images/omnibusf4pro_gps_setup.png)
![Omnibus F4 Pro GPS Setup](../assets/images/omnibusf4pro_gps_setup.png)
_Diagrams created by Albert Kravcov (skaman82)_

View file

@ -1,51 +0,0 @@
# Atomic Barrier Warning
If GCC is upgraded and a warning appears when compiling then the generated asm source must be verified.
e.g.
```
%% serial_softserial.c
warning "Please verify that ATOMIC_BARRIER works as intended"
```
To perform the verification, proceed as per discusson on issue #167 which reads:
I hope it's enough to check that optimized-away variable still has cleanup code at end of scope.
```
static int markme=0;
markme++;
ATOMIC_BLOCK_NB(0xff) {
ATOMIC_BARRIER(markme);
markme++;
};
markme++;
```
pass `-save-temps=obj` (or `-save-temps=cwd`, but lots of files will end up in same directory as makefile) to gcc link step (LTO is in use), find resulting `*.ltrans*.ltrans.s` (grep for `markme`, on linux it ends up in `/tmp`) and check that generated assembly sequence is:
```
MSR basepri_max, r3
# (possibly markme address load)
# barier (markme) start
# (increment markme, load and store to memory)
ldr r2, [r3]
adds r0, r2, #1
str r0, [r3]
# barier(markme) end
MSR basepri, r3
# (markme value should be cached in register on next increment)
```
The # barrier(markme) must surround access code and must be inside MSR basepri instructions ..
Similar approach is used for ATOMIC_BLOCK in avr libraries, so gcc should not break this behavior.
IMO attribute(cleanup) and asm volatile is defined in a way that should guarantee this.
attribute(cleanup) is probably safer way to implement atomic sections - another possibility is to explicitly place barriers in code, but that can (and will eventually) lead to missed barrier/basepri restore on same path creating very hard to find bug.
The MEMORY_BARRIER() code can be omitted and use ATOMIC_BLOCK with full memory barriers, but IMO it is better to explicitly state what memory is protected by barrier and gcc can use this knowledge to greatly improve generated code in future.

View file

@ -65,7 +65,7 @@ The `git clone` creates an `inav` directory; we can enter this directory, config
## Build tooling
For 2.6 and later, inav uses `cmake` as its primary build tool. `cmake` simplies various platform and hardware dependencies required to cross compile multiple targets. `cmake` still uses GNU `make` to invoke the actual compiler. It is necessary to configure the build enviroment with `cmake` before we can build any firmware.
For 2.6 and later, inav uses `cmake` as its primary build tool. `cmake` simplifies various platform and hardware dependencies required to cross compile multiple targets. `cmake` still uses GNU `make` to invoke the actual compiler. It is necessary to configure the build environment with `cmake` before we can build any firmware.
## Using `cmake`
@ -96,14 +96,14 @@ Once `cmake` has generated the `build/Makefile`, this `Makfile` (with `make`) is
The generated `Makefile` uses different a target selection mechanism from the older (pre 2.6) top level `Makefile`; you can generate a list of targets with `make help` (or, as the list is extremely long), pipe this into a pager, e.g. `make help | less`.
Typically, to build a single target, just pass the target name to `make`; note that unlike eariler releases, `make` without a target specified will build **all** targets.
Typically, to build a single target, just pass the target name to `make`; note that unlike earlier releases, `make` without a target specified will build **all** targets.
```
# Build the MATEKF405 firmware
make MATEKF405
```
One can also build multiple targets from a sinlge `make` command:
One can also build multiple targets from a single `make` command:
```
make MATEKF405 MATEKF722
@ -128,7 +128,7 @@ make clean_MATEKF405
make clean_MATEKF405 clean_MATEKF722
```
### `cmake` cache maintainance
### `cmake` cache maintenance
`cmake` caches the build environment, so you don't need to rerun `cmake` each time you build a target. Two `make` options are provided to maintain the `cmake` cache.
@ -141,7 +141,7 @@ It is unlikely that the typical user will need to employ these options, other th
In order to update your local firmware build:
* Navigate to the local iNav repository
* Navigate to the local inav repository
* Use the following steps to pull the latest changes and rebuild your local version of inav firmware from the `build` directory:
```
@ -154,3 +154,9 @@ $ make <TARGET>
## Advanced Usage
For more advanced development information and `git` usage, please refer to the [development guide](https://github.com/iNavFlight/inav/blob/master/docs/development/Development.md).
## Unsupported platforms
If you're using a host platform for which Arm does not supply a cross-compiler (Arm32, IA32), and the distro either does not package a suitable compiler or it's too old, then you can usually find a suitable compiler in the [xpack devtools collection](https://github.com/xpack-dev-tools/arm-none-eabi-gcc-xpack).
You will need to configure `cmake` to use the external compiler.

View file

@ -20,13 +20,13 @@ Install Ubuntu:
NOTE: from this point all commands are entered into the Ubunto shell command window
Update the repo packages:
1. `sudo apt update`
- `sudo apt update`
Install Git, Make, gcc and Ruby
1. `sudo apt-get install git`
1. `sudo apt-get install make`
1. `sudo apt-get install cmake`
1. `sudo apt-get install ruby`
- `sudo apt-get install git make cmake ruby`
Install python and python-yaml to allow updates to settings.md
- `sudo apt-get install python3 python-yaml`
### CMAKE and Ubuntu 18_04
@ -78,6 +78,12 @@ cd build
make MATEKF722
```
## Updating the documents
```
cd /mnt/c/inav
python3 src/utils/update_cli_docs.py
```
## Flashing:
Launch windows configurator GUI and from within the firmware flasher select `Load firmware[Local]`
Hex files can be found in the folder `c:\inav\build`
@ -132,3 +138,28 @@ appendWindowsPath=false
8. `cd build`
9. `cmake ..`
9. `make {TARGET}` should be working again
### Building targets is very slow
I was pretty shocked when my new i7 -10750 laptop took 25 minutes to build a single target. My old i3-4030 could do the same job in about 2.5 minutes. If you're also suffering from slow builds. Open an elevated PowerShell window and type
```
wsl -l -v
```
If you see your Linux distribution is using WSL 2, this is the problem. WSL 2 is quicker than WSL 1 for a lot of things. However, if your files are on a windows mounted drive in Linux, it is extremely slow. There are two options:
1. Put your files on the Linux file system
2. Change to WSL 1
#### Using the Linux file system (recommended)
To use the Linux file system, make sure the distro is running. Open File Explorer and navigate to `\\wsl$`. In that path you will find your distros listed. At this point, map a network drive to your distro. Inside the distro, you can find your home directory at `/home/~username~/`. Create your GitHub folders here.
If after this you have problems with writing to the directories from within VSCode. Open the application for your distro and type
```
sudo chown -R ~username~ GitHub
```
`~Username~` is your root distro user that you created and `GitHub` should be the root folder for your GitHub repositories.
#### To switch back to WSL 1
To do this, in the elevated PowerShell window, you can see the name of your distro. Mine is **Ubuntu-20.04**, so I'll use that in this example. Simply type
```
wsl --set-version Ubuntu-20.04 1
```
and your distro will be converted to WSL 1. Once finished, reboot your system. Next time you compile a build, it will be faster.

View file

@ -79,30 +79,6 @@ Edit `./.vscode/tasks.json` to enable Building with `Ctrl + Shift + B` keyboard
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "Build Matek F722-SE",
"type": "shell",
"command": "make MATEKF722SE",
"group": "build",
"problemMatcher": [],
"options": {
"cwd": "${workspaceFolder}/build"
}
},
{
"label": "Build Matek F722",
"type": "shell",
"command": "make MATEKF722",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [],
"options": {
"cwd": "${workspaceFolder}/build"
}
}
,
{
"label": "Install/Update CMAKE",
"type": "shell",
@ -112,6 +88,37 @@ Edit `./.vscode/tasks.json` to enable Building with `Ctrl + Shift + B` keyboard
"options": {
"cwd": "${workspaceFolder}"
}
},
{
"label": "Compile autogenerated docs",
"type": "shell",
"command": "python3 src/utils/update_cli_docs.py",
"problemMatcher": [],
"options": {
"cwd": "${workspaceFolder}"
}
},
// Example of building a single target
{
"label": "Build Matek F722-WPX",
"type": "shell",
"command": "make MATEKF722WPX",
"group": "build",
"problemMatcher": [],
"options": {
"cwd": "${workspaceFolder}/build"
}
},
// Example of building multiple targets
{
"label": "Build Matek F405-STD & WING",
"type": "shell",
"command": "make MATEKF405 MATEKF405SE",
"group": "build",
"problemMatcher": [],
"options": {
"cwd": "${workspaceFolder}/build"
}
}
]
}

View file

@ -20,11 +20,6 @@
/* Includes ------------------------------------------------------------------*/
#include "stm32h7xx_ll_exti.h"
#ifdef USE_FULL_ASSERT
#include "stm32_assert.h"
#else
#define assert_param(expr) ((void)0U)
#endif
/** @addtogroup STM32H7xx_LL_Driver
* @{

View file

@ -21,11 +21,6 @@
/* Includes ------------------------------------------------------------------*/
#include "stm32h7xx_ll_i2c.h"
#include "stm32h7xx_ll_bus.h"
#ifdef USE_FULL_ASSERT
#include "stm32_assert.h"
#else
#define assert_param(expr) ((void)0U)
#endif
/** @addtogroup STM32H7xx_LL_Driver
* @{

View file

@ -71,26 +71,23 @@ main_sources(COMMON_SRC
drivers/accgyro/accgyro.c
drivers/accgyro/accgyro.h
drivers/accgyro/accgyro_adxl345.c
drivers/accgyro/accgyro_adxl345.h
drivers/accgyro/accgyro_bma280.c
drivers/accgyro/accgyro_bma280.h
drivers/accgyro/accgyro_bmi088.c
drivers/accgyro/accgyro_bmi088.h
drivers/accgyro/accgyro_bmi160.c
drivers/accgyro/accgyro_bmi160.h
drivers/accgyro/accgyro_bmi270.c
drivers/accgyro/accgyro_bmi270.h
drivers/accgyro/accgyro_bmi270_maximum_fifo.c
drivers/accgyro/accgyro_fake.c
drivers/accgyro/accgyro_fake.h
drivers/accgyro/accgyro_icm20689.c
drivers/accgyro/accgyro_icm20689.h
drivers/accgyro/accgyro_l3g4200d.c
drivers/accgyro/accgyro_l3g4200d.h
drivers/accgyro/accgyro_icm42605.c
drivers/accgyro/accgyro_icm42605.h
drivers/accgyro/accgyro_l3gd20.c
drivers/accgyro/accgyro_l3gd20.h
drivers/accgyro/accgyro_lsm303dlhc.c
drivers/accgyro/accgyro_lsm303dlhc.h
drivers/accgyro/accgyro_mma845x.c
drivers/accgyro/accgyro_mma845x.h
drivers/accgyro/accgyro_mpu.c
drivers/accgyro/accgyro_mpu.h
drivers/accgyro/accgyro_mpu3050.c
@ -162,6 +159,10 @@ main_sources(COMMON_SRC
drivers/compass/compass_qmc5883l.h
drivers/compass/compass_rm3100.c
drivers/compass/compass_rm3100.h
drivers/compass/compass_vcm5883.c
drivers/compass/compass_vcm5883.h
drivers/compass/compass_mlx90393.c
drivers/compass/compass_mlx90393.h
drivers/compass/compass_msp.c
drivers/compass/compass_msp.h
@ -228,10 +229,6 @@ main_sources(COMMON_SRC
drivers/pinio.c
drivers/pinio.h
drivers/rangefinder/rangefinder_hcsr04.c
drivers/rangefinder/rangefinder_hcsr04.h
drivers/rangefinder/rangefinder_hcsr04_i2c.c
drivers/rangefinder/rangefinder_hcsr04_i2c.h
drivers/rangefinder/rangefinder_srf10.c
drivers/rangefinder/rangefinder_srf10.h
drivers/rangefinder/rangefinder_vl53l0x.c
@ -242,13 +239,13 @@ main_sources(COMMON_SRC
drivers/rangefinder/rangefinder_virtual.h
drivers/rangefinder/rangefinder_us42.c
drivers/rangefinder/rangefinder_us42.h
drivers/rangefinder/rangefinder_tof10120_i2c.c
drivers/rangefinder/rangefinder_tof10120_i2c.h
drivers/resource.c
drivers/resource.h
drivers/rcc.c
drivers/rcc.h
drivers/rx_pwm.c
drivers/rx_pwm.h
drivers/rx_spi.c
drivers/rx_spi.h
drivers/serial.c
@ -323,6 +320,8 @@ main_sources(COMMON_SRC
flight/kalman.h
flight/smith_predictor.c
flight/smith_predictor.h
flight/rate_dynamics.c
flight/rate_dynamics.h
flight/mixer.c
flight/mixer.h
flight/pid.c
@ -349,8 +348,6 @@ main_sources(COMMON_SRC
io/beeper.c
io/beeper.h
io/esc_serialshot.c
io/esc_serialshot.h
io/servo_sbus.c
io/servo_sbus.h
io/frsky_osd.c
@ -411,8 +408,6 @@ main_sources(COMMON_SRC
rx/msp.h
rx/msp_override.c
rx/msp_override.h
rx/pwm.c
rx/pwm.h
rx/frsky_crc.c
rx/frsky_crc.h
rx/rx.c
@ -581,6 +576,8 @@ main_sources(COMMON_SRC
telemetry/ghst.h
telemetry/hott.c
telemetry/hott.h
telemetry/jetiexbus.c
telemetry/jetiexbus.h
telemetry/ibus_shared.c
telemetry/ibus_shared.h
telemetry/ibus.c

View file

@ -97,15 +97,32 @@
#define BLACKBOX_INVERTED_CARD_DETECTION 0
#endif
PG_REGISTER_WITH_RESET_TEMPLATE(blackboxConfig_t, blackboxConfig, PG_BLACKBOX_CONFIG, 1);
PG_REGISTER_WITH_RESET_TEMPLATE(blackboxConfig_t, blackboxConfig, PG_BLACKBOX_CONFIG, 2);
PG_RESET_TEMPLATE(blackboxConfig_t, blackboxConfig,
.device = DEFAULT_BLACKBOX_DEVICE,
.rate_num = SETTING_BLACKBOX_RATE_NUM_DEFAULT,
.rate_denom = SETTING_BLACKBOX_RATE_DENOM_DEFAULT,
.invertedCardDetection = BLACKBOX_INVERTED_CARD_DETECTION,
.includeFlags = BLACKBOX_FEATURE_NAV_PID | BLACKBOX_FEATURE_NAV_POS |
BLACKBOX_FEATURE_MAG | BLACKBOX_FEATURE_ACC | BLACKBOX_FEATURE_ATTITUDE |
BLACKBOX_FEATURE_RC_DATA | BLACKBOX_FEATURE_RC_COMMAND | BLACKBOX_FEATURE_MOTORS,
);
void blackboxIncludeFlagSet(uint32_t mask)
{
blackboxConfigMutable()->includeFlags |= mask;
}
void blackboxIncludeFlagClear(uint32_t mask)
{
blackboxConfigMutable()->includeFlags &= ~(mask);
}
bool blackboxIncludeFlag(uint32_t mask) {
return (blackboxConfig()->includeFlags & mask) == mask;
}
#define BLACKBOX_SHUTDOWN_TIMEOUT_MILLIS 200
static const int32_t blackboxSInterval = 4096;
@ -199,6 +216,9 @@ static const blackboxDeltaFieldDefinition_t blackboxMainFields[] = {
{"axisD", 0, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(SIGNED_VB), CONDITION(NONZERO_PID_D_0)},
{"axisD", 1, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(SIGNED_VB), CONDITION(NONZERO_PID_D_1)},
{"axisD", 2, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(SIGNED_VB), CONDITION(NONZERO_PID_D_2)},
{"axisF", 0, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(SIGNED_VB), FLIGHT_LOG_FIELD_CONDITION_ALWAYS},
{"axisF", 1, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(SIGNED_VB), FLIGHT_LOG_FIELD_CONDITION_ALWAYS},
{"axisF", 2, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(SIGNED_VB), FLIGHT_LOG_FIELD_CONDITION_ALWAYS},
{"fwAltP", -1, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(SIGNED_VB), CONDITION(FIXED_WING_NAV)},
{"fwAltI", -1, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(SIGNED_VB), CONDITION(FIXED_WING_NAV)},
@ -233,16 +253,16 @@ static const blackboxDeltaFieldDefinition_t blackboxMainFields[] = {
{"mcSurfaceOut",-1, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(SIGNED_VB), CONDITION(MC_NAV)},
/* rcData are encoded together as a group: */
{"rcData", 0, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(TAG8_4S16), CONDITION(ALWAYS)},
{"rcData", 1, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(TAG8_4S16), CONDITION(ALWAYS)},
{"rcData", 2, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(TAG8_4S16), CONDITION(ALWAYS)},
{"rcData", 3, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(TAG8_4S16), CONDITION(ALWAYS)},
{"rcData", 0, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(TAG8_4S16), FLIGHT_LOG_FIELD_CONDITION_RC_DATA},
{"rcData", 1, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(TAG8_4S16), FLIGHT_LOG_FIELD_CONDITION_RC_DATA},
{"rcData", 2, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(TAG8_4S16), FLIGHT_LOG_FIELD_CONDITION_RC_DATA},
{"rcData", 3, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(TAG8_4S16), FLIGHT_LOG_FIELD_CONDITION_RC_DATA},
/* rcCommands are encoded together as a group in P-frames: */
{"rcCommand", 0, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(TAG8_4S16), CONDITION(ALWAYS)},
{"rcCommand", 1, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(TAG8_4S16), CONDITION(ALWAYS)},
{"rcCommand", 2, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(TAG8_4S16), CONDITION(ALWAYS)},
{"rcCommand", 0, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(TAG8_4S16), FLIGHT_LOG_FIELD_CONDITION_RC_COMMAND},
{"rcCommand", 1, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(TAG8_4S16), FLIGHT_LOG_FIELD_CONDITION_RC_COMMAND},
{"rcCommand", 2, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(TAG8_4S16), FLIGHT_LOG_FIELD_CONDITION_RC_COMMAND},
/* Throttle is always in the range [minthrottle..maxthrottle]: */
{"rcCommand", 3, UNSIGNED, .Ipredict = PREDICT(MINTHROTTLE), .Iencode = ENCODING(UNSIGNED_VB), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(TAG8_4S16), CONDITION(ALWAYS)},
{"rcCommand", 3, UNSIGNED, .Ipredict = PREDICT(MINTHROTTLE), .Iencode = ENCODING(UNSIGNED_VB), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(TAG8_4S16), FLIGHT_LOG_FIELD_CONDITION_RC_COMMAND},
{"vbat", -1, UNSIGNED, .Ipredict = PREDICT(VBATREF), .Iencode = ENCODING(NEG_14BIT), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(TAG8_8SVB), FLIGHT_LOG_FIELD_CONDITION_VBAT},
{"amperage", -1, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(TAG8_8SVB), FLIGHT_LOG_FIELD_CONDITION_AMPERAGE},
@ -267,12 +287,12 @@ static const blackboxDeltaFieldDefinition_t blackboxMainFields[] = {
{"gyroADC", 0, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(AVERAGE_2), .Pencode = ENCODING(SIGNED_VB), CONDITION(ALWAYS)},
{"gyroADC", 1, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(AVERAGE_2), .Pencode = ENCODING(SIGNED_VB), CONDITION(ALWAYS)},
{"gyroADC", 2, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(AVERAGE_2), .Pencode = ENCODING(SIGNED_VB), CONDITION(ALWAYS)},
{"accSmooth", 0, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(AVERAGE_2), .Pencode = ENCODING(SIGNED_VB), CONDITION(ALWAYS)},
{"accSmooth", 1, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(AVERAGE_2), .Pencode = ENCODING(SIGNED_VB), CONDITION(ALWAYS)},
{"accSmooth", 2, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(AVERAGE_2), .Pencode = ENCODING(SIGNED_VB), CONDITION(ALWAYS)},
{"attitude", 0, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(AVERAGE_2), .Pencode = ENCODING(SIGNED_VB), CONDITION(ALWAYS)},
{"attitude", 1, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(AVERAGE_2), .Pencode = ENCODING(SIGNED_VB), CONDITION(ALWAYS)},
{"attitude", 2, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(AVERAGE_2), .Pencode = ENCODING(SIGNED_VB), CONDITION(ALWAYS)},
{"accSmooth", 0, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(AVERAGE_2), .Pencode = ENCODING(SIGNED_VB), FLIGHT_LOG_FIELD_CONDITION_ACC},
{"accSmooth", 1, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(AVERAGE_2), .Pencode = ENCODING(SIGNED_VB), FLIGHT_LOG_FIELD_CONDITION_ACC},
{"accSmooth", 2, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(AVERAGE_2), .Pencode = ENCODING(SIGNED_VB), FLIGHT_LOG_FIELD_CONDITION_ACC},
{"attitude", 0, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(AVERAGE_2), .Pencode = ENCODING(SIGNED_VB), FLIGHT_LOG_FIELD_CONDITION_ATTITUDE},
{"attitude", 1, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(AVERAGE_2), .Pencode = ENCODING(SIGNED_VB), FLIGHT_LOG_FIELD_CONDITION_ATTITUDE},
{"attitude", 2, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(AVERAGE_2), .Pencode = ENCODING(SIGNED_VB), FLIGHT_LOG_FIELD_CONDITION_ATTITUDE},
{"debug", 0, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(AVERAGE_2), .Pencode = ENCODING(SIGNED_VB), FLIGHT_LOG_FIELD_CONDITION_DEBUG},
{"debug", 1, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(AVERAGE_2), .Pencode = ENCODING(SIGNED_VB), FLIGHT_LOG_FIELD_CONDITION_DEBUG},
{"debug", 2, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(AVERAGE_2), .Pencode = ENCODING(SIGNED_VB), FLIGHT_LOG_FIELD_CONDITION_DEBUG},
@ -310,28 +330,26 @@ static const blackboxDeltaFieldDefinition_t blackboxMainFields[] = {
{"servo", 14, UNSIGNED, .Ipredict = PREDICT(1500), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(AVERAGE_2), .Pencode = ENCODING(SIGNED_VB), CONDITION(SERVOS)},
{"servo", 15, UNSIGNED, .Ipredict = PREDICT(1500), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(AVERAGE_2), .Pencode = ENCODING(SIGNED_VB), CONDITION(SERVOS)},
#ifdef NAV_BLACKBOX
{"navState", -1, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(SIGNED_VB), CONDITION(ALWAYS)},
{"navFlags", -1, UNSIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(SIGNED_VB), CONDITION(ALWAYS)},
{"navEPH", -1, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(SIGNED_VB), CONDITION(ALWAYS)},
{"navEPV", -1, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(SIGNED_VB), CONDITION(ALWAYS)},
{"navPos", 0, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(SIGNED_VB), CONDITION(ALWAYS)},
{"navPos", 1, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(SIGNED_VB), CONDITION(ALWAYS)},
{"navPos", 2, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(SIGNED_VB), CONDITION(ALWAYS)},
{"navVel", 0, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(AVERAGE_2), .Pencode = ENCODING(SIGNED_VB), CONDITION(ALWAYS)},
{"navVel", 1, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(AVERAGE_2), .Pencode = ENCODING(SIGNED_VB), CONDITION(ALWAYS)},
{"navVel", 2, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(AVERAGE_2), .Pencode = ENCODING(SIGNED_VB), CONDITION(ALWAYS)},
{"navAcc", 0, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(AVERAGE_2), .Pencode = ENCODING(SIGNED_VB), CONDITION(ALWAYS)},
{"navAcc", 1, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(AVERAGE_2), .Pencode = ENCODING(SIGNED_VB), CONDITION(ALWAYS)},
{"navAcc", 2, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(AVERAGE_2), .Pencode = ENCODING(SIGNED_VB), CONDITION(ALWAYS)},
{"navTgtVel", 0, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(AVERAGE_2), .Pencode = ENCODING(SIGNED_VB), CONDITION(ALWAYS)},
{"navTgtVel", 1, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(AVERAGE_2), .Pencode = ENCODING(SIGNED_VB), CONDITION(ALWAYS)},
{"navTgtVel", 2, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(AVERAGE_2), .Pencode = ENCODING(SIGNED_VB), CONDITION(ALWAYS)},
{"navTgtPos", 0, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(SIGNED_VB), CONDITION(ALWAYS)},
{"navTgtPos", 1, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(SIGNED_VB), CONDITION(ALWAYS)},
{"navTgtPos", 2, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(SIGNED_VB), CONDITION(ALWAYS)},
{"navSurf", 0, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(SIGNED_VB), CONDITION(ALWAYS)},
#endif
{"navEPH", -1, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(SIGNED_VB), FLIGHT_LOG_FIELD_CONDITION_NAV_POS},
{"navEPV", -1, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(SIGNED_VB), FLIGHT_LOG_FIELD_CONDITION_NAV_POS},
{"navPos", 0, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(SIGNED_VB), FLIGHT_LOG_FIELD_CONDITION_NAV_POS},
{"navPos", 1, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(SIGNED_VB), FLIGHT_LOG_FIELD_CONDITION_NAV_POS},
{"navPos", 2, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(SIGNED_VB), FLIGHT_LOG_FIELD_CONDITION_NAV_POS},
{"navVel", 0, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(AVERAGE_2), .Pencode = ENCODING(SIGNED_VB), FLIGHT_LOG_FIELD_CONDITION_NAV_POS},
{"navVel", 1, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(AVERAGE_2), .Pencode = ENCODING(SIGNED_VB), FLIGHT_LOG_FIELD_CONDITION_NAV_POS},
{"navVel", 2, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(AVERAGE_2), .Pencode = ENCODING(SIGNED_VB), FLIGHT_LOG_FIELD_CONDITION_NAV_POS},
{"navTgtVel", 0, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(AVERAGE_2), .Pencode = ENCODING(SIGNED_VB), FLIGHT_LOG_FIELD_CONDITION_NAV_POS},
{"navTgtVel", 1, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(AVERAGE_2), .Pencode = ENCODING(SIGNED_VB), FLIGHT_LOG_FIELD_CONDITION_NAV_POS},
{"navTgtVel", 2, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(AVERAGE_2), .Pencode = ENCODING(SIGNED_VB), FLIGHT_LOG_FIELD_CONDITION_NAV_POS},
{"navTgtPos", 0, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(SIGNED_VB), FLIGHT_LOG_FIELD_CONDITION_NAV_POS},
{"navTgtPos", 1, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(SIGNED_VB), FLIGHT_LOG_FIELD_CONDITION_NAV_POS},
{"navTgtPos", 2, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(SIGNED_VB), FLIGHT_LOG_FIELD_CONDITION_NAV_POS},
{"navSurf", -1, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(PREVIOUS), .Pencode = ENCODING(SIGNED_VB), FLIGHT_LOG_FIELD_CONDITION_NAV_POS},
{"navAcc", 0, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(AVERAGE_2), .Pencode = ENCODING(SIGNED_VB), FLIGHT_LOG_FIELD_CONDITION_NAV_ACC},
{"navAcc", 1, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(AVERAGE_2), .Pencode = ENCODING(SIGNED_VB), FLIGHT_LOG_FIELD_CONDITION_NAV_ACC},
{"navAcc", 2, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(AVERAGE_2), .Pencode = ENCODING(SIGNED_VB), FLIGHT_LOG_FIELD_CONDITION_NAV_ACC},
};
#ifdef USE_GPS
@ -422,6 +440,7 @@ typedef struct blackboxMainState_s {
int32_t axisPID_P[XYZ_AXIS_COUNT];
int32_t axisPID_I[XYZ_AXIS_COUNT];
int32_t axisPID_D[XYZ_AXIS_COUNT];
int32_t axisPID_F[XYZ_AXIS_COUNT];
int32_t axisPID_Setpoint[XYZ_AXIS_COUNT];
int32_t mcPosAxisP[XYZ_AXIS_COUNT];
@ -461,7 +480,6 @@ typedef struct blackboxMainState_s {
int32_t surfaceRaw;
#endif
uint16_t rssi;
#ifdef NAV_BLACKBOX
int16_t navState;
uint16_t navFlags;
uint16_t navEPH;
@ -474,7 +492,6 @@ typedef struct blackboxMainState_s {
int16_t navHeading;
int16_t navTargetHeading;
int16_t navSurface;
#endif
} blackboxMainState_t;
typedef struct blackboxGpsState_s {
@ -579,6 +596,9 @@ static bool testBlackboxConditionUncached(FlightLogFieldCondition condition)
case FLIGHT_LOG_FIELD_CONDITION_ALWAYS:
return true;
case FLIGHT_LOG_FIELD_CONDITION_MOTORS:
return blackboxIncludeFlag(BLACKBOX_FEATURE_MOTORS);
case FLIGHT_LOG_FIELD_CONDITION_AT_LEAST_MOTORS_1:
case FLIGHT_LOG_FIELD_CONDITION_AT_LEAST_MOTORS_2:
case FLIGHT_LOG_FIELD_CONDITION_AT_LEAST_MOTORS_3:
@ -587,7 +607,7 @@ static bool testBlackboxConditionUncached(FlightLogFieldCondition condition)
case FLIGHT_LOG_FIELD_CONDITION_AT_LEAST_MOTORS_6:
case FLIGHT_LOG_FIELD_CONDITION_AT_LEAST_MOTORS_7:
case FLIGHT_LOG_FIELD_CONDITION_AT_LEAST_MOTORS_8:
return getMotorCount() >= condition - FLIGHT_LOG_FIELD_CONDITION_AT_LEAST_MOTORS_1 + 1;
return (getMotorCount() >= condition - FLIGHT_LOG_FIELD_CONDITION_AT_LEAST_MOTORS_1 + 1) && blackboxIncludeFlag(BLACKBOX_FEATURE_MOTORS);
case FLIGHT_LOG_FIELD_CONDITION_SERVOS:
return isMixerUsingServos();
@ -596,11 +616,11 @@ static bool testBlackboxConditionUncached(FlightLogFieldCondition condition)
case FLIGHT_LOG_FIELD_CONDITION_NONZERO_PID_D_1:
case FLIGHT_LOG_FIELD_CONDITION_NONZERO_PID_D_2:
// D output can be set by either the D or the FF term
return pidBank()->pid[condition - FLIGHT_LOG_FIELD_CONDITION_NONZERO_PID_D_0].D != 0 || pidBank()->pid[condition - FLIGHT_LOG_FIELD_CONDITION_NONZERO_PID_D_0].FF != 0;
return pidBank()->pid[condition - FLIGHT_LOG_FIELD_CONDITION_NONZERO_PID_D_0].D != 0;
case FLIGHT_LOG_FIELD_CONDITION_MAG:
#ifdef USE_MAG
return sensors(SENSOR_MAG);
return sensors(SENSOR_MAG) && blackboxIncludeFlag(BLACKBOX_FEATURE_MAG);
#else
return false;
#endif
@ -634,14 +654,14 @@ static bool testBlackboxConditionUncached(FlightLogFieldCondition condition)
case FLIGHT_LOG_FIELD_CONDITION_FIXED_WING_NAV:
#ifdef USE_NAV
return STATE(FIXED_WING_LEGACY);
return STATE(FIXED_WING_LEGACY) && blackboxIncludeFlag(BLACKBOX_FEATURE_NAV_PID);
#else
return false;
#endif
case FLIGHT_LOG_FIELD_CONDITION_MC_NAV:
#ifdef USE_NAV
return !STATE(FIXED_WING_LEGACY);
return !STATE(FIXED_WING_LEGACY) && blackboxIncludeFlag(BLACKBOX_FEATURE_NAV_PID);
#else
return false;
#endif
@ -657,9 +677,28 @@ static bool testBlackboxConditionUncached(FlightLogFieldCondition condition)
case FLIGHT_LOG_FIELD_CONDITION_DEBUG:
return debugMode != DEBUG_NONE;
case FLIGHT_LOG_FIELD_CONDITION_NAV_ACC:
return blackboxIncludeFlag(BLACKBOX_FEATURE_NAV_ACC);
case FLIGHT_LOG_FIELD_CONDITION_NAV_POS:
return blackboxIncludeFlag(BLACKBOX_FEATURE_NAV_POS);
case FLIGHT_LOG_FIELD_CONDITION_ACC:
return blackboxIncludeFlag(BLACKBOX_FEATURE_ACC);
case FLIGHT_LOG_FIELD_CONDITION_ATTITUDE:
return blackboxIncludeFlag(BLACKBOX_FEATURE_ATTITUDE);
case FLIGHT_LOG_FIELD_CONDITION_RC_COMMAND:
return blackboxIncludeFlag(BLACKBOX_FEATURE_RC_COMMAND);
case FLIGHT_LOG_FIELD_CONDITION_RC_DATA:
return blackboxIncludeFlag(BLACKBOX_FEATURE_RC_DATA);
case FLIGHT_LOG_FIELD_CONDITION_NEVER:
return false;
default:
return false;
}
@ -733,6 +772,7 @@ static void writeIntraframe(void)
blackboxWriteSignedVB(blackboxCurrent->axisPID_D[x]);
}
}
blackboxWriteSignedVBArray(blackboxCurrent->axisPID_F, XYZ_AXIS_COUNT);
if (testBlackboxCondition(CONDITION(FIXED_WING_NAV))) {
blackboxWriteSignedVBArray(blackboxCurrent->fwAltPID, 3);
@ -756,16 +796,20 @@ static void writeIntraframe(void)
}
// Write raw stick positions
blackboxWriteSigned16VBArray(blackboxCurrent->rcData, 4);
if (testBlackboxCondition(FLIGHT_LOG_FIELD_CONDITION_RC_DATA)) {
blackboxWriteSigned16VBArray(blackboxCurrent->rcData, 4);
}
// Write roll, pitch and yaw first:
blackboxWriteSigned16VBArray(blackboxCurrent->rcCommand, 3);
if (testBlackboxCondition(FLIGHT_LOG_FIELD_CONDITION_RC_COMMAND)) {
blackboxWriteSigned16VBArray(blackboxCurrent->rcCommand, 3);
/*
* Write the throttle separately from the rest of the RC data so we can apply a predictor to it.
* Throttle lies in range [minthrottle..maxthrottle]:
*/
blackboxWriteUnsignedVB(blackboxCurrent->rcCommand[THROTTLE] - getThrottleIdleValue());
/*
* Write the throttle separately from the rest of the RC data so we can apply a predictor to it.
* Throttle lies in range [minthrottle..maxthrottle]:
*/
blackboxWriteUnsignedVB(blackboxCurrent->rcCommand[THROTTLE] - getThrottleIdleValue());
}
if (testBlackboxCondition(FLIGHT_LOG_FIELD_CONDITION_VBAT)) {
/*
@ -811,20 +855,28 @@ static void writeIntraframe(void)
}
blackboxWriteSigned16VBArray(blackboxCurrent->gyroADC, XYZ_AXIS_COUNT);
blackboxWriteSigned16VBArray(blackboxCurrent->accADC, XYZ_AXIS_COUNT);
blackboxWriteSigned16VBArray(blackboxCurrent->attitude, XYZ_AXIS_COUNT);
if (testBlackboxCondition(FLIGHT_LOG_FIELD_CONDITION_ACC)) {
blackboxWriteSigned16VBArray(blackboxCurrent->accADC, XYZ_AXIS_COUNT);
}
if (testBlackboxCondition(FLIGHT_LOG_FIELD_CONDITION_ATTITUDE)) {
blackboxWriteSigned16VBArray(blackboxCurrent->attitude, XYZ_AXIS_COUNT);
}
if (testBlackboxCondition(FLIGHT_LOG_FIELD_CONDITION_DEBUG)) {
blackboxWriteSignedVBArray(blackboxCurrent->debug, DEBUG32_VALUE_COUNT);
}
//Motors can be below minthrottle when disarmed, but that doesn't happen much
blackboxWriteUnsignedVB(blackboxCurrent->motor[0] - getThrottleIdleValue());
if (testBlackboxCondition(FLIGHT_LOG_FIELD_CONDITION_MOTORS)) {
//Motors can be below minthrottle when disarmed, but that doesn't happen much
blackboxWriteUnsignedVB(blackboxCurrent->motor[0] - getThrottleIdleValue());
//Motors tend to be similar to each other so use the first motor's value as a predictor of the others
const int motorCount = getMotorCount();
for (int x = 1; x < motorCount; x++) {
blackboxWriteSignedVB(blackboxCurrent->motor[x] - blackboxCurrent->motor[0]);
//Motors tend to be similar to each other so use the first motor's value as a predictor of the others
const int motorCount = getMotorCount();
for (int x = 1; x < motorCount; x++) {
blackboxWriteSignedVB(blackboxCurrent->motor[x] - blackboxCurrent->motor[0]);
}
}
if (testBlackboxCondition(FLIGHT_LOG_FIELD_CONDITION_SERVOS)) {
@ -834,36 +886,41 @@ static void writeIntraframe(void)
}
}
#ifdef NAV_BLACKBOX
blackboxWriteSignedVB(blackboxCurrent->navState);
blackboxWriteSignedVB(blackboxCurrent->navFlags);
blackboxWriteSignedVB(blackboxCurrent->navEPH);
blackboxWriteSignedVB(blackboxCurrent->navEPV);
for (int x = 0; x < XYZ_AXIS_COUNT; x++) {
blackboxWriteSignedVB(blackboxCurrent->navPos[x]);
/*
* NAV_POS fields
*/
if (testBlackboxCondition(FLIGHT_LOG_FIELD_CONDITION_NAV_POS)) {
blackboxWriteSignedVB(blackboxCurrent->navEPH);
blackboxWriteSignedVB(blackboxCurrent->navEPV);
for (int x = 0; x < XYZ_AXIS_COUNT; x++) {
blackboxWriteSignedVB(blackboxCurrent->navPos[x]);
}
for (int x = 0; x < XYZ_AXIS_COUNT; x++) {
blackboxWriteSignedVB(blackboxCurrent->navRealVel[x]);
}
for (int x = 0; x < XYZ_AXIS_COUNT; x++) {
blackboxWriteSignedVB(blackboxCurrent->navTargetVel[x]);
}
for (int x = 0; x < XYZ_AXIS_COUNT; x++) {
blackboxWriteSignedVB(blackboxCurrent->navTargetPos[x]);
}
blackboxWriteSignedVB(blackboxCurrent->navSurface);
}
for (int x = 0; x < XYZ_AXIS_COUNT; x++) {
blackboxWriteSignedVB(blackboxCurrent->navRealVel[x]);
if (testBlackboxCondition(FLIGHT_LOG_FIELD_CONDITION_NAV_ACC)) {
for (int x = 0; x < XYZ_AXIS_COUNT; x++) {
blackboxWriteSignedVB(blackboxCurrent->navAccNEU[x]);
}
}
for (int x = 0; x < XYZ_AXIS_COUNT; x++) {
blackboxWriteSignedVB(blackboxCurrent->navAccNEU[x]);
}
for (int x = 0; x < XYZ_AXIS_COUNT; x++) {
blackboxWriteSignedVB(blackboxCurrent->navTargetVel[x]);
}
for (int x = 0; x < XYZ_AXIS_COUNT; x++) {
blackboxWriteSignedVB(blackboxCurrent->navTargetPos[x]);
}
blackboxWriteSignedVB(blackboxCurrent->navSurface);
#endif
//Rotate our history buffers:
//The current state becomes the new "before" state
@ -943,6 +1000,9 @@ static void writeInterframe(void)
}
}
arraySubInt32(deltas, blackboxCurrent->axisPID_F, blackboxLast->axisPID_F, XYZ_AXIS_COUNT);
blackboxWriteSignedVBArray(deltas, XYZ_AXIS_COUNT);
if (testBlackboxCondition(CONDITION(FIXED_WING_NAV))) {
arraySubInt32(deltas, blackboxCurrent->fwAltPID, blackboxLast->fwAltPID, 3);
@ -981,18 +1041,22 @@ static void writeInterframe(void)
*/
// rcData
for (int x = 0; x < 4; x++) {
deltas[x] = blackboxCurrent->rcData[x] - blackboxLast->rcData[x];
}
if (testBlackboxCondition(FLIGHT_LOG_FIELD_CONDITION_RC_DATA)) {
for (int x = 0; x < 4; x++) {
deltas[x] = blackboxCurrent->rcData[x] - blackboxLast->rcData[x];
}
blackboxWriteTag8_4S16(deltas);
blackboxWriteTag8_4S16(deltas);
}
// rcCommand
for (int x = 0; x < 4; x++) {
deltas[x] = blackboxCurrent->rcCommand[x] - blackboxLast->rcCommand[x];
}
if (testBlackboxCondition(FLIGHT_LOG_FIELD_CONDITION_RC_COMMAND)) {
for (int x = 0; x < 4; x++) {
deltas[x] = blackboxCurrent->rcCommand[x] - blackboxLast->rcCommand[x];
}
blackboxWriteTag8_4S16(deltas);
blackboxWriteTag8_4S16(deltas);
}
//Check for sensors that are updated periodically (so deltas are normally zero)
int optionalFieldCount = 0;
@ -1039,47 +1103,64 @@ static void writeInterframe(void)
//Since gyros, accs and motors are noisy, base their predictions on the average of the history:
blackboxWriteArrayUsingAveragePredictor16(offsetof(blackboxMainState_t, gyroADC), XYZ_AXIS_COUNT);
blackboxWriteArrayUsingAveragePredictor16(offsetof(blackboxMainState_t, accADC), XYZ_AXIS_COUNT);
blackboxWriteArrayUsingAveragePredictor16(offsetof(blackboxMainState_t, attitude), XYZ_AXIS_COUNT);
if (testBlackboxCondition(FLIGHT_LOG_FIELD_CONDITION_ACC)) {
blackboxWriteArrayUsingAveragePredictor16(offsetof(blackboxMainState_t, accADC), XYZ_AXIS_COUNT);
}
if (testBlackboxCondition(FLIGHT_LOG_FIELD_CONDITION_ATTITUDE)) {
blackboxWriteArrayUsingAveragePredictor16(offsetof(blackboxMainState_t, attitude), XYZ_AXIS_COUNT);
}
if (testBlackboxCondition(FLIGHT_LOG_FIELD_CONDITION_DEBUG)) {
blackboxWriteArrayUsingAveragePredictor32(offsetof(blackboxMainState_t, debug), DEBUG32_VALUE_COUNT);
}
blackboxWriteArrayUsingAveragePredictor16(offsetof(blackboxMainState_t, motor), getMotorCount());
if (testBlackboxCondition(FLIGHT_LOG_FIELD_CONDITION_MOTORS)) {
blackboxWriteArrayUsingAveragePredictor16(offsetof(blackboxMainState_t, motor), getMotorCount());
}
if (testBlackboxCondition(FLIGHT_LOG_FIELD_CONDITION_SERVOS)) {
blackboxWriteArrayUsingAveragePredictor16(offsetof(blackboxMainState_t, servo), MAX_SUPPORTED_SERVOS);
}
#ifdef NAV_BLACKBOX
blackboxWriteSignedVB(blackboxCurrent->navState - blackboxLast->navState);
blackboxWriteSignedVB(blackboxCurrent->navFlags - blackboxLast->navFlags);
blackboxWriteSignedVB(blackboxCurrent->navEPH - blackboxLast->navEPH);
blackboxWriteSignedVB(blackboxCurrent->navEPV - blackboxLast->navEPV);
for (int x = 0; x < XYZ_AXIS_COUNT; x++) {
blackboxWriteSignedVB(blackboxCurrent->navPos[x] - blackboxLast->navPos[x]);
/*
* NAV_POS fields
*/
if (testBlackboxCondition(FLIGHT_LOG_FIELD_CONDITION_NAV_POS)) {
blackboxWriteSignedVB(blackboxCurrent->navEPH - blackboxLast->navEPH);
blackboxWriteSignedVB(blackboxCurrent->navEPV - blackboxLast->navEPV);
for (int x = 0; x < XYZ_AXIS_COUNT; x++) {
blackboxWriteSignedVB(blackboxCurrent->navPos[x] - blackboxLast->navPos[x]);
}
for (int x = 0; x < XYZ_AXIS_COUNT; x++) {
blackboxWriteSignedVB(blackboxHistory[0]->navRealVel[x] - (blackboxHistory[1]->navRealVel[x] + blackboxHistory[2]->navRealVel[x]) / 2);
}
for (int x = 0; x < XYZ_AXIS_COUNT; x++) {
blackboxWriteSignedVB(blackboxHistory[0]->navTargetVel[x] - (blackboxHistory[1]->navTargetVel[x] + blackboxHistory[2]->navTargetVel[x]) / 2);
}
for (int x = 0; x < XYZ_AXIS_COUNT; x++) {
blackboxWriteSignedVB(blackboxHistory[0]->navTargetPos[x] - blackboxLast->navTargetPos[x]);
}
blackboxWriteSignedVB(blackboxCurrent->navSurface - blackboxLast->navSurface);
}
for (int x = 0; x < XYZ_AXIS_COUNT; x++) {
blackboxWriteSignedVB(blackboxHistory[0]->navRealVel[x] - (blackboxHistory[1]->navRealVel[x] + blackboxHistory[2]->navRealVel[x]) / 2);
if (testBlackboxCondition(FLIGHT_LOG_FIELD_CONDITION_NAV_ACC)) {
for (int x = 0; x < XYZ_AXIS_COUNT; x++) {
blackboxWriteSignedVB(blackboxHistory[0]->navAccNEU[x] - (blackboxHistory[1]->navAccNEU[x] + blackboxHistory[2]->navAccNEU[x]) / 2);
}
}
for (int x = 0; x < XYZ_AXIS_COUNT; x++) {
blackboxWriteSignedVB(blackboxHistory[0]->navAccNEU[x] - (blackboxHistory[1]->navAccNEU[x] + blackboxHistory[2]->navAccNEU[x]) / 2);
}
for (int x = 0; x < XYZ_AXIS_COUNT; x++) {
blackboxWriteSignedVB(blackboxHistory[0]->navTargetVel[x] - (blackboxHistory[1]->navTargetVel[x] + blackboxHistory[2]->navTargetVel[x]) / 2);
}
for (int x = 0; x < XYZ_AXIS_COUNT; x++) {
blackboxWriteSignedVB(blackboxHistory[0]->navTargetPos[x] - blackboxLast->navTargetPos[x]);
}
blackboxWriteSignedVB(blackboxCurrent->navSurface - blackboxLast->navSurface);
#endif
//Rotate our history buffers
blackboxHistory[2] = blackboxHistory[1];
blackboxHistory[1] = blackboxHistory[0];
@ -1396,6 +1477,7 @@ static void loadMainState(timeUs_t currentTimeUs)
blackboxCurrent->axisPID_P[i] = axisPID_P[i];
blackboxCurrent->axisPID_I[i] = axisPID_I[i];
blackboxCurrent->axisPID_D[i] = axisPID_D[i];
blackboxCurrent->axisPID_F[i] = axisPID_F[i];
blackboxCurrent->gyroADC[i] = lrintf(gyro.gyroADCf[i]);
blackboxCurrent->accADC[i] = lrintf(acc.accADCf[i] * acc.dev.acc_1G);
#ifdef USE_MAG
@ -1479,7 +1561,6 @@ static void loadMainState(timeUs_t currentTimeUs)
blackboxCurrent->servo[i] = servo[i];
}
#ifdef NAV_BLACKBOX
blackboxCurrent->navState = navCurrentState;
blackboxCurrent->navFlags = navFlags;
blackboxCurrent->navEPH = navEPH;
@ -1492,7 +1573,6 @@ static void loadMainState(timeUs_t currentTimeUs)
blackboxCurrent->navTargetPos[i] = navTargetPosition[i];
}
blackboxCurrent->navSurface = navActualSurface;
#endif
}
/**
@ -1690,15 +1770,18 @@ static bool blackboxWriteSysinfo(void)
BLACKBOX_PRINT_HEADER_LINE("rates", "%d,%d,%d", currentControlRateProfile->stabilized.rates[ROLL],
currentControlRateProfile->stabilized.rates[PITCH],
currentControlRateProfile->stabilized.rates[YAW]);
BLACKBOX_PRINT_HEADER_LINE("rollPID", "%d,%d,%d", pidBank()->pid[PID_ROLL].P,
BLACKBOX_PRINT_HEADER_LINE("rollPID", "%d,%d,%d,%d", pidBank()->pid[PID_ROLL].P,
pidBank()->pid[PID_ROLL].I,
pidBank()->pid[PID_ROLL].D);
BLACKBOX_PRINT_HEADER_LINE("pitchPID", "%d,%d,%d", pidBank()->pid[PID_PITCH].P,
pidBank()->pid[PID_ROLL].D,
pidBank()->pid[PID_ROLL].FF);
BLACKBOX_PRINT_HEADER_LINE("pitchPID", "%d,%d,%d,%d", pidBank()->pid[PID_PITCH].P,
pidBank()->pid[PID_PITCH].I,
pidBank()->pid[PID_PITCH].D);
BLACKBOX_PRINT_HEADER_LINE("yawPID", "%d,%d,%d", pidBank()->pid[PID_YAW].P,
pidBank()->pid[PID_PITCH].D,
pidBank()->pid[PID_PITCH].FF);
BLACKBOX_PRINT_HEADER_LINE("yawPID", "%d,%d,%d,%d", pidBank()->pid[PID_YAW].P,
pidBank()->pid[PID_YAW].I,
pidBank()->pid[PID_YAW].D);
pidBank()->pid[PID_YAW].D,
pidBank()->pid[PID_YAW].FF);
BLACKBOX_PRINT_HEADER_LINE("altPID", "%d,%d,%d", pidBank()->pid[PID_POS_Z].P,
pidBank()->pid[PID_POS_Z].I,
pidBank()->pid[PID_POS_Z].D);
@ -1726,7 +1809,6 @@ static bool blackboxWriteSysinfo(void)
BLACKBOX_PRINT_HEADER_LINE("gyro_lpf_hz", "%d", gyroConfig()->gyro_main_lpf_hz);
BLACKBOX_PRINT_HEADER_LINE("gyro_lpf_type", "%d", gyroConfig()->gyro_main_lpf_type);
#ifdef USE_DYNAMIC_FILTERS
BLACKBOX_PRINT_HEADER_LINE("dynamicGyroNotchRange", "%d", gyroConfig()->dynamicGyroNotchRange);
BLACKBOX_PRINT_HEADER_LINE("dynamicGyroNotchQ", "%d", gyroConfig()->dynamicGyroNotchQ);
BLACKBOX_PRINT_HEADER_LINE("dynamicGyroNotchMinHz", "%d", gyroConfig()->dynamicGyroNotchMinHz);
#endif
@ -1749,9 +1831,7 @@ static bool blackboxWriteSysinfo(void)
BLACKBOX_PRINT_HEADER_LINE("motor_pwm_rate", "%d", motorConfig()->motorPwmRate);
BLACKBOX_PRINT_HEADER_LINE("debug_mode", "%d", systemConfig()->debug_mode);
BLACKBOX_PRINT_HEADER_LINE("features", "%d", featureConfig()->enabledFeatures);
#ifdef NAV_BLACKBOX
BLACKBOX_PRINT_HEADER_LINE("waypoints", "%d,%d", getWaypointCount(),isWaypointListValid());
#endif
BLACKBOX_PRINT_HEADER_LINE("acc_notch_hz", "%d", accelerometerConfig()->acc_notch_hz);
BLACKBOX_PRINT_HEADER_LINE("acc_notch_cutoff", "%d", accelerometerConfig()->acc_notch_cutoff);
BLACKBOX_PRINT_HEADER_LINE("pidSumLimit", "%d", pidProfile()->pidSumLimit);

View file

@ -21,11 +21,25 @@
#include "config/parameter_group.h"
typedef enum {
BLACKBOX_FEATURE_NAV_ACC = 1 << 0,
BLACKBOX_FEATURE_NAV_POS = 1 << 1,
BLACKBOX_FEATURE_NAV_PID = 1 << 2,
BLACKBOX_FEATURE_MAG = 1 << 3,
BLACKBOX_FEATURE_ACC = 1 << 4,
BLACKBOX_FEATURE_ATTITUDE = 1 << 5,
BLACKBOX_FEATURE_RC_DATA = 1 << 6,
BLACKBOX_FEATURE_RC_COMMAND = 1 << 7,
BLACKBOX_FEATURE_MOTORS = 1 << 8,
} blackboxFeatureMask_e;
typedef struct blackboxConfig_s {
uint16_t rate_num;
uint16_t rate_denom;
uint8_t device;
uint8_t invertedCardDetection;
uint32_t includeFlags;
} blackboxConfig_t;
PG_DECLARE(blackboxConfig_t, blackboxConfig);
@ -37,3 +51,6 @@ void blackboxUpdate(timeUs_t currentTimeUs);
void blackboxStart(void);
void blackboxFinish(void);
bool blackboxMayEditConfig(void);
void blackboxIncludeFlagSet(uint32_t mask);
void blackboxIncludeFlagClear(uint32_t mask);
bool blackboxIncludeFlag(uint32_t mask);

View file

@ -24,6 +24,7 @@
typedef enum FlightLogFieldCondition {
FLIGHT_LOG_FIELD_CONDITION_ALWAYS = 0,
FLIGHT_LOG_FIELD_CONDITION_MOTORS,
FLIGHT_LOG_FIELD_CONDITION_AT_LEAST_MOTORS_1,
FLIGHT_LOG_FIELD_CONDITION_AT_LEAST_MOTORS_2,
FLIGHT_LOG_FIELD_CONDITION_AT_LEAST_MOTORS_3,
@ -52,6 +53,14 @@ typedef enum FlightLogFieldCondition {
FLIGHT_LOG_FIELD_CONDITION_DEBUG,
FLIGHT_LOG_FIELD_CONDITION_NAV_ACC,
FLIGHT_LOG_FIELD_CONDITION_NAV_POS,
FLIGHT_LOG_FIELD_CONDITION_NAV_PID,
FLIGHT_LOG_FIELD_CONDITION_ACC,
FLIGHT_LOG_FIELD_CONDITION_ATTITUDE,
FLIGHT_LOG_FIELD_CONDITION_RC_DATA,
FLIGHT_LOG_FIELD_CONDITION_RC_COMMAND,
FLIGHT_LOG_FIELD_CONDITION_NEVER,
FLIGHT_LOG_FIELD_CONDITION_FIRST = FLIGHT_LOG_FIELD_CONDITION_ALWAYS,

View file

@ -53,8 +53,10 @@
#ifdef STM32H7
#define DMA_RAM __attribute__ ((section(".DMA_RAM")))
#define SLOW_RAM __attribute__ ((section(".SLOW_RAM")))
#else
#define DMA_RAM
#define SLOW_RAM
#endif
#define STATIC_FASTRAM static FASTRAM

View file

@ -72,7 +72,6 @@ typedef enum {
DEBUG_DYNAMIC_FILTER,
DEBUG_DYNAMIC_FILTER_FREQUENCY,
DEBUG_IRLOCK,
DEBUG_CD,
DEBUG_KALMAN_GAIN,
DEBUG_PID_MEASUREMENT,
DEBUG_SPM_CELLS, // Smartport master FLVSS
@ -81,12 +80,11 @@ typedef enum {
DEBUG_PCF8574,
DEBUG_DYNAMIC_GYRO_LPF,
DEBUG_AUTOLEVEL,
DEBUG_FW_D,
DEBUG_IMU2,
DEBUG_ALTITUDE,
DEBUG_GYRO_ALPHA_BETA_GAMMA,
DEBUG_SMITH_PREDICTOR,
DEBUG_AUTOTRIM,
DEBUG_AUTOTUNE,
DEBUG_RATE_DYNAMICS,
DEBUG_COUNT
} debugType_e;

View file

@ -432,7 +432,8 @@ static const OSD_Entry cmsx_menuMechanicsEntries[] =
{
OSD_LABEL_DATA_ENTRY("-- MECHANICS --", profileIndexString),
#ifdef USE_D_BOOST
OSD_SETTING_ENTRY("DBOOST_FACTOR", SETTING_D_BOOST_FACTOR),
OSD_SETTING_ENTRY("DBOOST_MIN", SETTING_D_BOOST_MIN),
OSD_SETTING_ENTRY("DBOOST_MAX", SETTING_D_BOOST_MAX),
#endif
#ifdef USE_ANTIGRAVITY
OSD_SETTING_ENTRY("ANTIGRAV. GAIN", SETTING_ANTIGRAVITY_GAIN),

View file

@ -43,12 +43,16 @@ static const OSD_Entry menuMiscEntries[]=
OSD_LABEL_ENTRY("-- MISC --"),
OSD_SETTING_ENTRY("THR IDLE", SETTING_THROTTLE_IDLE),
#if defined(USE_OSD) && defined(USE_ADC)
#ifdef USE_OSD
#ifdef USE_ADC
OSD_SETTING_ENTRY("OSD VOLT DECIMALS", SETTING_OSD_MAIN_VOLTAGE_DECIMALS),
OSD_SETTING_ENTRY("STATS ENERGY UNIT", SETTING_OSD_STATS_ENERGY_UNIT),
#endif
#endif // ADC
OSD_SETTING_ENTRY("STATS PAGE SWAP TIME", SETTING_OSD_STATS_PAGE_AUTO_SWAP_TIME),
#endif // OSD
OSD_SETTING_ENTRY("FS PROCEDURE", SETTING_FAILSAFE_PROCEDURE),
OSD_BACK_AND_END_ENTRY,
};

View file

@ -44,7 +44,8 @@ static const OSD_Entry cmsx_menuNavSettingsEntries[] =
OSD_LABEL_ENTRY("-- BASIC SETTINGS --"),
OSD_SETTING_ENTRY("CONTROL MODE", SETTING_NAV_USER_CONTROL_MODE),
OSD_SETTING_ENTRY("MAX NAV SPEED", SETTING_NAV_AUTO_SPEED),
OSD_SETTING_ENTRY("MC NAV SPEED", SETTING_NAV_AUTO_SPEED),
OSD_SETTING_ENTRY("MC MAX NAV SPEED", SETTING_NAV_MAX_AUTO_SPEED),
OSD_SETTING_ENTRY("MAX CRUISE SPEED", SETTING_NAV_MANUAL_SPEED),
OSD_SETTING_ENTRY("MAX NAV CLIMB RATE", SETTING_NAV_AUTO_CLIMB_RATE),
OSD_SETTING_ENTRY("MAX AH CLIMB RATE", SETTING_NAV_MANUAL_CLIMB_RATE),

View file

@ -34,7 +34,7 @@ void zeroCalibrationStartS(zeroCalibrationScalar_t * s, timeMs_t window, float t
{
// Reset parameters and state
s->params.state = ZERO_CALIBRATION_IN_PROGRESS;
s->params.startTimeMs = millis();
s->params.startTimeMs = 0;
s->params.windowSizeMs = window;
s->params.stdDevThreshold = threshold;
s->params.allowFailure = allowFailure;
@ -60,6 +60,13 @@ void zeroCalibrationAddValueS(zeroCalibrationScalar_t * s, const float v)
return;
}
// An unknown delay may have passed between `zeroCalibrationStartS` and first sample acquisition
// therefore our window measurement might be incorrect
// To account for that we reset the startTimeMs when acquiring the first sample
if (s->params.sampleCount == 0 && s->params.startTimeMs == 0) {
s->params.startTimeMs = millis();
}
// Add value
s->val.accumulatedValue += v;
s->params.sampleCount++;

View file

@ -18,7 +18,8 @@
#pragma once
#define FEET_PER_MILE 5280
#define FEET_PER_NAUTICALMILE 6076.118
#define FEET_PER_KILOFEET 1000 // Used for altitude
#define METERS_PER_KILOMETER 1000
#define METERS_PER_MILE 1609
#define METERS_PER_MILE 1609.344
#define METERS_PER_NAUTICALMILE 1852.001

View file

@ -109,6 +109,72 @@ void pt1FilterReset(pt1Filter_t *filter, float input)
filter->state = input;
}
/*
* PT2 LowPassFilter
*/
float pt2FilterGain(float f_cut, float dT)
{
const float order = 2.0f;
const float orderCutoffCorrection = 1 / sqrtf(powf(2, 1.0f / order) - 1);
float RC = 1 / (2 * orderCutoffCorrection * M_PIf * f_cut);
// float RC = 1 / (2 * 1.553773974f * M_PIf * f_cut);
// where 1.553773974 = 1 / sqrt( (2^(1 / order) - 1) ) and order is 2
return dT / (RC + dT);
}
void pt2FilterInit(pt2Filter_t *filter, float k)
{
filter->state = 0.0f;
filter->state1 = 0.0f;
filter->k = k;
}
void pt2FilterUpdateCutoff(pt2Filter_t *filter, float k)
{
filter->k = k;
}
FAST_CODE float pt2FilterApply(pt2Filter_t *filter, float input)
{
filter->state1 = filter->state1 + filter->k * (input - filter->state1);
filter->state = filter->state + filter->k * (filter->state1 - filter->state);
return filter->state;
}
/*
* PT3 LowPassFilter
*/
float pt3FilterGain(float f_cut, float dT)
{
const float order = 3.0f;
const float orderCutoffCorrection = 1 / sqrtf(powf(2, 1.0f / order) - 1);
float RC = 1 / (2 * orderCutoffCorrection * M_PIf * f_cut);
// float RC = 1 / (2 * 1.961459177f * M_PIf * f_cut);
// where 1.961459177 = 1 / sqrt( (2^(1 / order) - 1) ) and order is 3
return dT / (RC + dT);
}
void pt3FilterInit(pt3Filter_t *filter, float k)
{
filter->state = 0.0f;
filter->state1 = 0.0f;
filter->state2 = 0.0f;
filter->k = k;
}
void pt3FilterUpdateCutoff(pt3Filter_t *filter, float k)
{
filter->k = k;
}
FAST_CODE float pt3FilterApply(pt3Filter_t *filter, float input)
{
filter->state1 = filter->state1 + filter->k * (input - filter->state1);
filter->state2 = filter->state2 + filter->k * (filter->state1 - filter->state2);
filter->state = filter->state + filter->k * (filter->state2 - filter->state);
return filter->state;
}
// rate_limit = maximum rate of change of the output value in units per second
void rateLimitFilterInit(rateLimitFilter_t *filter)
{
@ -251,68 +317,35 @@ FAST_CODE void biquadFilterUpdate(biquadFilter_t *filter, float filterFreq, uint
filter->y2 = y2;
}
#ifdef USE_ALPHA_BETA_GAMMA_FILTER
void alphaBetaGammaFilterInit(alphaBetaGammaFilter_t *filter, float alpha, float boostGain, float halfLife, float dT) {
// beta, gamma, and eta gains all derived from
// http://yadda.icm.edu.pl/yadda/element/bwmeta1.element.baztech-922ff6cb-e991-417f-93f0-77448f1ef4ec/c/A_Study_Jeong_1_2017.pdf
FUNCTION_COMPILE_FOR_SIZE
void initFilter(const uint8_t filterType, filter_t *filter, const float cutoffFrequency, const uint32_t refreshRate) {
const float dT = refreshRate * 1e-6f;
const float xi = powf(-alpha + 1.0f, 0.25); // fourth rool of -a + 1
filter->xk = 0.0f;
filter->vk = 0.0f;
filter->ak = 0.0f;
filter->jk = 0.0f;
filter->a = alpha;
filter->b = (1.0f / 6.0f) * powf(1.0f - xi, 2) * (11.0f + 14.0f * xi + 11 * xi * xi);
filter->g = 2 * powf(1.0f - xi, 3) * (1 + xi);
filter->e = (1.0f / 6.0f) * powf(1 - xi, 4);
filter->dT = dT;
filter->dT2 = dT * dT;
filter->dT3 = dT * dT * dT;
pt1FilterInit(&filter->boostFilter, 100, dT);
const float boost = boostGain * 100;
filter->boost = (boost * boost / 10000) * 0.003;
filter->halfLife = halfLife != 0 ? powf(0.5f, dT / halfLife): 1.0f;
}
FAST_CODE float alphaBetaGammaFilterApply(alphaBetaGammaFilter_t *filter, float input) {
//xk - current system state (ie: position)
//vk - derivative of system state (ie: velocity)
//ak - derivative of system velociy (ie: acceleration)
//jk - derivative of system acceleration (ie: jerk)
float rk; // residual error
// give the filter limited history
filter->xk *= filter->halfLife;
filter->vk *= filter->halfLife;
filter->ak *= filter->halfLife;
filter->jk *= filter->halfLife;
// update our (estimated) state 'x' from the system (ie pos = pos + vel (last).dT)
filter->xk += filter->dT * filter->vk + (1.0f / 2.0f) * filter->dT2 * filter->ak + (1.0f / 6.0f) * filter->dT3 * filter->jk;
// update (estimated) velocity (also estimated dterm from measurement)
filter->vk += filter->dT * filter->ak + 0.5f * filter->dT2 * filter->jk;
filter->ak += filter->dT * filter->jk;
// what is our residual error (measured - estimated)
rk = input - filter->xk;
// artificially boost the error to increase the response of the filter
rk += pt1FilterApply(&filter->boostFilter, fabsf(rk) * rk * filter->boost);
if ((fabsf(rk * filter->a) > fabsf(input - filter->xk))) {
rk = (input - filter->xk) / filter->a;
if (cutoffFrequency) {
if (filterType == FILTER_PT1) {
pt1FilterInit(&filter->pt1, cutoffFrequency, dT);
} if (filterType == FILTER_PT2) {
pt2FilterInit(&filter->pt2, pt2FilterGain(cutoffFrequency, dT));
} if (filterType == FILTER_PT3) {
pt3FilterInit(&filter->pt3, pt3FilterGain(cutoffFrequency, dT));
} else {
biquadFilterInitLPF(&filter->biquad, cutoffFrequency, refreshRate);
}
}
filter->rk = rk; // for logging
// update our estimates given the residual error.
filter->xk += filter->a * rk;
filter->vk += filter->b / filter->dT * rk;
filter->ak += filter->g / (2.0f * filter->dT2) * rk;
filter->jk += filter->e / (6.0f * filter->dT3) * rk;
return filter->xk;
}
#endif
FUNCTION_COMPILE_FOR_SIZE
void assignFilterApplyFn(uint8_t filterType, float cutoffFrequency, filterApplyFnPtr *applyFn) {
*applyFn = nullFilterApply;
if (cutoffFrequency) {
if (filterType == FILTER_PT1) {
*applyFn = (filterApplyFnPtr) pt1FilterApply;
} if (filterType == FILTER_PT2) {
*applyFn = (filterApplyFnPtr) pt2FilterApply;
} if (filterType == FILTER_PT3) {
*applyFn = (filterApplyFnPtr) pt3FilterApply;
} else {
*applyFn = (filterApplyFnPtr) biquadFilterApply;
}
}
}

View file

@ -27,6 +27,17 @@ typedef struct pt1Filter_s {
float dT;
float alpha;
} pt1Filter_t;
typedef struct pt2Filter_s {
float state;
float state1;
float k;
} pt2Filter_t;
typedef struct pt3Filter_s {
float state;
float state1;
float state2;
float k;
} pt3Filter_t;
/* this holds the data required to update samples thru a filter */
typedef struct biquadFilter_s {
@ -36,12 +47,16 @@ typedef struct biquadFilter_s {
typedef union {
biquadFilter_t biquad;
pt1Filter_t pt1;
pt1Filter_t pt1;
pt2Filter_t pt2;
pt3Filter_t pt3;
} filter_t;
typedef enum {
FILTER_PT1 = 0,
FILTER_BIQUAD
FILTER_BIQUAD,
FILTER_PT2,
FILTER_PT3
} filterType_e;
typedef enum {
@ -87,6 +102,22 @@ float pt1FilterApply3(pt1Filter_t *filter, float input, float dT);
float pt1FilterApply4(pt1Filter_t *filter, float input, float f_cut, float dt);
void pt1FilterReset(pt1Filter_t *filter, float input);
/*
* PT2 LowPassFilter
*/
float pt2FilterGain(float f_cut, float dT);
void pt2FilterInit(pt2Filter_t *filter, float k);
void pt2FilterUpdateCutoff(pt2Filter_t *filter, float k);
float pt2FilterApply(pt2Filter_t *filter, float input);
/*
* PT3 LowPassFilter
*/
float pt3FilterGain(float f_cut, float dT);
void pt3FilterInit(pt3Filter_t *filter, float k);
void pt3FilterUpdateCutoff(pt3Filter_t *filter, float k);
float pt3FilterApply(pt3Filter_t *filter, float input);
void rateLimitFilterInit(rateLimitFilter_t *filter);
float rateLimitFilterApply4(rateLimitFilter_t *filter, float input, float rate_limit, float dT);
@ -100,4 +131,7 @@ float filterGetNotchQ(float centerFrequencyHz, float cutoffFrequencyHz);
void biquadFilterUpdate(biquadFilter_t *filter, float filterFreq, uint32_t refreshRate, float Q, biquadFilterType_e filterType);
void alphaBetaGammaFilterInit(alphaBetaGammaFilter_t *filter, float alpha, float boostGain, float halfLife, float dT);
float alphaBetaGammaFilterApply(alphaBetaGammaFilter_t *filter, float input);
float alphaBetaGammaFilterApply(alphaBetaGammaFilter_t *filter, float input);
void initFilter(uint8_t filterType, filter_t *filter, float cutoffFrequency, uint32_t refreshRate);
void assignFilterApplyFn(uint8_t filterType, float cutoffFrequency, filterApplyFnPtr *applyFn);

View file

@ -524,11 +524,15 @@ float bellCurve(const float x, const float curveWidth)
}
float fast_fsqrtf(const double value) {
float ret = 0.0f;
#ifdef USE_ARM_MATH
float squirt;
arm_sqrt_f32(value, &squirt);
return squirt;
arm_sqrt_f32(value, &ret);
#else
return sqrtf(value);
ret = sqrtf(value);
#endif
if (isnan(ret))
{
return 0;
}
return ret;
}

View file

@ -56,12 +56,16 @@
#define RADIANS_TO_CENTIDEGREES(angle) (((angle) * 100.0f) / RAD)
#define CENTIDEGREES_TO_RADIANS(angle) (((angle) / 100.0f) * RAD)
#define CENTIMETERS_TO_CENTIFEET(cm) (cm * (328 / 100.0))
#define CENTIMETERS_TO_FEET(cm) (cm * (328 / 10000.0))
#define CENTIMETERS_TO_CENTIFEET(cm) (cm / 0.3048)
#define CENTIMETERS_TO_FEET(cm) (cm / 30.48)
#define CENTIMETERS_TO_METERS(cm) (cm / 100)
#define METERS_TO_CENTIMETERS(m) (m * 100)
#define CMSEC_TO_CENTIMPH(cms) (cms * 2.2369363)
#define CMSEC_TO_CENTIKPH(cms) (cms * 3.6)
#define CMSEC_TO_CENTIKNOTS(cms) (cms * 1.943845)
// copied from https://code.google.com/p/cxutil/source/browse/include/cxutil/utility.h#70
#define _CHOOSE2(binoper, lexpr, lvar, rexpr, rvar) \
( __extension__ ({ \

View file

@ -25,12 +25,14 @@
#include "build/build_config.h"
#include "common/crc.h"
#include "common/utils.h"
#include "config/config_eeprom.h"
#include "config/config_streamer.h"
#include "config/parameter_group.h"
#include "drivers/system.h"
#include "drivers/flash.h"
#include "fc/config.h"
@ -76,6 +78,31 @@ typedef struct {
uint32_t word;
} PG_PACKED packingTest_t;
#if defined(CONFIG_IN_EXTERNAL_FLASH)
bool loadEEPROMFromExternalFlash(void)
{
const flashPartition_t *flashPartition = flashPartitionFindByType(FLASH_PARTITION_TYPE_CONFIG);
const flashGeometry_t *flashGeometry = flashGetGeometry();
uint32_t flashStartAddress = flashPartition->startSector * flashGeometry->sectorSize;
uint32_t totalBytesRead = 0;
int bytesRead = 0;
bool success = false;
do {
bytesRead = flashReadBytes(flashStartAddress + totalBytesRead, &eepromData[totalBytesRead], EEPROM_SIZE - totalBytesRead);
if (bytesRead > 0) {
totalBytesRead += bytesRead;
success = (totalBytesRead == EEPROM_SIZE);
}
} while (!success && bytesRead > 0);
return success;
}
#endif /* defined(CONFIG_IN_EXTERNAL_FLASH) */
void initEEPROM(void)
{
// Verify that this architecture packs as expected.
@ -86,6 +113,14 @@ void initEEPROM(void)
BUILD_BUG_ON(sizeof(configHeader_t) != 1);
BUILD_BUG_ON(sizeof(configFooter_t) != 2);
BUILD_BUG_ON(sizeof(configRecord_t) != 6);
#if defined(CONFIG_IN_EXTERNAL_FLASH)
bool eepromLoaded = loadEEPROMFromExternalFlash();
if (!eepromLoaded) {
// Flash read failed - just die now
failureMode(FAILURE_FLASH_READ_FAILED);
}
#endif
}
static uint16_t updateCRC(uint16_t crc, const void *data, uint32_t length)
@ -217,7 +252,9 @@ static bool writeSettingsToEEPROM(void)
.format = EEPROM_CONF_VERSION,
};
config_streamer_write(&streamer, (uint8_t *)&header, sizeof(header));
if (config_streamer_write(&streamer, (uint8_t *)&header, sizeof(header)) < 0) {
return false;
}
uint16_t crc = updateCRC(0, (uint8_t *)&header, sizeof(header));
PG_FOREACH(reg) {
const uint16_t regSize = pgSize(reg);
@ -231,9 +268,13 @@ static bool writeSettingsToEEPROM(void)
if (pgIsSystem(reg)) {
// write the only instance
record.flags |= CR_CLASSICATION_SYSTEM;
config_streamer_write(&streamer, (uint8_t *)&record, sizeof(record));
if (config_streamer_write(&streamer, (uint8_t *)&record, sizeof(record)) < 0) {
return false;
}
crc = updateCRC(crc, (uint8_t *)&record, sizeof(record));
config_streamer_write(&streamer, reg->address, regSize);
if (config_streamer_write(&streamer, reg->address, regSize) < 0) {
return false;
}
crc = updateCRC(crc, reg->address, regSize);
} else {
// write one instance for each profile
@ -241,10 +282,14 @@ static bool writeSettingsToEEPROM(void)
record.flags = 0;
record.flags |= ((profileIndex + 1) & CR_CLASSIFICATION_MASK);
config_streamer_write(&streamer, (uint8_t *)&record, sizeof(record));
if (config_streamer_write(&streamer, (uint8_t *)&record, sizeof(record)) < 0) {
return false;
}
crc = updateCRC(crc, (uint8_t *)&record, sizeof(record));
const uint8_t *address = reg->address + (regSize * profileIndex);
config_streamer_write(&streamer, address, regSize);
if (config_streamer_write(&streamer, address, regSize) < 0) {
return false;
}
crc = updateCRC(crc, address, regSize);
}
}
@ -254,13 +299,19 @@ static bool writeSettingsToEEPROM(void)
.terminator = 0,
};
config_streamer_write(&streamer, (uint8_t *)&footer, sizeof(footer));
if (config_streamer_write(&streamer, (uint8_t *)&footer, sizeof(footer)) < 0) {
return false;
}
crc = updateCRC(crc, (uint8_t *)&footer, sizeof(footer));
// append checksum now
config_streamer_write(&streamer, (uint8_t *)&crc, sizeof(crc));
if (config_streamer_write(&streamer, (uint8_t *)&crc, sizeof(crc)) < 0) {
return false;
}
config_streamer_flush(&streamer);
if (config_streamer_flush(&streamer) < 0) {
return false;
}
bool success = config_streamer_finish(&streamer) == 0;
@ -274,6 +325,10 @@ void writeConfigToEEPROM(void)
for (int attempt = 0; attempt < 3 && !success; attempt++) {
if (writeSettingsToEEPROM()) {
success = true;
#ifdef CONFIG_IN_EXTERNAL_FLASH
// copy it back from flash to the in-memory buffer.
success = loadEEPROMFromExternalFlash();
#endif
}
}

View file

@ -24,8 +24,6 @@
#include "common/axis.h"
#include "common/color.h"
#include "drivers/rx_pwm.h"
#include "fc/config.h"
#include "fc/rc_controls.h"
#include "flight/servos.h"

View file

@ -19,6 +19,11 @@
#include "platform.h"
#include "drivers/system.h"
#include "config/config_streamer.h"
#include "build/build_config.h"
#if !defined(CONFIG_IN_FLASH)
SLOW_RAM uint8_t eepromData[EEPROM_SIZE];
#endif
// Helper functions
extern void config_streamer_impl_unlock(void);
@ -35,6 +40,7 @@ void config_streamer_start(config_streamer_t *c, uintptr_t base, int size)
// base must start at FLASH_PAGE_SIZE boundary when using embedded flash.
c->address = base;
c->size = size;
c->end = base + size;
if (!c->unlocked) {
config_streamer_impl_unlock();
c->unlocked = true;
@ -44,6 +50,11 @@ void config_streamer_start(config_streamer_t *c, uintptr_t base, int size)
int config_streamer_write(config_streamer_t *c, const uint8_t *p, uint32_t size)
{
if ((c->address + size) > c->end) {
// trying to write past end of streamer
return -1;
}
for (const uint8_t *pat = p; pat != (uint8_t*)p + size; pat++) {
c->buffer.b[c->at++] = *pat;
@ -63,6 +74,9 @@ int config_streamer_status(config_streamer_t *c)
int config_streamer_flush(config_streamer_t *c)
{
if (c->at != 0) {
if ((c->address + c->at) > c->end) {
return -1;
}
memset(c->buffer.b + c->at, 0, sizeof(c->buffer) - c->at);
c->err = config_streamer_impl_write_word(c, &c->buffer.w);
c->at = 0;

View file

@ -20,10 +20,15 @@
#include <stdint.h>
#include <stdbool.h>
#include "drivers/flash_m25p16.h"
// Streams data out to the EEPROM, padding to the write size as
// needed, and updating the checksum as it goes.
#if defined(STM32H7)
#ifdef CONFIG_IN_EXTERNAL_FLASH
#define CONFIG_STREAMER_BUFFER_SIZE M25P16_PAGESIZE // Must match flash device page size
typedef uint32_t config_streamer_buffer_align_type_t;
#elif defined(STM32H7)
#define CONFIG_STREAMER_BUFFER_SIZE 32 // Flash word = 256-bits
typedef uint64_t config_streamer_buffer_align_type_t;
#else
@ -33,6 +38,7 @@ typedef uint32_t config_streamer_buffer_align_type_t;
typedef struct config_streamer_s {
uintptr_t address;
uintptr_t end;
int size;
union {
uint8_t b[CONFIG_STREAMER_BUFFER_SIZE];

View file

@ -0,0 +1,77 @@
/*
* This file is part of Cleanflight.
*
* Cleanflight is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Cleanflight is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include "platform.h"
#include "drivers/system.h"
#include "drivers/flash.h"
#include "config/config_streamer.h"
#if defined(CONFIG_IN_EXTERNAL_FLASH)
static bool streamerLocked = true;
void config_streamer_impl_unlock(void)
{
const flashGeometry_t *flashGeometry = flashGetGeometry();
if (flashGeometry->pageSize == CONFIG_STREAMER_BUFFER_SIZE) {
// streamer needs to buffer exactly one flash page
streamerLocked = false;
}
}
void config_streamer_impl_lock(void)
{
streamerLocked = true;
}
int config_streamer_impl_write_word(config_streamer_t *c, config_streamer_buffer_align_type_t *buffer)
{
if (streamerLocked) {
return -1;
}
uint32_t dataOffset = (uint32_t)(c->address - (uintptr_t)&eepromData[0]);
const flashPartition_t *flashPartition = flashPartitionFindByType(FLASH_PARTITION_TYPE_CONFIG);
const flashGeometry_t *flashGeometry = flashGetGeometry();
uint32_t flashStartAddress = flashPartition->startSector * flashGeometry->sectorSize;
uint32_t flashOverflowAddress = ((flashPartition->endSector + 1) * flashGeometry->sectorSize); // +1 to sector for inclusive
uint32_t flashAddress = flashStartAddress + dataOffset;
if (flashAddress + CONFIG_STREAMER_BUFFER_SIZE > flashOverflowAddress) {
return -2; // address is past end of partition
}
uint32_t flashSectorSize = flashGeometry->sectorSize;
if (flashAddress % flashSectorSize == 0) {
flashEraseSector(flashAddress);
}
if (flashPageProgram(flashAddress, (uint8_t *)buffer, CONFIG_STREAMER_BUFFER_SIZE) == flashAddress) {
// returned same address: programming failed
return -3;
}
c->address += CONFIG_STREAMER_BUFFER_SIZE;
return 0;
}
#endif

View file

@ -0,0 +1,61 @@
/*
* This file is part of Cleanflight.
*
* Cleanflight is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Cleanflight is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include "platform.h"
#include "drivers/system.h"
#include "config/config_streamer.h"
#if defined(CONFIG_IN_RAM)
static bool streamerLocked = true;
void config_streamer_impl_unlock(void)
{
streamerLocked = false;
}
void config_streamer_impl_lock(void)
{
streamerLocked = true;
}
int config_streamer_impl_write_word(config_streamer_t *c, config_streamer_buffer_align_type_t *buffer)
{
if (streamerLocked) {
return -1;
}
if (c->address == (uintptr_t)&eepromData[0]) {
memset(eepromData, 0, sizeof(eepromData));
}
config_streamer_buffer_align_type_t *destAddr = (config_streamer_buffer_align_type_t *)c->address;
config_streamer_buffer_align_type_t *srcAddr = buffer;
uint8_t nRows = CONFIG_STREAMER_BUFFER_SIZE / sizeof(config_streamer_buffer_align_type_t);
do {
*destAddr++ = *srcAddr++;
} while(--nRows != 0);
c->address += CONFIG_STREAMER_BUFFER_SIZE;
return 0;
}
#endif

View file

@ -20,7 +20,7 @@
#include "drivers/system.h"
#include "config/config_streamer.h"
#if defined(STM32F3)
#if defined(STM32F3) && !defined(CONFIG_IN_RAM) && !defined(CONFIG_IN_EXTERNAL_FLASH)
#define FLASH_PAGE_SIZE 0x800
@ -57,4 +57,4 @@ int config_streamer_impl_write_word(config_streamer_t *c, config_streamer_buffer
return 0;
}
#endif
#endif

View file

@ -20,7 +20,7 @@
#include "drivers/system.h"
#include "config/config_streamer.h"
#if defined(STM32F4)
#if defined(STM32F4) && !defined(CONFIG_IN_RAM) && !defined(CONFIG_IN_EXTERNAL_FLASH)
/*
Sector 0 0x08000000 - 0x08003FFF 16 Kbytes
@ -103,4 +103,4 @@ int config_streamer_impl_write_word(config_streamer_t *c, config_streamer_buffer
return 0;
}
#endif
#endif

View file

@ -20,7 +20,7 @@
#include "drivers/system.h"
#include "config/config_streamer.h"
#if defined(STM32F7)
#if defined(STM32F7) && !defined(CONFIG_IN_RAM) && !defined(CONFIG_IN_EXTERNAL_FLASH)
#if defined(STM32F745xx) || defined(STM32F746xx) || defined(STM32F765xx)
/*
@ -138,4 +138,4 @@ int config_streamer_impl_write_word(config_streamer_t *c, config_streamer_buffer
return 0;
}
#endif
#endif

View file

@ -20,7 +20,7 @@
#include "drivers/system.h"
#include "config/config_streamer.h"
#if defined(STM32H7)
#if defined(STM32H7) && !defined(CONFIG_IN_RAM) && !defined(CONFIG_IN_EXTERNAL_FLASH)
#if defined(STM32H743xx)
/* Sectors 0-7 of 128K each */
@ -96,4 +96,4 @@ int config_streamer_impl_write_word(config_streamer_t *c, config_streamer_buffer
return 0;
}
#endif
#endif

View file

@ -1,117 +0,0 @@
/*
* This file is part of Cleanflight.
*
* Cleanflight is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Cleanflight is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdbool.h>
#include <string.h>
#include <stdint.h>
#include <platform.h>
#include "drivers/system.h"
#include "drivers/bus.h"
#include "drivers/sensor.h"
#include "drivers/accgyro/accgyro.h"
#include "drivers/accgyro/accgyro_adxl345.h"
#ifdef USE_IMU_ADXL345
// ADXL345, Alternative address mode 0x53
#define ADXL345_ADDRESS 0x53
// Registers
#define ADXL345_BW_RATE 0x2C
#define ADXL345_POWER_CTL 0x2D
#define ADXL345_INT_ENABLE 0x2E
#define ADXL345_DATA_FORMAT 0x31
#define ADXL345_DATA_OUT 0x32
#define ADXL345_FIFO_CTL 0x38
// BW_RATE values
#define ADXL345_RATE_50 0x09
#define ADXL345_RATE_100 0x0A
#define ADXL345_RATE_200 0x0B
#define ADXL345_RATE_400 0x0C
#define ADXL345_RATE_800 0x0D
#define ADXL345_RATE_1600 0x0E
#define ADXL345_RATE_3200 0x0F
// various register values
#define ADXL345_POWER_MEAS 0x08
#define ADXL345_FULL_RANGE 0x08
#define ADXL345_RANGE_2G 0x00
#define ADXL345_RANGE_4G 0x01
#define ADXL345_RANGE_8G 0x02
#define ADXL345_RANGE_16G 0x03
#define ADXL345_FIFO_STREAM 0x80
static void adxl345Init(accDev_t *acc)
{
busWrite(acc->busDev, ADXL345_POWER_CTL, ADXL345_POWER_MEAS);
busWrite(acc->busDev, ADXL345_DATA_FORMAT, ADXL345_FULL_RANGE | ADXL345_RANGE_8G);
busWrite(acc->busDev, ADXL345_BW_RATE, ADXL345_RATE_100);
acc->acc_1G = 256; // 3.3V operation
}
static bool adxl345Read(accDev_t *acc)
{
uint8_t buf[6];
if (!busReadBuf(acc->busDev, ADXL345_DATA_OUT, buf, 6)) {
return false;
}
acc->ADCRaw[0] = buf[0] + (buf[1] << 8);
acc->ADCRaw[1] = buf[2] + (buf[3] << 8);
acc->ADCRaw[2] = buf[4] + (buf[5] << 8);
return true;
}
static bool deviceDetect(busDevice_t * dev)
{
bool ack = false;
uint8_t sig = 0;
ack = busRead(dev, 0x00, &sig);
if (!ack || sig != 0xE5)
return false;
return true;
}
bool adxl345Detect(accDev_t *acc)
{
acc->busDev = busDeviceInit(BUSTYPE_ANY, DEVHW_ADXL345, acc->imuSensorToUse, OWNER_MPU);
if (acc->busDev == NULL) {
return false;
}
if (!deviceDetect(acc->busDev)) {
busDeviceDeInit(acc->busDev);
return false;
}
acc->initFn = adxl345Init;
acc->readFn = adxl345Read;
acc->accAlign = acc->busDev->param;
return true;
}
#endif

View file

@ -1,93 +0,0 @@
/*
* This file is part of Cleanflight.
*
* Cleanflight is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Cleanflight is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdbool.h>
#include <string.h>
#include <stdint.h>
#include <platform.h>
#include "drivers/system.h"
#include "drivers/bus.h"
#include "drivers/sensor.h"
#include "drivers/accgyro/accgyro.h"
#include "drivers/accgyro/accgyro_bma280.h"
#ifdef USE_IMU_BMA280
// BMA280, default I2C address mode 0x18
#define BMA280_WHOAMI 0x00
#define BMA280_ADDRESS 0x18
#define BMA280_ACC_X_LSB 0x02
#define BMA280_PMU_BW 0x10
#define BMA280_PMU_RANGE 0x0F
static void bma280Init(accDev_t *acc)
{
busWrite(acc->busDev, BMA280_PMU_RANGE, 0x08); // +-8g range
busWrite(acc->busDev, BMA280_PMU_BW, 0x0E); // 500Hz BW
acc->acc_1G = 512 * 8;
}
static bool bma280Read(accDev_t *acc)
{
uint8_t buf[6];
if (!busReadBuf(acc->busDev, BMA280_ACC_X_LSB, buf, 6)) {
return false;
}
// Data format is lsb<5:0><crap><new_data_bit> | msb<13:6>
acc->ADCRaw[0] = (int16_t)((buf[0] >> 2) + (buf[1] << 8));
acc->ADCRaw[1] = (int16_t)((buf[2] >> 2) + (buf[3] << 8));
acc->ADCRaw[2] = (int16_t)((buf[4] >> 2) + (buf[5] << 8));
return true;
}
static bool deviceDetect(busDevice_t * dev)
{
bool ack = false;
uint8_t sig = 0;
ack = busRead(dev, BMA280_WHOAMI, &sig);
if (!ack || sig != 0xFB)
return false;
return true;
}
bool bma280Detect(accDev_t *acc)
{
acc->busDev = busDeviceInit(BUSTYPE_ANY, DEVHW_BMA280, acc->imuSensorToUse, OWNER_MPU);
if (acc->busDev == NULL) {
return false;
}
if (!deviceDetect(acc->busDev)) {
busDeviceDeInit(acc->busDev);
return false;
}
acc->initFn = bma280Init;
acc->readFn = bma280Read;
acc->accAlign = acc->busDev->param;
return true;
}
#endif

View file

@ -0,0 +1,354 @@
/*
* This file is part of Cleanflight and Betaflight.
*
* Cleanflight and Betaflight are free software. You can redistribute
* this software and/or modify this software under the terms of the
* GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option)
* any later version.
*
* Cleanflight and Betaflight are distributed in the hope that they
* will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software.
*
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdbool.h>
#include <stdint.h>
#include "platform.h"
#if defined(USE_IMU_BMI270)
#include "build/debug.h"
#include "common/axis.h"
#include "common/maths.h"
#include "common/utils.h"
#include "drivers/system.h"
#include "drivers/time.h"
#include "drivers/io.h"
#include "drivers/exti.h"
#include "drivers/bus.h"
#include "drivers/sensor.h"
#include "drivers/accgyro/accgyro.h"
#include "drivers/accgyro/accgyro_bmi270.h"
#define BMI270_CONFIG_SIZE 328
// Declaration for the device config (microcode) that must be uploaded to the sensor
extern const uint8_t bmi270_maximum_fifo_config_file[BMI270_CONFIG_SIZE];
// BMI270 registers (not the complete list)
typedef enum {
BMI270_REG_CHIP_ID = 0x00,
BMI270_REG_ERR_REG = 0x02,
BMI270_REG_STATUS = 0x03,
BMI270_REG_ACC_DATA_X_LSB = 0x0C,
BMI270_REG_GYR_DATA_X_LSB = 0x12,
BMI270_REG_SENSORTIME_0 = 0x18,
BMI270_REG_SENSORTIME_1 = 0x19,
BMI270_REG_SENSORTIME_2 = 0x1A,
BMI270_REG_EVENT = 0x1B,
BMI270_REG_INT_STATUS_0 = 0x1C,
BMI270_REG_INT_STATUS_1 = 0x1D,
BMI270_REG_INTERNAL_STATUS = 0x21,
BMI270_REG_TEMPERATURE_LSB = 0x22,
BMI270_REG_TEMPERATURE_MSB = 0x23,
BMI270_REG_FIFO_LENGTH_LSB = 0x24,
BMI270_REG_FIFO_LENGTH_MSB = 0x25,
BMI270_REG_FIFO_DATA = 0x26,
BMI270_REG_ACC_CONF = 0x40,
BMI270_REG_ACC_RANGE = 0x41,
BMI270_REG_GYRO_CONF = 0x42,
BMI270_REG_GYRO_RANGE = 0x43,
BMI270_REG_AUX_CONF = 0x44,
BMI270_REG_FIFO_DOWNS = 0x45,
BMI270_REG_FIFO_WTM_0 = 0x46,
BMI270_REG_FIFO_WTM_1 = 0x47,
BMI270_REG_FIFO_CONFIG_0 = 0x48,
BMI270_REG_FIFO_CONFIG_1 = 0x49,
BMI270_REG_SATURATION = 0x4A,
BMI270_REG_INT1_IO_CTRL = 0x53,
BMI270_REG_INT2_IO_CTRL = 0x54,
BMI270_REG_INT_LATCH = 0x55,
BMI270_REG_INT1_MAP_FEAT = 0x56,
BMI270_REG_INT2_MAP_FEAT = 0x57,
BMI270_REG_INT_MAP_DATA = 0x58,
BMI270_REG_INIT_CTRL = 0x59,
BMI270_REG_INIT_DATA = 0x5E,
BMI270_REG_ACC_SELF_TEST = 0x6D,
BMI270_REG_GYR_SELF_TEST_AXES = 0x6E,
BMI270_REG_PWR_CONF = 0x7C,
BMI270_REG_PWR_CTRL = 0x7D,
BMI270_REG_CMD = 0x7E,
} bmi270Register_e;
#define BMI270_CHIP_ID 0x24
#define BMI270_CMD_SOFTRESET 0xB6
#define BMI270_PWR_CONF_HP 0x00
#define BMI270_PWR_CTRL_GYR_EN 0x02
#define BMI270_PWR_CTRL_ACC_EN 0x04
#define BMI270_PWR_CTRL_TEMP_EN 0x08
#define BMI270_ACC_CONF_HP 0x80
#define BMI270_ACC_RANGE_8G 0x02
#define BMI270_ACC_RANGE_16G 0x03
#define BMI270_GYRO_CONF_NOISE_PERF 0x40
#define BMI270_GYRO_CONF_FILTER_PERF 0x80
#define BMI270_GYRO_RANGE_2000DPS 0x08
#define BMI270_INT_MAP_DATA_DRDY_INT1 0x04
#define BMI270_INT1_IO_CTRL_ACTIVE_HIGH 0x02
#define BMI270_INT1_IO_CTRL_OUTPUT_EN 0x08
#define BMI270_ODR_400 0x0A
#define BMI270_ODR_800 0x0B
#define BMI270_ODR_1600 0x0C
#define BMI270_ODR_3200 0x0D
#define BMI270_BWP_OSR4 0x00
#define BMI270_BWP_OSR2 0x10
#define BMI270_BWP_NORM 0x20
typedef struct __attribute__ ((__packed__)) bmi270ContextData_s {
uint16_t chipMagicNumber;
uint8_t lastReadStatus;
uint8_t __padding_dummy;
uint8_t accRaw[6];
uint8_t gyroRaw[6];
} bmi270ContextData_t;
STATIC_ASSERT(sizeof(bmi270ContextData_t) < BUS_SCRATCHPAD_MEMORY_SIZE, busDevice_scratchpad_memory_too_small);
static const gyroFilterAndRateConfig_t gyroConfigs[] = {
{ GYRO_LPF_256HZ, 3200, { BMI270_BWP_NORM | BMI270_ODR_3200} },
{ GYRO_LPF_256HZ, 1600, { BMI270_BWP_NORM | BMI270_ODR_1600} },
{ GYRO_LPF_256HZ, 800, { BMI270_BWP_NORM | BMI270_ODR_800 } },
{ GYRO_LPF_188HZ, 800, { BMI270_BWP_OSR2 | BMI270_ODR_800 } },
{ GYRO_LPF_188HZ, 400, { BMI270_BWP_NORM | BMI270_ODR_400 } },
{ GYRO_LPF_98HZ, 800, { BMI270_BWP_OSR4 | BMI270_ODR_800 } },
{ GYRO_LPF_98HZ, 400, { BMI270_BWP_OSR2 | BMI270_ODR_400 } },
{ GYRO_LPF_42HZ, 800, { BMI270_BWP_OSR4 | BMI270_ODR_800 } },
{ GYRO_LPF_42HZ, 400, { BMI270_BWP_OSR4 | BMI270_ODR_400 } },
};
// Toggle the CS to switch the device into SPI mode.
// Device switches initializes as I2C and switches to SPI on a low to high CS transition
static void bmi270EnableSPI(busDevice_t *dev)
{
IOLo(dev->busdev.spi.csnPin);
delay(1);
IOHi(dev->busdev.spi.csnPin);
delay(10);
}
static bool bmi270DeviceDetect(busDevice_t * busDev)
{
uint8_t id[2];
busSetSpeed(busDev, BUS_SPEED_INITIALIZATION);
bmi270EnableSPI(busDev);
busReadBuf(busDev, BMI270_REG_CHIP_ID, &id[0], 2);
if (id[1] == BMI270_CHIP_ID) {
return true;
}
return false;
}
static void bmi270UploadConfig(busDevice_t * busDev)
{
busWrite(busDev, BMI270_REG_PWR_CONF, 0);
delay(1);
busWrite(busDev, BMI270_REG_INIT_CTRL, 0);
delay(1);
// Transfer the config file
uint8_t reg = BMI270_REG_INIT_DATA;
busTransferDescriptor_t tfDesc[] = {
{.rxBuf = NULL, .txBuf=&reg, .length=1},
{.rxBuf = NULL, .txBuf=(uint8_t *)bmi270_maximum_fifo_config_file, .length=sizeof(bmi270_maximum_fifo_config_file)}
};
spiBusTransferMultiple(busDev, tfDesc, 2);
delay(10);
busWrite(busDev, BMI270_REG_INIT_CTRL, 1);
delay(1);
}
static void bmi270AccAndGyroInit(gyroDev_t *gyro)
{
busDevice_t * busDev = gyro->busDev;
gyroIntExtiInit(gyro);
// Perform a soft reset to set all configuration to default
// Delay 100ms before continuing configuration
busWrite(busDev, BMI270_REG_CMD, BMI270_CMD_SOFTRESET);
delay(100);
// Use standard bus speed
busSetSpeed(busDev, BUS_SPEED_STANDARD);
// Toggle the chip into SPI mode
bmi270EnableSPI(busDev);
bmi270UploadConfig(busDev);
// Configure the accelerometer
busWrite(busDev, BMI270_REG_ACC_CONF, BMI270_ODR_1600 | BMI270_BWP_OSR4 | BMI270_ACC_CONF_HP);
delay(1);
// Configure the accelerometer full-scale range
busWrite(busDev, BMI270_REG_ACC_RANGE, BMI270_ACC_RANGE_8G);
delay(1);
// Configure the gyro
// Figure out suitable filter configuration
const gyroFilterAndRateConfig_t * config = chooseGyroConfig(gyro->lpf, 1000000 / gyro->requestedSampleIntervalUs, &gyroConfigs[0], ARRAYLEN(gyroConfigs));
gyro->sampleRateIntervalUs = 1000000 / config->gyroRateHz;
busWrite(busDev, BMI270_REG_GYRO_CONF, config->gyroConfigValues[0] | BMI270_GYRO_CONF_NOISE_PERF | BMI270_GYRO_CONF_FILTER_PERF);
delay(1);
// Configure the gyro full-range scale
busWrite(busDev, BMI270_REG_GYRO_RANGE, BMI270_GYRO_RANGE_2000DPS);
delay(1);
// Configure the gyro data ready interrupt
#ifdef USE_MPU_DATA_READY_SIGNAL
busWrite(busDev, BMI270_REG_INT_MAP_DATA, BMI270_INT_MAP_DATA_DRDY_INT1);
delay(1);
#endif
// Configure the behavior of the INT1 pin
busWrite(busDev, BMI270_REG_INT1_IO_CTRL, BMI270_INT1_IO_CTRL_ACTIVE_HIGH | BMI270_INT1_IO_CTRL_OUTPUT_EN);
delay(1);
// Configure the device for performance mode
busWrite(busDev, BMI270_REG_PWR_CONF, BMI270_PWR_CONF_HP);
delay(1);
// Enable the gyro and accelerometer
busWrite(busDev, BMI270_REG_PWR_CTRL, BMI270_PWR_CTRL_GYR_EN | BMI270_PWR_CTRL_ACC_EN);
delay(1);
}
static bool bmi270yroReadScratchpad(gyroDev_t *gyro)
{
bmi270ContextData_t * ctx = busDeviceGetScratchpadMemory(gyro->busDev);
ctx->lastReadStatus = busReadBuf(gyro->busDev, BMI270_REG_ACC_DATA_X_LSB, &ctx->__padding_dummy, 6 + 6 + 1);
if (ctx->lastReadStatus) {
gyro->gyroADCRaw[X] = (int16_t)((ctx->gyroRaw[1] << 8) | ctx->gyroRaw[0]);
gyro->gyroADCRaw[Y] = (int16_t)((ctx->gyroRaw[3] << 8) | ctx->gyroRaw[2]);
gyro->gyroADCRaw[Z] = (int16_t)((ctx->gyroRaw[5] << 8) | ctx->gyroRaw[4]);
return true;
}
return false;
}
static bool bmi270AccReadScratchpad(accDev_t *acc)
{
bmi270ContextData_t * ctx = busDeviceGetScratchpadMemory(acc->busDev);
if (ctx->lastReadStatus) {
acc->ADCRaw[X] = (int16_t)((ctx->accRaw[1] << 8) | ctx->accRaw[0]);
acc->ADCRaw[Y] = (int16_t)((ctx->accRaw[3] << 8) | ctx->accRaw[2]);
acc->ADCRaw[Z] = (int16_t)((ctx->accRaw[5] << 8) | ctx->accRaw[4]);
return true;
}
return false;
}
static bool bmi270TemperatureRead(gyroDev_t *gyro, int16_t * data)
{
uint8_t buffer[3];
bool readStatus = busReadBuf(gyro->busDev, BMI270_REG_TEMPERATURE_LSB, &buffer[0], sizeof(buffer));
if (readStatus) {
// Convert to degC*10: degC = raw / 512 + 23
*data = 230 + ((10 * (int32_t)((int16_t)((buffer[2] << 8) | buffer[1]))) >> 9);
return true;
}
return false;
}
static void bmi270GyroInit(gyroDev_t *gyro)
{
bmi270AccAndGyroInit(gyro);
}
static void bmi270AccInit(accDev_t *acc)
{
// sensor is configured during gyro init
acc->acc_1G = 4096; // 8G sensor scale
}
bool bmi270AccDetect(accDev_t *acc)
{
acc->busDev = busDeviceOpen(BUSTYPE_SPI, DEVHW_BMI270, acc->imuSensorToUse);
if (acc->busDev == NULL) {
return false;
}
bmi270ContextData_t * ctx = busDeviceGetScratchpadMemory(acc->busDev);
if (ctx->chipMagicNumber != 0xB270) {
return false;
}
acc->initFn = bmi270AccInit;
acc->readFn = bmi270AccReadScratchpad;
return true;
}
bool bmi270GyroDetect(gyroDev_t *gyro)
{
gyro->busDev = busDeviceInit(BUSTYPE_SPI, DEVHW_BMI270, gyro->imuSensorToUse, OWNER_MPU);
if (gyro->busDev == NULL) {
return false;
}
if (!bmi270DeviceDetect(gyro->busDev)) {
busDeviceDeInit(gyro->busDev);
return false;
}
// Magic number for ACC detection to indicate that we have detected BMI270 gyro
bmi270ContextData_t * ctx = busDeviceGetScratchpadMemory(gyro->busDev);
ctx->chipMagicNumber = 0xB270;
gyro->initFn = bmi270GyroInit;
gyro->readFn = bmi270yroReadScratchpad;
gyro->temperatureFn = bmi270TemperatureRead;
gyro->intStatusFn = gyroCheckDataReady;
gyro->scale = 1.0f / 16.4f; // 2000 dps
return true;
}
#endif // USE_IMU_BMI270

View file

@ -0,0 +1,26 @@
/*
* This file is part of Cleanflight and Betaflight.
*
* Cleanflight and Betaflight are free software. You can redistribute
* this software and/or modify this software under the terms of the
* GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option)
* any later version.
*
* Cleanflight and Betaflight are distributed in the hope that they
* will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software.
*
* If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "drivers/bus.h"
bool bmi270AccDetect(accDev_t *acc);
bool bmi270GyroDetect(gyroDev_t *gyro);

View file

@ -0,0 +1,213 @@
/**
* Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved.
*
* BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @file bmi270_maximum_fifo.c
* @date 2020-11-04
* @version v2.63.1
*
*/
/***************************************************************************/
/*! Header files
****************************************************************************/
//#include "bmi270_maximum_fifo.h"
#include "platform.h"
/***************************************************************************/
/*! Global Variable
****************************************************************************/
/*! @name Global array that stores the configuration file of BMI270 */
const uint8_t bmi270_maximum_fifo_config_file[] = {
0xc8, 0x2e, 0x00, 0x2e, 0x80, 0x2e, 0x1a, 0x00, 0xc8, 0x2e, 0x00, 0x2e, 0xc8, 0x2e, 0x00, 0x2e, 0xc8, 0x2e, 0x00,
0x2e, 0xc8, 0x2e, 0x00, 0x2e, 0xc8, 0x2e, 0x00, 0x2e, 0xc8, 0x2e, 0x00, 0x2e, 0x90, 0x32, 0x21, 0x2e, 0x59, 0xf5,
0x10, 0x30, 0x21, 0x2e, 0x6a, 0xf5, 0x1a, 0x24, 0x22, 0x00, 0x80, 0x2e, 0x3b, 0x00, 0xc8, 0x2e, 0x44, 0x47, 0x22,
0x00, 0x37, 0x00, 0xa4, 0x00, 0xff, 0x0f, 0xd1, 0x00, 0x07, 0xad, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1,
0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00,
0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x11, 0x24, 0xfc, 0xf5, 0x80, 0x30, 0x40, 0x42, 0x50, 0x50, 0x00, 0x30, 0x12, 0x24, 0xeb,
0x00, 0x03, 0x30, 0x00, 0x2e, 0xc1, 0x86, 0x5a, 0x0e, 0xfb, 0x2f, 0x21, 0x2e, 0xfc, 0xf5, 0x13, 0x24, 0x63, 0xf5,
0xe0, 0x3c, 0x48, 0x00, 0x22, 0x30, 0xf7, 0x80, 0xc2, 0x42, 0xe1, 0x7f, 0x3a, 0x25, 0xfc, 0x86, 0xf0, 0x7f, 0x41,
0x33, 0x98, 0x2e, 0xc2, 0xc4, 0xd6, 0x6f, 0xf1, 0x30, 0xf1, 0x08, 0xc4, 0x6f, 0x11, 0x24, 0xff, 0x03, 0x12, 0x24,
0x00, 0xfc, 0x61, 0x09, 0xa2, 0x08, 0x36, 0xbe, 0x2a, 0xb9, 0x13, 0x24, 0x38, 0x00, 0x64, 0xbb, 0xd1, 0xbe, 0x94,
0x0a, 0x71, 0x08, 0xd5, 0x42, 0x21, 0xbd, 0x91, 0xbc, 0xd2, 0x42, 0xc1, 0x42, 0x00, 0xb2, 0xfe, 0x82, 0x05, 0x2f,
0x50, 0x30, 0x21, 0x2e, 0x21, 0xf2, 0x00, 0x2e, 0x00, 0x2e, 0xd0, 0x2e, 0xf0, 0x6f, 0x02, 0x30, 0x02, 0x42, 0x20,
0x26, 0xe0, 0x6f, 0x02, 0x31, 0x03, 0x40, 0x9a, 0x0a, 0x02, 0x42, 0xf0, 0x37, 0x05, 0x2e, 0x5e, 0xf7, 0x10, 0x08,
0x12, 0x24, 0x1e, 0xf2, 0x80, 0x42, 0x83, 0x84, 0xf1, 0x7f, 0x0a, 0x25, 0x13, 0x30, 0x83, 0x42, 0x3b, 0x82, 0xf0,
0x6f, 0x00, 0x2e, 0x00, 0x2e, 0xd0, 0x2e, 0x12, 0x40, 0x52, 0x42, 0x00, 0x2e, 0x12, 0x40, 0x52, 0x42, 0x3e, 0x84,
0x00, 0x40, 0x40, 0x42, 0x7e, 0x82, 0xe1, 0x7f, 0xf2, 0x7f, 0x98, 0x2e, 0x6a, 0xd6, 0x21, 0x30, 0x23, 0x2e, 0x61,
0xf5, 0xeb, 0x2c, 0xe1, 0x6f
};
// The rest of this is not needed, avoid compiler errors due to pedantic settings
#if false
/*! @name Global array that stores the feature input configuration of BMI270 */
const struct bmi2_feature_config bmi270_maximum_fifo_feat_in[BMI270_MAXIMUM_FIFO_MAX_FEAT_IN] = {
};
/*! @name Global array that stores the feature output configuration */
const struct bmi2_feature_config bmi270_maximum_fifo_feat_out[BMI270_MAXIMUM_FIFO_MAX_FEAT_OUT] = {
};
/******************************************************************************/
/*! Local Function Prototypes
******************************************************************************/
/*!
* @brief This internal API is used to validate the device pointer for
* null conditions.
*
* @param[in] dev : Structure instance of bmi2_dev.
*
* @return Result of API execution status
* @retval 0 -> Success
* @retval < 0 -> Fail
*/
static int8_t null_ptr_check(const struct bmi2_dev *dev);
/***************************************************************************/
/*! User Interface Definitions
****************************************************************************/
/*!
* @brief This API:
* 1) updates the device structure with address of the configuration file.
* 2) Initializes BMI270 sensor.
* 3) Writes the configuration file.
* 4) Updates the feature offset parameters in the device structure.
* 5) Updates the maximum number of pages, in the device structure.
*/
int8_t bmi270_maximum_fifo_init(struct bmi2_dev *dev)
{
/* Variable to define result */
int8_t rslt;
/* Null-pointer check */
rslt = null_ptr_check(dev);
if (rslt == BMI2_OK)
{
/* Assign chip id of BMI270 */
dev->chip_id = BMI270_MAXIMUM_FIFO_CHIP_ID;
dev->config_size = sizeof(bmi270_maximum_fifo_config_file);
/* Enable the variant specific features if any */
dev->variant_feature = BMI2_GYRO_CROSS_SENS_ENABLE | BMI2_MAXIMUM_FIFO_VARIANT;
/* An extra dummy byte is read during SPI read */
if (dev->intf == BMI2_SPI_INTF)
{
dev->dummy_byte = 1;
}
else
{
dev->dummy_byte = 0;
}
/* If configuration file pointer is not assigned any address */
if (!dev->config_file_ptr)
{
/* Give the address of the configuration file array to
* the device pointer
*/
dev->config_file_ptr = bmi270_maximum_fifo_config_file;
}
/* Initialize BMI2 sensor */
rslt = bmi2_sec_init(dev);
if (rslt == BMI2_OK)
{
/* Assign the offsets of the feature input
* configuration to the device structure
*/
dev->feat_config = bmi270_maximum_fifo_feat_in;
/* Assign the offsets of the feature output to
* the device structure
*/
dev->feat_output = bmi270_maximum_fifo_feat_out;
/* Assign the maximum number of pages to the
* device structure
*/
dev->page_max = BMI270_MAXIMUM_FIFO_MAX_PAGE_NUM;
/* Assign maximum number of input sensors/
* features to device structure
*/
dev->input_sens = BMI270_MAXIMUM_FIFO_MAX_FEAT_IN;
/* Assign maximum number of output sensors/
* features to device structure
*/
dev->out_sens = BMI270_MAXIMUM_FIFO_MAX_FEAT_OUT;
/* Get the gyroscope cross axis sensitivity */
rslt = bmi2_get_gyro_cross_sense(dev);
}
}
return rslt;
}
/***************************************************************************/
/*! Local Function Definitions
****************************************************************************/
/*!
* @brief This internal API is used to validate the device structure pointer for
* null conditions.
*/
static int8_t null_ptr_check(const struct bmi2_dev *dev)
{
/* Variable to define result */
int8_t rslt = BMI2_OK;
if ((dev == NULL) || (dev->read == NULL) || (dev->write == NULL) || (dev->delay_us == NULL))
{
/* Device structure pointer is not valid */
rslt = BMI2_E_NULL_PTR;
}
return rslt;
}
#endif

View file

@ -0,0 +1,272 @@
/*
* This file is part of INAV.
*
* INAV is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* INAV is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with INAV. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include "platform.h"
#include "build/debug.h"
#include "common/axis.h"
#include "common/maths.h"
#include "common/utils.h"
#include "drivers/system.h"
#include "drivers/time.h"
#include "drivers/exti.h"
#include "drivers/sensor.h"
#include "drivers/accgyro/accgyro.h"
#include "drivers/accgyro/accgyro_mpu.h"
#include "drivers/accgyro/accgyro_icm42605.h"
#if defined(USE_IMU_ICM42605)
#define ICM42605_RA_PWR_MGMT0 0x4E
#define ICM42605_PWR_MGMT0_ACCEL_MODE_LN (3 << 0)
#define ICM42605_PWR_MGMT0_GYRO_MODE_LN (3 << 2)
#define ICM42605_PWR_MGMT0_TEMP_DISABLE_OFF (0 << 5)
#define ICM42605_PWR_MGMT0_TEMP_DISABLE_ON (1 << 5)
#define ICM42605_RA_GYRO_CONFIG0 0x4F
#define ICM42605_RA_ACCEL_CONFIG0 0x50
#define ICM42605_RA_GYRO_ACCEL_CONFIG0 0x52
#define ICM42605_ACCEL_UI_FILT_BW_LOW_LATENCY (14 << 4)
#define ICM42605_GYRO_UI_FILT_BW_LOW_LATENCY (14 << 0)
#define ICM42605_RA_GYRO_DATA_X1 0x25
#define ICM42605_RA_ACCEL_DATA_X1 0x1F
#define ICM42605_RA_INT_CONFIG 0x14
#define ICM42605_INT1_MODE_PULSED (0 << 2)
#define ICM42605_INT1_MODE_LATCHED (1 << 2)
#define ICM42605_INT1_DRIVE_CIRCUIT_OD (0 << 1)
#define ICM42605_INT1_DRIVE_CIRCUIT_PP (1 << 1)
#define ICM42605_INT1_POLARITY_ACTIVE_LOW (0 << 0)
#define ICM42605_INT1_POLARITY_ACTIVE_HIGH (1 << 0)
#define ICM42605_RA_INT_CONFIG0 0x63
#define ICM42605_UI_DRDY_INT_CLEAR_ON_SBR ((0 << 5) || (0 << 4))
#define ICM42605_UI_DRDY_INT_CLEAR_ON_SBR_DUPLICATE ((0 << 5) || (0 << 4)) // duplicate settings in datasheet, Rev 1.2.
#define ICM42605_UI_DRDY_INT_CLEAR_ON_F1BR ((1 << 5) || (0 << 4))
#define ICM42605_UI_DRDY_INT_CLEAR_ON_SBR_AND_F1BR ((1 << 5) || (1 << 4))
#define ICM42605_RA_INT_CONFIG1 0x64
#define ICM42605_INT_ASYNC_RESET_BIT 4
#define ICM42605_INT_TDEASSERT_DISABLE_BIT 5
#define ICM42605_INT_TDEASSERT_ENABLED (0 << ICM42605_INT_TDEASSERT_DISABLE_BIT)
#define ICM42605_INT_TDEASSERT_DISABLED (1 << ICM42605_INT_TDEASSERT_DISABLE_BIT)
#define ICM42605_INT_TPULSE_DURATION_BIT 6
#define ICM42605_INT_TPULSE_DURATION_100 (0 << ICM42605_INT_TPULSE_DURATION_BIT)
#define ICM42605_INT_TPULSE_DURATION_8 (1 << ICM42605_INT_TPULSE_DURATION_BIT)
#define ICM42605_RA_INT_SOURCE0 0x65
#define ICM42605_UI_DRDY_INT1_EN_DISABLED (0 << 3)
#define ICM42605_UI_DRDY_INT1_EN_ENABLED (1 << 3)
static void icm42605AccInit(accDev_t *acc)
{
acc->acc_1G = 512 * 4;
}
static bool icm42605AccRead(accDev_t *acc)
{
uint8_t data[6];
const bool ack = busReadBuf(acc->busDev, ICM42605_RA_ACCEL_DATA_X1, data, 6);
if (!ack) {
return false;
}
acc->ADCRaw[X] = (int16_t)((data[0] << 8) | data[1]);
acc->ADCRaw[Y] = (int16_t)((data[2] << 8) | data[3]);
acc->ADCRaw[Z] = (int16_t)((data[4] << 8) | data[5]);
return true;
}
bool icm42605AccDetect(accDev_t *acc)
{
acc->busDev = busDeviceOpen(BUSTYPE_ANY, DEVHW_ICM42605, acc->imuSensorToUse);
if (acc->busDev == NULL) {
return false;
}
mpuContextData_t * ctx = busDeviceGetScratchpadMemory(acc->busDev);
if (ctx->chipMagicNumber != 0x4265) {
return false;
}
acc->initFn = icm42605AccInit;
acc->readFn = icm42605AccRead;
acc->accAlign = acc->busDev->param;
return true;
}
static const gyroFilterAndRateConfig_t icm42605GyroConfigs[] = {
/* DLPF ODR */
{ GYRO_LPF_256HZ, 8000, { 6, 3 } }, /* 400 Hz LPF */
{ GYRO_LPF_256HZ, 4000, { 5, 4 } }, /* 250 Hz LPF */
{ GYRO_LPF_256HZ, 2000, { 3, 5 } }, /* 250 Hz LPF */
{ GYRO_LPF_256HZ, 1000, { 1, 6 } }, /* 250 Hz LPF */
{ GYRO_LPF_256HZ, 500, { 0, 15 } }, /* 250 Hz LPF */
{ GYRO_LPF_188HZ, 1000, { 3, 6 } }, /* 125 HZ */
{ GYRO_LPF_188HZ, 500, { 1, 15 } }, /* 125 HZ */
{ GYRO_LPF_98HZ, 1000, { 4, 6 } }, /* 100 HZ*/
{ GYRO_LPF_98HZ, 500, { 2, 15 } }, /* 100 HZ*/
{ GYRO_LPF_42HZ, 1000, { 6, 6 } }, /* 50 HZ */
{ GYRO_LPF_42HZ, 500, { 4, 15 } },
{ GYRO_LPF_20HZ, 1000, { 7, 6 } }, /* 25 HZ */
{ GYRO_LPF_20HZ, 500, { 6, 15 } },
{ GYRO_LPF_10HZ, 1000, { 7, 6 } }, /* 25 HZ */
{ GYRO_LPF_10HZ, 500, { 7, 15 } } /* 12.5 HZ */
};
static void icm42605AccAndGyroInit(gyroDev_t *gyro)
{
busDevice_t * dev = gyro->busDev;
const gyroFilterAndRateConfig_t * config = chooseGyroConfig(gyro->lpf, 1000000 / gyro->requestedSampleIntervalUs,
&icm42605GyroConfigs[0], ARRAYLEN(icm42605GyroConfigs));
gyro->sampleRateIntervalUs = 1000000 / config->gyroRateHz;
gyroIntExtiInit(gyro);
busSetSpeed(dev, BUS_SPEED_INITIALIZATION);
busWrite(dev, ICM42605_RA_PWR_MGMT0, ICM42605_PWR_MGMT0_TEMP_DISABLE_OFF | ICM42605_PWR_MGMT0_ACCEL_MODE_LN | ICM42605_PWR_MGMT0_GYRO_MODE_LN);
delay(15);
/* ODR and dynamic range */
busWrite(dev, ICM42605_RA_GYRO_CONFIG0, (0x00) << 5 | (config->gyroConfigValues[1] & 0x0F)); /* 2000 deg/s */
delay(15);
busWrite(dev, ICM42605_RA_ACCEL_CONFIG0, (0x00) << 5 | (config->gyroConfigValues[1] & 0x0F)); /* 16 G deg/s */
delay(15);
/* LPF bandwidth */
busWrite(dev, ICM42605_RA_GYRO_ACCEL_CONFIG0, (config->gyroConfigValues[1]) | (config->gyroConfigValues[1] << 4));
delay(15);
busWrite(dev, ICM42605_RA_INT_CONFIG, ICM42605_INT1_MODE_PULSED | ICM42605_INT1_DRIVE_CIRCUIT_PP | ICM42605_INT1_POLARITY_ACTIVE_HIGH);
delay(15);
busWrite(dev, ICM42605_RA_INT_CONFIG0, ICM42605_UI_DRDY_INT_CLEAR_ON_SBR);
delay(100);
#ifdef USE_MPU_DATA_READY_SIGNAL
uint8_t intConfig1Value;
busWrite(dev, ICM42605_RA_INT_SOURCE0, ICM42605_UI_DRDY_INT1_EN_ENABLED);
// Datasheet says: "User should change setting to 0 from default setting of 1, for proper INT1 and INT2 pin operation"
busRead(dev, ICM42605_RA_INT_CONFIG1, &intConfig1Value);
intConfig1Value &= ~(1 << ICM42605_INT_ASYNC_RESET_BIT);
intConfig1Value |= (ICM42605_INT_TPULSE_DURATION_8 | ICM42605_INT_TDEASSERT_DISABLED);
busWrite(dev, ICM42605_RA_INT_CONFIG1, intConfig1Value);
delay(15);
#endif
busSetSpeed(dev, BUS_SPEED_FAST);
}
static bool icm42605DeviceDetect(busDevice_t * dev)
{
uint8_t tmp;
uint8_t attemptsRemaining = 5;
busSetSpeed(dev, BUS_SPEED_INITIALIZATION);
busWrite(dev, ICM42605_RA_PWR_MGMT0, 0x00);
do {
delay(150);
busRead(dev, MPU_RA_WHO_AM_I, &tmp);
switch (tmp) {
/* ICM42605 and ICM42688P share the register structure*/
case ICM42605_WHO_AM_I_CONST:
case ICM42688P_WHO_AM_I_CONST:
return true;
default:
// Retry detection
break;
}
} while (attemptsRemaining--);
return false;
}
static bool icm42605GyroRead(gyroDev_t *gyro)
{
uint8_t data[6];
const bool ack = busReadBuf(gyro->busDev, ICM42605_RA_GYRO_DATA_X1, data, 6);
if (!ack) {
return false;
}
gyro->gyroADCRaw[X] = (int16_t)((data[0] << 8) | data[1]);
gyro->gyroADCRaw[Y] = (int16_t)((data[2] << 8) | data[3]);
gyro->gyroADCRaw[Z] = (int16_t)((data[4] << 8) | data[5]);
return true;
}
bool icm42605GyroDetect(gyroDev_t *gyro)
{
gyro->busDev = busDeviceInit(BUSTYPE_ANY, DEVHW_ICM42605, gyro->imuSensorToUse, OWNER_MPU);
if (gyro->busDev == NULL) {
return false;
}
if (!icm42605DeviceDetect(gyro->busDev)) {
busDeviceDeInit(gyro->busDev);
return false;
}
// Magic number for ACC detection to indicate that we have detected icm42605 gyro
mpuContextData_t * ctx = busDeviceGetScratchpadMemory(gyro->busDev);
ctx->chipMagicNumber = 0x4265;
gyro->initFn = icm42605AccAndGyroInit;
gyro->readFn = icm42605GyroRead;
gyro->intStatusFn = gyroCheckDataReady;
gyro->temperatureFn = NULL;
gyro->scale = 1.0f / 16.4f; // 16.4 dps/lsb scalefactor
gyro->gyroAlign = gyro->busDev->param;
return true;
}
#endif

View file

@ -17,6 +17,5 @@
#pragma once
#define RANGEFINDER_HCSR04_i2C_TASK_PERIOD_MS 100
bool hcsr04i2c0Detect(rangefinderDev_t *dev);
bool icm42605AccDetect(accDev_t *acc);
bool icm42605GyroDetect(gyroDev_t *gyro);

View file

@ -1,145 +0,0 @@
/*
* This file is part of Cleanflight.
*
* Cleanflight is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Cleanflight is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdbool.h>
#include <string.h>
#include <stdint.h>
#include <platform.h>
#include "drivers/system.h"
#include "drivers/time.h"
#include "drivers/bus_i2c.h"
#include "common/maths.h"
#include "common/axis.h"
#include "drivers/sensor.h"
#include "drivers/accgyro/accgyro.h"
#include "drivers/accgyro/accgyro_l3g4200d.h"
// L3G4200D, Standard address 0x68
#define L3G4200D_ADDRESS 0x68
#define L3G4200D_ID 0xD3
#define L3G4200D_AUTOINCR 0x80
// Registers
#define L3G4200D_WHO_AM_I 0x0F
#define L3G4200D_CTRL_REG1 0x20
#define L3G4200D_CTRL_REG2 0x21
#define L3G4200D_CTRL_REG3 0x22
#define L3G4200D_CTRL_REG4 0x23
#define L3G4200D_CTRL_REG5 0x24
#define L3G4200D_REFERENCE 0x25
#define L3G4200D_STATUS_REG 0x27
#define L3G4200D_GYRO_OUT 0x28
// Bits
#define L3G4200D_POWER_ON 0x0F
#define L3G4200D_FS_SEL_2000DPS 0xF0
#define L3G4200D_DLPF_32HZ 0x00
#define L3G4200D_DLPF_54HZ 0x40
#define L3G4200D_DLPF_78HZ 0x80
#define L3G4200D_DLPF_93HZ 0xC0
static void l3g4200dInit(gyroDev_t *gyro)
{
bool ack;
uint8_t mpuLowPassFilter = L3G4200D_DLPF_32HZ;
switch (gyro->lpf) {
default:
case 3: // BITS_DLPF_CFG_42HZ
mpuLowPassFilter = L3G4200D_DLPF_32HZ;
break;
case 2: // BITS_DLPF_CFG_98HZ
mpuLowPassFilter = L3G4200D_DLPF_54HZ;
break;
case 1: // BITS_DLPF_CFG_188HZ
mpuLowPassFilter = L3G4200D_DLPF_78HZ;
break;
case 0: // BITS_DLPF_CFG_256HZ
mpuLowPassFilter = L3G4200D_DLPF_93HZ;
break;
}
delay(100);
ack = busWrite(gyro->busDev, L3G4200D_CTRL_REG4, L3G4200D_FS_SEL_2000DPS);
if (!ack) {
failureMode(FAILURE_ACC_INIT);
}
delay(5);
busWrite(gyro->busDev, L3G4200D_CTRL_REG1, L3G4200D_POWER_ON | mpuLowPassFilter);
}
// Read 3 gyro values into user-provided buffer. No overrun checking is done.
static bool l3g4200dRead(gyroDev_t *gyro)
{
uint8_t buf[6];
if (!busReadBuf(gyro->busDev, L3G4200D_AUTOINCR | L3G4200D_GYRO_OUT, buf, 6)) {
return false;
}
gyro->gyroADCRaw[X] = (int16_t)((buf[0] << 8) | buf[1]);
gyro->gyroADCRaw[Y] = (int16_t)((buf[2] << 8) | buf[3]);
gyro->gyroADCRaw[Z] = (int16_t)((buf[4] << 8) | buf[5]);
return true;
}
static bool deviceDetect(busDevice_t * busDev)
{
busSetSpeed(busDev, BUS_SPEED_INITIALIZATION);
for (int retry = 0; retry < 5; retry++) {
uint8_t deviceid;
delay(150);
bool ack = busRead(busDev, L3G4200D_WHO_AM_I, &deviceid);
if (ack && deviceid == L3G4200D_ID) {
return true;
}
};
return false;
}
bool l3g4200dDetect(gyroDev_t *gyro)
{
gyro->busDev = busDeviceInit(BUSTYPE_ANY, DEVHW_L3G4200, gyro->imuSensorToUse, OWNER_MPU);
if (gyro->busDev == NULL) {
return false;
}
if (!deviceDetect(gyro->busDev)) {
busDeviceDeInit(gyro->busDev);
return false;
}
gyro->initFn = l3g4200dInit;
gyro->readFn = l3g4200dRead;
gyro->scale = 1.0f / 14.2857f; // 14.2857dps/lsb scalefactor
gyro->gyroAlign = gyro->busDev->param;
return true;
}

View file

@ -1,20 +0,0 @@
/*
* This file is part of Cleanflight.
*
* Cleanflight is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Cleanflight is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
bool l3g4200dDetect(gyroDev_t *gyro);

View file

@ -1,144 +0,0 @@
/*
* This file is part of Cleanflight.
*
* Cleanflight is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Cleanflight is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdbool.h>
#include <stdint.h>
#include "platform.h"
#include "drivers/time.h"
#include "drivers/io.h"
#include "drivers/bus_i2c.h"
#include "drivers/sensor.h"
#include "drivers/accgyro/accgyro.h"
#include "drivers/accgyro/accgyro_mma845x.h"
// MMA8452QT, Standard address 0x1C
// ACC_INT2 routed to PA5
#define MMA8452_ADDRESS 0x1C
#define MMA8452_DEVICE_SIGNATURE 0x2A
#define MMA8451_DEVICE_SIGNATURE 0x1A
#define MMA8452_STATUS 0x00
#define MMA8452_OUT_X_MSB 0x01
#define MMA8452_WHO_AM_I 0x0D
#define MMA8452_XYZ_DATA_CFG 0x0E
#define MMA8452_HP_FILTER_CUTOFF 0x0F
#define MMA8452_CTRL_REG1 0x2A
#define MMA8452_CTRL_REG2 0x2B
#define MMA8452_CTRL_REG3 0x2C
#define MMA8452_CTRL_REG4 0x2D
#define MMA8452_CTRL_REG5 0x2E
#define MMA8452_FS_RANGE_8G 0x02
#define MMA8452_FS_RANGE_4G 0x01
#define MMA8452_FS_RANGE_2G 0x00
#define MMA8452_HPF_CUTOFF_LV1 0x00
#define MMA8452_HPF_CUTOFF_LV2 0x01
#define MMA8452_HPF_CUTOFF_LV3 0x02
#define MMA8452_HPF_CUTOFF_LV4 0x03
#define MMA8452_CTRL_REG2_B7_ST 0x80
#define MMA8452_CTRL_REG2_B6_RST 0x40
#define MMA8452_CTRL_REG2_B4_SMODS1 0x10
#define MMA8452_CTRL_REG2_B3_SMODS0 0x08
#define MMA8452_CTRL_REG2_B2_SLPE 0x04
#define MMA8452_CTRL_REG2_B1_MODS1 0x02
#define MMA8452_CTRL_REG2_B0_MODS0 0x01
#define MMA8452_CTRL_REG2_MODS_LP 0x03
#define MMA8452_CTRL_REG2_MODS_HR 0x02
#define MMA8452_CTRL_REG2_MODS_LNLP 0x01
#define MMA8452_CTRL_REG2_MODS_NOR 0x00
#define MMA8452_CTRL_REG3_IPOL 0x02
#define MMA8452_CTRL_REG4_INT_EN_DRDY 0x01
#define MMA8452_CTRL_REG1_LNOISE 0x04
#define MMA8452_CTRL_REG1_ACTIVE 0x01
/*
static inline void mma8451ConfigureInterrupt(void)
{
busWrite(acc->busDev, MMA8452_CTRL_REG3, MMA8452_CTRL_REG3_IPOL); // Interrupt polarity (active HIGH)
busWrite(acc->busDev, MMA8452_CTRL_REG4, MMA8452_CTRL_REG4_INT_EN_DRDY); // Enable DRDY interrupt (unused by this driver)
busWrite(acc->busDev, MMA8452_CTRL_REG5, 0); // DRDY routed to INT2
}
*/
static void mma8452Init(accDev_t *acc)
{
busWrite(acc->busDev, MMA8452_CTRL_REG1, 0); // Put device in standby to configure stuff
busWrite(acc->busDev, MMA8452_XYZ_DATA_CFG, MMA8452_FS_RANGE_8G);
busWrite(acc->busDev, MMA8452_HP_FILTER_CUTOFF, MMA8452_HPF_CUTOFF_LV4);
busWrite(acc->busDev, MMA8452_CTRL_REG2, MMA8452_CTRL_REG2_MODS_HR | MMA8452_CTRL_REG2_MODS_HR << 3); // High resolution measurement in both sleep and active modes
// mma8451ConfigureInterrupt();
busWrite(acc->busDev, MMA8452_CTRL_REG1, MMA8452_CTRL_REG1_LNOISE | MMA8452_CTRL_REG1_ACTIVE); // Turn on measurements, low noise at max scale mode, Data Rate 800Hz. LNoise mode makes range +-4G.
acc->acc_1G = 256;
}
static bool mma8452Read(accDev_t *acc)
{
uint8_t buf[6];
if (!busReadBuf(acc->busDev, MMA8452_OUT_X_MSB, buf, 6)) {
return false;
}
acc->ADCRaw[0] = ((int16_t)((buf[0] << 8) | buf[1]) >> 2) / 4;
acc->ADCRaw[1] = ((int16_t)((buf[2] << 8) | buf[3]) >> 2) / 4;
acc->ADCRaw[2] = ((int16_t)((buf[4] << 8) | buf[5]) >> 2) / 4;
return true;
}
static bool deviceDetect(busDevice_t * busDev)
{
bool ack = false;
uint8_t sig = 0;
ack = busRead(busDev, MMA8452_WHO_AM_I, &sig);
if (!ack || (sig != MMA8452_DEVICE_SIGNATURE && sig != MMA8451_DEVICE_SIGNATURE))
return false;
return true;
}
bool mma8452Detect(accDev_t *acc)
{
acc->busDev = busDeviceInit(BUSTYPE_ANY, DEVHW_MMA8452, acc->imuSensorToUse, OWNER_MPU);
if (acc->busDev == NULL) {
return false;
}
if (!deviceDetect(acc->busDev)) {
busDeviceDeInit(acc->busDev);
return false;
}
acc->initFn = mma8452Init;
acc->readFn = mma8452Read;
acc->accAlign = acc->busDev->param;
return true;
}

View file

@ -1,20 +0,0 @@
/*
* This file is part of Cleanflight.
*
* Cleanflight is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Cleanflight is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
bool mma8452Detect(accDev_t *acc);

View file

@ -35,6 +35,8 @@
#define ICM20602_WHO_AM_I_CONST (0x12)
#define ICM20608G_WHO_AM_I_CONST (0xAF)
#define ICM20689_WHO_AM_I_CONST (0x98)
#define ICM42605_WHO_AM_I_CONST (0x42)
#define ICM42688P_WHO_AM_I_CONST (0x47)
// RA = Register Address

View file

@ -197,7 +197,13 @@ static bool bmp388StartUP(baroDev_t *baro)
static bool bmp388GetUP(baroDev_t *baro)
{
busReadBuf(baro->busDev, BMP388_DATA_0_REG, sensor_data, BMP388_DATA_FRAME_SIZE + 1);
if (baro->busDev->busType == BUSTYPE_SPI) {
// In SPI mode, first byte read is a dummy byte
busReadBuf(baro->busDev, BMP388_DATA_0_REG, &sensor_data[0], BMP388_DATA_FRAME_SIZE + 1);
} else {
// In I2C mode, no dummy byte is read
busReadBuf(baro->busDev, BMP388_DATA_0_REG, &sensor_data[1], BMP388_DATA_FRAME_SIZE);
}
bmp388_up = sensor_data[1] << 0 | sensor_data[2] << 8 | sensor_data[3] << 16;
bmp388_ut = sensor_data[4] << 0 | sensor_data[5] << 8 | sensor_data[6] << 16;
@ -289,14 +295,26 @@ STATIC_UNIT_TESTED bool bmp388Calculate(baroDev_t *baro, int32_t *pressure, int3
#define DETECTION_MAX_RETRY_COUNT 5
static bool deviceDetect(busDevice_t * busDev)
{
for (int retry = 0; retry < DETECTION_MAX_RETRY_COUNT; retry++) {
uint8_t chipId[2];
uint8_t chipId[2];
uint8_t nRead;
uint8_t * pId;
if (busDev->busType == BUSTYPE_SPI) {
// In SPI mode, first byte read is a dummy byte
nRead = 2;
pId = &chipId[1];
} else {
// In I2C mode, no dummy byte is read
nRead = 1;
pId = &chipId[0];
}
for (int retry = 0; retry < DETECTION_MAX_RETRY_COUNT; retry++) {
delay(100);
bool ack = busReadBuf(busDev, BMP388_CHIP_ID_REG, chipId, 2);
bool ack = busReadBuf(busDev, BMP388_CHIP_ID_REG, chipId, nRead);
if (ack && chipId[1] == BMP388_DEFAULT_CHIP_ID) {
if (ack && *pId == BMP388_DEFAULT_CHIP_ID) {
return true;
}
};
@ -318,11 +336,16 @@ bool bmp388Detect(baroDev_t *baro)
return false;
}
uint8_t calibration_buf[sizeof(bmp388_calib_param_t) + 1];
// read calibration
busReadBuf(baro->busDev, BMP388_TRIMMING_NVM_PAR_T1_LSB_REG, calibration_buf, sizeof(bmp388_calib_param_t) + 1);
memcpy(&bmp388_cal, calibration_buf + 1, sizeof(bmp388_calib_param_t));
if (baro->busDev->busType == BUSTYPE_SPI) {
// In SPI mode, first byte read is a dummy byte
uint8_t calibration_buf[sizeof(bmp388_calib_param_t) + 1];
busReadBuf(baro->busDev, BMP388_TRIMMING_NVM_PAR_T1_LSB_REG, calibration_buf, sizeof(bmp388_calib_param_t) + 1);
memcpy(&bmp388_cal, calibration_buf + 1, sizeof(bmp388_calib_param_t));
} else {
// In I2C mode, no dummy byte is read
busReadBuf(baro->busDev, BMP388_TRIMMING_NVM_PAR_T1_LSB_REG, (uint8_t*)&bmp388_cal, sizeof(bmp388_calib_param_t));
}
// set oversampling + power mode (forced), and start sampling
busWrite(baro->busDev, BMP388_OSR_REG,

View file

@ -76,14 +76,10 @@ typedef enum {
DEVHW_NONE = 0,
/* Dedicated ACC chips */
DEVHW_BMA280,
DEVHW_ADXL345,
DEVHW_MMA8452,
DEVHW_LSM303DLHC,
/* Dedicated GYRO chips */
DEVHW_L3GD20,
DEVHW_L3G4200,
/* Combined ACC/GYRO chips */
DEVHW_MPU3050,
@ -94,6 +90,8 @@ typedef enum {
DEVHW_BMI088_GYRO,
DEVHW_BMI088_ACC,
DEVHW_ICM20689,
DEVHW_ICM42605,
DEVHW_BMI270,
/* Combined ACC/GYRO/MAG chips */
DEVHW_MPU9250,
@ -119,6 +117,8 @@ typedef enum {
DEVHW_MAG3110,
DEVHW_LIS3MDL,
DEVHW_RM3100,
DEVHW_VCM5883,
DEVHW_MLX90393,
/* Temp sensor chips */
DEVHW_LM75_0,
@ -138,10 +138,10 @@ typedef enum {
/* Rangefinder modules */
DEVHW_SRF10,
DEVHW_HCSR04_I2C, // DIY-style adapter
DEVHW_VL53L0X,
DEVHW_VL53L1X,
DEVHW_US42,
DEVHW_TOF10120_I2C,
/* Other hardware */
DEVHW_MS4525, // Pitot meter

View file

@ -87,7 +87,7 @@ typedef struct i2cBusState_s {
I2CDevice device;
bool initialized;
i2cState_t state;
uint32_t timeout;
timeUs_t timeout;
/* Active transfer */
bool allowRawAccess;

View file

@ -121,7 +121,7 @@ typedef struct i2cBusState_s {
I2CDevice device;
bool initialized;
i2cState_t state;
uint32_t timeout;
timeUs_t timeout;
/* Active transfer */
bool allowRawAccess;

View file

@ -0,0 +1,176 @@
/*
* This file is part of iNav.
*
* iNav is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* iNav is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with iNav. If not, see <http://www.gnu.org/licenses/>.
*/
#include "platform.h"
#ifdef USE_MAG_MLX90393
#include <stdbool.h>
#include <stdint.h>
#include <math.h>
#include "build/debug.h"
#include "common/axis.h"
#include "common/maths.h"
#include "common/utils.h"
#include "drivers/time.h"
#include "drivers/io.h"
#include "drivers/bus.h"
#include "drivers/sensor.h"
#include "drivers/compass/compass.h"
#define MLX90393_MEASURE_3D 0b00001110
#define MLX90393_NOP 0b00000000
#define MLX90393_START_BURST_MODE 0b00010000 //uses with zyxt flags
#define MLX90393_START_WAKE_UP_ON_CHANGE_MODE 0b00100000 //uses with zyxt flags
#define MLX90393_START_SINGLE_MEASUREMENT_MODE 0b00110000 //uses with zyxt flags
#define MLX90393_READ_MEASUREMENT 0b01000000 //uses with zyxt flags
#define MLX90393_READ_REGISTER 0b01010000
#define MLX90393_WRITE_REGISTER 0b01100000
#define MLX90393_EXIT_MODE 0b10000000
#define MLX90393_MEMORY_RECALL 0b11010000
#define MLX90393_MEMORY_STORE 0b11100000
#define MLX90393_RESET 0b11110000
#define MLX90393_BURST_MODE_FLAG 0b10000000
#define MLX90393_WAKE_UP_ON_CHANGE_MODE_FLAG 0b01000000
#define MLX90393_SINGLE_MEASUREMENT_MODE_FLAG 0b00100000
#define MLX90393_ERROR_FLAG 0b00010000
#define MLX90393_SINGLE_ERROR_DETECTION_FLAG 0b00001000
#define MLX90393_RESET_FLAG 0b00000100
#define MLX90393_D1_FLAG 0b00000010
#define MLX90393_D0_FLAG 0b00000001
#define DETECTION_MAX_RETRY_COUNT 5
#define REG_BUF_LEN 3
// Register 1
#define GAIN_SEL_HALLCONF_REG 0x0 //from datasheet 0x0 << 2 = 0x0
// GAIN - 0b111
// Hall_conf - 0xC
#define GAIN_SEL_HALLCONF_REG_VALUE 0x007C
// Register 2
#define TCMP_EN_REG 0x4 //from datasheet 0x1 << 2 = 0x4
// Burst Data Rate 0b000100
#define TCMP_EN_REG_VALUE 0x62C4
// Register 3
#define RES_XYZ_OSR_FLT_REG 0x8 //from datasheet 0x2 << 2 = 0x8
// Oversampling 0b01
// Filtering 0b111
#define RES_XYZ_OSR_FLT_REG_VALUE 0x001D
static void mlx90393WriteRegister(magDev_t * mag, uint8_t reg_val, uint16_t value) {
uint8_t buf[REG_BUF_LEN] = {0};
buf[0] = (value >> 8) & 0xFF;
buf[1] = (value >> 0) & 0xFF;
buf[2] = reg_val;
busWriteBuf(mag->busDev, MLX90393_WRITE_REGISTER, buf, REG_BUF_LEN);
// PAUSE
delay(20);
// To skip ACK FLAG of Write
uint8_t sig = 0;
busRead(mag->busDev, MLX90393_NOP, &sig);
return;
}
// =======================================================================================
static bool mlx90393Read(magDev_t * mag)
{
uint8_t buf[7] = {0};
busReadBuf(mag->busDev, MLX90393_READ_MEASUREMENT | MLX90393_MEASURE_3D, buf, 7);
mag->magADCRaw[X] = ((short)(buf[1] << 8 | buf[2]));
mag->magADCRaw[Y] = ((short)(buf[3] << 8 | buf[4]));
mag->magADCRaw[Z] = ((short)(buf[5] << 8 | buf[6]));
return true;
}
static bool deviceDetect(magDev_t * mag)
{
for (int retryCount = 0; retryCount < DETECTION_MAX_RETRY_COUNT; retryCount++) {
uint8_t sig = 0;
bool ack = busRead(mag->busDev, MLX90393_RESET, &sig);
delay(20);
if (ack && ((sig & MLX90393_RESET_FLAG) == MLX90393_RESET_FLAG)) { // Check Reset Flag -> MLX90393
return true;
}
}
return false;
}
//--------------------------------------------------
static bool mlx90393Init(magDev_t * mag)
{
uint8_t sig = 0;
delay(20);
// Remove reset flag
busRead(mag->busDev, MLX90393_NOP, &sig);
// Exit if already in burst mode. (For example when external i2c source power the bus.)
busRead(mag->busDev, MLX90393_EXIT_MODE, &sig);
// Writing Registers
mlx90393WriteRegister(mag, GAIN_SEL_HALLCONF_REG, GAIN_SEL_HALLCONF_REG_VALUE);
mlx90393WriteRegister(mag, TCMP_EN_REG, TCMP_EN_REG_VALUE);
mlx90393WriteRegister(mag, RES_XYZ_OSR_FLT_REG, RES_XYZ_OSR_FLT_REG_VALUE);
// Start burst mode
busRead(mag->busDev, MLX90393_START_BURST_MODE | MLX90393_MEASURE_3D, &sig);
return true;
}
// ==========================================================================
bool mlx90393Detect(magDev_t * mag)
{
mag->busDev = busDeviceInit(BUSTYPE_ANY, DEVHW_MLX90393, mag->magSensorToUse, OWNER_COMPASS);
if (mag->busDev == NULL) {
return false;
}
if (!deviceDetect(mag)) {
busDeviceDeInit(mag->busDev);
return false;
}
mag->init = mlx90393Init;
mag->read = mlx90393Read;
return true;
}
#endif

View file

@ -1,20 +1,20 @@
/*
* This file is part of Cleanflight.
* This file is part of iNav.
*
* Cleanflight is free software: you can redistribute it and/or modify
* iNav is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Cleanflight is distributed in the hope that it will be useful,
* iNav is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
* along with iNav. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
bool bma280Detect(accDev_t *acc);
bool mlx90393Detect(magDev_t* mag);

Some files were not shown because too many files have changed in this diff Show more