Compare commits

...

105 commits

Author SHA1 Message Date
Dominic Clifton 98f7549aa4 Fix serial command handling of telemetry baud rates. Set min blackbox
bad rate to be 19200 to match the confiurator.
2015-05-31 12:36:10 +01:00
Dominic Clifton ca22fb0ee3 Replace CLI serial port configuration code with a new serial command.
This is done to make it clearer in configuration dumps which ports are
enabled and configured.

There is a nice code size reduction due to less strings being needed.

Serial documentation updated.

Closes #966.
2015-05-31 11:50:58 +01:00
Dominic Clifton 27db9ad0fe Merge pull request #945 from inkonova/v1.8.1-mixerFix
removed multiple declaration of function mixerUseConfigs
2015-05-30 07:27:33 +01:00
Dominic Clifton 6f3c16fe6c Reducing the maximum number of mode ranges from 40 to 20 to free up some
configuration storage space.
2015-05-30 00:03:56 +01:00
Dominic Clifton e6733b4dfc Cleanup status indicator code.
This primarily is to avaoid stalling the main loop when beeping and
flashing.

This is needed because oneshot ESCs do not receive updates when the main
loop is stalled.

Additionally the beeper code for sticks held in disarm position is
changed since it also clashed with profile selection.  Now profile
selections can be seen and heard clearly.

Other subsections of the system that changed the LED0 state while the
main loop is running have been updated to use the status indicator API
instead of blindly hitting the hardware which previously caused lots of
odd LED flashing behaviour - now it is consistent.
2015-05-29 23:37:33 +01:00
Dominic Clifton 22a98af25a Removing unnecessary idlePulse parameter from pwmOneshotMotorConfig. 2015-05-29 20:36:43 +01:00
Dominic Clifton 0c1a6c5c2f Merge branch 'lock_active_features' of https://github.com/ProDrone/cleanflight into ProDrone-lock_active_features
Conflicts:
	src/test/unit/rc_controls_unittest.cc
2015-05-29 20:05:25 +01:00
Dominic Clifton 25fe9f73df Adding note about GCC version for unit tests in the Developer docs. 2015-05-29 19:53:21 +01:00
Dominic Clifton c29900f012 Fix compilation of tests on Cygwin. Tested with GCC 4.9.2. 2015-05-29 19:51:01 +01:00
Dominic Clifton 36c8b482d1 Re-order initialisers to be the same as the structure declation to avoid
GCC compilation error.

Error message is: "sorry, unimplemented: non-trivial designated
initializers not supported"
2015-05-29 19:49:01 +01:00
Dominic Clifton a54b073419 Re-enabling pthread for travis builds. 2015-05-29 19:16:22 +01:00
Dominic Clifton 41d737e29a Merge pull request #869 from SteveAmor/remove_tricopter_yaw_gyro_smoothing
Remove tricopter yaw gyro smoothing from imuUpdate
2015-05-29 15:39:02 +01:00
Dominic Clifton b194288668 Merge pull request #937 from MJ666/ALIENWII32_update
AlienWii32 updates
2015-05-29 15:30:38 +01:00
Dominic Clifton 704dcf46ba Fix all warnings when compiling unit tests.
Use C++11 for the C++ unit test code to make the tests easier to read.
Previously we were using a 17 year old standard (!) (g++98)

GoogleTest is compiled with some additional flags to avoid some specific
warnings.  Consider enabling the warnings when upgrading GoogleTest.

See https://code.google.com/p/googletest/issues/detail?id=433

Closes #941
2015-05-29 15:26:10 +01:00
Dominic Clifton 0df22f8049 Remove some test duplication in RcControls unit rest by using test
fixture classes.
2015-05-29 14:41:27 +01:00
Dominic Clifton dcc54a9aec Remove duplicate const keywords which were generating warnings when
compiling unit tests.
2015-05-29 14:23:12 +01:00
Dominic Clifton 55180070d6 Merge pull request #964 from nzmichaelh/more-const
various: optimise RAM and flash usage
2015-05-29 11:13:41 +01:00
Michael Hope c9349ce83b msp: rework the different size encoders.
Tidy the encoders up.  Reduce the code size stacking the encoders for
different sizes.

Signed-off-by: Michael Hope <mlhx@google.com>
2015-05-29 05:42:22 +02:00
Michael Hope 31f933ac21 various: mark more constant data so it goes into flash instead of RAM.
Signed-off-by: Michael Hope <mlhx@google.com>
2015-05-29 05:42:08 +02:00
Dominic Clifton a7d347689d Merge pull request #953 from enly1/Telemetry_Switch_Fix
Telemetry_Switch TELEMETRY_BOX conditional logic incorrect
2015-05-28 23:36:20 +01:00
Dominic Clifton 70cda73add Update port identifier for Naze32. Add basic documentation of the Paris
Air Hero 32 board.
2015-05-28 14:07:32 +01:00
Dominic Clifton c37454ca3a Add note explaining that the softserial feature must be enabled to allow
configuration of softserial ports.  Fix some typos.
2015-05-28 14:06:37 +01:00
Nicholas Sherlock 3ddea2a849 Fix blackbox baudrate upper bound on CLI
Closes #960
2015-05-28 14:27:49 +12:00
enly1 [Simon Love] 7df9f7d0d5 Telemetry_Switch TELEMETRY_BOX conditional logic incorrect - corrected so TELEMETRY_BOX now available in GUI with telemetry_switch=1 2015-05-26 20:43:05 +01:00
Mauro Mombelli 51a067db6d removed mixerUseConfigs multile declaration 2015-05-23 20:24:07 +02:00
Dominic Clifton 93454d82a7 Updating sonar docs - adding a note that sonar is not available on the
CC3D OPBL build.
2015-05-23 11:53:45 +01:00
Dominic Clifton 0257cb0541 CC3D - Disable SONAR support on OPBL builds due to code size. 2015-05-23 11:49:48 +01:00
Dominic Clifton 4ed6fdfea5 CC3D - Add sonar.
This also ensures that the PWM mapping does not use the sonar pins when
sonar is enabled in a board agnostic way.
Conflicts:
	src/main/config/config.c
	src/main/drivers/pwm_mapping.h
	src/main/main.c
	src/main/target/CC3D/target.h
2015-05-22 22:35:41 +01:00
Dominic Clifton a370d60595 Support UART3 and I2C on Paris Air Hero 32 Flex port (aka Naze32_SP).
This change also allows serial ports to be removed at runtime.  e.g.
UART3 on Naze32 and SoftSerial 1 & 2 when softserial is not enabled.
2015-05-22 20:49:33 +01:00
Dominic Clifton f2013ab863 Merge pull request #936 from sherlockflight/blackbox-arm-beep
Fix Blackbox arming beep time logging
2015-05-22 14:02:54 +01:00
Michael Jakob c5ce2ff8c6 Fix typo in documentation 2015-05-22 12:13:17 +02:00
Michael Jakob 196a0f7369 Fix documentation links 2015-05-22 11:53:42 +02:00
Michael Jakob e3e55c64eb AlienWii32 updates
Updated configuration defaults
Documentation updates AlienWii and Spektrum bind
2015-05-22 11:18:35 +02:00
ProDrone bbb86b30fa Delayed motor PWM enable when using Oneshot 2015-05-22 00:30:29 +02:00
Dominic Clifton 11a4622a46 Adding attributions for some of the Graupner SumH code. 2015-05-21 23:10:00 +01:00
Dominic Clifton d9de29129e Fix missing use of doubles instead of floats in SumH code. 2015-05-21 23:04:45 +01:00
ProDrone d1d73d933e Always stop motor PWM prior to soft restart 2015-05-21 16:02:49 +02:00
ProDrone 655bd574c2 Added missing stuff to unittests 2015-05-21 14:16:22 +02:00
Nicholas Sherlock 94faf58e43 Update Blackbox docs to reflect new arming beep 2015-05-21 16:32:51 +12:00
Dominic Clifton 20a6f829d5 SPRacingF3 - Add support for airplane pwm mappings. 2015-05-21 02:02:33 +01:00
ProDrone a153302b48 Minor comment update. 2015-05-21 02:03:09 +02:00
ProDrone b75de91f35 Instead of trying to latch the desired features...
...and apply them after a soft reset (which also required an additional
write to flash), it is now such that features and settings are modified
and stored in flash as before.

After initialisation completes, the active features are latched and are
not to be modified until the next startup. This guarantees that all
saved modifications are persistent even when power is switched of
(without a reset in between).

When a soft reset is required, the active features and the currently
configured features are used to detect if the oneshot feature has
changed state, in which case motor PWM outputs are stopped and soft
reset is done after a 1.5 second delay.

During normal operation the active features will not change and all
changes to features ordered via MSP commands or the CLI are applied to
the configuration that gets saved to flash.

The required effect of modifying features without changing the actions
in the running mainloop is achieved. The user needs to be aware that
changes to features are not applied immidiatly.
2015-05-21 01:27:45 +02:00
Dominic Clifton 48570502cb Fixing missing pitch/roll rate inflight adjustment function
configuration settings.
2015-05-20 20:30:39 +01:00
Dominic Clifton adf0ca9fcf Cleanup Cli.md formatting. 2015-05-20 11:32:46 +01:00
Dominic Clifton 3077d115aa Updating documentation around rx_min_usec rx_max_usec and mode
ranges.
2015-05-20 11:11:27 +01:00
Dominic Clifton 321c3e4ed9 Adding notes about GPS and MAG sensor positioning. 2015-05-20 11:10:13 +01:00
Dominic Clifton 11eb0bf4d4 Update adding the new adjustment functions to the Inflight adjustments
documentation
2015-05-20 09:32:11 +01:00
Dominic Clifton 7a01bab50f Constrain invalid values by using rx_min_usec and rc_max_usec. Provide
sensible/fix min/max settings for those settings.

This fixes erratic flight behaviour before failsafe kicks in on SBus
receivers.

An X8R SBus RX in failsafe mode outputs 880 on all channels.

See #918 and #919
2015-05-20 00:28:52 +01:00
Dominic Clifton 22bf890cf0 Allow mixer to use failsafe throttle value that is less than
minthrottle.
2015-05-19 23:45:27 +01:00
Dominic Clifton d0a9d14b87 Allow CLI to be compiled out.
First cut, as proof-of-concept.  This allows CJMCU target to be built
without CLI and with Blackbox.
2015-05-19 23:42:41 +01:00
Dominic Clifton 67c6967da7 Ensure rx signal loss detection works for parallel pwm. 2015-05-19 22:48:05 +01:00
Dominic Clifton 23303198bb Update unit test for mixer behavior changed in
cc5c736362
2015-05-19 21:42:48 +01:00
Dominic Clifton 3a334c54fc Revert "Updating failsafe documentation to include details about how failsafe"
This reverts commit 5a05c19bb6.

Fixed by cc5c736362
2015-05-19 21:31:54 +01:00
Dominic Clifton 43a74f0d46 Merge pull request #917 from MJ666/yaw_jump_updates
Flight - Yaw jump updates
2015-05-19 21:20:48 +01:00
Dominic Clifton 33e0718884 Merge pull request #911 from borisbstyle/docs
PID1 Horizon Doc changed + TPA doc adjusted.
2015-05-19 21:20:26 +01:00
Dominic Clifton cc5c736362 Fix failsafe_throttle being ignored if it was less than min_check
when MOTOR_STOP was enabled.
2015-05-19 21:16:24 +01:00
Dominic Clifton 53eec05809 Avoid updating in-flight adjustments when not receiving rx data. 2015-05-19 20:44:01 +01:00
Dominic Clifton 26f2affd88 Ignore SBus end byte checking, this should improve compatibility with
some Futaba SBUS RX's that send telemetry data after SBus frames.  Fixes
#590
2015-05-19 19:41:15 +01:00
Dominic Clifton 5a05c19bb6 Updating failsafe documentation to include details about how failsafe
works in combination with other settings and when using failsafe in
conjunction with MOTOR_STOP.

See #912 and #488
2015-05-19 17:50:24 +01:00
Michael Jakob 0ef236a50a Another documentation update 2015-05-19 17:54:57 +02:00
Michael Jakob 50d5ec4e21 Fix typo in CLI.md 2015-05-19 17:47:06 +02:00
Michael Jakob 42218f1ea5 The yaw_p_limit minimum is now set to 100 to prevent misconfigurations.
Maximum value of 500 is now removing the limit (same as for
yaw_jump_prevention_limit)
Moving defines for PID controllers to headerfiles.
Some general code cleanup.
Documentation update
2015-05-19 17:42:03 +02:00
atomiclama 713e138c42 Changed idle pulse width from fixed 1ms to that configured.
Stops motors, that have none standard pulse ranges, from running up
after a save or exit from cli.
2015-05-19 16:02:27 +01:00
borisbstyle 73415be167 PID1 Horizon Doc changed + TPA doc adjusted. 2015-05-18 17:06:38 +02:00
Dominic Clifton 3037a91b06 Merge pull request #908 from datamafia/master
Doc edits I found and fixed while setting up some boards.
2015-05-18 09:08:30 +01:00
Nicholas Sherlock 4e7b647c1e Fix missing blackbox logging of synchronisation beep 2015-05-18 18:57:50 +12:00
Dominic Clifton c174a52ebe Allow independent pitch and roll in-flight PID adjustment. Fixes #149. 2015-05-17 23:43:55 +01:00
Dominic Clifton c868d7177a Enabling travis apt cache. 2015-05-17 22:48:17 +01:00
Marc 34f1633306 insight on first 4 channels 2015-05-17 17:40:01 -04:00
Dominic Clifton e57c814e2a CJMCU - Disable cli playsound to save flash space. 2015-05-17 22:21:01 +01:00
Dominic Clifton 8427583ba8 Merge pull request #868 from SteveAmor/document_servo_low_pass_filter_Cli.md
Added servo low pass filtering to Cli.md
2015-05-17 21:36:56 +01:00
Dominic Clifton 85acf7dc1d Merge pull request #895 from borisbstyle/pid1-horizon
Fix for extreme D level term PID1 Horizon
2015-05-17 21:32:50 +01:00
Dominic Clifton 97700349b9 Merge pull request #898 from samcook/fix-fakeheading
Tidy up the fake lat/long heading tidyup
2015-05-17 21:30:33 +01:00
Dominic Clifton fd1724f3ab Merge pull request #900 from MasterZap/doc-f
Fix documentation about 16 channel S.Bus to be clearer.
2015-05-17 21:30:18 +01:00
Dominic Clifton 3dc675f24d Merge pull request #901 from MJ666/AlienWii_failsafe
Remove obsolate failsafe setting for the ALIENWII32 targets
2015-05-17 21:26:56 +01:00
Marc b073603707 verbiage 2015-05-17 15:17:10 -04:00
Marc ce1498da0d verbiage 2015-05-17 15:15:32 -04:00
Marc 356b8e2be2 Minor edit
TPA acronym, spelling error
2015-05-17 10:42:01 -04:00
Michael Jakob be0561c576 Not all AlienWii F3 variants have an voltage divider. Disable feature
VBAT by default.
2015-05-17 10:59:48 +02:00
Michael Jakob 7a3976e3a0 Set Spektrum 1024bit as default for better copatibility with entry level
transmitters
2015-05-17 10:57:35 +02:00
Steveis 6448b4b3d7 Replaced gyroData with gyroADC as they both contain the same value 2015-05-17 07:14:42 +01:00
Michael Jakob 088d136c7c Remove obsolate failsafe setting for the ALIENWII32 targets 2015-05-15 17:56:34 +02:00
borisbstyle 984eada98b PID1 Horizon sensitivity range increased 2015-05-15 15:28:03 +02:00
MasterZap e355463e26 Fix documentation about 16 channel S.Bus to be clearer.
The text mentioned the "Serial Chapter" which isn't really helping you at all (IMHO), I removed that. The stuff you actually want is just a few paragraphs down in the same document....
2015-05-15 14:45:17 +02:00
Sam Cook d6dc1f7bd8 Fix invocation of sendFakeLatLong() after 802218b77b.
Fix spelling in sendFakeLatLongThatAllowsHeadingDisplay function name.
2015-05-15 12:32:03 +01:00
Dominic Clifton dee68f5e4f Clarify Battery voltage detection statement in docs. Fixes #696. 2015-05-15 12:13:27 +01:00
borisbstyle 4bdc64bff9 Fix for extreme D level term PID1 Horizon 2015-05-15 02:16:46 +02:00
Dominic Clifton 19be109189 Merge pull request #890 from ProDrone/cli_processing_mod_1
Some mods to CLI command interpretation and output
2015-05-14 20:10:49 +01:00
Dominic Clifton 802218b77b Remove some logic and boolean arguments from FrSky GPS code. See
d58387c PR #855
2015-05-14 20:04:52 +01:00
Dominic Clifton d58387c44a Merge pull request #855 from samcook/frsky-heading
Frsky telemetry heading without GPS
2015-05-14 20:00:21 +01:00
Dominic Clifton 8174517789 Merge pull request #876 from SteveAmor/increment_pid_controllers
Corrected the number of pid controllers available
2015-05-14 19:56:46 +01:00
Dominic Clifton 0fa271a8a3 Merge pull request #875 from SteveAmor/update_fork
Git command to update your fork
2015-05-14 19:56:27 +01:00
Dominic Clifton d6a2042c55 Merge pull request #881 from sherlockflight/gimli-fix
Patch Gimli to fix underscores_inside_words in PDF manuals
2015-05-14 19:54:53 +01:00
Dominic Clifton cf4a552b94 Merge pull request #891 from borisbstyle/pid1-horizon
PID1 Horizon Mode Fixed
2015-05-14 19:31:45 +01:00
borisbstyle 3c1b678a37 Fix truncation in horizonstrength calculation 2015-05-14 20:00:35 +02:00
ProDrone 6d9394d783 Optimized comment stripper code (again) 2015-05-14 19:59:36 +02:00
ProDrone 0ee67a521b Optimized comment stripper code 2015-05-14 19:59:35 +02:00
ProDrone 1df9097e32 Added # to versionstring and strip comments
Prepended the version string with a # to avoid the CLI from interpreting
the version string as a command when pasting a dump file back (restore
in CLI).

Strip comments starting with `# comment` from lines. This is to allow
adding comments to CLI dumped backup files. For this i have an automated
addition of comments and/or manual comments by the user in mind.
2015-05-14 19:59:34 +02:00
borisbstyle 0b274cc6e8 PID1 Horizon Improved 2015-05-14 00:54:41 +02:00
Nicholas Sherlock 3b95ae49e9 Patch Gimli to fix underscores_inside_words in PDF manuals 2015-05-12 22:26:36 +12:00
Steveis c6c7c9f8ec Correct number of pid controllers available 2015-05-11 17:08:26 +01:00
Steveis 9dff3e2ce1 Git command to update your fork 2015-05-11 16:23:47 +01:00
Steveis 318592b063 Removed tricopter yaw gyro smoothing from imuUpdate 2015-05-10 11:02:44 +01:00
Steveis 359f42cfde Added servo low pass filtering to Cli.md 2015-05-10 10:31:37 +01:00
Sam Cook 6776f9c02d Send a (non-zero) fake location when GPS isn't present to enable display of compass heading on OpenTX 2015-05-08 18:20:56 +01:00
87 changed files with 1336 additions and 773 deletions

View file

@ -9,12 +9,20 @@ TARGET_FILE=obj/cleanflight_${TARGET}
if [ $RUNTESTS ] ; then
cd ./src/test && make test
# A hacky way of running the unit tests at the same time as the normal builds.
# A hacky way of building the docs at the same time as the normal builds.
elif [ $PUBLISHDOCS ] ; then
if [ $PUBLISH_URL ] ; then
sudo apt-get install zlib1g-dev libssl-dev wkhtmltopdf libxml2-dev libxslt-dev #ruby-rvm
rvmsudo gem install gimli
# Patch Gimli to fix underscores_inside_words
curl -L https://github.com/walle/gimli/archive/v0.5.9.tar.gz | tar zxf -
sed -i 's/).render(/, :no_intra_emphasis => true).render(/' gimli-0.5.9/ext/github_markup.rb
cd gimli-0.5.9/
gem build gimli.gemspec && rvmsudo gem install gimli
cd ../
./build_docs.sh

View file

@ -33,6 +33,8 @@ install:
before_script: arm-none-eabi-gcc --version
script: ./.travis.sh
cache: apt
notifications:
irc: "chat.freenode.net#cleanflight"
use_notice: true

View file

@ -444,6 +444,7 @@ CC3D_SRC = \
drivers/serial_softserial.c \
drivers/serial_uart.c \
drivers/serial_uart_stm32f10x.c \
drivers/sonar_hcsr04.c \
drivers/sound_beeper_stm32f10x.c \
drivers/system_stm32f10x.c \
drivers/timer.c \

View file

@ -7,7 +7,7 @@ Low battery warnings can:
* Help ensure you have time to safely land the aircraft
* Help maintain the life and safety of your LiPo/LiFe batteries, which should not be discharged below manufacturer recommendations
Minimum and maximum cell voltages can be set, and these voltages are used to detect the number of cells you are using.
Minimum and maximum cell voltages can be set, and these voltages are used to auto-detect the number of cells in the battery when it is first connected.
Per-cell monitoring is not supported, as we only use one ADC to read the battery voltage.

View file

@ -203,9 +203,9 @@ flight problems like vibration or PID setting issues.
The Blackbox starts recording data as soon as you arm your craft, and stops when you disarm.
If your craft has a buzzer attached, a short beep will be played when you arm and recording begins. You can later use
this beep to synchronize your recorded flight video with the rendered flight data log (the beep is shown as a blue line
in the flight data log, which you can sync against the beep in your recorded audio track).
If your craft has a buzzer attached, you can use Cleanflight's arming beep to synchronize your Blackbox log with your
flight video. Cleanflight's arming beep is a "long, short" pattern. The beginning of the first long beep will be shown
as a blue line in the flight data log, which you can sync against your recorded audio track.
You should wait a few seconds after disarming your craft to allow the Blackbox to finish saving its data.
@ -224,8 +224,9 @@ minutes.
![Dataflash tab in Configurator](Screenshots/blackbox-dataflash.png)
After downloading the log, be sure to erase the chip to make it ready for reuse by clicking the "erase flash" button.
If you try to start recording a new flight when the dataflash is already full, the Blackbox will not make its regular
arming beep and nothing will be recorded.
If you try to start recording a new flight when the dataflash is already full, Blackbox logging will be disabled and
nothing will be recorded.
## Converting logs to CSV or PNG
After your flights, you'll have a series of flight log files with a .TXT extension. You'll need to decode these with

View file

@ -1,13 +1,13 @@
# Board - AlienWii32 (ALIENWIIF1 and ALIENWIIF3 target)
The AlienWii32 is actually in prototype stage and only a few samples exist. There are two different variants and some more field testing with some users is ongoing. The information below is preliminary and will be updated as needed.
The AlienWii32 is actually in prototype stage and few samples exist. There are some different variants and field testing with some users is ongoing. The information below is preliminary and will be updated as needed.
Here are the hardware specifications:
- STM32F103CBT6 MCU (ALIENWIIF1)
- STM32F303CCT6 MCU (ALIENWIIF3)
- MPU6050 accelerometer/gyro sensor unit
- 8x 4.2A brushed ESCs, integrated, to run the strongest micro motors
- 4-8 x 4.2A brushed ESCs, integrated, to run the strongest micro motors
- extra-wide traces on the PCB, for maximum power throughput
- USB port, integrated
- (*) serial connection for external DSM2/DSMX sat receiver (e.g. Spektrum SAT, OrangeRx R100, Lemon RX or Deltang Rx31)
@ -16,11 +16,16 @@ Here are the hardware specifications:
- motor connections are at the corners for a clean look with reduced wiring
- dimensions: 29x33mm
- direct operation from an single cell lipoly battery
- 3.3V LDO power regulator (ALIENWIIF1 only)
- 3.3V buck-boost power converter (ALIENWIIF3 only)
- battery monitoring with an white LED for buzzer functionality (ALIENWIIF3 only)
- 3.3V LDO power regulator (older prototypes)
- 3.3V buck-boost power converter (newer prototypes and production versions)
- battery monitoring with an LED for buzzer functionality (actualy for an ALIENWIIF3 variant)
(*) Spektrum Compatible DSM2 satellites are supported out of the box. DSMX sat will work with DSM2 protocol with default settings (DSM2, 11bit, 11ms is preset).
(*) Spektrum Compatible DSM2 satellites are supported out of the box. DSMX sat will work with DSM2 protocol with default settings (DSM2, 11bit, 11ms is preset). This is chosen for maximum compatibility. For optimal connection it is recommended to adjust settings to match the capabilities of your transmitter and satellite receiver. If possible it is recommended to use the DSMX protocol since it is known as more reliable. Also to make use of additional channels you should adjust the following two parameters with the Cleanflight Configurator.
set serialrx_provider = 1 (0 for 1024bit, 1 for 2048bit)
set spektrum_sat_bind = 5
For more detail of the different bind modes please refer the [Spektrum Bind](Spektrum bind.md) document
Deltang receivers in serial mode will work like any other Spektrum satellite receiver (10bit, 22ms) only the bind process will be different.
@ -30,4 +35,4 @@ The pin layout for the ALIENWIIF1 is very similar to NAZE32 or the related clone
The AlienWii32 F1 board can be flashed like the Naze board or the related clones. All the different methods will work in the same way.
The AlienWii32 F3 board needs to be flashed via the USB port in DFU mode. Flashing via the Cleanflight GUI is not possible yet. The DFU mode can be activated via setting the BOOT0 jumper during power on of the board. The second method is to connect with an terminal program (i.e. Putty) to the board and enter the character "R" immediately after connecting. Details about the flashing process can be found in the related section of the Sparky documentation. The BOOT0 jumper should be removed and the board needs to be repowerd after firmware flashing. Please be aware, during reboot of the AlienWii F3 board, the GUI will disconnect and an manual reconnect is required.
The AlienWii32 F3 board needs to be flashed via the USB port in DFU mode. Flashing via the Cleanflight GUI is not possible yet. The DFU mode can be activated via setting the BOOT0 jumper during power on of the board. The second method is to connect with an terminal program (i.e. Putty) to the board and enter the character "R" immediately after connecting. Details about the flashing process can be found in the related section of the [Sparky](Board - Sparky.md) documentation. The BOOT0 jumper should be removed and the board needs to be repowerd after firmware flashing. Please be aware, during reboot of the AlienWii F3 board, the GUI will disconnect and an manual reconnect is required.

View file

@ -23,8 +23,8 @@ The 8 pin RC_Input connector has the following pinouts when used in RX_PPM/RX_SE
| 1 | Ground | |
| 2 | +5V | |
| 3 | PPM Input | Enable `feature RX_PPM` |
| 4 | SoftSerial1 TX | Enable `feature SOFTSERIAL` |
| 5 | SoftSerial1 RX | Enable `feature SOFTSERIAL` |
| 4 | SoftSerial1 TX / Sonar trigger | |
| 5 | SoftSerial1 RX / Sonar Echo | |
| 6 | Current | Enable `feature CURRENT_METER`. Connect to the output of a current sensor, 0v-3.3v input |
| 7 | Battery Voltage sensor | Enable `feature VBAT`. Connect to main battery using a voltage divider, 0v-3.3v input |
| 8 | RSSI | Enable `feature RSSI_ADC`. Connect to the output of a PWM-RSSI conditioner, 0v-3.3v input |

View file

@ -1,22 +1,22 @@
# Board - Naze32
The Naze32 target supports all Naze hardware revisions. Revison 4 and Revision 5 are used and
The Naze32 target supports all Naze hardware revisions. Revision 4 and 5 are used and
frequently flown by the primary maintainer. Previous Naze hardware revisions may have issues,
if found please report via the [github issue tracker](https://github.com/cleanflight/cleanflight/issues).
# Serial Ports
## Serial Ports
| Value | Identifier | RX | TX | Notes |
| ----- | ------------ | ---------- | ------------------ | ------------------------------------------------------------------------------------------- |
| 1 | USART1 | RX / PA10 | TX / PA9 / TELEM | TELEM output is always inverted (for FrSky). Internally connected to USB port via CP2102 IC |
| 2 | USART2 | RC4 / PA3 | RC3 / PA2 | |
| 3 | SOFTSERIAL1 | RC5 / PA6 | RC6 / PA7 | |
| 4 | SOFTSERIAL2 | RC7 / PB0 | RC8 / PB1 | |
| 4 | SOFTSERIAL1 | RC5 / PA6 | RC6 / PA7 | |
| 5 | SOFTSERIAL2 | RC7 / PB0 | RC8 / PB1 | |
* You cannot use USART1/TX/TELEM pins at the same time.
* You may encounter flashing problems if you have something connected to the RX/TX pins. Try disconnecting RX/TX.
# Pinouts
## Pinouts
The 10 pin RC I/O connector has the following pinouts when used in RX_PPM/RX_SERIAL mode.
@ -42,14 +42,14 @@ When SOFTSERIAL is enabled, LED_STRIP and CURRENT_METER are unavailable, but two
| 9 | 7 | SOFTSERIAL2 RX | |
| 10 | 8 | SOFTSERIAL2 TX | |
# Recovery
## Recovery
## Board
### Board
+ Short the two pads labelled 'Boot' **taking extra care not to touch the 5V pad**
+ Apply power to the board
+ Remove the short on the board
## Cleanflight configurator
### Cleanflight configurator
+ Select the correct hardware and the desired release of the Clearflight firmware
+ Put a check in the "No reboot sequence"
+ Flash firmware

View file

@ -0,0 +1,48 @@
# Board - Paris Air Hero 32 / Acro Naze 32 Mini
This board uses the same firmware as the Naze32 board.
## Sensors
MPU6500 via SPI interface.
## Ports
6 x 3pin ESC / Servo outputs
1 x 8pin JST connector (PPM/PWM/UART2)
1 x 4pin JST connector (UART3/I2C)
## Pinouts
The 10 pin RC I/O connector has the following pinouts when used in RX_PPM/RX_SERIAL mode.
From right to left when looking at the socket from the edge of the board.
| Pin | Function | Notes |
| --- | -------------- | -------------------------------- |
| 1 | Ground | |
| 2 | +5V | |
| 3 | RX_PPM | Enable `feature RX_PPM` |
| 4 | RSSI_ADC | Enable `feature RSSI_ADC`. Connect to the output of a PWM-RSSI conditioner, 0v-3.3v input |
| 5 | USART2 TX | |
| 6 | USART2 RX | Built-in inverter |
| 7 | LED_STRIP | Enable `feature LED_STRIP` |
| 8 | unused | |
When SOFTSERIAL is enabled, LED_STRIP and CURRENT_METER are unavailable, but one SoftSerial port is made available to use instead.
| Pin | Function | Notes |
| --- | -------------- | -------------------------------- |
| 7 | SOFTSERIAL1 RX | Enable `feature SOFTSERIAL` |
| 8 | SOFTSERIAL1 TX | |
## Serial Ports
| Value | Identifier | RX | TX | Notes |
| ----- | ------------ | ---------- | ------------------ | ------------------------------------------------------------------------------------------- |
| 1 | USART1 | RX / PA10 | TX / PA9 / TELEM | TELEM output is always inverted (for FrSky). Internally connected to USB port via CP2102 IC |
| 2 | USART2 | RC4 / PA3 | RC3 / PA2 | |
| 3 | USART3 | F3 / PB11 | F2 / PB10 | Flex port is configured as UART3 when port is configured |
| 4 | SOFTSERIAL1 | RC5 / PA6 | RC6 / PA7 | |

View file

@ -71,178 +71,181 @@ Re-apply any new defaults as desired.
## CLI Command Reference
| Command | Description |
|----------------|------------------------------------------------|
| adjrange | show/set adjustment ranges settings |
| aux | show/set aux settings |
| cmix | design custom mixer |
| color | configure colors |
| defaults | reset to defaults and reboot |
| dump | print configurable settings in a pastable form |
| exit | |
| feature | list or -val or val |
| get | get variable value |
| gpspassthrough | passthrough gps to serial |
| help | |
| led | configure leds |
| map | mapping of rc channel order |
| mixer | mixer name or list |
| motor | get/set motor output value |
| play_sound | index, or none for next |
| profile | index (0 to 2) |
| rateprofile | index (0 to 2) |
| save | save and reboot |
| set | name=value or blank or * for list |
| status | show system status |
| version | |
| `Command` | Description |
|------------------|------------------------------------------------|
| `adjrange` | show/set adjustment ranges settings |
| `aux` | show/set aux settings |
| `cmix` | design custom mixer |
| `color` | configure colors |
| `defaults` | reset to defaults and reboot |
| `dump` | print configurable settings in a pastable form |
| `exit` | |
| `feature` | list or -val or val |
| `get` | get variable value |
| `gpspassthrough` | passthrough gps to serial |
| `help` | |
| `led` | configure leds |
| `map` | mapping of rc channel order |
| `mixer` | mixer name or list |
| `motor` | get/set motor output value |
| `play_sound` | index, or none for next |
| `profile` | index (0 to 2) |
| `rateprofile` | index (0 to 2) |
| `save` | save and reboot |
| `set` | name=value or blank or * for list |
| `status` | show system status |
| `version` | |
## CLI Variable Reference
| Variable | Description/Units | Min | Max | Default | Type | Datatype |
|-------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------|--------|---------------|--------------|----------|
| looptime | This is the main loop time (in us). Changing this affects PID effect with some PID controllers (see PID section for details). Default of 3500us/285Hz should work for everyone. Setting it to zero does not limit loop time, so it will go as fast as possible. | 0 | 9000 | 3500 | Master | UINT16 |
| emf_avoidance | Default value is 0 for 72MHz processor speed. Setting this to 1 increases the processor speed, to move the 6th harmonic away from 432MHz. | 0 | 1 | 0 | Master | UINT8 |
| mid_rc | This is an important number to set in order to avoid trimming receiver/transmitter. Most standard receivers will have this at 1500, however Futaba transmitters will need this set to 1520. A way to find out if this needs to be changed, is to clear all trim/subtrim on transmitter, and connect to GUI. Note the value most channels idle at - this should be the number to choose. Once midrc is set, use subtrim on transmitter to make sure all channels (except throttle of course) are centered at midrc value. | 1200 | 1700 | 1500 | Master | UINT16 |
| min_check | These are min/max values (in us) which, when a channel is smaller (min) or larger (max) than the value will activate various RC commands, such as arming, or stick configuration. Normally, every RC channel should be set so that min = 1000us, max = 2000us. On most transmitters this usually means 125% endpoints. Default check values are 100us above/below this value. | 0 | 2000 | 1100 | Master | UINT16 |
| max_check | These are min/max values (in us) which, when a channel is smaller (min) or larger (max) than the value will activate various RC commands, such as arming, or stick configuration. Normally, every RC channel should be set so that min = 1000us, max = 2000us. On most transmitters this usually means 125% endpoints. Default check values are 100us above/below this value. | 0 | 2000 | 1900 | Master | UINT16 |
| rssi_channel | | 0 | 18 | 0 | Master | INT8 |
| rssi_scale | | 1 | 255 | 30 | Master | UINT8 |
| rssi_ppm_invert | | 0 | 1 | 0 | Master | UINT8 |
| input_filtering_mode | | 0 | 1 | 0 | Master | INT8 |
| min_throttle | These are min/max values (in us) that are sent to esc when armed. Defaults of 1150/1850 are OK for everyone, for use with AfroESC, they could be set to 1064/1864. | 0 | 2000 | 1150 | Master | UINT16 |
| max_throttle | These are min/max values (in us) that are sent to esc when armed. Defaults of 1150/1850 are OK for everyone, for use with AfroESC, they could be set to 1064/1864. | 0 | 2000 | 1850 | Master | UINT16 |
| min_command | This is the PWM value sent to ESCs when they are not armed. If ESCs beep slowly when powered up, try decreasing this value. It can also be used for calibrating all ESCs at once. | 0 | 2000 | 1000 | Master | UINT16 |
| servo_center_pulse | | 0 | 2000 | 1500 | Master | UINT16 |
| 3d_deadband_low | | 0 | 2000 | 1406 | Master | UINT16 |
| 3d_deadband_high | | 0 | 2000 | 1514 | Master | UINT16 |
| 3d_neutral | | 0 | 2000 | 1460 | Master | UINT16 |
| 3d_deadband_throttle | | 0 | 2000 | 50 | Master | UINT16 |
| motor_pwm_rate | Output frequency (in Hz) for motor pins. Defaults are 400Hz for motor. If setting above 500Hz, will switch to brushed (direct drive) motors mode. For example, setting to 8000 will use brushed mode at 8kHz switching frequency. Up to 32kHz is supported. Note, that in brushed mode, minthrottle is offset to zero. Default is 16000 for boards with brushed motors. | 50 | 32000 | 400 | Master | UINT16 |
| servo_pwm_rate | Output frequency (in Hz) servo pins. Default is 50Hz. When using tricopters or gimbal with digital servo, this rate can be increased. Max of 498Hz (for 500Hz pwm period), and min of 50Hz. Most digital servos will support for example 330Hz. | 50 | 498 | 50 | Master | UINT16 |
| retarded_arm | Disabled by default, enabling (setting to 1) allows disarming by throttle low + roll. This could be useful for mode-1 users and non-acro tricopters, where default arming by yaw could move tail servo too much. | 0 | 1 | 0 | Master | UINT8 |
| disarm_kill_switch | Enabled by default. Disarms the motors independently of throttle value. Setting to 0 reverts to the old behaviour of disarming only when the throttle is low. Only applies when arming and disarming with an AUX channel. | 0 | 1 | 1 | Master | UINT8 |
| auto_disarm_delay | | 0 | 60 | 5 | Master | UINT8 |
| small_angle | If the copter tilt angle exceed this value the copter will refuse to arm. default is 25°. | 0 | 180 | 25 | Master | UINT8 |
| pid_at_min_throttle | If enabled, the copter will process the pid algorithm at minimum throttle. Cannot be used when `retarded_arm` is enabled. | 0 | 1 | 1 | Master | UINT8 |
| flaps_speed | | 0 | 100 | 0 | Master | UINT8 |
| fixedwing_althold_dir | | -1 | 1 | 1 | Master | INT8 |
| reboot_character | | 48 | 126 | 82 | Master | UINT8 |
| gps_provider | | 0 | 1 | 0 | Master | UINT8 |
| gps_sbas_mode | | 0 | 4 | 0 | Master | UINT8 |
| gps_auto_config | | 0 | 1 | 1 | Master | UINT8 |
| gps_auto_baud | | 0 | 1 | 0 | Master | UINT8 |
| gps_pos_p | | 0 | 200 | 15 | Profile | UINT8 |
| gps_pos_i | | 0 | 200 | 0 | Profile | UINT8 |
| gps_pos_d | | 0 | 200 | 0 | Profile | UINT8 |
| gps_posr_p | | 0 | 200 | 34 | Profile | UINT8 |
| gps_posr_i | | 0 | 200 | 14 | Profile | UINT8 |
| gps_posr_d | | 0 | 200 | 53 | Profile | UINT8 |
| gps_nav_p | | 0 | 200 | 25 | Profile | UINT8 |
| gps_nav_i | | 0 | 200 | 33 | Profile | UINT8 |
| gps_nav_d | | 0 | 200 | 83 | Profile | UINT8 |
| gps_wp_radius | | 0 | 2000 | 200 | Profile | UINT16 |
| nav_controls_heading | | 0 | 1 | 1 | Profile | UINT8 |
| nav_speed_min | | 10 | 2000 | 100 | Profile | UINT16 |
| nav_speed_max | | 10 | 2000 | 300 | Profile | UINT16 |
| nav_slew_rate | | 0 | 100 | 30 | Profile | UINT8 |
| serialrx_provider | When feature SERIALRX is enabled, this allows connection to several receivers which output data via digital interface resembling serial. See RX section. | 0 | 6 | 0 | Master | UINT8 |
| spektrum_sat_bind | | 0 | 10 | 0 | Master | UINT8 |
| telemetry_switch | Which aux channel to use to change serial output & baud rate (MSP / Telemetry). It disables automatic switching to Telemetry when armed. | 0 | 1 | 0 | Master | UINT8 |
| telemetry_inversion | | 0 | 1 | 0 | Master | UINT8 |
| frsky_default_lattitude | | -90 | 90 | 0 | Master | FLOAT |
| frsky_default_longitude | | -180 | 180 | 0 | Master | FLOAT |
| frsky_coordinates_format | | 0 | 1 | 0 | Master | UINT8 |
| frsky_unit | | 0 | 1 | 0 | Master | UINT8 |
| battery_capacity | | 0 | 20000 | 0 | Master | UINT16 |
| vbat_scale | Result is Vbatt in 0.1V steps. 3.3V = ADC Vref, 4095 = 12bit adc, 110 = 11:1 voltage divider (10k:1k) x 10 for 0.1V. Adjust this slightly if reported pack voltage is different from multimeter reading. You can get current voltage by typing "status"" in cli." | 0 | 255 | 110 | Master | UINT8 |
| vbat_max_cell_voltage | Maximum voltage per cell, used for auto-detecting battery voltage in 0.1V units, default is 43 (4.3V) | 10 | 50 | 43 | Master | UINT8 |
| vbat_min_cell_voltage | Minimum voltage per cell, this triggers battery out alarms, in 0.1V units, default is 33 (3.3V) | 10 | 50 | 33 | Master | UINT8 |
| vbat_warning_cell_voltage | | 10 | 50 | 35 | Master | UINT8 |
| current_meter_scale | This sets the output voltage to current scaling for the current sensor in 0.1 mV/A steps. 400 is 40mV/A such as the ACS756 sensor outputs. 183 is the setting for the Überdistro with a 0.25mOhm shunt. | -10000 | 10000 | 400 | Master | INT16 |
| current_meter_offset | This sets the output offset voltage of the current sensor in millivolts. | 0 | 3300 | 0 | Master | UINT16 |
| multiwii_current_meter_output | Default current output via MSP is in 0.01A steps. Setting this to 1 causes output in default multiwii scaling (1mA steps). | 0 | 1 | None defined! | Master | UINT8 |
| current_meter_type | | 0 | 2 | 1 | Master | UINT8 |
| align_gyro | When running on non-default hardware or adding support for new sensors/sensor boards, these values are used for sensor orientation. Default of zero means the driver determines alignment (and this generally means it's configured for standard hardware). Default orientation of X forward, Y right, Z up is 1. After that, the numbers are as follows, and mean sensor is rotated. CW0_DEG=1, CW90_DEG=2, CW180_DEG=3, CW270_DEG=4, CW0_DEG_FLIP=5, CW90_DEG_FLIP=6, CW180_DEG_FLIP=7, CW270_DEG_FLIP=8. This should cover all orientations. When carefully understood, these values can also be used to rotate (in 90deg steps) or flip the board. | 0 | 8 | 0 | Master | UINT8 |
| align_acc | When running on non-default hardware or adding support for new sensors/sensor boards, these values are used for sensor orientation. Default of zero means the driver determines alignment (and this generally means it's configured for standard hardware). Default orientation of X forward, Y right, Z up is 1. After that, the numbers are as follows, and mean sensor is rotated. CW0_DEG=1, CW90_DEG=2, CW180_DEG=3, CW270_DEG=4, CW0_DEG_FLIP=5, CW90_DEG_FLIP=6, CW180_DEG_FLIP=7, CW270_DEG_FLIP=8. This should cover all orientations. When carefully understood, these values can also be used to rotate (in 90deg steps) or flip the board. | 0 | 8 | 0 | Master | UINT8 |
| align_mag | When running on non-default hardware or adding support for new sensors/sensor boards, these values are used for sensor orientation. Default of zero means the driver determines alignment (and this generally means it's configured for standard hardware). Default orientation of X forward, Y right, Z up is 1. After that, the numbers are as follows, and mean sensor is rotated. CW0_DEG=1, CW90_DEG=2, CW180_DEG=3, CW270_DEG=4, CW0_DEG_FLIP=5, CW90_DEG_FLIP=6, CW180_DEG_FLIP=7, CW270_DEG_FLIP=8. This should cover all orientations. When carefully understood, these values can also be used to rotate (in 90deg steps) or flip the board. | 0 | 8 | 0 | Master | UINT8 |
| align_board_roll | Arbitrary board rotation in degrees, to allow mounting it sideways / upside down / rotated etc | -180 | 360 | 0 | Master | INT16 |
| align_board_pitch | Arbitrary board rotation in degrees, to allow mounting it sideways / upside down / rotated etc | -180 | 360 | 0 | Master | INT16 |
| align_board_yaw | Arbitrary board rotation in degrees, to allow mounting it sideways / upside down / rotated etc | -180 | 360 | 0 | Master | INT16 |
| max_angle_inclination | This setting controls max inclination (tilt) allowed in angle (level) mode. default 500 (50 degrees). | 100 | 900 | 500 | Master | UINT16 |
| gyro_lpf | Hardware lowpass filter for gyro. Allowed values depend on the driver - For example MPU6050 allows 5,10,20,42,98,188,256Hz, while MPU3050 doesn't allow 5Hz. If you have to set gyro lpf below 42Hz generally means the frame is vibrating too much, and that should be fixed first. Values outside of supported range will usually be ignored by drivers, and will configure lpf to default value of 42Hz. | 0 | 256 | 42 | Master | UINT16 |
| moron_threshold | When powering up, gyro bias is calculated. If the model is shaking/moving during this initial calibration, offsets are calculated incorrectly, and could lead to poor flying performance. This threshold (default of 32) means how much average gyro reading could differ before re-calibration is triggered. | 0 | 128 | 32 | Master | UINT8 |
| gyro_cmpf_factor | This setting controls the Gyro Weight for the Gyro/Acc complementary filter. Increasing this value reduces and delays Acc influence on the output of the filter. | 100 | 1000 | 600 | Master | UINT16 |
| gyro_cmpfm_factor | This setting controls the Gyro Weight for the Gyro/Magnetometer complementary filter. Increasing this value reduces and delays the Magnetometer influence on the output of the filter. | 100 | 1000 | 250 | Master | UINT16 |
| alt_hold_deadband | | 1 | 250 | 40 | Profile | UINT8 |
| alt_hold_fast_change | | 0 | 1 | 1 | Profile | UINT8 |
| 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. | 0 | 32 | 0 | Profile | UINT8 |
| yaw_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. | 0 | 100 | 0 | Profile | UINT8 |
| throttle_correction_value | The throttle_correction_value will be added to the throttle input. It will be maximal at the throttle_correction_angle and over, null when the copter is leveled and proportional in bewteen. The angle is set with 0.1 deg steps from 1 to 900, ie : 300 = 30.0 deg, 225 = 22.5 deg. | 0 | 150 | 0 | Profile | UINT8 |
| throttle_correction_angle | The throttle_correction_value will be added to the throttle input. It will be maximal at the throttle_correction_angle and over, null when the copter is leveled and proportional in bewteen. The angle is set with 0.1 deg steps from 1 to 900, ie : 300 = 30.0 deg, 225 = 22.5 deg. | 1 | 900 | 800 | Profile | UINT16 |
| yaw_control_direction | | -1 | 1 | 1 | Master | INT8 |
| yaw_direction | | -1 | 1 | 1 | Profile | INT8 |
| yaw_jump_prevention_limit | Prevent yaw jumps during yaw stops. To disable set to 500. | 200 | 80 | 500 | Master | UINT16 |
| tri_unarmed_servo | On tricopter mix only, if this is set to 1, servo will always be correcting regardless of armed state. to disable this, set it to 0. | 0 | 1 | 1 | Profile | INT8 |
| default_rate_profile | Default = profile number | 0 | 2 | | Profile | UINT8 |
| rc_rate | | 0 | 250 | 90 | Rate Profile | UINT8 |
| rc_expo | | 0 | 100 | 65 | Rate Profile | UINT8 |
| rc_yaw_expo | | 0 | 100 | 0 | Rate Profile | UINT8 |
| thr_mid | | 0 | 100 | 50 | Rate Profile | UINT8 |
| thr_expo | | 0 | 100 | 0 | Rate Profile | UINT8 |
| roll_pitch_rate | | 0 | 100 | 0 | Rate Profile | UINT8 |
| yaw_rate | | 0 | 100 | 0 | Rate Profile | UINT8 |
| tpa_rate | Throttle PID attenuation reduces influence of P on ROLL and PITCH as throttle increases. For every 1% throttle after the TPA breakpoint, P is reduced by the TPA rate. | 0 | 100 | 0 | Rate Profile | UINT8 |
| tpa_breakpoint | See tpa_rate. | 1000 | 2000 | 1500 | Rate Profile | UINT16 |
| failsafe_delay | | 0 | 200 | 10 | Profile | UINT8 |
| failsafe_off_delay | | 0 | 200 | 200 | Profile | UINT8 |
| failsafe_throttle | | 1000 | 2000 | 1200 | Profile | UINT16 |
| rx_min_usec | | 100 | 2000 | 985 | Profile | UINT16 |
| rx_max_usec | | 100 | 3000 | 2115 | Profile | UINT16 |
| gimbal_flags | When feature SERVO_TILT is enabled, this can be a combination of the following numbers: 1=normal gimbal (default), 2=tiltmix gimbal, 4=in PPM (or SERIALRX) input mode, this will forward AUX1..4 RC inputs to PWM5..8 pins | 0 | 255 | 1 | Profile | UINT8 |
| acc_hardware | This is used to suggest which accelerometer driver should load, or to force no accelerometer in case gyro-only flight is needed. Default (0) will attempt to auto-detect among enabled drivers. Otherwise, to force a particular device, set it to 2 for ADXL345, 3 for MPU6050 integrated accelerometer, 4 for MMA8452, 5 for BMA280, 6 for LSM303DLHC, 7 for SPI_MPU6000, 8 for SPI_MPU6500 or 1 to disable accelerometer alltogether - resulting in gyro-only operation. | 0 | 9 | 0 | Master | UINT8 |
| acc_lpf_factor | This setting controls the Low Pass Filter factor for ACC. Increasing this value reduces ACC noise (visible in GUI), but would increase ACC lag time. Zero = no filter | 0 | 250 | 4 | Profile | UINT8 |
| accxy_deadband | | 0 | 100 | 40 | Profile | UINT8 |
| accz_deadband | | 0 | 100 | 40 | Profile | UINT8 |
| accz_lpf_cutoff | | 1 | 20 | 5 | Profile | FLOAT |
| acc_unarmedcal | | 0 | 1 | 1 | Profile | UINT8 |
| acc_trim_pitch | | -300 | 300 | 0 | Profile | INT16 |
| acc_trim_roll | | -300 | 300 | 0 | Profile | INT16 |
| baro_tab_size | | 0 | 48 | 21 | Profile | UINT8 |
| baro_noise_lpf | | 0 | 1 | 0.6 | Profile | FLOAT |
| baro_cf_vel | | 0 | 1 | 0.985 | Profile | FLOAT |
| baro_cf_alt | | 0 | 1 | 0.965 | Profile | FLOAT |
| mag_hardware | | 0 | 3 | 0 | Master | UINT8 |
| mag_declination | Current location magnetic declination in format. For example, -6deg 37min, = for Japan. Leading zero in ddd not required. Get your local magnetic declination here: http://magnetic-declination.com/ | -18000 | 18000 | 0 | Profile | INT16 |
| pid_controller | | 0 | 4 | 0 | Profile | UINT8 |
| p_pitch | | 0 | 200 | 40 | Profile | UINT8 |
| i_pitch | | 0 | 200 | 30 | Profile | UINT8 |
| d_pitch | | 0 | 200 | 23 | Profile | UINT8 |
| p_roll | | 0 | 200 | 40 | Profile | UINT8 |
| i_roll | | 0 | 200 | 30 | Profile | UINT8 |
| d_roll | | 0 | 200 | 23 | Profile | UINT8 |
| p_yaw | | 0 | 200 | 85 | Profile | UINT8 |
| i_yaw | | 0 | 200 | 45 | Profile | UINT8 |
| d_yaw | | 0 | 200 | 0 | Profile | UINT8 |
| p_pitchf | | 0 | 100 | 2.5 | Profile | FLOAT |
| i_pitchf | | 0 | 100 | 0.6 | Profile | FLOAT |
| d_pitchf | | 0 | 100 | 0.06 | Profile | FLOAT |
| p_rollf | | 0 | 100 | 2.5 | Profile | FLOAT |
| i_rollf | | 0 | 100 | 0.6 | Profile | FLOAT |
| d_rollf | | 0 | 100 | 0.06 | Profile | FLOAT |
| p_yawf | | 0 | 100 | 8 | Profile | FLOAT |
| i_yawf | | 0 | 100 | 0.5 | Profile | FLOAT |
| d_yawf | | 0 | 100 | 0.05 | Profile | FLOAT |
| level_horizon | | 0 | 10 | 3 | Profile | FLOAT |
| level_angle | | 0 | 10 | 5 | Profile | FLOAT |
| sensitivity_horizon | | 0 | 250 | 75 | Profile | UINT8 |
| p_alt | | 0 | 200 | 50 | Profile | UINT8 |
| i_alt | | 0 | 200 | 0 | Profile | UINT8 |
| d_alt | | 0 | 200 | 0 | Profile | UINT8 |
| p_level | | 0 | 200 | 90 | Profile | UINT8 |
| i_level | | 0 | 200 | 10 | Profile | UINT8 |
| d_level | | 0 | 200 | 100 | Profile | UINT8 |
| p_vel | | 0 | 200 | 120 | Profile | UINT8 |
| i_vel | | 0 | 200 | 45 | Profile | UINT8 |
| d_vel | | 0 | 200 | 1 | Profile | UINT8 |
| blackbox_rate_num | | 1 | 32 | 1 | Master | UINT8 |
| blackbox_rate_denom | | 1 | 32 | 1 | Master | UINT8 |
| `Variable` | Description/Units | Min | Max | Default | Type | Datatype |
|---------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------|--------|---------------|--------------|----------|
| `looptime` | This is the main loop time (in us). Changing this affects PID effect with some PID controllers (see PID section for details). Default of 3500us/285Hz should work for everyone. Setting it to zero does not limit loop time, so it will go as fast as possible. | 0 | 9000 | 3500 | Master | UINT16 |
| `emf_avoidance` | Default value is 0 for 72MHz processor speed. Setting this to 1 increases the processor speed, to move the 6th harmonic away from 432MHz. | 0 | 1 | 0 | Master | UINT8 |
| `mid_rc` | This is an important number to set in order to avoid trimming receiver/transmitter. Most standard receivers will have this at 1500, however Futaba transmitters will need this set to 1520. A way to find out if this needs to be changed, is to clear all trim/subtrim on transmitter, and connect to GUI. Note the value most channels idle at - this should be the number to choose. Once midrc is set, use subtrim on transmitter to make sure all channels (except throttle of course) are centered at midrc value. | 1200 | 1700 | 1500 | Master | UINT16 |
| `min_check` | These are min/max values (in us) which, when a channel is smaller (min) or larger (max) than the value will activate various RC commands, such as arming, or stick configuration. Normally, every RC channel should be set so that min = 1000us, max = 2000us. On most transmitters this usually means 125% endpoints. Default check values are 100us above/below this value. | 0 | 2000 | 1100 | Master | UINT16 |
| `max_check` | These are min/max values (in us) which, when a channel is smaller (min) or larger (max) than the value will activate various RC commands, such as arming, or stick configuration. Normally, every RC channel should be set so that min = 1000us, max = 2000us. On most transmitters this usually means 125% endpoints. Default check values are 100us above/below this value. | 0 | 2000 | 1900 | Master | UINT16 |
| `rssi_channel` | | 0 | 18 | 0 | Master | INT8 |
| `rssi_scale` | | 1 | 255 | 30 | Master | UINT8 |
| `rssi_ppm_invert` | | 0 | 1 | 0 | Master | UINT8 |
| `input_filtering_mode` | | 0 | 1 | 0 | Master | INT8 |
| `min_throttle` | These are min/max values (in us) that are sent to esc when armed. Defaults of 1150/1850 are OK for everyone, for use with AfroESC, they could be set to 1064/1864. | 0 | 2000 | 1150 | Master | UINT16 |
| `max_throttle` | These are min/max values (in us) that are sent to esc when armed. Defaults of 1150/1850 are OK for everyone, for use with AfroESC, they could be set to 1064/1864. | 0 | 2000 | 1850 | Master | UINT16 |
| `min_command` | This is the PWM value sent to ESCs when they are not armed. If ESCs beep slowly when powered up, try decreasing this value. It can also be used for calibrating all ESCs at once. | 0 | 2000 | 1000 | Master | UINT16 |
| `servo_center_pulse` | | 0 | 2000 | 1500 | Master | UINT16 |
| `3d_deadband_low` | | 0 | 2000 | 1406 | Master | UINT16 |
| `3d_deadband_high` | | 0 | 2000 | 1514 | Master | UINT16 |
| `3d_neutral` | | 0 | 2000 | 1460 | Master | UINT16 |
| `3d_deadband_throttle` | | 0 | 2000 | 50 | Master | UINT16 |
| `motor_pwm_rate` | Output frequency (in Hz) for motor pins. Defaults are 400Hz for motor. If setting above 500Hz, will switch to brushed (direct drive) motors mode. For example, setting to 8000 will use brushed mode at 8kHz switching frequency. Up to 32kHz is supported. Note, that in brushed mode, minthrottle is offset to zero. Default is 16000 for boards with brushed motors. | 50 | 32000 | 400 | Master | UINT16 |
| `servo_pwm_rate` | Output frequency (in Hz) servo pins. Default is 50Hz. When using tricopters or gimbal with digital servo, this rate can be increased. Max of 498Hz (for 500Hz pwm period), and min of 50Hz. Most digital servos will support for example 330Hz. | 50 | 498 | 50 | Master | UINT16 |
| `servo_lowpass_freq` | Selects the servo PWM output cutoff frequency. Valid values range from 10 to 400. This is a fraction of the loop frequency in 1/1000ths. For example, `40` means `0.040`. The cutoff frequency can be determined by the following formula: `Frequency = 1000 * servo_lowpass_freq / looptime` | 10 | 400 | 400 | Master | INT16 |
| `servo_lowpass_enable` | Disabled by default. | 0 | 1 | 0 | Master | INT8 |
| `retarded_arm` | Disabled by default, enabling (setting to 1) allows disarming by throttle low + roll. This could be useful for mode-1 users and non-acro tricopters, where default arming by yaw could move tail servo too much. | 0 | 1 | 0 | Master | UINT8 |
| `disarm_kill_switch` | Enabled by default. Disarms the motors independently of throttle value. Setting to 0 reverts to the old behaviour of disarming only when the throttle is low. Only applies when arming and disarming with an AUX channel. | 0 | 1 | 1 | Master | UINT8 |
| `auto_disarm_delay` | | 0 | 60 | 5 | Master | UINT8 |
| `small_angle` | If the copter tilt angle exceed this value the copter will refuse to arm. default is 25°. | 0 | 180 | 25 | Master | UINT8 |
| `pid_at_min_throttle` | If enabled, the copter will process the pid algorithm at minimum throttle. Cannot be used when `retarded_arm` is enabled. | 0 | 1 | 1 | Master | UINT8 |
| `flaps_speed` | | 0 | 100 | 0 | Master | UINT8 |
| `fixedwing_althold_dir` | | -1 | 1 | 1 | Master | INT8 |
| `reboot_character` | | 48 | 126 | 82 | Master | UINT8 |
| `gps_provider` | | 0 | 1 | 0 | Master | UINT8 |
| `gps_sbas_mode` | | 0 | 4 | 0 | Master | UINT8 |
| `gps_auto_config` | | 0 | 1 | 1 | Master | UINT8 |
| `gps_auto_baud` | | 0 | 1 | 0 | Master | UINT8 |
| `gps_pos_p` | | 0 | 200 | 15 | Profile | UINT8 |
| `gps_pos_i` | | 0 | 200 | 0 | Profile | UINT8 |
| `gps_pos_d` | | 0 | 200 | 0 | Profile | UINT8 |
| `gps_posr_p` | | 0 | 200 | 34 | Profile | UINT8 |
| `gps_posr_i` | | 0 | 200 | 14 | Profile | UINT8 |
| `gps_posr_d` | | 0 | 200 | 53 | Profile | UINT8 |
| `gps_nav_p` | | 0 | 200 | 25 | Profile | UINT8 |
| `gps_nav_i` | | 0 | 200 | 33 | Profile | UINT8 |
| `gps_nav_d` | | 0 | 200 | 83 | Profile | UINT8 |
| `gps_wp_radius` | | 0 | 2000 | 200 | Profile | UINT16 |
| `nav_controls_heading` | | 0 | 1 | 1 | Profile | UINT8 |
| `nav_speed_min` | | 10 | 2000 | 100 | Profile | UINT16 |
| `nav_speed_max` | | 10 | 2000 | 300 | Profile | UINT16 |
| `nav_slew_rate` | | 0 | 100 | 30 | Profile | UINT8 |
| `serialrx_provider` | When feature SERIALRX is enabled, this allows connection to several receivers which output data via digital interface resembling serial. See RX section. | 0 | 6 | 0 | Master | UINT8 |
| `spektrum_sat_bind` | | 0 | 10 | 0 | Master | UINT8 |
| `telemetry_switch` | Which aux channel to use to change serial output & baud rate (MSP / Telemetry). It disables automatic switching to Telemetry when armed. | 0 | 1 | 0 | Master | UINT8 |
| `telemetry_inversion` | | 0 | 1 | 0 | Master | UINT8 |
| `frsky_default_lattitude` | | -90 | 90 | 0 | Master | FLOAT |
| `frsky_default_longitude` | | -180 | 180 | 0 | Master | FLOAT |
| `frsky_coordinates_format` | | 0 | 1 | 0 | Master | UINT8 |
| `frsky_unit` | | 0 | 1 | 0 | Master | UINT8 |
| `battery_capacity` | | 0 | 20000 | 0 | Master | UINT16 |
| `vbat_scale` | Result is Vbatt in 0.1V steps. 3.3V = ADC Vref, 4095 = 12bit adc, 110 = 11:1 voltage divider (10k:1k) x 10 for 0.1V. Adjust this slightly if reported pack voltage is different from multimeter reading. You can get current voltage by typing "status"" in cli." | 0 | 255 | 110 | Master | UINT8 |
| `vbat_max_cell_voltage` | Maximum voltage per cell, used for auto-detecting battery voltage in 0.1V units, default is 43 (4.3V) | 10 | 50 | 43 | Master | UINT8 |
| `vbat_min_cell_voltage` | Minimum voltage per cell, this triggers battery out alarms, in 0.1V units, default is 33 (3.3V) | 10 | 50 | 33 | Master | UINT8 |
| `vbat_warning_cell_voltage` | | 10 | 50 | 35 | Master | UINT8 |
| `current_meter_scale` | This sets the output voltage to current scaling for the current sensor in 0.1 mV/A steps. 400 is 40mV/A such as the ACS756 sensor outputs. 183 is the setting for the Überdistro with a 0.25mOhm shunt. | -10000 | 10000 | 400 | Master | INT16 |
| `current_meter_offset` | This sets the output offset voltage of the current sensor in millivolts. | 0 | 3300 | 0 | Master | UINT16 |
| `multiwii_current_meter_output` | Default current output via MSP is in 0.01A steps. Setting this to 1 causes output in default multiwii scaling (1mA steps). | 0 | 1 | None defined! | Master | UINT8 |
| `current_meter_type` | | 0 | 2 | 1 | Master | UINT8 |
| `align_gyro` | When running on non-default hardware or adding support for new sensors/sensor boards, these values are used for sensor orientation. Default of zero means the driver determines alignment (and this generally means it's configured for standard hardware). Default orientation of X forward, Y right, Z up is 1. After that, the numbers are as follows, and mean sensor is rotated. CW0_DEG=1, CW90_DEG=2, CW180_DEG=3, CW270_DEG=4, CW0_DEG_FLIP=5, CW90_DEG_FLIP=6, CW180_DEG_FLIP=7, CW270_DEG_FLIP=8. This should cover all orientations. When carefully understood, these values can also be used to rotate (in 90deg steps) or flip the board. | 0 | 8 | 0 | Master | UINT8 |
| `align_acc` | When running on non-default hardware or adding support for new sensors/sensor boards, these values are used for sensor orientation. Default of zero means the driver determines alignment (and this generally means it's configured for standard hardware). Default orientation of X forward, Y right, Z up is 1. After that, the numbers are as follows, and mean sensor is rotated. CW0_DEG=1, CW90_DEG=2, CW180_DEG=3, CW270_DEG=4, CW0_DEG_FLIP=5, CW90_DEG_FLIP=6, CW180_DEG_FLIP=7, CW270_DEG_FLIP=8. This should cover all orientations. When carefully understood, these values can also be used to rotate (in 90deg steps) or flip the board. | 0 | 8 | 0 | Master | UINT8 |
| `align_mag` | When running on non-default hardware or adding support for new sensors/sensor boards, these values are used for sensor orientation. Default of zero means the driver determines alignment (and this generally means it's configured for standard hardware). Default orientation of X forward, Y right, Z up is 1. After that, the numbers are as follows, and mean sensor is rotated. CW0_DEG=1, CW90_DEG=2, CW180_DEG=3, CW270_DEG=4, CW0_DEG_FLIP=5, CW90_DEG_FLIP=6, CW180_DEG_FLIP=7, CW270_DEG_FLIP=8. This should cover all orientations. When carefully understood, these values can also be used to rotate (in 90deg steps) or flip the board. | 0 | 8 | 0 | Master | UINT8 |
| `align_board_roll` | Arbitrary board rotation in degrees, to allow mounting it sideways / upside down / rotated etc | -180 | 360 | 0 | Master | INT16 |
| `align_board_pitch` | Arbitrary board rotation in degrees, to allow mounting it sideways / upside down / rotated etc | -180 | 360 | 0 | Master | INT16 |
| `align_board_yaw` | Arbitrary board rotation in degrees, to allow mounting it sideways / upside down / rotated etc | -180 | 360 | 0 | Master | INT16 |
| `max_angle_inclination` | This setting controls max inclination (tilt) allowed in angle (level) mode. default 500 (50 degrees). | 100 | 900 | 500 | Master | UINT16 |
| `gyro_lpf` | Hardware lowpass filter for gyro. Allowed values depend on the driver - For example MPU6050 allows 5,10,20,42,98,188,256Hz, while MPU3050 doesn't allow 5Hz. If you have to set gyro lpf below 42Hz generally means the frame is vibrating too much, and that should be fixed first. Values outside of supported range will usually be ignored by drivers, and will configure lpf to default value of 42Hz. | 0 | 256 | 42 | Master | UINT16 |
| `moron_threshold` | When powering up, gyro bias is calculated. If the model is shaking/moving during this initial calibration, offsets are calculated incorrectly, and could lead to poor flying performance. This threshold (default of 32) means how much average gyro reading could differ before re-calibration is triggered. | 0 | 128 | 32 | Master | UINT8 |
| `gyro_cmpf_factor` | This setting controls the Gyro Weight for the Gyro/Acc complementary filter. Increasing this value reduces and delays Acc influence on the output of the filter. | 100 | 1000 | 600 | Master | UINT16 |
| `gyro_cmpfm_factor` | This setting controls the Gyro Weight for the Gyro/Magnetometer complementary filter. Increasing this value reduces and delays the Magnetometer influence on the output of the filter. | 100 | 1000 | 250 | Master | UINT16 |
| `alt_hold_deadband` | | 1 | 250 | 40 | Profile | UINT8 |
| `alt_hold_fast_change` | | 0 | 1 | 1 | Profile | UINT8 |
| `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. | 0 | 32 | 0 | Profile | UINT8 |
| `yaw_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. | 0 | 100 | 0 | Profile | UINT8 |
| `throttle_correction_value` | The throttle_correction_value will be added to the throttle input. It will be maximal at the throttle_correction_angle and over, null when the copter is leveled and proportional in bewteen. The angle is set with 0.1 deg steps from 1 to 900, ie : 300 = 30.0 deg, 225 = 22.5 deg. | 0 | 150 | 0 | Profile | UINT8 |
| `throttle_correction_angle` | The throttle_correction_value will be added to the throttle input. It will be maximal at the throttle_correction_angle and over, null when the copter is leveled and proportional in bewteen. The angle is set with 0.1 deg steps from 1 to 900, ie : 300 = 30.0 deg, 225 = 22.5 deg. | 1 | 900 | 800 | Profile | UINT16 |
| `yaw_control_direction` | | -1 | 1 | 1 | Master | INT8 |
| `yaw_direction` | | -1 | 1 | 1 | Profile | INT8 |
| `yaw_jump_prevention_limit` | Prevent yaw jumps during yaw stops. To disable set to 500. | 200 | 80 | 500 | Master | UINT16 |
| `tri_unarmed_servo` | On tricopter mix only, if this is set to 1, servo will always be correcting regardless of armed state. to disable this, set it to 0. | 0 | 1 | 1 | Profile | INT8 |
| `default_rate_profile` | Default = profile number | 0 | 2 | | Profile | UINT8 |
| `rc_rate` | | 0 | 250 | 90 | Rate Profile | UINT8 |
| `rc_expo` | | 0 | 100 | 65 | Rate Profile | UINT8 |
| `rc_yaw_expo` | | 0 | 100 | 0 | Rate Profile | UINT8 |
| `thr_mid` | | 0 | 100 | 50 | Rate Profile | UINT8 |
| `thr_expo` | | 0 | 100 | 0 | Rate Profile | UINT8 |
| `roll_pitch_rate` | | 0 | 100 | 0 | Rate Profile | UINT8 |
| `yaw_rate` | | 0 | 100 | 0 | Rate Profile | UINT8 |
| `tpa_rate` | Throttle PID attenuation reduces influence of P on ROLL and PITCH as throttle increases. For every 1% throttle after the TPA breakpoint, P is reduced by the TPA rate. | 0 | 100 | 0 | Rate Profile | UINT8 |
| `tpa_breakpoint` | See tpa_rate. | 1000 | 2000 | 1500 | Rate Profile | UINT16 |
| `failsafe_delay` | | 0 | 200 | 10 | Profile | UINT8 |
| `failsafe_off_delay` | | 0 | 200 | 200 | Profile | UINT8 |
| `failsafe_throttle` | | 1000 | 2000 | 1200 | Profile | UINT16 |
| `rx_min_usec` | Defines the shortest pulse width value used when ensuring the channel value is valid. If the receiver gives a pulse value lower than this value then the channel will be marked as bad and will default to the value of `mid_rc`. | 100 | 2000 | 985 | Profile | UINT16 |
| `rx_max_usec` | Defines the longest pulse width value used when ensuring the channel value is valid. If the receiver gives a pulse value higher than this value then the channel will be marked as bad and will default to the value of `mid_rc`. | 100 | 3000 | 2115 | Profile | UINT16 |
| `gimbal_flags` | When feature SERVO_TILT is enabled, this can be a combination of the following numbers: 1=normal gimbal (default), 2=tiltmix gimbal, 4=in PPM (or SERIALRX) input mode, this will forward AUX1..4 RC inputs to PWM5..8 pins | 0 | 255 | 1 | Profile | UINT8 |
| `acc_hardware` | This is used to suggest which accelerometer driver should load, or to force no accelerometer in case gyro-only flight is needed. Default (0) will attempt to auto-detect among enabled drivers. Otherwise, to force a particular device, set it to 2 for ADXL345, 3 for MPU6050 integrated accelerometer, 4 for MMA8452, 5 for BMA280, 6 for LSM303DLHC, 7 for SPI_MPU6000, 8 for SPI_MPU6500 or 1 to disable accelerometer alltogether - resulting in gyro-only operation. | 0 | 9 | 0 | Master | UINT8 |
| `acc_lpf_factor` | This setting controls the Low Pass Filter factor for ACC. Increasing this value reduces ACC noise (visible in GUI), but would increase ACC lag time. Zero = no filter | 0 | 250 | 4 | Profile | UINT8 |
| `accxy_deadband` | | 0 | 100 | 40 | Profile | UINT8 |
| `accz_deadband` | | 0 | 100 | 40 | Profile | UINT8 |
| `accz_lpf_cutoff` | | 1 | 20 | 5 | Profile | FLOAT |
| `acc_unarmedcal` | | 0 | 1 | 1 | Profile | UINT8 |
| `acc_trim_pitch` | | -300 | 300 | 0 | Profile | INT16 |
| `acc_trim_roll` | | -300 | 300 | 0 | Profile | INT16 |
| `baro_tab_size` | | 0 | 48 | 21 | Profile | UINT8 |
| `baro_noise_lpf` | | 0 | 1 | 0.6 | Profile | FLOAT |
| `baro_cf_vel` | | 0 | 1 | 0.985 | Profile | FLOAT |
| `baro_cf_alt` | | 0 | 1 | 0.965 | Profile | FLOAT |
| `mag_hardware` | | 0 | 3 | 0 | Master | UINT8 |
| `mag_declination` | Current location magnetic declination in format. For example, -6deg 37min, = for Japan. Leading zero in ddd not required. Get your local magnetic declination here: http://magnetic-declination.com/ | -18000 | 18000 | 0 | Profile | INT16 |
| `pid_controller` | | 0 | 5 | 0 | Profile | UINT8 |
| `p_pitch` | | 0 | 200 | 40 | Profile | UINT8 |
| `i_pitch` | | 0 | 200 | 30 | Profile | UINT8 |
| `d_pitch` | | 0 | 200 | 23 | Profile | UINT8 |
| `p_roll` | | 0 | 200 | 40 | Profile | UINT8 |
| `i_roll` | | 0 | 200 | 30 | Profile | UINT8 |
| `d_roll` | | 0 | 200 | 23 | Profile | UINT8 |
| `p_yaw` | | 0 | 200 | 85 | Profile | UINT8 |
| `i_yaw` | | 0 | 200 | 45 | Profile | UINT8 |
| `d_yaw` | | 0 | 200 | 0 | Profile | UINT8 |
| `p_pitchf` | | 0 | 100 | 2.5 | Profile | FLOAT |
| `i_pitchf` | | 0 | 100 | 0.6 | Profile | FLOAT |
| `d_pitchf` | | 0 | 100 | 0.06 | Profile | FLOAT |
| `p_rollf` | | 0 | 100 | 2.5 | Profile | FLOAT |
| `i_rollf` | | 0 | 100 | 0.6 | Profile | FLOAT |
| `d_rollf` | | 0 | 100 | 0.06 | Profile | FLOAT |
| `p_yawf` | | 0 | 100 | 8 | Profile | FLOAT |
| `i_yawf` | | 0 | 100 | 0.5 | Profile | FLOAT |
| `d_yawf` | | 0 | 100 | 0.05 | Profile | FLOAT |
| `level_horizon` | | 0 | 10 | 3 | Profile | FLOAT |
| `level_angle` | | 0 | 10 | 5 | Profile | FLOAT |
| `sensitivity_horizon` | | 0 | 250 | 75 | Profile | UINT8 |
| `p_alt` | | 0 | 200 | 50 | Profile | UINT8 |
| `i_alt` | | 0 | 200 | 0 | Profile | UINT8 |
| `d_alt` | | 0 | 200 | 0 | Profile | UINT8 |
| `p_level` | | 0 | 200 | 90 | Profile | UINT8 |
| `i_level` | | 0 | 200 | 10 | Profile | UINT8 |
| `d_level` | | 0 | 200 | 100 | Profile | UINT8 |
| `p_vel` | | 0 | 200 | 120 | Profile | UINT8 |
| `i_vel` | | 0 | 200 | 45 | Profile | UINT8 |
| `d_vel` | | 0 | 200 | 1 | Profile | UINT8 |
| `yaw_p_limit` | Limiter for yaw P term. This parameter is only affecting PID controller 3-5. To disable set to 500 (actual default). | 100 | 500 | 500 | Profile | UINT16 |
| `blackbox_rate_num` | | 1 | 32 | 1 | Master | UINT8 |
| `blackbox_rate_denom` | | 1 | 32 | 1 | Master | UINT8 |

View file

@ -64,7 +64,12 @@ Now, there are two ways to [configure CF](Configuration.md); via the Configurat
* Minimum Command - This is the "idle" signal level that will be sent to the ESCs when the craft is disarmed, which should not cause the motors to spin. A typical value would be 1000.
* Finally, click Save and Reboot.
* Receiver tab: Check that the channel inputs move according to your Tx inputs. Check that the Channel map is correct, along with the RSSI Channel, if you use that. You can also set EXPO here instead of your Tx. Click Save!
* Receiver tab:
* Check that the channel inputs move according to your Tx inputs.
* Check that the Channel map is correct along with the RSSI Channel, if you use that.
* Verify the range of each channel goes from ~1000 to ~2000. See also [controls](Controls.md). and `rx_min_usec` and `rx_max_usec`.
* You can also set EXPO here instead of your Tx.
* Click Save!
* Modes tab: Setup the desired modes. See the [modes](Modes.md) chapter for what each mode does, but for the beginning you mainly need HORIZON, if any.
* Before finishing this section, you should calibrate the ESCs, install the FC to the frame, and connect the RSSI cable, buzzer and battery if you have chosen to use those.

View file

@ -1,5 +1,11 @@
# GPS
GPS features in Cleanflight are experimental. Please share your findings with the developers.
GPS works best if the GPS receiver is mounted above and away from other sources of interference.
The compass/mag sensor should be well away from sources of magnetic interference, e.g. keep it away from power wires, motors, ESCs.
Two GPS protocols are supported. NMEA text and UBLOX binary.
## Configuration

View file

@ -110,6 +110,14 @@ this reason ensure that you define enough ranges to cover the range channel's us
| 10 | YAW_I |
| 11 | YAW_D |
| 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 |
| 18 | ROLL_P |
| 19 | ROLL_I |
| 20 | ROLL_D |
## Examples

View file

@ -34,9 +34,9 @@ auxillary receiver channels and other events such as failsafe detection.
In this mode, the "head" of the multicopter is always pointing to the same direction as when the feature was activated. This means that when the multicopter rotates around the Z axis (yaw), the controls will always respond according the same "head" direction.
With this mode is easier to control the multicopter, even fly it with the physical head towards you since the controls always respond the same. This is a friendly mode to new users of multicopters and can prevent losing the control when you don't know the head direction.
With this mode it is easier to control the multicopter, even fly it with the physical head towards you since the controls always respond the same. This is a friendly mode to new users of multicopters and can prevent losing the control when you don't know the head direction.
## GPS Return To Home
### GPS Return To Home
WORK-IN-PROGRESS. This mode is not reliable yet, please share your experiences with the developers.
@ -46,7 +46,7 @@ This mode should be enabled in conjunction with Angle or Horizon modes and an Al
Requires a 3D GPS fix and minimum of 5 satellites in view.
## GPS Position Hold
### GPS Position Hold
WORK-IN-PROGRESS. This mode is not reliable yet, please share your experiences with the developers.
@ -62,10 +62,11 @@ Requires a 3D GPS fix and minimum of 5 satellites in view.
Spare auxillary receiver channels can be used to enable/disable modes. Some modes can only be enabled this way.
Configure your transmitter so that switches or dial (pots) send channel data on channels 5 and upwards.
e.g. You can configure a 3 position switch to send 1000 when the switch is low, 1500 when the switch is in the middle and 2000 when the switch is high.
Configure your transmitter so that switches or dials (potentiometers) send channel data on channels 5 and upwards (the first 4 channels are usually occupied by the throttle, aileron, rudder, and elevator channels).
Configure your tx/rx channel limits to use values between 1000 and 2000.
_e.g. You can configure a 3 position switch to send 1000 when the switch is low, 1500 when the switch is in the middle and 2000 when the switch is high._
Configure your tx/rx channel limits to use values between 1000 and 2000. The range used by mode ranges is fixed to 900 to 2100.
When a channel is within a specifed range the corresponding mode is enabled.

View file

@ -31,9 +31,13 @@ set too high, the craft will oscillate (but with slower oscillations than with P
##TPA and TPA Breakpoint
TPA stands for Throttle PID Attenuation and according to [AlexYork.net](http://blog.alexyorke.net/what-is-tpa/):
> "TPA basically allows an aggressively tuned multi-rotor (one that feels very locked in) to reduce its PID gains when throttle is applied beyond the TPA threshold/breakpoint in order to eliminate fast oscillations.."
Note that TPA is set via CLI or on the PID TUNING tab of the GUI. tpa_breakpoint is set via CLI
Also note that TPA and tpa_breakpoint may not be used in certain PID Contorllers. Check the description on the individual controller.
Also note that TPA and tpa_breakpoint may not be used in certain PID Controllers. Check the description on the individual controller.
TPA applies a PID value reduction in relation to full Throttle. It is used to apply dampening of PID values as full throttle is reached.
@ -46,6 +50,7 @@ An Example: With TPA = 50 (or .5 in the GUI) and tpa_breakpoint = 1500 (assumed
* At 1500 on the throttle channel, the PIDs will begin to be dampened.
* At 3/4 throttle (1750), PIDs are reduced by approximately 25% (half way between 1500 and 2000 the dampening will be 50% of the total TPA value of 50% in this example)
* At full throttle (2000) the full amount of dampening set in TPA is applied. (50% reduction in this example)
* TPA can lead into increase of rotation rate when more throttle applied. You can get faster flips and rolls when more throttle applied due to coupling of PID's and rates. Only PID controllers 1 and 2 are using linear TPA implementation, where no rotation rates are affected when TPA is being used.
![tpa example chart](https://cloud.githubusercontent.com/assets/1668170/6053290/655255dc-ac92-11e4-9491-1a58d868c131.png "TPA Example Chart")
@ -90,11 +95,7 @@ settings).
In Angle mode, this controller uses the LEVEL "P" PID setting to decide how strong the auto-level correction should
be. Note that the default value for P_Level is 90. This is more than likely too high of a value for most, and will cause the model to be very unstable in Angle Mode, and could result in loss of control. It is recommended to change this value to 20 before using PID Controller 1 in Angle Mode.
In Horizon mode, this controller uses the LEVEL "I" PID setting to decide how much auto-level correction should be
applied. The default Cleanflight setting for "I" will result in virtually no auto-leveling being applied, so that will
need to be increased in order to perform like PID controller 0.
The LEVEL "D" setting is not used by this controller.
In Horizon mode, this controller uses the LEVEL "I" PID setting to decide how much auto-level correction should be applied. Level "I" term: Strength of horizon auto-level. value of 0.030 in the configurator equals to 3.0 for Level P. Level "D" term: Strength of horizon transition. 0 is more stick travel on level and 255 is more rate mode what means very narrow angle of leveling.
### PID controller 2, "LuxFloat"

View file

@ -47,11 +47,11 @@ http://www.lemon-rx.com/shop/index.php?route=product/product&product_id=118
### S.BUS
16 channels via serial currently supported. See the Serial chapter in the documentation for a configuration example.
16 channels via serial currently supported. See below how to set up your transmitter.
* In most cases you will need an inverter between the receiver output and the flight controller hardware.
* You probably need an inverter between the receiver output and the flight controller. However, some flight controllers have this built in (the main port on CC3D, for example), and doesn't need one.
* Softserial ports cannot be used with SBUS because it runs at too high of a bitrate (1Mbps). Refer to the chapter specific to your board to determine which port(s) may be used.
* You will need to configure the channel mapping in the GUI (Receiver tab) or CLI (`map` command).
* You will need to configure the channel mapping in the GUI (Receiver tab) or CLI (`map` command). Note that channels above 8 are mapped "straight", with no remapping.
These receivers are reported working:
@ -67,14 +67,15 @@ http://www.futaba-rc.com/systems/futk8100-8j/
#### OpenTX S.BUS configuration
If using OpenTX set the transmitter module to D16 mode and select CH1-16 on the transmitter before binding to allow reception
of 16 channels.
If using OpenTX set the transmitter module to D16 mode and ALSO select CH1-16 on the transmitter before binding to allow reception
of all 16 channels.
OpenTX 2.09, which is shipped on some Taranis X9D Plus transmitters, has a bug - [issue:1701](https://github.com/opentx/opentx/issues/1701).
The bug prevents use of all 16 channels. Upgrade to the latest OpenTX version to allow correct reception of all 16 channels,
without the fix you are limited to 8 channels regardless of the CH1-16/D16 settings.
### XBUS
The firmware currently supports the MODE B version of the XBus protocol.

View file

@ -13,11 +13,11 @@ a dedicated USB to UART adapter. VCP does not 'use' a physical UART port.
* UART - A pair of dedicated hardware transmit and receive pins with signal detection and generation done in hardware.
* SoftSerial - A pair of hardware transmit and receive pins with signal detection and generation done in software.
UART is the most efficent in terms of CPU usage.
SoftSerial is the least efficient and slowest, SoftSerial should only be used for low-bandwith usages, such as telemetry transmission.
UART is the most efficient in terms of CPU usage.
SoftSerial is the least efficient and slowest, SoftSerial should only be used for low-bandwidth usages, such as telemetry transmission.
UART ports are sometimes exposed via on-board USB to UART converters, such as the CP2102 as found on the Naze and Flip32 boards.
If the flight controller does not have an onboard USB to UART converter and doesn't support VCP then an external USB to UART board is required.
If the flight controller does not have an on-board USB to UART converter and doesn't support VCP then an external USB to UART board is required.
These are sometimes referred to as FTDI boards. FTDI is just a common manufacturer of a chip (the FT232RL) used on USB to UART boards.
When selecting a USB to UART converter choose one that has DTR exposed as well as a selector for 3.3v and 5v since they are more useful.
@ -31,9 +31,9 @@ Both SoftSerial and UART ports can be connected to your computer via USB to UART
## Serial Configuration
Serial port configuration is best done via the configurator. You can use the CLI too but the commands are reserved for developers and advanced users.
Serial port configuration is best done via the configurator.
Configure serial ports first, then enable/disable features that use the ports.
Configure serial ports first, then enable/disable features that use the ports. To configure SoftSerial ports the SOFTSERIAL feature must be also be enabled.
### Constraints
@ -52,9 +52,23 @@ e.g. after configuring a port for GPS enable the GPS feature.
* You can use as many different telemetry systems as you like at the same time.
* You can only use each telemetry system once. e.g. FrSky telemetry cannot be used on two port, but MSP Telemetry + FrSky on different ports is fine.
### Configuration via CLI
You can use the CLI for configuration but the commands are reserved for developers and advanced users.
The `serial` CLI command takes 6 arguments.
1. Identifier
1. Function bitmask (see serialPortFunction_e in the source)
1. MSP baud rate
1. GPS baud rate
1. Telemetry baud rate (auto baud allowed)
1. Blackbox baud rate
### Baud Rates
Each baud rate is assigned an identifier, they are as follows:
The allowable baud rates are as follows:
| Identifier | Baud rate |
| ---------- | --------- |
@ -66,3 +80,4 @@ Each baud rate is assigned an identifier, they are as follows:
| 5 | 115200 |
| 6 | 230400 |
| 7 | 250000 |

View file

@ -19,6 +19,8 @@ Currently the only supported sensor is the HCSR04 sensor.
| Parallel PWM/ADC current sensor | PB8 / Motor 5 | PB9 / Motor 6 | NO (5v tolerant) |
| PPM/Serial RX | PB0 / RC7 | PB1 / RC8 | YES (3.3v input) |
#### Constraints
Current meter cannot be used in conjunction with Parallel PWM and Sonar.
### Olimexino
@ -27,4 +29,18 @@ Current meter cannot be used in conjunction with Parallel PWM and Sonar.
| ------------- | ------------- | ------------------- |
| PB0 / RC7 | PB1 / RC8 | YES (3.3v input) |
Current meter cannot be used in conjunction with sonar.
#### Constraints
Current meter cannot be used in conjunction with Sonar.
### CC3D
| Trigger | Echo | Inline 1k resistors |
| ------------- | ------------- | ------------------- |
| PB5 | PB0 | YES (3.3v input) |
Sonar support is not available when using the OpenPilot bootloader (OPBL).
#### Constraints
Sonar cannot be used in conjuction with SoftSerial or Parallel PWM.

View file

@ -34,12 +34,12 @@ Please refer to the satellite receiver documentation for more details of the spe
## Table with spektrum_sat_bind parameter value
| Value | Receiver mode | Notes |
| ----- | ---------------| -------------------|
| 3 | DSM2 1024/22ms | |
| 5 | DSM2 2048/11ms | default AlienWii32 |
| 7 | DSMX 22ms | |
| 9 | DSMX 11ms | |
| Value | Receiver mode | Notes |
| ----- | ------------------| -------------------|
| 3 | DSM2 1024bit/22ms | |
| 5 | DSM2 2048bit/11ms | default AlienWii32 |
| 7 | DSMX 1024bit/22ms | |
| 9 | DSMX 2048bit/11ms | |
More detailed information regarding the satellite binding process can be found here:
http://wiki.openpilot.org/display/Doc/Spektrum+Satellite
@ -50,15 +50,15 @@ NAZE, NAZE32PRO, CJMCU, SPARKY, EUSTM32F103RC, CC3D targets and ALIENWIIF1, ALIE
### Connecting a Spektrum-compatible satellite to a Flip32+ flight controller
The Flip32+ is wired in a rather strange way, i.e. the dedicated connector for the satellite module uses the same UART pins as the USB adapter. This means that you can't use that connector as it maps to UART1 which you really shouldn't assign to SERIAL_RX as that will break USB functionality.
The Flip32/Flip32+ is wired in a rather strange way, i.e. the dedicated connector for the satellite module uses the same UART pins as the USB adapter. This means that you can't use that connector as it maps to UART1 which you really shouldn't assign to SERIAL_RX as that will break USB functionality. (Looks this problem is fixed in later versions of the Flip32/Flip32+)
In order to connect the satellite to a Flip32+, you have to wire the serial data pin to RC_CH4. This is the fourth pin from the top in the left column of the 3x6 header on the right side of the board. GND and +3.3V may either be obtained from the dedicated SAT connector or from any ground pin and pin 1 of the BOOT connector which also provides 3.3V.
#### Tested satellite transmitter combinations
| Satellite | Remote | Remark |
| -------------------- | -------------- | ------------------------------------------ |
| Orange R100 | Spektrum DX6i | Bind value 3 |
| Lemon RX DSM2/DSMX | Spektrum DX8 | |
| Lemon RX DSMX | Walkera Devo10 | Deviation firmware 4.01 up to 12 channels |
| Lemon RX DSM2 | Walkera Devo7 | Deviation firmware |
| Satellite | Remote | Remark |
| -------------------- | -------------- | -------------------------------------------------------- |
| Orange R100 | Spektrum DX6i | Bind value 3 |
| Lemon RX DSM2/DSMX | Spektrum DX8 | Bind value 5 |
| Lemon RX DSMX | Walkera Devo10 | Bind value 9, Deviation firmware 4.01 up to 12 channels |
| Lemon RX DSM2 | Walkera Devo7 | Bind value 9, Deviation firmware |

View file

@ -61,6 +61,8 @@ You can also step-debug the tests in eclipse and you can use the GoogleTest test
The tests are currently always compiled with debugging information enabled, there may be additional warnings, if you see any warnings please attempt to fix them and submit pull requests with the fixes.
Tests are verified and working with GCC 4.9.2.
## Using git and github
Ensure you understand the github workflow: https://guides.github.com/introduction/flow/index.html
@ -93,6 +95,7 @@ Later, you can get the changes from the cleanflight repo into your `master` bran
2. `git checkout master`
3. `git fetch cleanflight`
4. `git merge cleanflight/master`
5. `git push origin master` is an optional step that will update your fork on github
You can also perform the git commands using the git client inside Eclipse. Refer to the Eclipse git manual.

View file

@ -1,8 +1,8 @@
### IO variables
`gyroData/8192*2000 = deg/s`
`gyroADC/8192*2000 = deg/s`
`gyroData/4 ~ deg/s`
`gyroADC/4 ~ deg/s`
`rcCommand` - `<-500 - 500>` nominal, but is scaled with `rcRate/100`, max +-1250
@ -23,7 +23,7 @@ Iacc = intergrate(error, limit +-10000) * I8[PIDLEVEL] / 4096
#### Gyro term
```
Pgyro = rcCommand[axis];
error = rcCommand[axis] * 10 * 8 / pidProfile->P8[axis] - gyroData[axis] / 4; (conversion so that error is in deg/s ?)
error = rcCommand[axis] * 10 * 8 / pidProfile->P8[axis] - gyroADC[axis] / 4; (conversion so that error is in deg/s ?)
Igyro = integrate(error, limit +-16000) / 10 / 8 * I8[axis] / 100 (conversion back to mixer units ?)
```
@ -52,12 +52,12 @@ reset I term if
#### Gyro stabilization
```
P -= gyroData[axis] / 4 * dynP8 / 10 / 8
D = -mean(diff(gyroData[axis] / 4), over 3 samples) * 3 * dynD8 / 32
P -= gyroADC[axis] / 4 * dynP8 / 10 / 8
D = -mean(diff(gyroADC[axis] / 4), over 3 samples) * 3 * dynD8 / 32
[equivalent to :]
D = - (gyroData[axis]/4 - (<3 loops old>gyroData[axis]/4)) * dynD8 / 32
D = - (gyroADC[axis]/4 - (<3 loops old>gyroADC[axis]/4)) * dynD8 / 32
```
This can be seen as sum of
- PI controller (handles rcCommand, HORIZON/ANGLE); `Igyro` is only output based on gyroData
- PD controller(parameters dynP8/dynD8) with zero setpoint acting on gyroData
- PI controller (handles rcCommand, HORIZON/ANGLE); `Igyro` is only output based on gyroADC
- PD controller(parameters dynP8/dynD8) with zero setpoint acting on gyroADC

View file

@ -5,7 +5,7 @@
uint32_t SystemCoreClock = SYSCLK_FREQ_72MHz; /*!< System Clock Frequency (Core Clock) */
__I uint8_t AHBPrescTable[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9 };
static const uint8_t AHBPrescTable[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9 };
uint32_t hse_value = 8000000;

View file

@ -190,8 +190,8 @@
* @{
*/
static __I uint8_t APBAHBPrescTable[16] = {0, 0, 0, 0, 1, 2, 3, 4, 1, 2, 3, 4, 6, 7, 8, 9};
static __I uint8_t ADCPrescTable[4] = {2, 4, 6, 8};
static const uint8_t APBAHBPrescTable[16] = {0, 0, 0, 0, 1, 2, 3, 4, 1, 2, 3, 4, 6, 7, 8, 9};
static const uint8_t ADCPrescTable[4] = {2, 4, 6, 8};
extern uint32_t hse_value;
/**

View file

@ -202,9 +202,9 @@ static const blackboxMainFieldDefinition_t blackboxMainFields[] = {
#endif
/* Gyros and accelerometers base their P-predictions on the average of the previous 2 frames to reduce noise impact */
{"gyroData", 0, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(AVERAGE_2), .Pencode = ENCODING(SIGNED_VB), CONDITION(ALWAYS)},
{"gyroData", 1, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(AVERAGE_2), .Pencode = ENCODING(SIGNED_VB), CONDITION(ALWAYS)},
{"gyroData", 2, SIGNED, .Ipredict = PREDICT(0), .Iencode = ENCODING(SIGNED_VB), .Ppredict = PREDICT(AVERAGE_2), .Pencode = ENCODING(SIGNED_VB), CONDITION(ALWAYS)},
{"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)},
@ -250,7 +250,6 @@ typedef enum BlackboxState {
BLACKBOX_STATE_SEND_GPS_H_HEADERS,
BLACKBOX_STATE_SEND_GPS_G_HEADERS,
BLACKBOX_STATE_SEND_SYSINFO,
BLACKBOX_STATE_PRERUN,
BLACKBOX_STATE_RUNNING,
BLACKBOX_STATE_SHUTTING_DOWN
} BlackboxState;
@ -268,6 +267,8 @@ extern uint32_t currentTime;
static BlackboxState blackboxState = BLACKBOX_STATE_DISABLED;
static uint32_t blackboxLastArmingBeep = 0;
static struct {
uint32_t headerIndex;
@ -485,7 +486,7 @@ static void writeIntraframe(void)
#endif
for (x = 0; x < XYZ_AXIS_COUNT; x++) {
blackboxWriteSignedVB(blackboxCurrent->gyroData[x]);
blackboxWriteSignedVB(blackboxCurrent->gyroADC[x]);
}
for (x = 0; x < XYZ_AXIS_COUNT; x++) {
@ -601,7 +602,7 @@ static void writeInterframe(void)
//Since gyros, accs and motors are noisy, base the prediction on the average of the history:
for (x = 0; x < XYZ_AXIS_COUNT; x++) {
blackboxWriteSignedVB(blackboxHistory[0]->gyroData[x] - (blackboxHistory[1]->gyroData[x] + blackboxHistory[2]->gyroData[x]) / 2);
blackboxWriteSignedVB(blackboxHistory[0]->gyroADC[x] - (blackboxHistory[1]->gyroADC[x] + blackboxHistory[2]->gyroADC[x]) / 2);
}
for (x = 0; x < XYZ_AXIS_COUNT; x++) {
@ -684,6 +685,12 @@ void startBlackbox(void)
*/
blackboxBuildConditionCache();
/*
* Record the beeper's current idea of the last arming beep time, so that we can detect it changing when
* it finally plays the beep for this arming event.
*/
blackboxLastArmingBeep = getArmingBeepTimeMicros();
blackboxSetState(BLACKBOX_STATE_SEND_HEADER);
}
}
@ -774,7 +781,7 @@ static void loadBlackboxState(void)
}
for (i = 0; i < XYZ_AXIS_COUNT; i++) {
blackboxCurrent->gyroData[i] = gyroData[i];
blackboxCurrent->gyroADC[i] = gyroADC[i];
}
for (i = 0; i < XYZ_AXIS_COUNT; i++) {
@ -1012,16 +1019,19 @@ void blackboxLogEvent(FlightLogEvent event, flightLogEventData_t *data)
}
}
// Write the time of the last arming beep to the log as a synchronization point
static void blackboxLogArmingBeep()
/* If an arming beep has played since it was last logged, write the time of the arming beep to the log as a synchronization point */
static void blackboxCheckAndLogArmingBeep()
{
flightLogEvent_syncBeep_t eventData;
// Get time of last arming beep (in system-uptime microseconds)
eventData.time = getArmingBeepTimeMicros();
// Use != so that we can still detect a change if the counter wraps
if (getArmingBeepTimeMicros() != blackboxLastArmingBeep) {
blackboxLastArmingBeep = getArmingBeepTimeMicros();
// Write the time to the log
blackboxLogEvent(FLIGHT_LOG_EVENT_SYNC_BEEP, (flightLogEventData_t *) &eventData);
eventData.time = blackboxLastArmingBeep;
blackboxLogEvent(FLIGHT_LOG_EVENT_SYNC_BEEP, (flightLogEventData_t *) &eventData);
}
}
/**
@ -1082,14 +1092,9 @@ void handleBlackbox(void)
//Keep writing chunks of the system info headers until it returns true to signal completion
if (blackboxWriteSysinfo()) {
blackboxSetState(BLACKBOX_STATE_PRERUN);
blackboxSetState(BLACKBOX_STATE_RUNNING);
}
break;
case BLACKBOX_STATE_PRERUN:
blackboxSetState(BLACKBOX_STATE_RUNNING);
blackboxLogArmingBeep();
break;
case BLACKBOX_STATE_RUNNING:
// On entry to this state, blackboxIteration, blackboxPFrameIndex and blackboxIFrameIndex are reset to 0
@ -1099,6 +1104,8 @@ void handleBlackbox(void)
loadBlackboxState();
writeIntraframe();
} else {
blackboxCheckAndLogArmingBeep();
/* Adding a magic shift of "masterConfig.blackbox_rate_num - 1" in here creates a better spread of
* recorded / skipped frames when the I frame's position is considered:
*/

View file

@ -29,7 +29,7 @@ typedef struct blackboxValues_t {
int32_t axisPID_P[XYZ_AXIS_COUNT], axisPID_I[XYZ_AXIS_COUNT], axisPID_D[XYZ_AXIS_COUNT];
int16_t rcCommand[4];
int16_t gyroData[XYZ_AXIS_COUNT];
int16_t gyroADC[XYZ_AXIS_COUNT];
int16_t accSmooth[XYZ_AXIS_COUNT];
int16_t motor[MAX_SUPPORTED_MOTORS];
int16_t servo[MAX_SUPPORTED_SERVOS];

View file

@ -44,7 +44,7 @@
#include "sensors/boardalignment.h"
#include "sensors/battery.h"
#include "io/statusindicator.h"
#include "io/beeper.h"
#include "io/serial.h"
#include "io/gimbal.h"
#include "io/escservo.h"
@ -73,17 +73,6 @@
#define BRUSHED_MOTORS_PWM_RATE 16000
#define BRUSHLESS_MOTORS_PWM_RATE 400
void mixerUseConfigs(
#ifdef USE_SERVOS
servoParam_t *servoConfToUse,
gimbalConfig_t *gimbalConfigToUse,
#endif
flight3DConfig_t *flight3DConfigToUse,
escAndServoConfig_t *escAndServoConfigToUse,
mixerConfig_t *mixerConfigToUse,
airplaneConfig_t *airplaneConfigToUse,
rxConfig_t *rxConfig
);
void useRcControlsConfig(modeActivationCondition_t *modeActivationConditions, escAndServoConfig_t *escAndServoConfigToUse, pidProfile_t *pidProfileToUse);
#define FLASH_TO_RESERVE_FOR_CONFIG 0x800
@ -134,11 +123,12 @@ void useRcControlsConfig(modeActivationCondition_t *modeActivationConditions, es
master_t masterConfig; // master config struct with data independent from profiles
profile_t *currentProfile;
static uint32_t activeFeaturesLatch = 0;
static uint8_t currentControlRateProfileIndex = 0;
controlRateConfig_t *currentControlRateProfile;
static const uint8_t EEPROM_CONF_VERSION = 99;
static const uint8_t EEPROM_CONF_VERSION = 101;
static void resetAccelerometerTrims(flightDynamicsTrims_t *accelerometerTrims)
{
@ -180,7 +170,7 @@ static void resetPidProfile(pidProfile_t *pidProfile)
pidProfile->I8[PIDVEL] = 45;
pidProfile->D8[PIDVEL] = 1;
pidProfile->yaw_p_limit = 0;
pidProfile->yaw_p_limit = YAW_P_LIMIT_MAX;
pidProfile->P_f[ROLL] = 2.5f; // new PID with preliminary defaults test carefully
pidProfile->I_f[ROLL] = 0.6f;
@ -358,7 +348,7 @@ static void resetConf(void)
{
int i;
#ifdef USE_SERVOS
int8_t servoRates[MAX_SUPPORTED_SERVOS] = { 30, 30, 100, 100, 100, 100, 100, 100 };
int8_t servoRates[MAX_SUPPORTED_SERVOS] = { 30, 30, 100, 100, 100, 100, 100, 100, 100, 100 };
;
#endif
@ -528,7 +518,6 @@ static void resetConf(void)
#ifdef ALIENWII32
featureSet(FEATURE_RX_SERIAL);
featureSet(FEATURE_MOTOR_STOP);
featureSet(FEATURE_FAILSAFE);
#ifdef ALIENWIIF3
masterConfig.serialConfig.portConfigs[2].functionMask = FUNCTION_RX_SERIAL;
masterConfig.batteryConfig.vbatscale = 20;
@ -726,26 +715,26 @@ void activateConfig(void)
void validateAndFixConfig(void)
{
if (!(feature(FEATURE_RX_PARALLEL_PWM) || feature(FEATURE_RX_PPM) || feature(FEATURE_RX_SERIAL) || feature(FEATURE_RX_MSP))) {
if (!(featureConfigured(FEATURE_RX_PARALLEL_PWM) || featureConfigured(FEATURE_RX_PPM) || featureConfigured(FEATURE_RX_SERIAL) || featureConfigured(FEATURE_RX_MSP))) {
featureSet(FEATURE_RX_PARALLEL_PWM); // Consider changing the default to PPM
}
if (feature(FEATURE_RX_PPM)) {
if (featureConfigured(FEATURE_RX_PPM)) {
featureClear(FEATURE_RX_PARALLEL_PWM);
}
if (feature(FEATURE_RX_MSP)) {
if (featureConfigured(FEATURE_RX_MSP)) {
featureClear(FEATURE_RX_SERIAL);
featureClear(FEATURE_RX_PARALLEL_PWM);
featureClear(FEATURE_RX_PPM);
}
if (feature(FEATURE_RX_SERIAL)) {
if (featureConfigured(FEATURE_RX_SERIAL)) {
featureClear(FEATURE_RX_PARALLEL_PWM);
featureClear(FEATURE_RX_PPM);
}
if (feature(FEATURE_RX_PARALLEL_PWM)) {
if (featureConfigured(FEATURE_RX_PARALLEL_PWM)) {
#if defined(STM32F10X)
// rssi adc needs the same ports
featureClear(FEATURE_RSSI_ADC);
@ -766,7 +755,7 @@ void validateAndFixConfig(void)
#if defined(LED_STRIP) && (defined(USE_SOFTSERIAL1) || defined(USE_SOFTSERIAL2))
if (feature(FEATURE_SOFTSERIAL) && (
if (featureConfigured(FEATURE_SOFTSERIAL) && (
0
#ifdef USE_SOFTSERIAL1
|| (LED_STRIP_TIMER == SOFTSERIAL_1_TIMER)
@ -781,7 +770,7 @@ void validateAndFixConfig(void)
#endif
#if defined(NAZE) && defined(SONAR)
if (feature(FEATURE_RX_PARALLEL_PWM) && feature(FEATURE_SONAR) && feature(FEATURE_CURRENT_METER) && masterConfig.batteryConfig.currentMeterType == CURRENT_SENSOR_ADC) {
if (featureConfigured(FEATURE_RX_PARALLEL_PWM) && featureConfigured(FEATURE_SONAR) && featureConfigured(FEATURE_CURRENT_METER) && masterConfig.batteryConfig.currentMeterType == CURRENT_SENSOR_ADC) {
featureClear(FEATURE_CURRENT_METER);
}
#endif
@ -806,6 +795,12 @@ void validateAndFixConfig(void)
masterConfig.mixerConfig.pid_at_min_throttle = 0;
}
#if defined(CC3D) && defined(SONAR) && defined(USE_SOFTSERIAL1)
if (feature(FEATURE_SONAR) && feature(FEATURE_SOFTSERIAL)) {
featureClear(FEATURE_SONAR);
}
#endif
useRxConfig(&masterConfig.rxConfig);
serialConfig_t *serialConfig = &masterConfig.serialConfig;
@ -846,7 +841,7 @@ void readEEPROMAndNotify(void)
{
// re-read written data
readEEPROM();
blinkLedAndSoundBeeper(15, 20, 1);
beeperConfirmationBeeps(1);
}
void writeEEPROM(void)
@ -927,7 +922,7 @@ void changeProfile(uint8_t profileIndex)
masterConfig.current_profile_index = profileIndex;
writeEEPROM();
readEEPROM();
blinkLedAndSoundBeeper(2, 40, profileIndex + 1);
beeperConfirmationBeeps(profileIndex + 1);
}
void changeControlRateProfile(uint8_t profileIndex)
@ -939,11 +934,32 @@ void changeControlRateProfile(uint8_t profileIndex)
activateControlRateConfig();
}
bool feature(uint32_t mask)
void handleOneshotFeatureChangeOnRestart(void)
{
// Shutdown PWM on all motors prior to soft restart
StopPwmAllMotors();
delay(50);
// Apply additional delay when OneShot125 feature changed from on to off state
if (feature(FEATURE_ONESHOT125) && !featureConfigured(FEATURE_ONESHOT125)) {
delay(ONESHOT_FEATURE_CHANGED_DELAY_ON_BOOT_MS);
}
}
void latchActiveFeatures()
{
activeFeaturesLatch = masterConfig.enabledFeatures;
}
bool featureConfigured(uint32_t mask)
{
return masterConfig.enabledFeatures & mask;
}
bool feature(uint32_t mask)
{
return activeFeaturesLatch & mask;
}
void featureSet(uint32_t mask)
{
masterConfig.enabledFeatures |= mask;

View file

@ -19,6 +19,7 @@
#define MAX_PROFILE_COUNT 3
#define MAX_CONTROL_RATE_PROFILE_COUNT 3
#define ONESHOT_FEATURE_CHANGED_DELAY_ON_BOOT_MS 1500
typedef enum {
@ -44,6 +45,9 @@ typedef enum {
FEATURE_BLACKBOX = 1 << 19
} features_e;
void handleOneshotFeatureChangeOnRestart(void);
void latchActiveFeatures(void);
bool featureConfigured(uint32_t mask);
bool feature(uint32_t mask);
void featureSet(uint32_t mask);
void featureClear(uint32_t mask);

View file

@ -57,7 +57,7 @@
static uint8_t mpuLowPassFilter = L3G4200D_DLPF_32HZ;
static void l3g4200dInit(void);
static void l3g4200dRead(int16_t *gyroData);
static void l3g4200dRead(int16_t *gyroADC);
bool l3g4200dDetect(gyro_t *gyro, uint16_t lpf)
{
@ -110,13 +110,13 @@ static void l3g4200dInit(void)
}
// Read 3 gyro values into user-provided buffer. No overrun checking is done.
static void l3g4200dRead(int16_t *gyroData)
static void l3g4200dRead(int16_t *gyroADC)
{
uint8_t buf[6];
i2cRead(L3G4200D_ADDRESS, L3G4200D_AUTOINCR | L3G4200D_GYRO_OUT, 6, buf);
gyroData[X] = (int16_t)((buf[0] << 8) | buf[1]);
gyroData[Y] = (int16_t)((buf[2] << 8) | buf[3]);
gyroData[Z] = (int16_t)((buf[4] << 8) | buf[5]);
gyroADC[X] = (int16_t)((buf[0] << 8) | buf[1]);
gyroADC[Y] = (int16_t)((buf[2] << 8) | buf[3]);
gyroADC[Z] = (int16_t)((buf[4] << 8) | buf[5]);
}

View file

@ -120,7 +120,7 @@ void l3gd20GyroInit(void)
delay(100);
}
static void l3gd20GyroRead(int16_t *gyroData)
static void l3gd20GyroRead(int16_t *gyroADC)
{
uint8_t buf[6];
@ -134,9 +134,9 @@ static void l3gd20GyroRead(int16_t *gyroData)
GPIO_SetBits(L3GD20_CS_GPIO, L3GD20_CS_PIN);
gyroData[0] = (int16_t)((buf[0] << 8) | buf[1]);
gyroData[1] = (int16_t)((buf[2] << 8) | buf[3]);
gyroData[2] = (int16_t)((buf[4] << 8) | buf[5]);
gyroADC[0] = (int16_t)((buf[0] << 8) | buf[1]);
gyroADC[1] = (int16_t)((buf[2] << 8) | buf[3]);
gyroADC[2] = (int16_t)((buf[4] << 8) | buf[5]);
#if 0
debug[0] = (int16_t)((buf[1] << 8) | buf[0]);

View file

@ -106,7 +106,7 @@ void lsm303dlhcAccInit(void)
}
// Read 3 gyro values into user-provided buffer. No overrun checking is done.
static void lsm303dlhcAccRead(int16_t *gyroData)
static void lsm303dlhcAccRead(int16_t *gyroADC)
{
uint8_t buf[6];
@ -116,9 +116,9 @@ static void lsm303dlhcAccRead(int16_t *gyroData)
return;
// the values range from -8192 to +8191
gyroData[X] = (int16_t)((buf[1] << 8) | buf[0]) / 2;
gyroData[Y] = (int16_t)((buf[3] << 8) | buf[2]) / 2;
gyroData[Z] = (int16_t)((buf[5] << 8) | buf[4]) / 2;
gyroADC[X] = (int16_t)((buf[1] << 8) | buf[0]) / 2;
gyroADC[Y] = (int16_t)((buf[3] << 8) | buf[2]) / 2;
gyroADC[Z] = (int16_t)((buf[5] << 8) | buf[4]) / 2;
#if 0
debug[0] = (int16_t)((buf[1] << 8) | buf[0]);

View file

@ -58,7 +58,7 @@
static uint8_t mpuLowPassFilter = MPU3050_DLPF_42HZ;
static void mpu3050Init(void);
static void mpu3050Read(int16_t *gyroData);
static void mpu3050Read(int16_t *gyroADC);
static void mpu3050ReadTemp(int16_t *tempData);
bool mpu3050Detect(gyro_t *gyro, uint16_t lpf)
@ -121,15 +121,15 @@ static void mpu3050Init(void)
}
// Read 3 gyro values into user-provided buffer. No overrun checking is done.
static void mpu3050Read(int16_t *gyroData)
static void mpu3050Read(int16_t *gyroADC)
{
uint8_t buf[6];
i2cRead(MPU3050_ADDRESS, MPU3050_GYRO_OUT, 6, buf);
gyroData[0] = (int16_t)((buf[0] << 8) | buf[1]);
gyroData[1] = (int16_t)((buf[2] << 8) | buf[3]);
gyroData[2] = (int16_t)((buf[4] << 8) | buf[5]);
gyroADC[0] = (int16_t)((buf[0] << 8) | buf[1]);
gyroADC[1] = (int16_t)((buf[2] << 8) | buf[3]);
gyroADC[2] = (int16_t)((buf[4] << 8) | buf[5]);
}
static void mpu3050ReadTemp(int16_t *tempData)

View file

@ -175,7 +175,7 @@ static uint8_t mpuLowPassFilter = INV_FILTER_42HZ;
static void mpu6050AccInit(void);
static void mpu6050AccRead(int16_t *accData);
static void mpu6050GyroInit(void);
static void mpu6050GyroRead(int16_t *gyroData);
static void mpu6050GyroRead(int16_t *gyroADC);
typedef enum {
MPU_6050_HALF_RESOLUTION,
@ -439,7 +439,7 @@ static void mpu6050GyroInit(void)
#endif
}
static void mpu6050GyroRead(int16_t *gyroData)
static void mpu6050GyroRead(int16_t *gyroADC)
{
uint8_t buf[6];
@ -447,7 +447,7 @@ static void mpu6050GyroRead(int16_t *gyroData)
return;
}
gyroData[0] = (int16_t)((buf[0] << 8) | buf[1]);
gyroData[1] = (int16_t)((buf[2] << 8) | buf[3]);
gyroData[2] = (int16_t)((buf[4] << 8) | buf[5]);
gyroADC[0] = (int16_t)((buf[0] << 8) | buf[1]);
gyroADC[1] = (int16_t)((buf[2] << 8) | buf[3]);
gyroADC[2] = (int16_t)((buf[4] << 8) | buf[5]);
}

View file

@ -125,8 +125,8 @@ static bool mpuSpi6000InitDone = false;
#define DISABLE_MPU6000 GPIO_SetBits(MPU6000_CS_GPIO, MPU6000_CS_PIN)
#define ENABLE_MPU6000 GPIO_ResetBits(MPU6000_CS_GPIO, MPU6000_CS_PIN)
void mpu6000SpiGyroRead(int16_t *gyroData);
void mpu6000SpiAccRead(int16_t *gyroData);
void mpu6000SpiGyroRead(int16_t *gyroADC);
void mpu6000SpiAccRead(int16_t *gyroADC);
static void mpu6000WriteRegister(uint8_t reg, uint8_t data)
{

View file

@ -16,5 +16,5 @@
bool mpu6000SpiAccDetect(acc_t *acc);
bool mpu6000SpiGyroDetect(gyro_t *gyro, uint16_t lpf);
void mpu6000SpiGyroRead(int16_t *gyroData);
void mpu6000SpiAccRead(int16_t *gyroData);
void mpu6000SpiGyroRead(int16_t *gyroADC);
void mpu6000SpiAccRead(int16_t *gyroADC);

View file

@ -74,7 +74,7 @@ static uint8_t mpuLowPassFilter = INV_FILTER_42HZ;
static void mpu6500AccInit(void);
static void mpu6500AccRead(int16_t *accData);
static void mpu6500GyroInit(void);
static void mpu6500GyroRead(int16_t *gyroData);
static void mpu6500GyroRead(int16_t *gyroADC);
extern uint16_t acc_1G;
@ -188,13 +188,13 @@ static void mpu6500GyroInit(void)
mpu6500WriteRegister(MPU6500_RA_RATE_DIV, 0); // 1kHz S/R
}
static void mpu6500GyroRead(int16_t *gyroData)
static void mpu6500GyroRead(int16_t *gyroADC)
{
uint8_t buf[6];
mpu6500ReadRegister(MPU6500_RA_GYRO_XOUT_H, buf, 6);
gyroData[X] = (int16_t)((buf[0] << 8) | buf[1]);
gyroData[Y] = (int16_t)((buf[2] << 8) | buf[3]);
gyroData[Z] = (int16_t)((buf[4] << 8) | buf[5]);
gyroADC[X] = (int16_t)((buf[0] << 8) | buf[1]);
gyroADC[Y] = (int16_t)((buf[2] << 8) | buf[3]);
gyroADC[Z] = (int16_t)((buf[4] << 8) | buf[5]);
}

View file

@ -31,7 +31,7 @@
void pwmBrushedMotorConfig(const timerHardware_t *timerHardware, uint8_t motorIndex, uint16_t motorPwmRate, uint16_t idlePulse);
void pwmBrushlessMotorConfig(const timerHardware_t *timerHardware, uint8_t motorIndex, uint16_t motorPwmRate, uint16_t idlePulse);
void pwmOneshotMotorConfig(const timerHardware_t *timerHardware, uint8_t motorIndex, uint16_t idlePulse);
void pwmOneshotMotorConfig(const timerHardware_t *timerHardware, uint8_t motorIndex);
void pwmServoConfig(const timerHardware_t *timerHardware, uint8_t servoIndex, uint16_t servoPwmRate, uint16_t servoCenterPulse);
/*
@ -321,12 +321,39 @@ static const uint16_t multiPWM[] = {
};
static const uint16_t airPPM[] = {
// TODO
PWM1 | (MAP_TO_PPM_INPUT << 8), // PPM input
PWM9 | (MAP_TO_MOTOR_OUTPUT << 8), // motor #1
PWM10 | (MAP_TO_MOTOR_OUTPUT << 8), // motor #2
PWM11 | (MAP_TO_SERVO_OUTPUT << 8), // servo #1
PWM12 | (MAP_TO_SERVO_OUTPUT << 8),
PWM13 | (MAP_TO_SERVO_OUTPUT << 8),
PWM14 | (MAP_TO_SERVO_OUTPUT << 8),
PWM15 | (MAP_TO_SERVO_OUTPUT << 8),
PWM16 | (MAP_TO_SERVO_OUTPUT << 8),
PWM5 | (MAP_TO_SERVO_OUTPUT << 8),
PWM6 | (MAP_TO_SERVO_OUTPUT << 8),
PWM7 | (MAP_TO_SERVO_OUTPUT << 8),
PWM8 | (MAP_TO_SERVO_OUTPUT << 8), // servo #10
0xFFFF
};
static const uint16_t airPWM[] = {
// TODO
PWM1 | (MAP_TO_PWM_INPUT << 8), // input #1
PWM2 | (MAP_TO_PWM_INPUT << 8),
PWM3 | (MAP_TO_PWM_INPUT << 8),
PWM4 | (MAP_TO_PWM_INPUT << 8),
PWM5 | (MAP_TO_PWM_INPUT << 8),
PWM6 | (MAP_TO_PWM_INPUT << 8),
PWM7 | (MAP_TO_PWM_INPUT << 8),
PWM8 | (MAP_TO_PWM_INPUT << 8), // input #8
PWM9 | (MAP_TO_MOTOR_OUTPUT << 8), // motor #1
PWM10 | (MAP_TO_MOTOR_OUTPUT << 8), // motor #2
PWM11 | (MAP_TO_SERVO_OUTPUT << 8), // servo #1
PWM12 | (MAP_TO_SERVO_OUTPUT << 8),
PWM13 | (MAP_TO_SERVO_OUTPUT << 8),
PWM14 | (MAP_TO_SERVO_OUTPUT << 8),
PWM15 | (MAP_TO_SERVO_OUTPUT << 8),
PWM16 | (MAP_TO_SERVO_OUTPUT << 8), // server #6
0xFFFF
};
#endif
@ -381,29 +408,6 @@ pwmOutputConfiguration_t *pwmInit(drv_pwm_config_t *init)
continue;
#endif
#ifdef SONAR
// skip Sonar pins
// FIXME - Hack - See sonar.c sonarInit() and sonarHardware_t
if (init->useSonar && timerHardwarePtr->gpio == GPIOB) {
#if defined(SPRACINGF3) || defined(OLIMEXINO)
if (timerHardwarePtr->pin == GPIO_Pin_0 || timerHardwarePtr->pin == GPIO_Pin_1) {
continue;
}
#endif
#if defined(NAZE)
if (init->useParallelPWM) {
if (timerHardwarePtr->pin == GPIO_Pin_8 || timerHardwarePtr->pin == GPIO_Pin_9) {
continue;
}
} else {
if (timerHardwarePtr->pin == GPIO_Pin_0 || timerHardwarePtr->pin == GPIO_Pin_1) {
continue;
}
}
#endif
}
#endif
#ifdef SOFTSERIAL_1_TIMER
if (init->useSoftSerial && timerHardwarePtr->tim == SOFTSERIAL_1_TIMER)
continue;
@ -444,6 +448,17 @@ pwmOutputConfiguration_t *pwmInit(drv_pwm_config_t *init)
}
#endif
#ifdef SONAR
if (init->sonarGPIOConfig && timerHardwarePtr->gpio == init->sonarGPIOConfig->gpio &&
(
timerHardwarePtr->pin == init->sonarGPIOConfig->triggerPin ||
timerHardwarePtr->pin == init->sonarGPIOConfig->echoPin
)
) {
continue;
}
#endif
// hacks to allow current functionality
if (type == MAP_TO_PWM_INPUT && !init->useParallelPWM)
continue;
@ -528,7 +543,7 @@ pwmOutputConfiguration_t *pwmInit(drv_pwm_config_t *init)
channelIndex++;
} else if (type == MAP_TO_MOTOR_OUTPUT) {
if (init->useOneshot) {
pwmOneshotMotorConfig(timerHardwarePtr, pwmOutputConfiguration.motorCount, init->idlePulse);
pwmOneshotMotorConfig(timerHardwarePtr, pwmOutputConfiguration.motorCount);
} else if (init->motorPwmRate > 500) {
pwmBrushedMotorConfig(timerHardwarePtr, pwmOutputConfiguration.motorCount, init->motorPwmRate, init->idlePulse);
} else {

View file

@ -18,10 +18,10 @@
#pragma once
#define MAX_PWM_MOTORS 12
#define MAX_PWM_SERVOS 8
#define MAX_PWM_SERVOS 10
#define MAX_MOTORS 12
#define MAX_SERVOS 8
#define MAX_SERVOS 10
#define MAX_PWM_OUTPUT_PORTS MAX_PWM_MOTORS // must be set to the largest of either MAX_MOTORS or MAX_SERVOS
#if MAX_PWM_OUTPUT_PORTS < MAX_MOTORS || MAX_PWM_OUTPUT_PORTS < MAX_SERVOS
@ -36,6 +36,12 @@
#define PWM_TIMER_MHZ 1
#define ONESHOT125_TIMER_MHZ 8
typedef struct sonarGPIOConfig_s {
GPIO_TypeDef *gpio;
uint16_t triggerPin;
uint16_t echoPin;
} sonarGPIOConfig_t;
typedef struct drv_pwm_config_t {
bool useParallelPWM;
bool usePPM;
@ -65,6 +71,7 @@ typedef struct drv_pwm_config_t {
uint16_t motorPwmRate;
uint16_t idlePulse; // PWM value to use when initializing the driver. set this to either PULSE_1MS (regular pwm),
// some higher value (used by 3d mode), or 0, for brushed pwm drivers.
sonarGPIOConfig_t *sonarGPIOConfig;
} drv_pwm_config_t;

View file

@ -142,6 +142,16 @@ void pwmWriteMotor(uint8_t index, uint16_t value)
motors[index]->pwmWritePtr(index, value);
}
void pwmShutdownPulsesForAllMotors(uint8_t motorCount)
{
uint8_t index;
for(index = 0; index < motorCount; index++){
// Set the compare register to 0, which stops the output pulsing if the timer overflows
*motors[index]->ccr = 0;
}
}
void pwmCompleteOneshotMotorUpdate(uint8_t motorCount)
{
uint8_t index;
@ -176,9 +186,9 @@ void pwmBrushlessMotorConfig(const timerHardware_t *timerHardware, uint8_t motor
motors[motorIndex]->pwmWritePtr = pwmWriteStandard;
}
void pwmOneshotMotorConfig(const timerHardware_t *timerHardware, uint8_t motorIndex, uint16_t idlePulse)
void pwmOneshotMotorConfig(const timerHardware_t *timerHardware, uint8_t motorIndex)
{
motors[motorIndex] = pwmOutConfig(timerHardware, ONESHOT125_TIMER_MHZ, 0xFFFF, idlePulse);
motors[motorIndex] = pwmOutConfig(timerHardware, ONESHOT125_TIMER_MHZ, 0xFFFF, 0);
motors[motorIndex]->pwmWritePtr = pwmWriteStandard;
}

View file

@ -18,6 +18,7 @@
#pragma once
void pwmWriteMotor(uint8_t index, uint16_t value);
void pwmShutdownPulsesForAllMotors(uint8_t motorCount);
void pwmCompleteOneshotMotorUpdate(uint8_t motorCount);
void pwmWriteServo(uint8_t index, uint16_t value);

View file

@ -58,6 +58,11 @@ static void ECHO_EXTI_IRQHandler(void)
EXTI_ClearITPendingBit(sonarHardware->exti_line);
}
void EXTI0_IRQHandler(void)
{
ECHO_EXTI_IRQHandler();
}
void EXTI1_IRQHandler(void)
{
ECHO_EXTI_IRQHandler();

View file

@ -25,6 +25,8 @@ typedef struct sonarHardware_s {
IRQn_Type exti_irqn;
} sonarHardware_t;
#define SONAR_GPIO GPIOB
void hcsr04_init(const sonarHardware_t *sonarHardware);
void hcsr04_start_reading(void);

View file

@ -60,7 +60,7 @@ typedef struct timerOvrHandlerRec_s {
typedef struct {
TIM_TypeDef *tim;
GPIO_TypeDef *gpio;
uint32_t pin;
uint16_t pin;
uint8_t channel;
uint8_t irq;
uint8_t outputEnable;

View file

@ -48,7 +48,6 @@
int16_t accSmooth[XYZ_AXIS_COUNT];
int32_t accSum[XYZ_AXIS_COUNT];
int16_t gyroData[FLIGHT_DYNAMICS_INDEX_COUNT] = { 0, 0, 0 };
uint32_t accTimeSum = 0; // keep track for integration of acc
int accSumCount = 0;
@ -298,11 +297,10 @@ static void imuCalculateEstimatedAttitude(void)
imuCalculateAcceleration(deltaT); // rotate acc vector into earth frame
}
void imuUpdate(rollAndPitchTrims_t *accelerometerTrims, uint8_t mixerMode)
void imuUpdate(rollAndPitchTrims_t *accelerometerTrims)
{
static int16_t gyroYawSmooth = 0;
gyroUpdate();
if (sensors(SENSOR_ACC)) {
updateAccelerationReadings(accelerometerTrims); // TODO rename to accelerometerUpdate and rename many other 'Acceleration' references to be 'Accelerometer'
imuCalculateEstimatedAttitude();
@ -311,16 +309,6 @@ void imuUpdate(rollAndPitchTrims_t *accelerometerTrims, uint8_t mixerMode)
accADC[Y] = 0;
accADC[Z] = 0;
}
gyroData[FD_ROLL] = gyroADC[FD_ROLL];
gyroData[FD_PITCH] = gyroADC[FD_PITCH];
if (mixerMode == MIXER_TRI) {
gyroData[FD_YAW] = (gyroYawSmooth * 2 + gyroADC[FD_YAW]) / 3;
gyroYawSmooth = gyroData[FD_YAW];
} else {
gyroData[FD_YAW] = gyroADC[FD_YAW];
}
}
int16_t calculateThrottleAngleCorrection(uint8_t throttle_correction_value)

View file

@ -24,7 +24,6 @@ extern float accVelScale;
extern t_fp_vector EstG;
extern int16_t accSmooth[XYZ_AXIS_COUNT];
extern int32_t accSum[XYZ_AXIS_COUNT];
extern int16_t gyroData[FLIGHT_DYNAMICS_INDEX_COUNT];
extern int16_t smallAngle;
typedef struct rollAndPitchInclination_s {
@ -62,7 +61,7 @@ void imuConfigure(
);
void calculateEstimatedAltitude(uint32_t currentTime);
void imuUpdate(rollAndPitchTrims_t *accelerometerTrims, uint8_t mixerMode);
void imuUpdate(rollAndPitchTrims_t *accelerometerTrims);
float calculateThrottleAngleScale(uint16_t throttle_correction_angle);
int16_t calculateThrottleAngleCorrection(uint8_t throttle_correction_value);
float calculateAccZLowPassFilterRCTimeConstant(float accz_lpf_cutoff);

View file

@ -44,6 +44,7 @@
#include "sensors/acceleration.h"
#include "flight/mixer.h"
#include "flight/failsafe.h"
#include "flight/pid.h"
#include "flight/imu.h"
#include "flight/lowpass.h"
@ -512,6 +513,11 @@ void stopMotors(void)
delay(50); // give the timers and ESCs a chance to react.
}
void StopPwmAllMotors()
{
pwmShutdownPulsesForAllMotors(motorCount);
}
#ifndef USE_QUAD_MIXER_ONLY
static void airplaneMixer(void)
{
@ -564,7 +570,7 @@ void mixTable(void)
{
uint32_t i;
if (motorCount >= 4 && mixerConfig->yaw_jump_prevention_limit < 500) {
if (motorCount >= 4 && mixerConfig->yaw_jump_prevention_limit < YAW_JUMP_PREVENTION_LIMIT_HIGH) {
// prevent "yaw jump" during yaw correction (500 is disabled jump protection)
axisPID[YAW] = constrain(axisPID[YAW], -mixerConfig->yaw_jump_prevention_limit - ABS(rcCommand[YAW]), mixerConfig->yaw_jump_prevention_limit + ABS(rcCommand[YAW]));
}
@ -677,6 +683,8 @@ void mixTable(void)
if (ARMING_FLAG(ARMED)) {
bool isFailsafeActive = failsafeIsActive();
// Find the maximum motor output.
int16_t maxMotor = motor[0];
for (i = 1; i < motorCount; i++) {
@ -701,14 +709,18 @@ void mixTable(void)
motor[i] = constrain(motor[i], escAndServoConfig->mincommand, flight3DConfig->deadband3d_low);
}
} else {
// If we're at minimum throttle and FEATURE_MOTOR_STOP enabled,
// do not spin the motors.
motor[i] = constrain(motor[i], escAndServoConfig->minthrottle, escAndServoConfig->maxthrottle);
if ((rcData[THROTTLE]) < rxConfig->mincheck) {
if (feature(FEATURE_MOTOR_STOP)) {
motor[i] = escAndServoConfig->mincommand;
} else if (mixerConfig->pid_at_min_throttle == 0) {
motor[i] = escAndServoConfig->minthrottle;
if (isFailsafeActive) {
motor[i] = constrain(motor[i], escAndServoConfig->mincommand, escAndServoConfig->maxthrottle);
} else {
// If we're at minimum throttle and FEATURE_MOTOR_STOP enabled,
// do not spin the motors.
motor[i] = constrain(motor[i], escAndServoConfig->minthrottle, escAndServoConfig->maxthrottle);
if ((rcData[THROTTLE]) < rxConfig->mincheck) {
if (feature(FEATURE_MOTOR_STOP)) {
motor[i] = escAndServoConfig->mincommand;
} else if (mixerConfig->pid_at_min_throttle == 0) {
motor[i] = escAndServoConfig->minthrottle;
}
}
}
}

View file

@ -18,7 +18,10 @@
#pragma once
#define MAX_SUPPORTED_MOTORS 12
#define MAX_SUPPORTED_SERVOS 8
#define MAX_SUPPORTED_SERVOS 10
#define YAW_JUMP_PREVENTION_LIMIT_LOW 80
#define YAW_JUMP_PREVENTION_LIMIT_HIGH 500
// Note: this is called MultiType/MULTITYPE_* in baseflight.
typedef enum mixerMode
@ -97,6 +100,10 @@ typedef struct servoParam_t {
int8_t forwardFromChannel; // RX channel index, 0 based. See CHANNEL_FORWARDING_DISABLED
} servoParam_t;
struct gimbalConfig_s;
struct escAndServoConfig_s;
struct rxConfig_s;
extern int16_t servo[MAX_SUPPORTED_SERVOS];
bool isMixerUsingServos(void);
void writeServos(void);
@ -106,9 +113,21 @@ void filterServos(void);
extern int16_t motor[MAX_SUPPORTED_MOTORS];
extern int16_t motor_disarmed[MAX_SUPPORTED_MOTORS];
void mixerUseConfigs(
#ifdef USE_SERVOS
servoParam_t *servoConfToUse,
struct gimbalConfig_s *gimbalConfigToUse,
#endif
flight3DConfig_t *flight3DConfigToUse,
struct escAndServoConfig_s *escAndServoConfigToUse,
mixerConfig_t *mixerConfigToUse,
airplaneConfig_t *airplaneConfigToUse,
struct rxConfig_s *rxConfigToUse);
void writeAllMotors(int16_t mc);
void mixerLoadMix(int index, motorMixer_t *customMixers);
void mixerResetMotors(void);
void mixTable(void);
void writeMotors(void);
void stopMotors(void);
void StopPwmAllMotors(void);

View file

@ -174,7 +174,7 @@ static void pidLuxFloat(pidProfile_t *pidProfile, controlRateConfig_t *controlRa
}
}
gyroRate = gyroData[axis] * gyro.scale; // gyro output scaled to dps
gyroRate = gyroADC[axis] * gyro.scale; // gyro output scaled to dps
// --------low-level gyro-based PID. ----------
// Used in stand-alone mode for ACRO, controlled by higher level regulators in other modes
@ -258,12 +258,12 @@ static void pidMultiWii(pidProfile_t *pidProfile, controlRateConfig_t *controlRa
}
if (!FLIGHT_MODE(ANGLE_MODE) || FLIGHT_MODE(HORIZON_MODE) || axis == FD_YAW) { // MODE relying on GYRO or YAW axis
error = (int32_t) rcCommand[axis] * 10 * 8 / pidProfile->P8[axis];
error -= gyroData[axis] / 4;
error -= gyroADC[axis] / 4;
PTermGYRO = rcCommand[axis];
errorGyroI[axis] = constrain(errorGyroI[axis] + error, -16000, +16000); // WindUp
if ((ABS(gyroData[axis]) > (640 * 4)) || (axis == FD_YAW && ABS(rcCommand[axis]) > 100))
if ((ABS(gyroADC[axis]) > (640 * 4)) || (axis == FD_YAW && ABS(rcCommand[axis]) > 100))
errorGyroI[axis] = 0;
ITermGYRO = (errorGyroI[axis] / 125 * pidProfile->I8[axis]) / 64;
@ -281,9 +281,9 @@ static void pidMultiWii(pidProfile_t *pidProfile, controlRateConfig_t *controlRa
}
}
PTerm -= ((int32_t)gyroData[axis] / 4) * dynP8[axis] / 10 / 8; // 32 bits is needed for calculation
delta = (gyroData[axis] - lastGyro[axis]) / 4;
lastGyro[axis] = gyroData[axis];
PTerm -= ((int32_t)gyroADC[axis] / 4) * dynP8[axis] / 10 / 8; // 32 bits is needed for calculation
delta = (gyroADC[axis] - lastGyro[axis]) / 4;
lastGyro[axis] = gyroADC[axis];
deltaSum = delta1[axis] + delta2[axis] + delta;
delta2[axis] = delta1[axis];
delta1[axis] = delta;
@ -298,8 +298,6 @@ static void pidMultiWii(pidProfile_t *pidProfile, controlRateConfig_t *controlRa
}
}
#define GYRO_I_MAX 256
static void pidMultiWii23(pidProfile_t *pidProfile, controlRateConfig_t *controlRateConfig, uint16_t max_angle_inclination,
rollAndPitchTrims_t *angleTrim, rxConfig_t *rxConfig)
{
@ -321,10 +319,10 @@ static void pidMultiWii23(pidProfile_t *pidProfile, controlRateConfig_t *control
rc = rcCommand[axis] << 1;
error = rc - (gyroData[axis] / 4);
error = rc - (gyroADC[axis] / 4);
errorGyroI[axis] = constrain(errorGyroI[axis] + error, -16000, +16000); // WindUp 16 bits is ok here
if (ABS(gyroData[axis]) > (640 * 4)) {
if (ABS(gyroADC[axis]) > (640 * 4)) {
errorGyroI[axis] = 0;
}
@ -361,10 +359,10 @@ static void pidMultiWii23(pidProfile_t *pidProfile, controlRateConfig_t *control
PTerm = PTermACC + ((PTerm - PTermACC) * prop >> 9);
}
PTerm -= ((int32_t)(gyroData[axis] / 4) * dynP8[axis]) >> 6; // 32 bits is needed for calculation
PTerm -= ((int32_t)(gyroADC[axis] / 4) * dynP8[axis]) >> 6; // 32 bits is needed for calculation
delta = (gyroData[axis] - lastGyro[axis]) / 4; // 16 bits is ok here, the dif between 2 consecutive gyro reads is limited to 800
lastGyro[axis] = gyroData[axis];
delta = (gyroADC[axis] - lastGyro[axis]) / 4; // 16 bits is ok here, the dif between 2 consecutive gyro reads is limited to 800
lastGyro[axis] = gyroADC[axis];
DTerm = delta1[axis] + delta2[axis] + delta;
delta2[axis] = delta1[axis];
delta1[axis] = delta;
@ -383,9 +381,9 @@ static void pidMultiWii23(pidProfile_t *pidProfile, controlRateConfig_t *control
//YAW
rc = (int32_t)rcCommand[FD_YAW] * (2 * controlRateConfig->rates[FD_YAW] + 30) >> 5;
#ifdef ALIENWII32
error = rc - gyroData[FD_YAW];
error = rc - gyroADC[FD_YAW];
#else
error = rc - (gyroData[FD_YAW] / 4);
error = rc - (gyroADC[FD_YAW] / 4);
#endif
errorGyroI[FD_YAW] += (int32_t)error * pidProfile->I8[FD_YAW];
errorGyroI[FD_YAW] = constrain(errorGyroI[FD_YAW], 2 - ((int32_t)1 << 28), -2 + ((int32_t)1 << 28));
@ -394,7 +392,7 @@ static void pidMultiWii23(pidProfile_t *pidProfile, controlRateConfig_t *control
PTerm = (int32_t)error * pidProfile->P8[FD_YAW] >> 6; // TODO: Bitwise shift on a signed integer is not recommended
// Constrain YAW by D value if not servo driven in that case servolimits apply
if(motorCount >= 4 && pidProfile->yaw_p_limit) {
if(motorCount >= 4 && pidProfile->yaw_p_limit < YAW_P_LIMIT_MAX) {
PTerm = constrain(PTerm, -pidProfile->yaw_p_limit, pidProfile->yaw_p_limit);
}
@ -452,12 +450,12 @@ static void pidMultiWiiHybrid(pidProfile_t *pidProfile, controlRateConfig_t *con
}
if (!FLIGHT_MODE(ANGLE_MODE) || FLIGHT_MODE(HORIZON_MODE)) { // MODE relying on GYRO
error = (int32_t) rcCommand[axis] * 10 * 8 / pidProfile->P8[axis];
error -= gyroData[axis] / 4;
error -= gyroADC[axis] / 4;
PTermGYRO = rcCommand[axis];
errorGyroI[axis] = constrain(errorGyroI[axis] + error, -16000, +16000); // WindUp
if (ABS(gyroData[axis]) > (640 * 4))
if (ABS(gyroADC[axis]) > (640 * 4))
errorGyroI[axis] = 0;
ITermGYRO = (errorGyroI[axis] / 125 * pidProfile->I8[axis]) / 64;
@ -475,9 +473,9 @@ static void pidMultiWiiHybrid(pidProfile_t *pidProfile, controlRateConfig_t *con
}
}
PTerm -= ((int32_t)gyroData[axis] / 4) * dynP8[axis] / 10 / 8; // 32 bits is needed for calculation
delta = (gyroData[axis] - lastGyro[axis]) / 4;
lastGyro[axis] = gyroData[axis];
PTerm -= ((int32_t)gyroADC[axis] / 4) * dynP8[axis] / 10 / 8; // 32 bits is needed for calculation
delta = (gyroADC[axis] - lastGyro[axis]) / 4;
lastGyro[axis] = gyroADC[axis];
deltaSum = delta1[axis] + delta2[axis] + delta;
delta2[axis] = delta1[axis];
delta1[axis] = delta;
@ -493,9 +491,9 @@ static void pidMultiWiiHybrid(pidProfile_t *pidProfile, controlRateConfig_t *con
//YAW
rc = (int32_t)rcCommand[FD_YAW] * (2 * controlRateConfig->rates[FD_YAW] + 30) >> 5;
#ifdef ALIENWII32
error = rc - gyroData[FD_YAW];
error = rc - gyroADC[FD_YAW];
#else
error = rc - (gyroData[FD_YAW] / 4);
error = rc - (gyroADC[FD_YAW] / 4);
#endif
errorGyroI[FD_YAW] += (int32_t)error * pidProfile->I8[FD_YAW];
errorGyroI[FD_YAW] = constrain(errorGyroI[FD_YAW], 2 - ((int32_t)1 << 28), -2 + ((int32_t)1 << 28));
@ -504,7 +502,7 @@ static void pidMultiWiiHybrid(pidProfile_t *pidProfile, controlRateConfig_t *con
PTerm = (int32_t)error * pidProfile->P8[FD_YAW] >> 6;
// Constrain YAW by D value if not servo driven in that case servolimits apply
if(motorCount >= 4 && pidProfile->yaw_p_limit) {
if(motorCount >= 4 && pidProfile->yaw_p_limit < YAW_P_LIMIT_MAX) {
PTerm = constrain(PTerm, -pidProfile->yaw_p_limit, pidProfile->yaw_p_limit);
}
@ -520,16 +518,12 @@ static void pidMultiWiiHybrid(pidProfile_t *pidProfile, controlRateConfig_t *con
#endif
}
#define RCconstPI 0.159154943092f // 0.5f / M_PI;
#define MAIN_CUT_HZ 12.0f // (default 12Hz, Range 1-50Hz)
#define OLD_YAW 0 // [0/1] 0 = multiwii 2.3 yaw, 1 = older yaw.
static void pidHarakiri(pidProfile_t *pidProfile, controlRateConfig_t *controlRateConfig, uint16_t max_angle_inclination,
rollAndPitchTrims_t *angleTrim, rxConfig_t *rxConfig)
{
UNUSED(rxConfig);
float delta, RCfactor, rcCommandAxis, MainDptCut, gyroDataQuant;
float delta, RCfactor, rcCommandAxis, MainDptCut, gyroADCQuant;
float PTerm, ITerm, DTerm, PTermACC = 0.0f, ITermACC = 0.0f, ITermGYRO, error, prop = 0.0f;
static float lastGyro[2] = { 0.0f, 0.0f }, lastDTerm[2] = { 0.0f, 0.0f };
uint8_t axis;
@ -546,8 +540,8 @@ rollAndPitchTrims_t *angleTrim, rxConfig_t *rxConfig)
}
for (axis = 0; axis < 2; axis++) {
int32_t tmp = (int32_t)((float)gyroData[axis] * 0.3125f); // Multiwii masks out the last 2 bits, this has the same idea
gyroDataQuant = (float)tmp * 3.2f; // but delivers more accuracy and also reduces jittery flight
int32_t tmp = (int32_t)((float)gyroADC[axis] * 0.3125f); // Multiwii masks out the last 2 bits, this has the same idea
gyroADCQuant = (float)tmp * 3.2f; // but delivers more accuracy and also reduces jittery flight
rcCommandAxis = (float)rcCommand[axis]; // Calculate common values for pid controllers
if (FLIGHT_MODE(ANGLE_MODE) || FLIGHT_MODE(HORIZON_MODE)) {
#ifdef GPS
@ -569,10 +563,10 @@ rollAndPitchTrims_t *angleTrim, rxConfig_t *rxConfig)
}
if (!FLIGHT_MODE(ANGLE_MODE)) {
if (ABS((int16_t)gyroData[axis]) > 2560) {
if (ABS((int16_t)gyroADC[axis]) > 2560) {
errorGyroIf[axis] = 0.0f;
} else {
error = (rcCommandAxis * 320.0f / (float)pidProfile->P8[axis]) - gyroDataQuant;
error = (rcCommandAxis * 320.0f / (float)pidProfile->P8[axis]) - gyroADCQuant;
errorGyroIf[axis] = constrainf(errorGyroIf[axis] + error * ACCDeltaTimeINS, -192.0f, +192.0f);
}
@ -590,10 +584,10 @@ rollAndPitchTrims_t *angleTrim, rxConfig_t *rxConfig)
ITerm = ITermACC;
}
PTerm -= gyroDataQuant * dynP8[axis] * 0.003f;
delta = (gyroDataQuant - lastGyro[axis]) / ACCDeltaTimeINS;
PTerm -= gyroADCQuant * dynP8[axis] * 0.003f;
delta = (gyroADCQuant - lastGyro[axis]) / ACCDeltaTimeINS;
lastGyro[axis] = gyroDataQuant;
lastGyro[axis] = gyroADCQuant;
lastDTerm[axis] += RCfactor * (delta - lastDTerm[axis]);
DTerm = lastDTerm[axis] * dynD8[axis] * 0.00007f;
@ -611,7 +605,7 @@ rollAndPitchTrims_t *angleTrim, rxConfig_t *rxConfig)
if (OLD_YAW) { // [0/1] 0 = multiwii 2.3 yaw, 1 = older yaw. hardcoded for now
PTerm = ((int32_t)pidProfile->P8[FD_YAW] * (100 - (int32_t)controlRateConfig->rates[FD_YAW] * (int32_t)ABS(rcCommand[FD_YAW]) / 500)) / 100;
int32_t tmp = lrintf(gyroData[FD_YAW] * 0.25f);
int32_t tmp = lrintf(gyroADC[FD_YAW] * 0.25f);
PTerm = rcCommand[FD_YAW] - tmp * PTerm / 80;
if ((ABS(tmp) > 640) || (ABS(rcCommand[FD_YAW]) > 100)) {
errorGyroI[FD_YAW] = 0;
@ -622,7 +616,7 @@ rollAndPitchTrims_t *angleTrim, rxConfig_t *rxConfig)
}
} else {
int32_t tmp = ((int32_t)rcCommand[FD_YAW] * (((int32_t)controlRateConfig->rates[FD_YAW] << 1) + 40)) >> 5;
error = tmp - lrintf(gyroData[FD_YAW] * 0.25f); // Less Gyrojitter works actually better
error = tmp - lrintf(gyroADC[FD_YAW] * 0.25f); // Less Gyrojitter works actually better
if (ABS(tmp) > 50) {
errorGyroI[FD_YAW] = 0;
@ -633,7 +627,7 @@ rollAndPitchTrims_t *angleTrim, rxConfig_t *rxConfig)
ITerm = constrain(errorGyroI[FD_YAW] >> 13, -GYRO_I_MAX, +GYRO_I_MAX);
PTerm = ((int32_t)error * (int32_t)pidProfile->P8[FD_YAW]) >> 6;
if(motorCount >= 4 && pidProfile->yaw_p_limit) { // Constrain FD_YAW by D value if not servo driven in that case servolimits apply
if(motorCount >= 4 && pidProfile->yaw_p_limit < YAW_P_LIMIT_MAX) { // Constrain FD_YAW by D value if not servo driven in that case servolimits apply
PTerm = constrain(PTerm, -pidProfile->yaw_p_limit, pidProfile->yaw_p_limit);
}
}
@ -660,6 +654,30 @@ static void pidRewrite(pidProfile_t *pidProfile, controlRateConfig_t *controlRat
static int32_t lastError[3] = { 0, 0, 0 };
int32_t AngleRateTmp, RateError;
int8_t horizonLevelStrength = 100;
int32_t stickPosAil, stickPosEle, mostDeflectedPos;
if (FLIGHT_MODE(HORIZON_MODE)) {
// Figure out the raw stick positions
stickPosAil = getRcStickDeflection(FD_ROLL, rxConfig->midrc);
stickPosEle = getRcStickDeflection(FD_PITCH, rxConfig->midrc);
if(ABS(stickPosAil) > ABS(stickPosEle)){
mostDeflectedPos = ABS(stickPosAil);
}
else {
mostDeflectedPos = ABS(stickPosEle);
}
// Progressively turn off the horizon self level strength as the stick is banged over
horizonLevelStrength = (500 - mostDeflectedPos) / 5; // 100 at centre stick, 0 = max stick deflection
// Using Level D as a Sensitivity for Horizon. 0 more level to 255 more rate. Default value of 100 seems to work fine.
// For more rate mode increase D and slower flips and rolls will be possible
horizonLevelStrength = constrain((10 * (horizonLevelStrength - 100) * (10 * pidProfile->D8[PIDLEVEL] / 80) / 100) + 100, 0, 100);
}
// ----------PID controller----------
for (axis = 0; axis < 3; axis++) {
uint8_t rate = controlRateConfig->rates[axis];
@ -686,8 +704,8 @@ static void pidRewrite(pidProfile_t *pidProfile, controlRateConfig_t *controlRat
if (!FLIGHT_MODE(ANGLE_MODE)) { //control is GYRO based (ACRO and HORIZON - direct sticks control is applied to rate PID
AngleRateTmp = ((int32_t)(rate + 27) * rcCommand[axis]) >> 4;
if (FLIGHT_MODE(HORIZON_MODE)) {
// mix up angle error to desired AngleRateTmp to add a little auto-level feel
AngleRateTmp += (errorAngle * pidProfile->I8[PIDLEVEL]) >> 8;
// mix up angle error to desired AngleRateTmp to add a little auto-level feel. horizonLevelStrength is scaled to the stick input
AngleRateTmp += (errorAngle * pidProfile->I8[PIDLEVEL] * horizonLevelStrength / 100) >> 4;
}
} else { // it's the ANGLE mode - control is angle based, so control loop is needed
AngleRateTmp = (errorAngle * pidProfile->P8[PIDLEVEL]) >> 4;
@ -698,7 +716,7 @@ static void pidRewrite(pidProfile_t *pidProfile, controlRateConfig_t *controlRat
// Used in stand-alone mode for ACRO, controlled by higher level regulators in other modes
// -----calculate scaled error.AngleRates
// multiplication of rcCommand corresponds to changing the sticks scaling here
RateError = AngleRateTmp - (gyroData[axis] / 4);
RateError = AngleRateTmp - (gyroADC[axis] / 4);
// -----calculate P component
PTerm = (RateError * pidProfile->P8[axis] * PIDweight[axis] / 100) >> 7;

View file

@ -17,6 +17,12 @@
#pragma once
#define GYRO_I_MAX 256 // Gyro I limiter
#define RCconstPI 0.159154943092f // 0.5f / M_PI;
#define MAIN_CUT_HZ 12.0f // (default 12Hz, Range 1-50Hz)
#define OLD_YAW 0 // [0/1] 0 = MultiWii 2.3 yaw, 1 = older yaw.
#define YAW_P_LIMIT_MIN 100 // Maximum value for yaw P limiter
#define YAW_P_LIMIT_MAX 500 // Maximum value for yaw P limiter
typedef enum {
PIDROLL,

View file

@ -20,6 +20,7 @@
#include "stdlib.h"
#include "platform.h"
#include "build_config.h"
#include "drivers/gpio.h"
#include "drivers/sound_beeper.h"
@ -29,6 +30,7 @@
#include "rx/rx.h"
#include "io/rc_controls.h"
#include "io/statusindicator.h"
#ifdef GPS
#include "io/gps.h"
@ -37,8 +39,13 @@
#include "config/runtime_config.h"
#include "config/config.h"
#include "io/beeper.h"
#if FLASH_SIZE > 64
#define BEEPER_NAMES
#endif
#define MAX_MULTI_BEEPS 20 //size limit for 'beep_multiBeeps[]'
#define BEEPER_COMMAND_REPEAT 0xFE
@ -70,7 +77,7 @@ static const uint8_t beep_disarmBeep[] = {
};
// beeps while stick held in disarm position (after pause)
static const uint8_t beep_disarmRepeatBeep[] = {
0, 35, 40, 5, BEEPER_COMMAND_STOP
0, 100, 10, BEEPER_COMMAND_STOP
};
// Long beep and pause after that
static const uint8_t beep_lowBatteryBeep[] = {
@ -105,6 +112,11 @@ static const uint8_t beep_2shortBeeps[] = {
static const uint8_t beep_2longerBeeps[] = {
20, 15, 35, 5, BEEPER_COMMAND_STOP
};
// 3 beeps
static const uint8_t beep_gyroCalibrated[] = {
20, 10, 20, 10, 20, 10, BEEPER_COMMAND_STOP
};
// array used for variable # of beeps (reporting GPS sat count, etc)
static uint8_t beep_multiBeeps[MAX_MULTI_BEEPS + 2];
@ -128,25 +140,34 @@ typedef struct beeperTableEntry_s {
uint8_t mode;
uint8_t priority; // 0 = Highest
const uint8_t *sequence;
#ifdef BEEPER_NAMES
const char *name;
#endif
} beeperTableEntry_t;
#ifdef BEEPER_NAMES
#define BEEPER_ENTRY(a,b,c,d) a,b,c,d
#else
#define BEEPER_ENTRY(a,b,c,d) a,b,c
#endif
static const beeperTableEntry_t const beeperTable[] = {
{ BEEPER_RX_LOST_LANDING, 0, beep_sos, "RX_LOST_LANDING" },
{ BEEPER_RX_LOST, 1, beep_txLostBeep, "RX_LOST" },
{ BEEPER_DISARMING, 2, beep_disarmBeep, "DISARMING" },
{ BEEPER_ARMING, 3, beep_armingBeep, "ARMING" },
{ BEEPER_ARMING_GPS_FIX, 4, beep_armedGpsFix, "ARMING_GPS_FIX" },
{ BEEPER_BAT_CRIT_LOW, 5, beep_critBatteryBeep, "BAT_CRIT_LOW" },
{ BEEPER_BAT_LOW, 6, beep_lowBatteryBeep, "BAT_LOW" },
{ BEEPER_GPS_STATUS, 7, beep_multiBeeps, NULL },
{ BEEPER_RX_SET, 8, beep_shortBeep, "RX_SET" },
{ BEEPER_DISARM_REPEAT, 9, beep_disarmRepeatBeep, "DISARM_REPEAT" },
{ BEEPER_ACC_CALIBRATION, 10, beep_2shortBeeps, "ACC_CALIBRATION" },
{ BEEPER_ACC_CALIBRATION_FAIL, 11, beep_2longerBeeps, "ACC_CALIBRATION_FAIL" },
{ BEEPER_READY_BEEP, 12, beep_readyBeep, "READY_BEEP" },
{ BEEPER_MULTI_BEEPS, 13, beep_multiBeeps, NULL }, // FIXME having this listed makes no sense since the beep array will not be initialised.
{ BEEPER_ARMED, 14, beep_armedBeep, "ARMED" },
{ BEEPER_ENTRY(BEEPER_GYRO_CALIBRATED, 0, beep_gyroCalibrated, "GYRO_CALIBRATED") },
{ BEEPER_ENTRY(BEEPER_RX_LOST_LANDING, 1, beep_sos, "RX_LOST_LANDING") },
{ BEEPER_ENTRY(BEEPER_RX_LOST, 2, beep_txLostBeep, "RX_LOST") },
{ BEEPER_ENTRY(BEEPER_DISARMING, 3, beep_disarmBeep, "DISARMING") },
{ BEEPER_ENTRY(BEEPER_ARMING, 4, beep_armingBeep, "ARMING") },
{ BEEPER_ENTRY(BEEPER_ARMING_GPS_FIX, 5, beep_armedGpsFix, "ARMING_GPS_FIX") },
{ BEEPER_ENTRY(BEEPER_BAT_CRIT_LOW, 6, beep_critBatteryBeep, "BAT_CRIT_LOW") },
{ BEEPER_ENTRY(BEEPER_BAT_LOW, 7, beep_lowBatteryBeep, "BAT_LOW") },
{ BEEPER_ENTRY(BEEPER_GPS_STATUS, 8, beep_multiBeeps, NULL) },
{ BEEPER_ENTRY(BEEPER_RX_SET, 9, beep_shortBeep, "RX_SET") },
{ BEEPER_ENTRY(BEEPER_ACC_CALIBRATION, 10, beep_2shortBeeps, "ACC_CALIBRATION") },
{ BEEPER_ENTRY(BEEPER_ACC_CALIBRATION_FAIL, 11, beep_2longerBeeps, "ACC_CALIBRATION_FAIL") },
{ BEEPER_ENTRY(BEEPER_READY_BEEP, 12, beep_readyBeep, "READY_BEEP") },
{ BEEPER_ENTRY(BEEPER_MULTI_BEEPS, 13, beep_multiBeeps, NULL) }, // FIXME having this listed makes no sense since the beep array will not be initialised.
{ BEEPER_ENTRY(BEEPER_DISARM_REPEAT, 14, beep_disarmRepeatBeep, "DISARM_REPEAT") },
{ BEEPER_ENTRY(BEEPER_ARMED, 15, beep_armedBeep, "ARMED") },
};
static const beeperTableEntry_t *currentBeeperEntry = NULL;
@ -196,6 +217,10 @@ void beeper(beeperMode_e mode)
void beeperSilence(void)
{
BEEP_OFF;
warningLedDisable();
warningLedRefresh();
beeperIsOn = 0;
beeperNextToggleTime = 0;
@ -278,7 +303,9 @@ void beeperUpdate(void)
beeperIsOn = 1;
if (currentBeeperEntry->sequence[beeperPos] != 0) {
BEEP_ON;
//if this was arming beep then mark time (for blackbox)
warningLedEnable();
warningLedRefresh();
// if this was arming beep then mark time (for blackbox)
if (
beeperPos == 0
&& (currentBeeperEntry->mode == BEEPER_ARMING || currentBeeperEntry->mode == BEEPER_ARMING_GPS_FIX)
@ -290,6 +317,8 @@ void beeperUpdate(void)
beeperIsOn = 0;
if (currentBeeperEntry->sequence[beeperPos] != 0) {
BEEP_OFF;
warningLedDisable();
warningLedRefresh();
}
}
@ -318,7 +347,7 @@ static void beeperProcessCommand(void)
*/
uint32_t getArmingBeepTimeMicros(void)
{
return armingBeepTimeMicros;
return armingBeepTimeMicros;
}
/*
@ -327,8 +356,7 @@ uint32_t getArmingBeepTimeMicros(void)
*/
beeperMode_e beeperModeForTableIndex(int idx)
{
return (idx >= 0 && idx < (int)BEEPER_TABLE_ENTRY_COUNT) ?
beeperTable[idx].mode : BEEPER_SILENCE;
return (idx >= 0 && idx < (int)BEEPER_TABLE_ENTRY_COUNT) ? beeperTable[idx].mode : BEEPER_SILENCE;
}
/*
@ -336,8 +364,12 @@ beeperMode_e beeperModeForTableIndex(int idx)
*/
const char *beeperNameForTableIndex(int idx)
{
return (idx >= 0 && idx < (int)BEEPER_TABLE_ENTRY_COUNT) ?
beeperTable[idx].name : NULL;
#ifndef BEEPER_NAMES
UNUSED(idx);
return NULL;
#else
return (idx >= 0 && idx < (int)BEEPER_TABLE_ENTRY_COUNT) ? beeperTable[idx].name : NULL;
#endif
}
/*

View file

@ -21,6 +21,7 @@ typedef enum {
// IMPORTANT: these are in priority order, 0 = Highest
BEEPER_SILENCE = 0, // Silence, see beeperSilence()
BEEPER_GYRO_CALIBRATED,
BEEPER_RX_LOST_LANDING, // Beeps SOS when armed and TX is turned off or signal lost (autolanding/autodisarm)
BEEPER_RX_LOST, // Beeps when TX is turned off or signal lost (repeat until TX is okay)
BEEPER_DISARMING, // Beep when disarming the board

View file

@ -83,7 +83,7 @@ static char lineBuffer[SCREEN_CHARACTER_COLUMN_COUNT + 1];
#define HALF_SCREEN_CHARACTER_COLUMN_COUNT (SCREEN_CHARACTER_COLUMN_COUNT / 2)
#define IS_SCREEN_CHARACTER_COLUMN_COUNT_ODD (SCREEN_CHARACTER_COLUMN_COUNT & 1)
const char* pageTitles[] = {
static const char* const pageTitles[] = {
"CLEANFLIGHT",
"ARMED",
"BATTERY",

View file

@ -140,23 +140,23 @@ void processRcStickPositions(rxConfig_t *rxConfig, throttleStatus_e throttleStat
return;
}
if (isUsingSticksToArm) {
// Disarm on throttle down + yaw
if (isUsingSticksToArm) {
// Disarm on throttle down + yaw
if (rcSticks == THR_LO + YAW_LO + PIT_CE + ROL_CE) {
if (ARMING_FLAG(ARMED)) //board was armed
if (ARMING_FLAG(ARMED))
mwDisarm();
else { //board was not armed
beeper(BEEPER_DISARM_REPEAT); //sound tone while stick held
rcDelayCommand = 0; //reset so disarm tone will repeat
else {
beeper(BEEPER_DISARM_REPEAT); // sound tone while stick held
rcDelayCommand = 0; // reset so disarm tone will repeat
}
}
// Disarm on roll (only when retarded_arm is enabled)
if (retarded_arm && (rcSticks == THR_LO + YAW_CE + PIT_CE + ROL_LO)) {
if (ARMING_FLAG(ARMED)) //board was armed
if (ARMING_FLAG(ARMED))
mwDisarm();
else { //board was not armed
beeper(BEEPER_DISARM_REPEAT); //sound tone while stick held
rcDelayCommand = 0; //reset so disarm tone will repeat
else {
beeper(BEEPER_DISARM_REPEAT); // sound tone while stick held
rcDelayCommand = 0; // reset so disarm tone will repeat
}
}
}
@ -371,6 +371,46 @@ static const adjustmentConfig_t defaultAdjustmentConfigs[ADJUSTMENT_FUNCTION_COU
.adjustmentFunction = ADJUSTMENT_RATE_PROFILE,
.mode = ADJUSTMENT_MODE_SELECT,
.data.selectConfig.switchPositions = 3
},
{
.adjustmentFunction = ADJUSTMENT_PITCH_RATE,
.mode = ADJUSTMENT_MODE_STEP,
.data.stepConfig.step = 1
},
{
.adjustmentFunction = ADJUSTMENT_ROLL_RATE,
.mode = ADJUSTMENT_MODE_STEP,
.data.stepConfig.step = 1
},
{
.adjustmentFunction = ADJUSTMENT_PITCH_P,
.mode = ADJUSTMENT_MODE_STEP,
.data.stepConfig.step = 1
},
{
.adjustmentFunction = ADJUSTMENT_PITCH_I,
.mode = ADJUSTMENT_MODE_STEP,
.data.stepConfig.step = 1
},
{
.adjustmentFunction = ADJUSTMENT_PITCH_D,
.mode = ADJUSTMENT_MODE_STEP,
.data.stepConfig.step = 1
},
{
.adjustmentFunction = ADJUSTMENT_ROLL_P,
.mode = ADJUSTMENT_MODE_STEP,
.data.stepConfig.step = 1
},
{
.adjustmentFunction = ADJUSTMENT_ROLL_I,
.mode = ADJUSTMENT_MODE_STEP,
.data.stepConfig.step = 1
},
{
.adjustmentFunction = ADJUSTMENT_ROLL_D,
.mode = ADJUSTMENT_MODE_STEP,
.data.stepConfig.step = 1
}
};
@ -434,40 +474,67 @@ void applyStepAdjustment(controlRateConfig_t *controlRateConfig, uint8_t adjustm
controlRateConfig->rates[FD_YAW] = constrain(newValue, 0, CONTROL_RATE_CONFIG_YAW_RATE_MAX);
break;
case ADJUSTMENT_PITCH_ROLL_P:
case ADJUSTMENT_PITCH_P:
if (IS_PID_CONTROLLER_FP_BASED(pidProfile->pidController)) {
newFloatValue = pidProfile->P_f[PIDPITCH] + (float)(delta / 10.0f);
pidProfile->P_f[PIDPITCH] = constrainf(newFloatValue, 0, 100); // FIXME magic numbers repeated in serial_cli.c
newFloatValue = pidProfile->P_f[PIDROLL] + (float)(delta / 10.0f);
pidProfile->P_f[PIDROLL] = constrainf(newFloatValue, 0, 100); // FIXME magic numbers repeated in serial_cli.c
} else {
newValue = (int)pidProfile->P8[PIDPITCH] + delta;
pidProfile->P8[PIDPITCH] = constrain(newValue, 0, 200); // FIXME magic numbers repeated in serial_cli.c
}
if (adjustmentFunction == ADJUSTMENT_PITCH_P) {
break;
}
// follow though for combined ADJUSTMENT_PITCH_ROLL_P
case ADJUSTMENT_ROLL_P:
if (IS_PID_CONTROLLER_FP_BASED(pidProfile->pidController)) {
newFloatValue = pidProfile->P_f[PIDROLL] + (float)(delta / 10.0f);
pidProfile->P_f[PIDROLL] = constrainf(newFloatValue, 0, 100); // FIXME magic numbers repeated in serial_cli.c
} else {
newValue = (int)pidProfile->P8[PIDROLL] + delta;
pidProfile->P8[PIDROLL] = constrain(newValue, 0, 200); // FIXME magic numbers repeated in serial_cli.c
}
break;
case ADJUSTMENT_PITCH_ROLL_I:
case ADJUSTMENT_PITCH_I:
if (IS_PID_CONTROLLER_FP_BASED(pidProfile->pidController)) {
newFloatValue = pidProfile->I_f[PIDPITCH] + (float)(delta / 100.0f);
pidProfile->I_f[PIDPITCH] = constrainf(newFloatValue, 0, 100); // FIXME magic numbers repeated in serial_cli.c
newFloatValue = pidProfile->I_f[PIDROLL] + (float)(delta / 100.0f);
pidProfile->I_f[PIDROLL] = constrainf(newFloatValue, 0, 100); // FIXME magic numbers repeated in serial_cli.c
} else {
newValue = (int)pidProfile->I8[PIDPITCH] + delta;
pidProfile->I8[PIDPITCH] = constrain(newValue, 0, 200); // FIXME magic numbers repeated in serial_cli.c
}
if (adjustmentFunction == ADJUSTMENT_PITCH_I) {
break;
}
// follow though for combined ADJUSTMENT_PITCH_ROLL_I
case ADJUSTMENT_ROLL_I:
if (IS_PID_CONTROLLER_FP_BASED(pidProfile->pidController)) {
newFloatValue = pidProfile->I_f[PIDROLL] + (float)(delta / 100.0f);
pidProfile->I_f[PIDROLL] = constrainf(newFloatValue, 0, 100); // FIXME magic numbers repeated in serial_cli.c
} else {
newValue = (int)pidProfile->I8[PIDROLL] + delta;
pidProfile->I8[PIDROLL] = constrain(newValue, 0, 200); // FIXME magic numbers repeated in serial_cli.c
}
break;
case ADJUSTMENT_PITCH_ROLL_D:
case ADJUSTMENT_PITCH_D:
if (IS_PID_CONTROLLER_FP_BASED(pidProfile->pidController)) {
newFloatValue = pidProfile->D_f[PIDPITCH] + (float)(delta / 1000.0f);
pidProfile->D_f[PIDPITCH] = constrainf(newFloatValue, 0, 100); // FIXME magic numbers repeated in serial_cli.c
newFloatValue = pidProfile->D_f[PIDROLL] + (float)(delta / 1000.0f);
pidProfile->D_f[PIDROLL] = constrainf(newFloatValue, 0, 100); // FIXME magic numbers repeated in serial_cli.c
} else {
newValue = (int)pidProfile->D8[PIDPITCH] + delta;
pidProfile->D8[PIDPITCH] = constrain(newValue, 0, 200); // FIXME magic numbers repeated in serial_cli.c
}
if (adjustmentFunction == ADJUSTMENT_PITCH_D) {
break;
}
// follow though for combined ADJUSTMENT_PITCH_ROLL_D
case ADJUSTMENT_ROLL_D:
if (IS_PID_CONTROLLER_FP_BASED(pidProfile->pidController)) {
newFloatValue = pidProfile->D_f[PIDROLL] + (float)(delta / 1000.0f);
pidProfile->D_f[PIDROLL] = constrainf(newFloatValue, 0, 100); // FIXME magic numbers repeated in serial_cli.c
} else {
newValue = (int)pidProfile->D8[PIDROLL] + delta;
pidProfile->D8[PIDROLL] = constrain(newValue, 0, 200); // FIXME magic numbers repeated in serial_cli.c
}
@ -531,6 +598,9 @@ void processRcAdjustments(controlRateConfig_t *controlRateConfig, rxConfig_t *rx
uint8_t adjustmentIndex;
uint32_t now = millis();
bool canUseRxData = rxIsReceivingSignal();
for (adjustmentIndex = 0; adjustmentIndex < MAX_SIMULTANEOUS_ADJUSTMENT_COUNT; adjustmentIndex++) {
adjustmentState_t *adjustmentState = &adjustmentStates[adjustmentIndex];
@ -550,6 +620,9 @@ void processRcAdjustments(controlRateConfig_t *controlRateConfig, rxConfig_t *rx
MARK_ADJUSTMENT_FUNCTION_AS_READY(adjustmentIndex);
}
if (!canUseRxData) {
continue;
}
uint8_t channelIndex = NON_AUX_CHANNEL_COUNT + adjustmentState->auxChannelIndex;

View file

@ -84,12 +84,7 @@ typedef enum {
#define THR_CE (3 << (2 * THROTTLE))
#define THR_HI (2 << (2 * THROTTLE))
#define MAX_MODE_ACTIVATION_CONDITION_COUNT 40
// 40 is enough for 1 mode for each position of 11 * 3 position switches and a 6 pos switch.
// however, that is unlikely because you don't define the 'off' positions, so for a 3 position
// switch it's normal that only 2 values would be configured.
// this leaves plenty of 'slots' free for cases where you enable multiple modes for a switch
// position (like gps rth + horizon + baro + beeper)
#define MAX_MODE_ACTIVATION_CONDITION_COUNT 20
#define CHANNEL_RANGE_MIN 900
#define CHANNEL_RANGE_MAX 2100
@ -170,9 +165,16 @@ typedef enum {
ADJUSTMENT_RATE_PROFILE,
ADJUSTMENT_PITCH_RATE,
ADJUSTMENT_ROLL_RATE,
ADJUSTMENT_PITCH_P,
ADJUSTMENT_PITCH_I,
ADJUSTMENT_PITCH_D,
ADJUSTMENT_ROLL_P,
ADJUSTMENT_ROLL_I,
ADJUSTMENT_ROLL_D,
} adjustmentFunction_e;
#define ADJUSTMENT_FUNCTION_COUNT 15
#define ADJUSTMENT_FUNCTION_COUNT 21
typedef enum {
ADJUSTMENT_MODE_STEP,

View file

@ -53,7 +53,7 @@
static serialConfig_t *serialConfig;
static serialPortUsage_t serialPortUsageList[SERIAL_PORT_COUNT];
serialPortIdentifier_e serialPortIdentifiers[SERIAL_PORT_COUNT] = {
const serialPortIdentifier_e serialPortIdentifiers[SERIAL_PORT_COUNT] = {
#ifdef USE_VCP
SERIAL_PORT_USB_VCP,
#endif
@ -74,7 +74,9 @@ serialPortIdentifier_e serialPortIdentifiers[SERIAL_PORT_COUNT] = {
#endif
};
uint32_t baudRates[] = {0, 9600, 19200, 38400, 57600, 115200, 230400, 250000}; // see baudRate_e
static uint8_t serialPortCount;
const uint32_t baudRates[] = {0, 9600, 19200, 38400, 57600, 115200, 230400, 250000}; // see baudRate_e
#define BAUD_RATE_COUNT (sizeof(baudRates) / sizeof(baudRates[0]))
@ -87,7 +89,7 @@ baudRate_e lookupBaudRateIndex(uint32_t baudRate)
return index;
}
}
return 0;
return BAUD_AUTO;
}
static serialPortUsage_t *findSerialPortUsageByIdentifier(serialPortIdentifier_e identifier)
@ -226,16 +228,22 @@ bool isSerialConfigValid(serialConfig_t *serialConfigToCheck)
return true;
}
bool doesConfigurationUsePort(serialPortIdentifier_e identifier)
serialPortConfig_t *serialFindPortConfiguration(serialPortIdentifier_e identifier)
{
uint8_t index;
for (index = 0; index < SERIAL_PORT_COUNT; index++) {
serialPortConfig_t *candidate = &serialConfig->portConfigs[index];
if (candidate->identifier == identifier && candidate->functionMask) {
return true;
if (candidate->identifier == identifier) {
return candidate;
}
}
return false;
return NULL;
}
bool doesConfigurationUsePort(serialPortIdentifier_e identifier)
{
serialPortConfig_t *candidate = serialFindPortConfiguration(identifier);
return candidate != NULL && candidate->functionMask;
}
serialPort_t *openSerialPort(
@ -246,6 +254,13 @@ serialPort_t *openSerialPort(
portMode_t mode,
portOptions_t options)
{
#if (!defined(USE_VCP) && !defined(USE_USART1) && !defined(USE_USART2) && !defined(USE_USART3) && !defined(USE_SOFTSERIAL1) && !defined(USE_SOFTSERIAL1))
UNUSED(callback);
UNUSED(baudRate);
UNUSED(mode);
UNUSED(options);
#endif
serialPortUsage_t *serialPortUsage = findSerialPortUsageByIdentifier(identifier);
if (!serialPortUsage || serialPortUsage->function != FUNCTION_NONE) {
// not available / already in use
@ -324,6 +339,7 @@ void serialInit(serialConfig_t *initialSerialConfig, bool softserialEnabled)
serialConfig = initialSerialConfig;
serialPortCount = SERIAL_PORT_COUNT;
memset(&serialPortUsageList, 0, sizeof(serialPortUsageList));
for (index = 0; index < SERIAL_PORT_COUNT; index++) {
@ -339,18 +355,46 @@ void serialInit(serialConfig_t *initialSerialConfig, bool softserialEnabled)
#endif
) {
serialPortUsageList[index].identifier = SERIAL_PORT_NONE;
serialPortCount--;
}
}
}
}
void serialRemovePort(serialPortIdentifier_e identifier)
{
for (uint8_t index = 0; index < SERIAL_PORT_COUNT; index++) {
if (serialPortUsageList[index].identifier == identifier) {
serialPortUsageList[index].identifier = SERIAL_PORT_NONE;
serialPortCount--;
}
}
}
uint8_t serialGetAvailablePortCount(void)
{
return serialPortCount;
}
bool serialIsPortAvailable(serialPortIdentifier_e identifier)
{
for (uint8_t index = 0; index < SERIAL_PORT_COUNT; index++) {
if (serialPortUsageList[index].identifier == identifier) {
return true;
}
}
return false;
}
void handleSerial(void)
{
#ifdef USE_CLI
// in cli mode, all serial stuff goes to here. enter cli mode by sending #
if (cliMode) {
cliProcess();
return;
}
#endif
mspProcess();
}
@ -366,9 +410,14 @@ void cliEnter(serialPort_t *serialPort);
void evaluateOtherData(serialPort_t *serialPort, uint8_t receivedChar)
{
#ifndef USE_CLI
UNUSED(serialPort);
#else
if (receivedChar == '#') {
cliEnter(serialPort);
} else if (receivedChar == serialConfig->reboot_character) {
}
#endif
if (receivedChar == serialConfig->reboot_character) {
systemResetToBootloader();
}
}

View file

@ -46,7 +46,7 @@ typedef enum {
BAUD_250000,
} baudRate_e;
extern uint32_t baudRates[];
extern const uint32_t baudRates[];
// serial port identifiers are now fixed, these values are used by MSP commands.
typedef enum {
@ -61,7 +61,7 @@ typedef enum {
SERIAL_PORT_IDENTIFIER_MAX = SERIAL_PORT_SOFTSERIAL2
} serialPortIdentifier_e;
extern serialPortIdentifier_e serialPortIdentifiers[SERIAL_PORT_COUNT];
extern const serialPortIdentifier_e serialPortIdentifiers[SERIAL_PORT_COUNT];
//
// runtime
@ -96,7 +96,11 @@ typedef struct serialConfig_s {
//
// configuration
//
void serialRemovePort(serialPortIdentifier_e identifier);
uint8_t serialGetAvailablePortCount(void);
bool serialIsPortAvailable(serialPortIdentifier_e identifier);
bool isSerialConfigValid(serialConfig_t *serialConfig);
serialPortConfig_t *serialFindPortConfiguration(serialPortIdentifier_e identifier);
bool doesConfigurationUsePort(serialPortIdentifier_e portIdentifier);
serialPortConfig_t *findSerialPortConfig(serialPortFunction_e function);
serialPortConfig_t *findNextSerialPortConfig(serialPortFunction_e function);
@ -123,6 +127,7 @@ void waitForSerialPortToFinishTransmitting(serialPort_t *serialPort);
baudRate_e lookupBaudRateIndex(uint32_t baudRate);
//
// msp/cli/bootloader
//

View file

@ -84,6 +84,12 @@
#include "serial_cli.h"
// FIXME remove this for targets that don't need a CLI. Perhaps use a no-op macro when USE_CLI is not enabled
// signal that we're in cli mode
uint8_t cliMode = 0;
#ifdef USE_CLI
extern uint16_t cycleTime; // FIXME dependency on mw.c
void gpsEnablePassthrough(serialPort_t *gpsPassthroughPort);
@ -103,6 +109,7 @@ static void cliProfile(char *cmdline);
static void cliRateProfile(char *cmdline);
static void cliReboot(void);
static void cliSave(char *cmdline);
static void cliSerial(char *cmdline);
static void cliServo(char *cmdline);
static void cliSet(char *cmdline);
static void cliGet(char *cmdline);
@ -132,9 +139,6 @@ static void cliFlashWrite(char *cmdline);
static void cliFlashRead(char *cmdline);
#endif
// signal that we're in cli mode
uint8_t cliMode = 0;
// buffer
static char cliBuffer[48];
static uint32_t bufferIndex = 0;
@ -217,6 +221,7 @@ const clicmd_t cmdTable[] = {
{ "profile", "index (0 to 2)", cliProfile },
{ "rateprofile", "index (0 to 2)", cliRateProfile },
{ "save", "save and reboot", cliSave },
{ "serial", "show/set serial settings", cliSerial },
#ifdef USE_SERVOS
{ "servo", "servo config", cliServo },
#endif
@ -284,40 +289,6 @@ const clivalue_t valueTable[] = {
{ "fixedwing_althold_dir", VAR_INT8 | MASTER_VALUE, &masterConfig.airplaneConfig.fixedwing_althold_dir, -1, 1 },
{ "serial_port_1_functions", VAR_UINT16 | MASTER_VALUE, &masterConfig.serialConfig.portConfigs[0].functionMask, 0, 0xFFFF },
{ "serial_port_1_msp_baudrate", VAR_UINT8 | MASTER_VALUE, &masterConfig.serialConfig.portConfigs[0].msp_baudrateIndex, BAUD_9600, BAUD_115200 },
{ "serial_port_1_telemetry_baudrate", VAR_UINT8 | MASTER_VALUE, &masterConfig.serialConfig.portConfigs[0].telemetry_baudrateIndex, BAUD_AUTO, BAUD_115200 },
{ "serial_port_1_blackbox_baudrate", VAR_UINT8 | MASTER_VALUE, &masterConfig.serialConfig.portConfigs[0].blackbox_baudrateIndex, BAUD_9600, BAUD_115200 },
{ "serial_port_1_gps_baudrate", VAR_UINT8 | MASTER_VALUE, &masterConfig.serialConfig.portConfigs[0].gps_baudrateIndex, BAUD_9600, BAUD_115200 },
#if (SERIAL_PORT_COUNT >= 2)
{ "serial_port_2_functions", VAR_UINT16 | MASTER_VALUE, &masterConfig.serialConfig.portConfigs[1].functionMask, 0, 0xFFFF },
{ "serial_port_2_msp_baudrate", VAR_UINT8 | MASTER_VALUE, &masterConfig.serialConfig.portConfigs[1].msp_baudrateIndex, BAUD_9600, BAUD_115200 },
{ "serial_port_2_telemetry_baudrate", VAR_UINT8 | MASTER_VALUE, &masterConfig.serialConfig.portConfigs[1].telemetry_baudrateIndex, BAUD_AUTO, BAUD_115200 },
{ "serial_port_2_blackbox_baudrate", VAR_UINT8 | MASTER_VALUE, &masterConfig.serialConfig.portConfigs[1].blackbox_baudrateIndex, BAUD_9600, BAUD_115200 },
{ "serial_port_2_gps_baudrate", VAR_UINT8 | MASTER_VALUE, &masterConfig.serialConfig.portConfigs[1].gps_baudrateIndex, BAUD_9600, BAUD_115200 },
#if (SERIAL_PORT_COUNT >= 3)
{ "serial_port_3_functions", VAR_UINT16 | MASTER_VALUE, &masterConfig.serialConfig.portConfigs[2].functionMask, 0, 0xFFFF},
{ "serial_port_3_msp_baudrate", VAR_UINT8 | MASTER_VALUE, &masterConfig.serialConfig.portConfigs[2].msp_baudrateIndex, BAUD_9600, BAUD_115200 },
{ "serial_port_3_telemetry_baudrate", VAR_UINT8 | MASTER_VALUE, &masterConfig.serialConfig.portConfigs[2].telemetry_baudrateIndex, BAUD_AUTO, BAUD_115200 },
{ "serial_port_3_blackbox_baudrate", VAR_UINT8 | MASTER_VALUE, &masterConfig.serialConfig.portConfigs[2].blackbox_baudrateIndex, BAUD_9600, BAUD_115200 },
{ "serial_port_3_gps_baudrate", VAR_UINT8 | MASTER_VALUE, &masterConfig.serialConfig.portConfigs[2].gps_baudrateIndex, BAUD_9600, BAUD_115200 },
#if (SERIAL_PORT_COUNT >= 4)
{ "serial_port_4_functions", VAR_UINT16 | MASTER_VALUE, &masterConfig.serialConfig.portConfigs[3].functionMask, 0, 0xFFFF },
{ "serial_port_4_msp_baudrate", VAR_UINT8 | MASTER_VALUE, &masterConfig.serialConfig.portConfigs[3].msp_baudrateIndex, BAUD_9600, BAUD_115200 },
{ "serial_port_4_telemetry_baudrate", VAR_UINT8 | MASTER_VALUE, &masterConfig.serialConfig.portConfigs[3].telemetry_baudrateIndex, BAUD_AUTO, BAUD_115200 },
{ "serial_port_4_blackbox_baudrate", VAR_UINT8 | MASTER_VALUE, &masterConfig.serialConfig.portConfigs[3].blackbox_baudrateIndex, BAUD_9600, BAUD_115200 },
{ "serial_port_4_gps_baudrate", VAR_UINT8 | MASTER_VALUE, &masterConfig.serialConfig.portConfigs[3].gps_baudrateIndex, BAUD_9600, BAUD_115200 },
#if (SERIAL_PORT_COUNT >= 5)
{ "serial_port_5_functions", VAR_UINT16 | MASTER_VALUE, &masterConfig.serialConfig.portConfigs[4].functionMask, 0, 0xFFFF },
{ "serial_port_5_msp_baudrate", VAR_UINT8 | MASTER_VALUE, &masterConfig.serialConfig.portConfigs[4].msp_baudrateIndex, BAUD_9600, BAUD_115200 },
{ "serial_port_5_telemetry_baudrate", VAR_UINT8 | MASTER_VALUE, &masterConfig.serialConfig.portConfigs[4].telemetry_baudrateIndex, BAUD_AUTO, BAUD_115200 },
{ "serial_port_5_blackbox_baudrate", VAR_UINT8 | MASTER_VALUE, &masterConfig.serialConfig.portConfigs[4].blackbox_baudrateIndex, BAUD_9600, BAUD_115200 },
{ "serial_port_5_gps_baudrate", VAR_UINT8 | MASTER_VALUE, &masterConfig.serialConfig.portConfigs[4].gps_baudrateIndex, BAUD_9600, BAUD_115200 },
#endif
#endif
#endif
#endif
{ "reboot_character", VAR_UINT8 | MASTER_VALUE, &masterConfig.serialConfig.reboot_character, 48, 126 },
#ifdef GPS
@ -359,7 +330,7 @@ const clivalue_t valueTable[] = {
{ "vbat_max_cell_voltage", VAR_UINT8 | MASTER_VALUE, &masterConfig.batteryConfig.vbatmaxcellvoltage, 10, 50 },
{ "vbat_min_cell_voltage", VAR_UINT8 | MASTER_VALUE, &masterConfig.batteryConfig.vbatmincellvoltage, 10, 50 },
{ "vbat_warning_cell_voltage", VAR_UINT8 | MASTER_VALUE, &masterConfig.batteryConfig.vbatwarningcellvoltage, 10, 50 },
{ "current_meter_scale", VAR_INT16 | MASTER_VALUE, &masterConfig.batteryConfig.currentMeterScale, -10000, 10000 },
{ "current_meter_scale", VAR_INT16 | MASTER_VALUE, &masterConfig.batteryConfig.currentMeterScale, -10000, 10000 },
{ "current_meter_offset", VAR_UINT16 | MASTER_VALUE, &masterConfig.batteryConfig.currentMeterOffset, 0, 3300 },
{ "multiwii_current_meter_output", VAR_UINT8 | MASTER_VALUE, &masterConfig.batteryConfig.multiwiiCurrentMeterOutput, 0, 1 },
{ "current_meter_type", VAR_UINT8 | MASTER_VALUE, &masterConfig.batteryConfig.currentMeterType, 0, CURRENT_SENSOR_MAX },
@ -391,7 +362,7 @@ const clivalue_t valueTable[] = {
{ "pid_at_min_throttle", VAR_UINT8 | MASTER_VALUE, &masterConfig.mixerConfig.pid_at_min_throttle, 0, 1 },
{ "yaw_direction", VAR_INT8 | MASTER_VALUE, &masterConfig.mixerConfig.yaw_direction, -1, 1 },
{ "yaw_jump_prevention_limit", VAR_UINT16 | MASTER_VALUE, &masterConfig.mixerConfig.yaw_jump_prevention_limit, 80, 500 },
{ "yaw_jump_prevention_limit", VAR_UINT16 | MASTER_VALUE, &masterConfig.mixerConfig.yaw_jump_prevention_limit, YAW_JUMP_PREVENTION_LIMIT_LOW, YAW_JUMP_PREVENTION_LIMIT_HIGH },
#ifdef USE_SERVOS
{ "tri_unarmed_servo", VAR_INT8 | MASTER_VALUE, &masterConfig.mixerConfig.tri_unarmed_servo, 0, 1 },
{ "servo_lowpass_freq", VAR_INT16 | MASTER_VALUE, &masterConfig.mixerConfig.servo_lowpass_freq, 10, 400},
@ -414,8 +385,8 @@ const clivalue_t valueTable[] = {
{ "failsafe_off_delay", VAR_UINT8 | MASTER_VALUE, &masterConfig.failsafeConfig.failsafe_off_delay, 0, 200 },
{ "failsafe_throttle", VAR_UINT16 | MASTER_VALUE, &masterConfig.failsafeConfig.failsafe_throttle, PWM_RANGE_MIN, PWM_RANGE_MAX },
{ "rx_min_usec", VAR_UINT16 | MASTER_VALUE, &masterConfig.rxConfig.rx_min_usec, 100, PWM_RANGE_MAX },
{ "rx_max_usec", VAR_UINT16 | MASTER_VALUE, &masterConfig.rxConfig.rx_max_usec, 100, PWM_RANGE_MAX + (PWM_RANGE_MAX - PWM_RANGE_MIN) },
{ "rx_min_usec", VAR_UINT16 | MASTER_VALUE, &masterConfig.rxConfig.rx_min_usec, PWM_PULSE_MIN, PWM_PULSE_MAX },
{ "rx_max_usec", VAR_UINT16 | MASTER_VALUE, &masterConfig.rxConfig.rx_max_usec, PWM_PULSE_MIN, PWM_PULSE_MAX },
#ifdef USE_SERVOS
{ "gimbal_flags", VAR_UINT8 | PROFILE_VALUE, &masterConfig.profile[0].gimbalConfig.gimbal_flags, 0, 255},
@ -476,7 +447,7 @@ const clivalue_t valueTable[] = {
{ "i_vel", VAR_UINT8 | PROFILE_VALUE, &masterConfig.profile[0].pidProfile.I8[PIDVEL], 0, 200 },
{ "d_vel", VAR_UINT8 | PROFILE_VALUE, &masterConfig.profile[0].pidProfile.D8[PIDVEL], 0, 200 },
{ "yaw_p_limit", VAR_UINT16 | PROFILE_VALUE, &masterConfig.profile[0].pidProfile.yaw_p_limit, 0, 500 },
{ "yaw_p_limit", VAR_UINT16 | PROFILE_VALUE, &masterConfig.profile[0].pidProfile.yaw_p_limit, YAW_P_LIMIT_MIN, YAW_P_LIMIT_MAX },
#ifdef BLACKBOX
{ "blackbox_rate_num", VAR_UINT8 | MASTER_VALUE, &masterConfig.blackbox_rate_num, 1, 32 },
@ -588,6 +559,102 @@ static void cliAux(char *cmdline)
}
}
static void cliSerial(char *cmdline)
{
int i, val;
char *ptr;
if (isEmpty(cmdline)) {
for (i = 0; i < SERIAL_PORT_COUNT; i++) {
if (!serialIsPortAvailable(masterConfig.serialConfig.portConfigs[i].identifier)) {
continue;
};
printf("serial %d %d %ld %ld %ld %ld\r\n" ,
masterConfig.serialConfig.portConfigs[i].identifier,
masterConfig.serialConfig.portConfigs[i].functionMask,
baudRates[masterConfig.serialConfig.portConfigs[i].msp_baudrateIndex],
baudRates[masterConfig.serialConfig.portConfigs[i].gps_baudrateIndex],
baudRates[masterConfig.serialConfig.portConfigs[i].telemetry_baudrateIndex],
baudRates[masterConfig.serialConfig.portConfigs[i].blackbox_baudrateIndex]
);
}
return;
}
serialPortConfig_t portConfig;
memset(&portConfig, 0 , sizeof(portConfig));
serialPortConfig_t *currentConfig;
uint8_t validArgumentCount = 0;
ptr = cmdline;
val = atoi(ptr++);
currentConfig = serialFindPortConfiguration(val);
if (currentConfig) {
portConfig.identifier = val;
validArgumentCount++;
}
ptr = strchr(ptr, ' ');
if (ptr) {
val = atoi(++ptr);
portConfig.functionMask = val & 0xFFFF;
validArgumentCount++;
}
for (i = 0; i < 4; i ++) {
ptr = strchr(ptr, ' ');
if (!ptr) {
break;
}
val = atoi(++ptr);
uint8_t baudRateIndex = lookupBaudRateIndex(val);
if (baudRates[baudRateIndex] != (uint32_t) val) {
break;
}
switch(i) {
case 0:
if (baudRateIndex < BAUD_9600 || baudRateIndex > BAUD_115200) {
continue;
}
portConfig.msp_baudrateIndex = baudRateIndex;
break;
case 1:
if (baudRateIndex < BAUD_9600 || baudRateIndex > BAUD_115200) {
continue;
}
portConfig.gps_baudrateIndex = baudRateIndex;
break;
case 2:
if (baudRateIndex != BAUD_AUTO && baudRateIndex > BAUD_115200) {
continue;
}
portConfig.telemetry_baudrateIndex = baudRateIndex;
break;
case 3:
if (baudRateIndex < BAUD_19200 || baudRateIndex > BAUD_250000) {
continue;
}
portConfig.blackbox_baudrateIndex = baudRateIndex;
break;
}
validArgumentCount++;
}
if (validArgumentCount < 6) {
cliPrint("Parse error\r\n");
return;
}
memcpy(currentConfig, &portConfig, sizeof(portConfig));
}
static void cliAdjustmentRange(char *cmdline)
{
@ -1063,6 +1130,9 @@ static void cliDump(char *cmdline)
buf[i] = '\0';
printf("map %s\r\n", buf);
cliPrint("\r\n\r\n# serial\r\n");
cliSerial("");
#ifdef LED_STRIP
cliPrint("\r\n\r\n# led\r\n");
cliLed("");
@ -1334,6 +1404,9 @@ static void cliMotor(char *cmdline)
static void cliPlaySound(char *cmdline)
{
#if FLASH_SIZE <= 64
UNUSED(cmdline);
#else
int i;
const char *name;
static int lastSoundIdx = -1;
@ -1363,6 +1436,7 @@ static void cliPlaySound(char *cmdline)
beeperSilence();
printf("Playing sound %d: %s\r\n", i, name);
beeper(beeperModeForTableIndex(i));
#endif
}
static void cliProfile(char *cmdline)
@ -1403,6 +1477,7 @@ static void cliReboot(void) {
cliPrint("\r\nRebooting");
waitForSerialPortToFinishTransmitting(cliPort);
stopMotors();
handleOneshotFeatureChangeOnRestart();
systemReset();
}
@ -1645,7 +1720,7 @@ static void cliVersion(char *cmdline)
{
UNUSED(cmdline);
printf("Cleanflight/%s %s %s / %s (%s)",
printf("# Cleanflight/%s %s %s / %s (%s)",
targetName,
FC_VERSION_STRING,
buildDate,
@ -1711,14 +1786,21 @@ void cliProcess(void)
clicmd_t target;
cliPrint("\r\n");
// Strip comment starting with # from line
char *p = cliBuffer;
p = strchr(p, '#');
if (NULL != p) {
bufferIndex = (uint32_t)(p - cliBuffer);
}
// Strip trailing whitespace
while (bufferIndex > 0 && cliBuffer[bufferIndex - 1] == ' ') {
bufferIndex--;
}
cliBuffer[bufferIndex] = 0; // null terminate
if (cliBuffer[0] != '#') {
// Process non-empty lines
if (bufferIndex > 0) {
cliBuffer[bufferIndex] = 0; // null terminate
target.name = cliBuffer;
target.param = NULL;
@ -1727,10 +1809,10 @@ void cliProcess(void)
cmd->func(cliBuffer + strlen(cmd->name) + 1);
else
cliPrint("Unknown command, try 'help'");
bufferIndex = 0;
}
memset(cliBuffer, 0, sizeof(cliBuffer));
bufferIndex = 0;
// 'exit' will reset this flag, so we don't need to print prompt again
if (!cliMode)
@ -1756,3 +1838,4 @@ void cliInit(serialConfig_t *serialConfig)
{
UNUSED(serialConfig);
}
#endif

View file

@ -140,12 +140,12 @@ void useRcControlsConfig(modeActivationCondition_t *modeActivationConditions, es
#define BASEFLIGHT_IDENTIFIER "BAFL";
#define FLIGHT_CONTROLLER_IDENTIFIER_LENGTH 4
static const char *flightControllerIdentifier = CLEANFLIGHT_IDENTIFIER; // 4 UPPER CASE alpha numeric characters that identify the flight controller.
static const char * const flightControllerIdentifier = CLEANFLIGHT_IDENTIFIER; // 4 UPPER CASE alpha numeric characters that identify the flight controller.
#define FLIGHT_CONTROLLER_VERSION_LENGTH 3
#define FLIGHT_CONTROLLER_VERSION_MASK 0xFFF
const char *boardIdentifier = TARGET_BOARD_IDENTIFIER;
static const char * const boardIdentifier = TARGET_BOARD_IDENTIFIER;
#define BOARD_IDENTIFIER_LENGTH 4 // 4 UPPER CASE alpha numeric characters that identify the board being used.
#define BOARD_HARDWARE_REVISION_LENGTH 2
@ -396,40 +396,24 @@ static mspPort_t mspPorts[MAX_MSP_PORT_COUNT];
static mspPort_t *currentPort;
static void serialize32(uint32_t a)
{
static uint8_t t;
t = a;
serialWrite(mspSerialPort, t);
currentPort->checksum ^= t;
t = a >> 8;
serialWrite(mspSerialPort, t);
currentPort->checksum ^= t;
t = a >> 16;
serialWrite(mspSerialPort, t);
currentPort->checksum ^= t;
t = a >> 24;
serialWrite(mspSerialPort, t);
currentPort->checksum ^= t;
}
static void serialize16(int16_t a)
{
static uint8_t t;
t = a;
serialWrite(mspSerialPort, t);
currentPort->checksum ^= t;
t = a >> 8 & 0xff;
serialWrite(mspSerialPort, t);
currentPort->checksum ^= t;
}
static void serialize8(uint8_t a)
{
serialWrite(mspSerialPort, a);
currentPort->checksum ^= a;
}
static void serialize16(uint16_t a)
{
serialize8((uint8_t)(a >> 0));
serialize8((uint8_t)(a >> 8));
}
static void serialize32(uint32_t a)
{
serialize16((uint16_t)(a >> 0));
serialize16((uint16_t)(a >> 16));
}
static uint8_t read8(void)
{
return currentPort->inBuf[currentPort->indRX++] & 0xff;
@ -682,7 +666,7 @@ void mspInit(serialConfig_t *serialConfig)
activeBoxIds[activeBoxIdCount++] = BOXOSD;
if (feature(FEATURE_TELEMETRY && masterConfig.telemetryConfig.telemetry_switch))
if (feature(FEATURE_TELEMETRY) && masterConfig.telemetryConfig.telemetry_switch)
activeBoxIds[activeBoxIdCount++] = BOXTELEMETRY;
#ifdef AUTOTUNE
@ -833,7 +817,7 @@ static bool processOutCommand(uint8_t cmdMSP)
serialize16(accSmooth[i]);
}
for (i = 0; i < 3; i++)
serialize16(gyroData[i]);
serialize16(gyroADC[i]);
for (i = 0; i < 3; i++)
serialize16(magADC[i]);
break;
@ -851,7 +835,7 @@ static bool processOutCommand(uint8_t cmdMSP)
}
break;
case MSP_CHANNEL_FORWARDING:
headSerialReply(8);
headSerialReply(MAX_SUPPORTED_SERVOS);
for (i = 0; i < MAX_SUPPORTED_SERVOS; i++) {
serialize8(currentProfile->servoConf[i].forwardFromChannel);
}
@ -1183,9 +1167,12 @@ static bool processOutCommand(uint8_t cmdMSP)
case MSP_CF_SERIAL_CONFIG:
headSerialReply(
((sizeof(uint8_t) + sizeof(uint16_t) + (sizeof(uint8_t) * 4)) * SERIAL_PORT_COUNT)
((sizeof(uint8_t) + sizeof(uint16_t) + (sizeof(uint8_t) * 4)) * serialGetAvailablePortCount())
);
for (i = 0; i < SERIAL_PORT_COUNT; i++) {
if (!serialIsPortAvailable(masterConfig.serialConfig.portConfigs[i].identifier)) {
continue;
};
serialize8(masterConfig.serialConfig.portConfigs[i].identifier);
serialize16(masterConfig.serialConfig.portConfigs[i].functionMask);
serialize8(masterConfig.serialConfig.portConfigs[i].msp_baudrateIndex);
@ -1595,17 +1582,28 @@ static bool processInCommand(void)
{
uint8_t portConfigSize = sizeof(uint8_t) + sizeof(uint16_t) + (sizeof(uint8_t) * 4);
if ((SERIAL_PORT_COUNT * portConfigSize) != currentPort->dataSize) {
if (currentPort->dataSize % portConfigSize != 0) {
headSerialError(0);
break;
}
for (i = 0; i < SERIAL_PORT_COUNT; i++) {
masterConfig.serialConfig.portConfigs[i].identifier = read8();
masterConfig.serialConfig.portConfigs[i].functionMask = read16();
masterConfig.serialConfig.portConfigs[i].msp_baudrateIndex = read8();
masterConfig.serialConfig.portConfigs[i].gps_baudrateIndex = read8();
masterConfig.serialConfig.portConfigs[i].telemetry_baudrateIndex = read8();
masterConfig.serialConfig.portConfigs[i].blackbox_baudrateIndex = read8();
uint8_t remainingPortsInPacket = currentPort->dataSize / portConfigSize;
while (remainingPortsInPacket--) {
uint8_t identifier = read8();
serialPortConfig_t *portConfig = serialFindPortConfiguration(identifier);
if (!portConfig) {
headSerialError(0);
break;
}
portConfig->identifier = identifier;
portConfig->functionMask = read16();
portConfig->msp_baudrateIndex = read8();
portConfig->gps_baudrateIndex = read8();
portConfig->telemetry_baudrateIndex = read8();
portConfig->blackbox_baudrateIndex = read8();
}
}
break;
@ -1750,6 +1748,7 @@ void mspProcess(void)
delay(50);
}
stopMotors();
handleOneshotFeatureChangeOnRestart();
systemReset();
}
}

View file

@ -27,44 +27,63 @@
#include "statusindicator.h"
void blinkLedAndSoundBeeper(uint8_t num, uint8_t wait, uint8_t repeat)
{
uint8_t i, r;
for (r = 0; r < repeat; r++) {
for (i = 0; i < num; i++) {
LED0_TOGGLE; // switch LEDPIN state
BEEP_ON;
delay(wait);
BEEP_OFF;
}
delay(60);
}
}
static uint32_t warningLedTimer = 0;
void enableWarningLed(uint32_t currentTime)
typedef enum {
WARNING_LED_OFF = 0,
WARNING_LED_ON,
WARNING_LED_FLASH
} warningLedState_e;
static warningLedState_e warningLedState = WARNING_LED_OFF;
void warningLedResetTimer(void) {
uint32_t now = millis();
warningLedTimer = now + 500000;
}
void warningLedEnable(void)
{
if (warningLedTimer != 0) {
return; // already enabled
warningLedState = WARNING_LED_ON;
}
void warningLedDisable(void)
{
warningLedState = WARNING_LED_OFF;
}
void warningLedFlash(void)
{
warningLedState = WARNING_LED_FLASH;
}
void warningLedRefresh(void)
{
switch (warningLedState) {
case WARNING_LED_OFF:
LED0_OFF;
break;
case WARNING_LED_ON:
LED0_ON;
break;
case WARNING_LED_FLASH:
LED0_TOGGLE;
break;
}
warningLedTimer = currentTime + 500000;
LED0_ON;
uint32_t now = micros();
warningLedTimer = now + 500000;
}
void disableWarningLed(void)
void warningLedUpdate(void)
{
warningLedTimer = 0;
LED0_OFF;
}
uint32_t now = micros();
void updateWarningLed(uint32_t currentTime)
{
if (warningLedTimer && (int32_t)(currentTime - warningLedTimer) >= 0) {
LED0_TOGGLE;
warningLedTimer = warningLedTimer + 500000;
if ((int32_t)(now - warningLedTimer) < 0) {
return;
}
warningLedRefresh();
}

View file

@ -17,8 +17,8 @@
#pragma once
void blinkLedAndSoundBeeper(uint8_t num, uint8_t wait, uint8_t repeat);
void enableWarningLed(uint32_t currentTime);
void disableWarningLed(void);
void updateWarningLed(uint32_t currentTime);
void warningLedEnable(void);
void warningLedDisable(void);
void warningLedRefresh(void);
void warningLedUpdate(void);
void warningLedFlash(void);

View file

@ -47,6 +47,7 @@
#include "drivers/bus_spi.h"
#include "drivers/inverter.h"
#include "drivers/flash_m25p16.h"
#include "drivers/sonar_hcsr04.h"
#include "rx/rx.h"
@ -90,6 +91,7 @@
#include "debug.h"
extern uint32_t previousTime;
extern uint8_t motorControlEnable;
#ifdef SOFTSERIAL_LOOPBACK
serialPort_t *loopbackPort;
@ -114,6 +116,8 @@ void displayInit(rxConfig_t *intialRxConfig);
void ledStripInit(ledConfig_t *ledConfigsToUse, hsvColor_t *colorsToUse);
void loop(void);
void spektrumBind(rxConfig_t *rxConfig);
const sonarHardware_t *sonarGetHardwareConfiguration(batteryConfig_t *batteryConfig);
void sonarInit(const sonarHardware_t *sonarHardware);
#ifdef STM32F303xC
// from system_stm32f30x.c
@ -168,6 +172,9 @@ void init(void)
systemInit();
// Latch active features to be used for feature() in the remainder of init().
latchActiveFeatures();
ledInit();
#ifdef SPEKTRUM_BIND
@ -193,6 +200,21 @@ void init(void)
mixerInit(masterConfig.mixerMode, masterConfig.customMixer);
memset(&pwm_params, 0, sizeof(pwm_params));
#ifdef SONAR
const sonarHardware_t *sonarHardware = NULL;
if (feature(FEATURE_SONAR)) {
sonarHardware = sonarGetHardwareConfiguration(&masterConfig.batteryConfig);
sonarGPIOConfig_t sonarGPIOConfig = {
.echoPin = sonarHardware->trigger_pin,
.triggerPin = sonarHardware->echo_pin,
.gpio = SONAR_GPIO
};
pwm_params.sonarGPIOConfig = &sonarGPIOConfig;
}
#endif
// when using airplane/wing mixer, servo/motor outputs are remapped
if (masterConfig.mixerMode == MIXER_AIRPLANE || masterConfig.mixerMode == MIXER_FLYING_WING)
pwm_params.airplane = true;
@ -226,7 +248,7 @@ void init(void)
pwm_params.useOneshot = feature(FEATURE_ONESHOT125);
pwm_params.motorPwmRate = masterConfig.motor_pwm_rate;
pwm_params.idlePulse = PULSE_1MS; // standard PWM for brushless ESC (default, overridden below)
pwm_params.idlePulse = masterConfig.escAndServoConfig.mincommand;
if (feature(FEATURE_3D))
pwm_params.idlePulse = masterConfig.flight3DConfig.neutral3d;
if (pwm_params.motorPwmRate > 500)
@ -238,6 +260,9 @@ void init(void)
mixerUsePWMOutputConfiguration(pwmOutputConfiguration);
if (!feature(FEATURE_ONESHOT125))
motorControlEnable = true;
systemState |= SYSTEM_STATE_MOTORS_READY;
#ifdef BEEPER
@ -278,10 +303,22 @@ void init(void)
updateHardwareRevision();
#endif
#if defined(NAZE)
if (hardwareRevision == NAZE32_SP) {
serialRemovePort(SERIAL_PORT_SOFTSERIAL2);
} else {
serialRemovePort(SERIAL_PORT_USART3);
}
#endif
#ifdef USE_I2C
#if defined(NAZE)
if (hardwareRevision != NAZE32_SP) {
i2cInit(I2C_DEVICE);
} else {
if (!doesConfigurationUsePort(SERIAL_PORT_USART3)) {
i2cInit(I2C_DEVICE);
}
}
#elif defined(CC3D)
if (!doesConfigurationUsePort(SERIAL_PORT_USART3)) {
@ -347,7 +384,10 @@ void init(void)
imuInit();
mspInit(&masterConfig.serialConfig);
#ifdef USE_CLI
cliInit(&masterConfig.serialConfig);
#endif
failsafeInit(&masterConfig.rxConfig);
@ -368,7 +408,7 @@ void init(void)
#ifdef SONAR
if (feature(FEATURE_SONAR)) {
sonarInit(&masterConfig.batteryConfig);
sonarInit(sonarHardware);
}
#endif
@ -448,6 +488,10 @@ void init(void)
LED2_ON;
#endif
// Latch active features AGAIN since some may be modified by init().
latchActiveFeatures();
motorControlEnable = true;
systemState |= SYSTEM_STATE_READY;
}

View file

@ -97,6 +97,8 @@ uint16_t cycleTime = 0; // this is the number in micro second to achieve
int16_t magHold;
int16_t headFreeModeHold;
uint8_t motorControlEnable = false;
int16_t telemTemperature1; // gyro sensor temperature
static uint32_t disarmAt; // Time of automatic disarm when "Don't spin the motors when armed" is enabled and auto_disarm_delay is nonzero
@ -274,11 +276,6 @@ void annexCode(void)
ENABLE_ARMING_FLAG(OK_TO_ARM);
}
if (isCalibrating()) {
LED0_TOGGLE;
DISABLE_ARMING_FLAG(OK_TO_ARM);
}
if (!STATE(SMALL_ANGLE)) {
DISABLE_ARMING_FLAG(OK_TO_ARM);
}
@ -287,13 +284,18 @@ void annexCode(void)
DISABLE_ARMING_FLAG(OK_TO_ARM);
}
if (ARMING_FLAG(OK_TO_ARM)) {
disableWarningLed();
if (isCalibrating()) {
warningLedFlash();
DISABLE_ARMING_FLAG(OK_TO_ARM);
} else {
enableWarningLed(currentTime);
if (ARMING_FLAG(OK_TO_ARM)) {
warningLedDisable();
} else {
warningLedFlash();
}
}
updateWarningLed(currentTime);
warningLedUpdate();
}
#ifdef TELEMETRY
@ -386,7 +388,7 @@ void mwArm(void)
}
if (!ARMING_FLAG(ARMED)) {
blinkLedAndSoundBeeper(2, 255, 1);
beeperConfirmationBeeps(1);
}
}
@ -728,7 +730,7 @@ void loop(void)
if (masterConfig.looptime == 0 || (int32_t)(currentTime - loopTime) >= 0) {
loopTime = currentTime + masterConfig.looptime;
imuUpdate(&currentProfile->accelerometerTrims, masterConfig.mixerMode);
imuUpdate(&currentProfile->accelerometerTrims);
// Measure loop rate just after reading the sensors
currentTime = micros();
@ -801,7 +803,9 @@ void loop(void)
writeServos();
#endif
writeMotors();
if (motorControlEnable) {
writeMotors();
}
#ifdef BLACKBOX
if (!cliMode && feature(FEATURE_BLACKBOX)) {

View file

@ -49,6 +49,8 @@
#include "rx/rx.h"
//#define DEBUG_RX_SIGNAL_LOSS
void rxPwmInit(rxRuntimeConfig_t *rxRuntimeConfig, rcReadRawDataPtr *callback);
bool sbusInit(rxConfig_t *initialRxConfig, rxRuntimeConfig_t *rxRuntimeConfig, rcReadRawDataPtr *callback);
@ -73,9 +75,6 @@ int16_t rcData[MAX_SUPPORTED_RC_CHANNEL_COUNT]; // interval [1000;2000]
#define PPM_AND_PWM_SAMPLE_COUNT 4
#define PULSE_MIN 750 // minimum PWM pulse width which is considered valid
#define PULSE_MAX 2250 // maximum PWM pulse width which is considered valid
#define DELAY_50_HZ (1000000 / 50)
#define DELAY_10_HZ (1000000 / 10)
@ -259,7 +258,8 @@ void updateRx(uint32_t currentTime)
}
}
if (feature(FEATURE_RX_SERIAL | FEATURE_RX_MSP) && rxDataReceived) {
if ((feature(FEATURE_RX_SERIAL | FEATURE_RX_MSP) && rxDataReceived)
|| feature(FEATURE_RX_PARALLEL_PWM)) {
needRxSignalBefore = currentTime + DELAY_10_HZ;
}
@ -333,7 +333,7 @@ static void processRxChannels(void)
}
// validate the range
if (sample < PULSE_MIN || sample > PULSE_MAX)
if (sample < rxConfig->rx_min_usec || sample > rxConfig->rx_max_usec)
sample = rxConfig->midrc;
if (isRxDataDriven()) {

View file

@ -24,6 +24,9 @@
#define PWM_RANGE_MAX 2000
#define PWM_RANGE_MIDDLE (PWM_RANGE_MIN + ((PWM_RANGE_MAX - PWM_RANGE_MIN) / 2))
#define PWM_PULSE_MIN 750 // minimum PWM pulse width which is considered valid
#define PWM_PULSE_MAX 2250 // maximum PWM pulse width which is considered valid
#define DEFAULT_SERVO_MIN 1020
#define DEFAULT_SERVO_MIDDLE 1500
#define DEFAULT_SERVO_MAX 2000

View file

@ -65,7 +65,6 @@ static uint16_t sbusStateFlags = 0;
#define SBUS_FRAME_SIZE 25
#define SBUS_FRAME_BEGIN_BYTE 0x0F
#define SBUS_FRAME_END_BYTE 0x00
#define SBUS_BAUDRATE 100000
#define SBUS_PORT_OPTIONS (SERIAL_STOPBITS_2 | SERIAL_PARITY_EVEN | SERIAL_INVERTED)
@ -123,6 +122,13 @@ struct sbusFrame_s {
unsigned int chan14 : 11;
unsigned int chan15 : 11;
uint8_t flags;
/**
* The endByte is 0x00 on FrSky and some futaba RX's, on Some SBUS2 RX's the value indicates the telemetry byte that is sent after every 4th sbus frame.
*
* See https://github.com/cleanflight/cleanflight/issues/590#issuecomment-101027349
* and
* https://github.com/cleanflight/cleanflight/issues/590#issuecomment-101706023
*/
uint8_t endByte;
} __attribute__ ((__packed__));
@ -158,12 +164,11 @@ static void sbusDataReceive(uint16_t c)
sbusFramePosition++;
if (sbusFramePosition == SBUS_FRAME_SIZE) {
if (sbusFrame.frame.endByte == SBUS_FRAME_END_BYTE) {
sbusFrameDone = true;
// endByte currently ignored
sbusFrameDone = true;
#ifdef DEBUG_SBUS_PACKETS
debug[2] = sbusFrameTime;
debug[2] = sbusFrameTime;
#endif
}
} else {
sbusFrameDone = false;
}

View file

@ -15,6 +15,12 @@
* along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* References:
* http://fpv-treff.de/viewtopic.php?f=18&t=1368&start=3020#p44535
* http://fpv-community.de/showthread.php?29033-MultiWii-mit-Graupner-SUMD-SUMH-und-USB-Joystick-auf-ProMicro
*/
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
@ -112,9 +118,8 @@ uint8_t sumhFrameStatus(void)
}
for (channelIndex = 0; channelIndex < SUMH_MAX_CHANNEL_COUNT; channelIndex++) {
sumhChannels[channelIndex] = (((uint32_t)(sumhFrame[(channelIndex << 1) + 3]) << 8)
+ sumhFrame[(channelIndex << 1) + 4]) / 6.4 - 375;
+ sumhFrame[(channelIndex << 1) + 4]) / 6.4f - 375;
}
return SERIAL_RX_FRAME_COMPLETE;
}

View file

@ -26,6 +26,7 @@
#include "drivers/sensor.h"
#include "drivers/accgyro.h"
#include "sensors/sensors.h"
#include "io/beeper.h"
#include "io/statusindicator.h"
#include "sensors/boardalignment.h"
@ -95,10 +96,14 @@ static void performAcclerationCalibration(uint8_t gyroMovementCalibrationThresho
return;
}
gyroZero[axis] = (g[axis] + (CALIBRATING_GYRO_CYCLES / 2)) / CALIBRATING_GYRO_CYCLES;
blinkLedAndSoundBeeper(10, 15, 1);
}
}
if (isOnFinalGyroCalibrationCycle()) {
beeper(BEEPER_GYRO_CALIBRATED);
}
calibratingG--;
}
static void applyGyroZero(void)

View file

@ -122,8 +122,8 @@ const mpu6050Config_t *selectMPU6050Config(void)
#ifdef USE_FAKE_GYRO
static void fakeGyroInit(void) {}
static void fakeGyroRead(int16_t *gyroData) {
memset(gyroData, 0, sizeof(int16_t[XYZ_AXIS_COUNT]));
static void fakeGyroRead(int16_t *gyroADC) {
memset(gyroADC, 0, sizeof(int16_t[XYZ_AXIS_COUNT]));
}
static void fakeGyroReadTemp(int16_t *tempData) {
UNUSED(tempData);

View file

@ -38,7 +38,7 @@
static int32_t calculatedAltitude;
void sonarInit(batteryConfig_t *batteryConfig)
const sonarHardware_t *sonarGetHardwareConfiguration(batteryConfig_t *batteryConfig)
{
#if defined(NAZE) || defined(EUSTM32F103RC) || defined(PORT103R)
static const sonarHardware_t const sonarPWM56 = {
@ -57,9 +57,9 @@ void sonarInit(batteryConfig_t *batteryConfig)
};
// If we are using parallel PWM for our receiver or ADC current sensor, then use motor pins 5 and 6 for sonar, otherwise use rc pins 7 and 8
if (feature(FEATURE_RX_PARALLEL_PWM ) || (feature(FEATURE_CURRENT_METER) && batteryConfig->currentMeterType == CURRENT_SENSOR_ADC) ) {
hcsr04_init(&sonarPWM56);
return &sonarPWM56;
} else {
hcsr04_init(&sonarRC78);
return &sonarRC78;
}
#elif defined(OLIMEXINO)
UNUSED(batteryConfig);
@ -70,7 +70,17 @@ void sonarInit(batteryConfig_t *batteryConfig)
.exti_pin_source = GPIO_PinSource1,
.exti_irqn = EXTI1_IRQn
};
hcsr04_init(&sonarHardware);
return &sonarHardware;
#elif defined(CC3D)
UNUSED(batteryConfig);
static const sonarHardware_t const sonarHardware = {
.trigger_pin = Pin_5, // (PB5)
.echo_pin = Pin_0, // (PB0) - only 3.3v ( add a 1K Ohms resistor )
.exti_line = EXTI_Line0,
.exti_pin_source = GPIO_PinSource0,
.exti_irqn = EXTI0_IRQn
};
return &sonarHardware;
#elif defined(SPRACINGF3)
UNUSED(batteryConfig);
static const sonarHardware_t const sonarHardware = {
@ -80,11 +90,15 @@ void sonarInit(batteryConfig_t *batteryConfig)
.exti_pin_source = EXTI_PinSource1,
.exti_irqn = EXTI1_IRQn
};
hcsr04_init(&sonarHardware);
return &sonarHardware;
#else
#error Sonar not defined for target
#endif
}
void sonarInit(const sonarHardware_t *sonarHardware)
{
hcsr04_init(sonarHardware);
sensorsSet(SENSOR_SONAR);
calculatedAltitude = -1;
}

View file

@ -18,9 +18,9 @@
#pragma once
#include "sensors/battery.h"
void sonarInit(batteryConfig_t *batteryConfig);
void sonarUpdate(void);
int32_t sonarRead(void);
int32_t sonarCalculateAltitude(int32_t sonarAlt, int16_t tiltAngle);
int32_t sonarGetLatestAltitude(void);

View file

@ -104,7 +104,7 @@
#define ADC_DMA_CHANNEL DMA2_Channel1
#define ADC_AHB_PERIPHERAL RCC_AHBPeriph_DMA2
#define BOARD_HAS_VOLTAGE_DIVIDER
//#define BOARD_HAS_VOLTAGE_DIVIDER
#define VBAT_ADC_GPIO GPIOA
#define VBAT_ADC_GPIO_PIN GPIO_Pin_4
@ -116,7 +116,7 @@
//#define DISPLAY
#define AUTOTUNE
#define USE_SERVOS
#define USE_CLI
#define SPEKTRUM_BIND
// USART2, PA3

View file

@ -111,13 +111,18 @@
#define BLACKBOX
#define TELEMETRY
#define SERIAL_RX
#define SONAR
#define AUTOTUNE
#define USE_SERVOS
#define USE_CLI
#if defined(OPBL)
#undef AUTOTUNE // disabled for OPBL build due to code size.
// disabled some features for OPBL build due to code size.
#undef AUTOTUNE
#undef SONAR
#endif
#define SPEKTRUM_BIND
// USART3, PB11 (Flexport)
#define BIND_PORT GPIOB

View file

@ -123,3 +123,4 @@
#define SERIAL_RX
#define AUTOTUNE
#define USE_SERVOS
#define USE_CLI

View file

@ -59,6 +59,7 @@
#define SERIAL_RX
//#define USE_SERVOS
#define USE_CLI
#define SPEKTRUM_BIND
// USART2, PA3
@ -68,6 +69,10 @@
// Since the CJMCU PCB has holes for 4 motors in each corner we can save same flash space by disabling support for other mixers.
#define USE_QUAD_MIXER_ONLY
#if (FLASH_SIZE > 64)
#define BLACKBOX
#endif
//#undef USE_CLI
//#define BLACKBOX

View file

@ -125,6 +125,7 @@
#define SERIAL_RX
#define AUTOTUNE
#define USE_SERVOS
#define USE_CLI
#define SPEKTRUM_BIND
// USART2, PA3

View file

@ -119,9 +119,10 @@
#define USE_USART1
#define USE_USART2
#define USE_USART3
#define USE_SOFTSERIAL1
#define USE_SOFTSERIAL2
#define SERIAL_PORT_COUNT 4
#define SERIAL_PORT_COUNT 5
#define SOFTSERIAL_1_TIMER TIM3
#define SOFTSERIAL_1_TIMER_RX_HARDWARE 4 // PWM 5
@ -130,6 +131,13 @@
#define SOFTSERIAL_2_TIMER_RX_HARDWARE 6 // PWM 7
#define SOFTSERIAL_2_TIMER_TX_HARDWARE 7 // PWM 8
// USART3 only on NAZE32_SP - Flex Port
#define USART3_RX_PIN Pin_11
#define USART3_TX_PIN Pin_10
#define USART3_GPIO GPIOB
#define USART3_APB1_PERIPHERALS RCC_APB1Periph_USART3
#define USART3_APB2_PERIPHERALS RCC_APB2Periph_GPIOB
#define USE_I2C
#define I2C_DEVICE (I2CDEV_2)
@ -165,6 +173,7 @@
#define SERIAL_RX
#define AUTOTUNE
#define USE_SERVOS
#define USE_CLI
#define SPEKTRUM_BIND
// USART2, PA3

View file

@ -46,6 +46,7 @@
#define SERIAL_RX
#define AUTOTUNE
#define USE_SERVOS
#define USE_CLI
#define SPEKTRUM_BIND
// USART2, PA3

View file

@ -112,3 +112,4 @@
#define AUTOTUNE
#define BLACKBOX
#define USE_SERVOS
#define USE_CLI

View file

@ -136,3 +136,4 @@
#define SERIAL_RX
#define AUTOTUNE
#define USE_SERVOS
#define USE_CLI

View file

@ -109,11 +109,12 @@
#define AUTOTUNE
#define BLACKBOX
#define TELEMETRY
#define SERIAL_RX
#define GPS
#define DISPLAY
#define USE_SERVOS
#define TELEMETRY
#define USE_CLI
#define LED_STRIP
#if 1

View file

@ -153,3 +153,4 @@
#define AUTOTUNE
#define DISPLAY
#define USE_SERVOS
#define USE_CLI

View file

@ -97,3 +97,4 @@
#define SERIAL_RX
#define AUTOTUNE
#define USE_SERVOS
#define USE_CLI

View file

@ -302,29 +302,39 @@ static void sendLatLong(int32_t coord[2])
serialize16(coord[LON] < 0 ? 'W' : 'E');
}
static void sendFakeLatLong(void)
{
// Heading is only displayed on OpenTX if non-zero lat/long is also sent
int32_t coord[2] = {0,0};
coord[LAT] = (telemetryConfig->gpsNoFixLatitude * GPS_DEGREES_DIVIDER);
coord[LON] = (telemetryConfig->gpsNoFixLongitude * GPS_DEGREES_DIVIDER);
sendLatLong(coord);
}
static void sendFakeLatLongThatAllowsHeadingDisplay(void)
{
// Heading is only displayed on OpenTX if non-zero lat/long is also sent
int32_t coord[2] = {
1 * GPS_DEGREES_DIVIDER,
1 * GPS_DEGREES_DIVIDER
};
sendLatLong(coord);
}
#ifdef GPS
static void sendGPSLatLong(void)
{
// Don't set dummy GPS data, if we already had a GPS fix
// it can be usefull to keep last valid coordinates
static uint8_t gpsFixOccured = 0;
//Dummy data if no 3D fix, this way we can display heading in Taranis
if (STATE(GPS_FIX) || gpsFixOccured == 1) {
// If we have ever had a fix, send the last known lat/long
gpsFixOccured = 1;
sendLatLong(GPS_coord);
} else {
// Send dummy GPS Data in order to display compass value
// otherwise send fake lat/long in order to display compass value
sendFakeLatLong();
}
}
@ -521,14 +531,11 @@ void handleFrSkyTelemetry(rxConfig_t *rxConfig, uint16_t deadband3d_throttle)
sendSatalliteSignalQualityAsTemperature2();
sendGPSLatLong();
}
else if (telemetryConfig->gpsNoFixLatitude != 0 && telemetryConfig->gpsNoFixLongitude != 0) {
sendFakeLatLong();
else {
sendFakeLatLongThatAllowsHeadingDisplay();
}
#else
// Send GPS information to display compass information
if (telemetryConfig->gpsNoFixLatitude != 0 && telemetryConfig->gpsNoFixLongitude != 0) {
sendFakeLatLong();
}
sendFakeLatLongThatAllowsHeadingDisplay();
#endif
sendTelemetryTail();

View file

@ -15,7 +15,7 @@
* along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
*/
char *targetName = __TARGET__;
char *shortGitRevision = __REVISION__;
char *buildDate = __DATE__;
char *buildTime = __TIME__;
const char * const targetName = __TARGET__;
const char * const shortGitRevision = __REVISION__;
const char * const buildDate = __DATE__;
const char * const buildTime = __TIME__;

View file

@ -25,13 +25,13 @@
#define MW_VERSION 231
extern char* targetName;
extern const char* const targetName;
#define GIT_SHORT_REVISION_LENGTH 7 // lower case hexadecimal digits.
extern char* shortGitRevision;
extern const char* const shortGitRevision;
#define BUILD_DATE_LENGTH 11
extern char* buildDate; // "MMM DD YYYY" MMM = Jan/Feb/...
extern const char* const buildDate; // "MMM DD YYYY" MMM = Jan/Feb/...
#define BUILD_TIME_LENGTH 8
extern char* buildTime; // "HH:MM:SS"
extern const char* const buildTime; // "HH:MM:SS"

View file

@ -26,8 +26,8 @@ OBJECT_DIR = ../../obj/test
COMMON_FLAGS = \
-g \
-Wall \
-Wextra \
-pthread \
-Wextra \
-ggdb3 \
-O0 \
-DUNIT_TEST \
@ -39,7 +39,7 @@ C_FLAGS = $(COMMON_FLAGS) \
# Flags passed to the C++ compiler.
CXX_FLAGS = $(COMMON_FLAGS) \
-std=gnu++98
-std=gnu++11
# All tests produced by this Makefile. Remember to add new tests you
# created to the list.
@ -83,7 +83,7 @@ GTEST_SRCS_ = $(GTEST_DIR)/src/*.cc $(GTEST_DIR)/inc/gtest/*.h $(GTEST_HEADERS)
# compiles fast and for ordinary users its source rarely changes.
$(OBJECT_DIR)/gtest-all.o : $(GTEST_SRCS_)
@mkdir -p $(dir $@)
$(CXX) $(CXX_FLAGS) -I$(GTEST_DIR) -c \
$(CXX) $(CXX_FLAGS) -I$(GTEST_DIR) -Wno-missing-field-initializers -Wno-unused-const-variable -c \
$(GTEST_DIR)/src/gtest-all.cc -o $@
$(OBJECT_DIR)/gtest_main.o : $(GTEST_SRCS_)
@ -134,7 +134,7 @@ battery_unittest : \
$(OBJECT_DIR)/battery_unittest.o \
$(OBJECT_DIR)/gtest_main.a
$(CXX) $(CXX_FLAGS) -lpthread $^ -o $(OBJECT_DIR)/$@
$(CXX) $(CXX_FLAGS) $^ -o $(OBJECT_DIR)/$@
$(OBJECT_DIR)/common/encoding.o : $(USER_DIR)/common/encoding.c $(USER_DIR)/common/encoding.h $(GTEST_HEADERS)
@mkdir -p $(dir $@)
@ -153,7 +153,7 @@ encoding_unittest : \
$(OBJECT_DIR)/encoding_unittest.o \
$(OBJECT_DIR)/gtest_main.a
$(CXX) $(CXX_FLAGS) -lpthread $^ -o $(OBJECT_DIR)/$@
$(CXX) $(CXX_FLAGS) $^ -o $(OBJECT_DIR)/$@
$(OBJECT_DIR)/flight/imu.o : \
$(USER_DIR)/flight/imu.c \
@ -178,7 +178,7 @@ flight_imu_unittest : \
$(OBJECT_DIR)/common/maths.o \
$(OBJECT_DIR)/gtest_main.a
$(CXX) $(CXX_FLAGS) -lpthread $^ -o $(OBJECT_DIR)/$@
$(CXX) $(CXX_FLAGS) $^ -o $(OBJECT_DIR)/$@
$(OBJECT_DIR)/maths_unittest.o : \
$(TEST_DIR)/maths_unittest.cc \
@ -192,7 +192,7 @@ maths_unittest : \
$(OBJECT_DIR)/common/maths.o \
$(OBJECT_DIR)/gtest_main.a
$(CXX) $(CXX_FLAGS) -lpthread $^ -o $(OBJECT_DIR)/$@
$(CXX) $(CXX_FLAGS) $^ -o $(OBJECT_DIR)/$@
@ -217,7 +217,7 @@ altitude_hold_unittest : \
$(OBJECT_DIR)/altitude_hold_unittest.o \
$(OBJECT_DIR)/gtest_main.a
$(CXX) $(CXX_FLAGS) -lpthread $^ -o $(OBJECT_DIR)/$@
$(CXX) $(CXX_FLAGS) $^ -o $(OBJECT_DIR)/$@
$(OBJECT_DIR)/flight/gps_conversion.o : \
@ -241,7 +241,7 @@ gps_conversion_unittest : \
$(OBJECT_DIR)/gps_conversion_unittest.o \
$(OBJECT_DIR)/gtest_main.a
$(CXX) $(CXX_FLAGS) -lpthread $^ -o $(OBJECT_DIR)/$@
$(CXX) $(CXX_FLAGS) $^ -o $(OBJECT_DIR)/$@
@ -267,7 +267,7 @@ telemetry_hott_unittest : \
$(OBJECT_DIR)/flight/gps_conversion.o \
$(OBJECT_DIR)/gtest_main.a
$(CXX) $(CXX_FLAGS) -lpthread $^ -o $(OBJECT_DIR)/$@
$(CXX) $(CXX_FLAGS) $^ -o $(OBJECT_DIR)/$@
@ -293,7 +293,7 @@ rc_controls_unittest : \
$(OBJECT_DIR)/rc_controls_unittest.o \
$(OBJECT_DIR)/gtest_main.a
$(CXX) $(CXX_FLAGS) -lpthread $^ -o $(OBJECT_DIR)/$@
$(CXX) $(CXX_FLAGS) $^ -o $(OBJECT_DIR)/$@
$(OBJECT_DIR)/io/ledstrip.o : \
@ -317,7 +317,7 @@ ledstrip_unittest : \
$(OBJECT_DIR)/ledstrip_unittest.o \
$(OBJECT_DIR)/gtest_main.a
$(CXX) $(CXX_FLAGS) -lpthread $^ -o $(OBJECT_DIR)/$@
$(CXX) $(CXX_FLAGS) $^ -o $(OBJECT_DIR)/$@
@ -342,7 +342,7 @@ ws2811_unittest : \
$(OBJECT_DIR)/ws2811_unittest.o \
$(OBJECT_DIR)/gtest_main.a
$(CXX) $(CXX_FLAGS) -lpthread $^ -o $(OBJECT_DIR)/$@
$(CXX) $(CXX_FLAGS) $^ -o $(OBJECT_DIR)/$@
$(OBJECT_DIR)/flight/lowpass.o : \
@ -366,7 +366,7 @@ lowpass_unittest : \
$(OBJECT_DIR)/lowpass_unittest.o \
$(OBJECT_DIR)/gtest_main.a
$(CXX) $(CXX_FLAGS) -lpthread $^ -o $(OBJECT_DIR)/$@
$(CXX) $(CXX_FLAGS) $^ -o $(OBJECT_DIR)/$@
$(OBJECT_DIR)/flight/mixer.o : \
$(USER_DIR)/flight/mixer.c \
@ -390,7 +390,7 @@ flight_mixer_unittest : \
$(OBJECT_DIR)/common/maths.o \
$(OBJECT_DIR)/gtest_main.a
$(CXX) $(CXX_FLAGS) -lpthread $^ -o $(OBJECT_DIR)/$@
$(CXX) $(CXX_FLAGS) $^ -o $(OBJECT_DIR)/$@
$(OBJECT_DIR)/flight/failsafe.o : \
$(USER_DIR)/flight/failsafe.c \
@ -414,7 +414,7 @@ flight_failsafe_unittest : \
$(OBJECT_DIR)/common/maths.o \
$(OBJECT_DIR)/gtest_main.a
$(CXX) $(CXX_FLAGS) -lpthread $^ -o $(OBJECT_DIR)/$@
$(CXX) $(CXX_FLAGS) $^ -o $(OBJECT_DIR)/$@
$(OBJECT_DIR)/io/serial.o : \
$(USER_DIR)/io/serial.c \
@ -437,7 +437,7 @@ io_serial_unittest : \
$(OBJECT_DIR)/io_serial_unittest.o \
$(OBJECT_DIR)/gtest_main.a
$(CXX) $(CXX_FLAGS) -lpthread $^ -o $(OBJECT_DIR)/$@
$(CXX) $(CXX_FLAGS) $^ -o $(OBJECT_DIR)/$@
$(OBJECT_DIR)/rx/rx.o : \
$(USER_DIR)/rx/rx.c \
@ -461,7 +461,7 @@ rx_rx_unittest : \
$(OBJECT_DIR)/common/maths.o \
$(OBJECT_DIR)/gtest_main.a
$(CXX) $(CXX_FLAGS) -lpthread $^ -o $(OBJECT_DIR)/$@
$(CXX) $(CXX_FLAGS) $^ -o $(OBJECT_DIR)/$@
test: $(TESTS)
set -e && for test in $(TESTS) ; do \

View file

@ -48,18 +48,6 @@ extern "C" {
extern uint8_t servoCount;
void forwardAuxChannelsToServos(void);
void mixerUseConfigs(
#ifdef USE_SERVOS
servoParam_t *servoConfToUse,
gimbalConfig_t *gimbalConfigToUse,
#endif
flight3DConfig_t *flight3DConfigToUse,
escAndServoConfig_t *escAndServoConfigToUse,
mixerConfig_t *mixerConfigToUse,
airplaneConfig_t *airplaneConfigToUse,
rxConfig_t *rxConfigToUse
);
void mixerInit(mixerMode_e mixerMode, motorMixer_t *initialCustomMixers);
void mixerUsePWMOutputConfiguration(pwmOutputConfiguration_t *pwmOutputConfiguration);
}
@ -315,6 +303,15 @@ void pwmWriteMotor(uint8_t index, uint16_t value) {
motors[index].value = value;
}
void pwmShutdownPulsesForAllMotors(uint8_t motorCount)
{
uint8_t index;
for(index = 0; index < motorCount; index++){
motors[index].value = 0;
}
}
void pwmCompleteOneshotMotorUpdate(uint8_t motorCount) {
lastOneShotUpdateMotorCount = motorCount;
}
@ -323,4 +320,8 @@ void pwmWriteServo(uint8_t index, uint16_t value) {
servos[index].value = value;
}
bool failsafeIsActive(void) {
return false;
}
}

View file

@ -48,13 +48,18 @@ extern "C" {
extern void useRcControlsConfig(modeActivationCondition_t *modeActivationConditions, escAndServoConfig_t *escAndServoConfig, pidProfile_t *pidProfile);
}
TEST(RcControlsTest, updateActivatedModesWithAllInputsAtMidde)
class RcControlsModesTest : public ::testing::Test {
protected:
modeActivationCondition_t modeActivationConditions[MAX_MODE_ACTIVATION_CONDITION_COUNT];
virtual void SetUp() {
memset(&modeActivationConditions, 0, sizeof(modeActivationConditions));
}
};
TEST_F(RcControlsModesTest, updateActivatedModesWithAllInputsAtMidde)
{
// given
modeActivationCondition_t modeActivationConditions[MAX_MODE_ACTIVATION_CONDITION_COUNT];
memset(&modeActivationConditions, 0, sizeof(modeActivationConditions));
// and
rcModeActivationMask = 0;
// and
@ -79,12 +84,9 @@ TEST(RcControlsTest, updateActivatedModesWithAllInputsAtMidde)
}
}
TEST(RcControlsTest, updateActivatedModesUsingValidAuxConfigurationAndRXValues)
TEST_F(RcControlsModesTest, updateActivatedModesUsingValidAuxConfigurationAndRXValues)
{
// given
modeActivationCondition_t modeActivationConditions[MAX_MODE_ACTIVATION_CONDITION_COUNT];
memset(&modeActivationConditions, 0, sizeof(modeActivationConditions));
modeActivationConditions[0].modeId = (boxId_e)0;
modeActivationConditions[0].auxChannelIndex = AUX1 - NON_AUX_CHANNEL_COUNT;
modeActivationConditions[0].range.startStep = CHANNEL_VALUE_TO_STEP(1700);
@ -232,27 +234,33 @@ static const adjustmentConfig_t rateAdjustmentConfig = {
.data = { { 1 } }
};
TEST(RcControlsTest, processRcAdjustmentsSticksInMiddle)
{
// given
class RcControlsAdjustmentsTest : public ::testing::Test {
protected:
controlRateConfig_t controlRateConfig = {
.rcRate8 = 90,
.rcExpo8 = 0,
.thrMid8 = 0,
.thrExpo8 = 0,
.rates = {0,0,0},
.rates = {0, 0, 0},
.dynThrPID = 0,
.rcYawExpo8 = 0,
.tpa_breakpoint = 0
};
// and
memset(&rxConfig, 0, sizeof (rxConfig));
rxConfig.mincheck = DEFAULT_MIN_CHECK;
rxConfig.maxcheck = DEFAULT_MAX_CHECK;
rxConfig.midrc = 1500;
virtual void SetUp() {
adjustmentStateMask = 0;
memset(&adjustmentStates, 0, sizeof(adjustmentStates));
adjustmentStateMask = 0;
memset(&adjustmentStates, 0, sizeof(adjustmentStates));
memset(&rxConfig, 0, sizeof (rxConfig));
rxConfig.mincheck = DEFAULT_MIN_CHECK;
rxConfig.maxcheck = DEFAULT_MAX_CHECK;
rxConfig.midrc = 1500;
}
};
TEST_F(RcControlsAdjustmentsTest, processRcAdjustmentsSticksInMiddle)
{
// given
configureAdjustment(0, AUX3 - NON_AUX_CHANNEL_COUNT, &rateAdjustmentConfig);
// and
@ -275,28 +283,9 @@ TEST(RcControlsTest, processRcAdjustmentsSticksInMiddle)
EXPECT_EQ(adjustmentStateMask, 0);
}
TEST(RcControlsTest, processRcAdjustmentsWithRcRateFunctionSwitchUp)
TEST_F(RcControlsAdjustmentsTest, processRcAdjustmentsWithRcRateFunctionSwitchUp)
{
// given
controlRateConfig_t controlRateConfig = {
.rcRate8 = 90,
.rcExpo8 = 0,
.thrMid8 = 0,
.thrExpo8 = 0,
.rates = {0,0,0},
.dynThrPID = 0,
.tpa_breakpoint = 0
};
// and
memset(&rxConfig, 0, sizeof (rxConfig));
rxConfig.mincheck = DEFAULT_MIN_CHECK;
rxConfig.maxcheck = DEFAULT_MAX_CHECK;
rxConfig.midrc = 1500;
// and
adjustmentStateMask = 0;
memset(&adjustmentStates, 0, sizeof(adjustmentStates));
configureAdjustment(0, AUX3 - NON_AUX_CHANNEL_COUNT, &rateAdjustmentConfig);
// and
@ -441,28 +430,9 @@ static const adjustmentConfig_t rateProfileAdjustmentConfig = {
.data = { { 3 } }
};
TEST(RcControlsTest, processRcRateProfileAdjustments)
TEST_F(RcControlsAdjustmentsTest, processRcRateProfileAdjustments)
{
// given
controlRateConfig_t controlRateConfig = {
.rcRate8 = 90,
.rcExpo8 = 0,
.thrMid8 = 0,
.thrExpo8 = 0,
.rates = {0,0,0},
.dynThrPID = 0,
.tpa_breakpoint = 0
};
// and
memset(&rxConfig, 0, sizeof (rxConfig));
rxConfig.mincheck = DEFAULT_MIN_CHECK;
rxConfig.maxcheck = DEFAULT_MAX_CHECK;
rxConfig.midrc = 1500;
adjustmentStateMask = 0;
memset(&adjustmentStates, 0, sizeof(adjustmentStates));
int adjustmentIndex = 3;
configureAdjustment(adjustmentIndex, AUX4 - NON_AUX_CHANNEL_COUNT, &rateProfileAdjustmentConfig);
@ -528,7 +498,7 @@ static const adjustmentConfig_t pidYawDAdjustmentConfig = {
.data = { { 1 } }
};
TEST(RcControlsTest, processPIDIncreasePidController0)
TEST_F(RcControlsAdjustmentsTest, processPIDIncreasePidController0)
{
// given
modeActivationCondition_t modeActivationConditions[MAX_MODE_ACTIVATION_CONDITION_COUNT];
@ -554,15 +524,6 @@ TEST(RcControlsTest, processPIDIncreasePidController0)
controlRateConfig_t controlRateConfig;
memset(&controlRateConfig, 0, sizeof (controlRateConfig));
// and
memset(&rxConfig, 0, sizeof (rxConfig));
rxConfig.mincheck = DEFAULT_MIN_CHECK;
rxConfig.maxcheck = DEFAULT_MAX_CHECK;
rxConfig.midrc = 1500;
adjustmentStateMask = 0;
memset(&adjustmentStates, 0, sizeof(adjustmentStates));
configureAdjustment(0, AUX1 - NON_AUX_CHANNEL_COUNT, &pidPitchAndRollPAdjustmentConfig);
configureAdjustment(1, AUX2 - NON_AUX_CHANNEL_COUNT, &pidPitchAndRollIAdjustmentConfig);
configureAdjustment(2, AUX3 - NON_AUX_CHANNEL_COUNT, &pidPitchAndRollDAdjustmentConfig);
@ -614,7 +575,7 @@ TEST(RcControlsTest, processPIDIncreasePidController0)
EXPECT_EQ(28, pidProfile.D8[YAW]);
}
TEST(RcControlsTest, processPIDIncreasePidController2)
TEST_F(RcControlsAdjustmentsTest, processPIDIncreasePidController2)
{
// given
modeActivationCondition_t modeActivationConditions[MAX_MODE_ACTIVATION_CONDITION_COUNT];
@ -640,15 +601,6 @@ TEST(RcControlsTest, processPIDIncreasePidController2)
controlRateConfig_t controlRateConfig;
memset(&controlRateConfig, 0, sizeof (controlRateConfig));
// and
memset(&rxConfig, 0, sizeof (rxConfig));
rxConfig.mincheck = DEFAULT_MIN_CHECK;
rxConfig.maxcheck = DEFAULT_MAX_CHECK;
rxConfig.midrc = 1500;
adjustmentStateMask = 0;
memset(&adjustmentStates, 0, sizeof(adjustmentStates));
configureAdjustment(0, AUX1 - NON_AUX_CHANNEL_COUNT, &pidPitchAndRollPAdjustmentConfig);
configureAdjustment(1, AUX2 - NON_AUX_CHANNEL_COUNT, &pidPitchAndRollIAdjustmentConfig);
configureAdjustment(2, AUX3 - NON_AUX_CHANNEL_COUNT, &pidPitchAndRollDAdjustmentConfig);