;**** **** **** **** ****
;
; BLHeli program for controlling brushless motors in helicopters and multirotors
;
; Copyright 2011, 2012 Steffen Skaug
; This program is distributed under the terms of the GNU General Public License
;
; This file is part of BLHeli.
;
; BLHeli is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; BLHeli is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with BLHeli. If not, see .
;
;**** **** **** **** ****
;
; The software was initially designed for use with Eflite mCP X, but is now adapted to copters/planes in general
;
; The software was inspired by and started from from Bernard Konze's BLMC: http://home.versanet.de/~bkonze/blc_6a/blc_6a.htm
; And also Simon Kirby's TGY: https://github.com/sim-/tgy
;
; This file is best viewed with tab width set to 5
;
; The input signal can be positive 1kHz, 2kHz, 4kHz, 8kHz or 12kHz PWM (e.g. taken from the "resistor tap" on mCPx)
; And the input signal can be PPM (1-2ms) or OneShot125 (125-250us) at rates up to several hundred Hz.
; The code autodetects the various input modes/frequencies
; The code can also be programmed to accept inverted input signal.
;
; The first lines of the software must be modified according to the chosen environment:
; Uncomment the selected ESC and main/tail/multi mode
; BESC EQU "ESC"_"mode"
;
;**** **** **** **** ****
; Revision history:
; - Rev0.0: Initial revision
; - Rev1.0: Governor functionality added
; - Rev1.1: Increased tail gain to 1.0625. Implemented for tail only
; Decreased governor proportional and integral gain by 4
; Fixed bug that caused tail power not always to be max
; - Rev1.2: Governor integral gain should be higher in order to achieve full PWM range
; Integral gain can be higher, and is increased by 2x. An integral of +-128 can now be added to requested PWM
; - Rev1.3: Governor integral extended to 24bit
; Governor proportional gain increased by 2x
; Added slow spoolup/down for governor
; Set pwm to 100% (do not turn off nFET) for high values of current pwm
; Added support for PPM input (1us to 2us pulse)
; Removed USE_COMP_STORED as it was never used
; - Rev2.0 Added measurement of pwm frequency and support for 1kHz, 2kHz, 4kHz and 8kHz
; Optimized pwm on and off routines
; Improved mosfet switching in beep routines, to reduce current draw
; Added support for ICP1 interrupt pin input
; Added ADC measurement of supply voltage, with limiting of main motor power for low voltage
; Miscellaneous other changes
; - Rev2.1 Rewritten INT0 routine to be similar to ICP
; Reduced validation threshold (RCP_VALIDATE)
; Removed requirement for RCP to go to zero again in tail arming sequence
; Removed PPM support
; - Rev2.2 Added support for HC 5A 1S ESC with Atmega48V MPU
; Increased governor proportional gain by 2x
; - Rev3.0 Added functionality for programming from TX
; Added low voltage limit scaling for 2S and 3S
; - Rev11.2 Copied over from the SiLabs version and adapted to Atmel
; Now requiring a 16MHz capable MCU for fullspec performance
; - Rev12.0 Added programmable main spoolup time
; Added programmable temperature protection enable
; Bidirectional mode stop/start improved. Motor is now stopped before starting
; Power is limited for very low rpms (when BEMF is low), in order to avoid sync loss
; Damped light mode is made more smooth and quiet, particularly at low and high rpms
; Comparator signal qualification scheme is changed
; Demag compensation scheme is significantly changed
; Increased jitter tolerance for PPM frequency measurement
; Fully damped mode removed, and damped light only supported on damped capable ESCs
; Default tail mode changed to damped light
; Miscellaneous other changes
; - Rev12.1 Fixed bug in tail code
; Improved startup for Atmel
; Added support for multiple high BEC voltages
; Added support for RPM output
; - Rev12.2 Improved running smoothness, particularly for damped light
; Avoiding lockup at full throttle when input signal is noisy
; Avoiding detection of 1-wire programming signal as valid throttle signal
; - Rev13.0 Removed throttle change rate and damping force parameters
; Temperature protection default set to off
; Added support for OneShot125
; Improved commutation timing accuracy
; - Rev13.1 Removed startup ramp for MULTI
; Improved startup for some odd ESCs
; - Rev13.2 Still tweaking startup to make it more reliable and faster for all ESC/motor combos
; Increased deadband for bidirectional operation
; Relaxed signal detection criteria
; Miscellaneous other changes
; - Rev14.0 Improved running at high RPMs and increased max RPM limit
; Improved reliability of 3D (bidirectional) mode and startup
; Avoid being locked in bootloader (implemented in Suite 13202)
; Smoother running and greatly reduced step to full power in damped light mode
; Removed low voltage limiting for MULTI
; Added pwm dither parameter
; Added setting for enable/disable of low RPM power protection
; Added setting for enable/disable of PWM input
; Better AFW and damping for some ESCs (that have a slow high side driver)
; Miscellaneous other changes
; - Rev14.1 Fixed max throttle calibration bug (for non-oneshot)
; Fixed some closed loop mode bugs
; Relaxed signal jitter requirement for looptimes below 1000
; Added skipping of damping fet switching near max power, for improved high end throttle linearity, using the concept of SimonK
; Improved sync hold at high rpms
; - Rev14.2 Improved quality of comparator reading, giving better bemf detection (for improved startup amongst others)
; Removed mechanism where some ESCs could reset upon starting motor (due to ADC being read)
; Added stalled motor shutoff after about 10 seconds (for tail and multi code with PPM input)
; Greatly increased maximum rpm limit, and added rpm limiting at 250k erpm
; Improved bidirectional operation
; - Rev14.3 Moved reset vector to be just before the settings segment, in order to better recover from partially failed flashing operation
; Shortened stall detect time to about 5sec, and prevented going into tx programming after a stall
; Optimizations of software timing and running reliability
; - Rev14.4 Improved startup, particularly for larger motors
; Improved running at very high rpms
; Made damped light default for MULTI on ESCs that support it
; Miscellaneous other changes
;
;
;
;**** **** **** **** ****
; 8K Bytes of In-System Self-Programmable Flash
; 1K Bytes Internal SRAM
; 512 Bytes Internal EEPROM
; 16MHz clock
;
;**** **** **** **** ****
; Timer 0 (500ns counts) always counts up and is used for
; - RC pulse timeout and skip counts
; Timer 1 (500ns counts) always counts up and is used for
; - RC pulse measurement (via external interrupt 0 or input capture pin)
; - Commutation timing (via output compare register A interrupt)
; Timer 2 (500ns counts) always counts up and is used for
; - PWM generation
;
;**** **** **** **** ****
; Interrupt handling
; The Atmega8 disables all interrupts when entering an interrupt routine,
; The code reenables interrupts in some interrupt routines, in order to nest pwm interrupts
; - Interrupts are disabled during beeps, to avoid audible interference from interrupts
; - RC pulse interrupts are periodically disabled in order to reduce interference with pwm interrupts.
;
;**** **** **** **** ****
; Motor control:
; - Brushless motor control with 6 states for each electrical 360 degrees
; - An advance timing of 0deg has zero cross 30deg after one commutation and 30deg before the next
; - Timing advance in this implementation is set to 15deg nominally
; - "Damped" commutation schemes are available, where more than one pfet is on when pwm is off. This will absorb energy from bemf and make step settling more damped.
; Motor sequence starting from zero crossing:
; - Timer wait: Wt_Comm 15deg ; Time to wait from zero cross to actual commutation
; - Timer wait: Wt_Advance 15deg ; Time to wait for timing advance. Nominal commutation point is after this
; - Timer wait: Wt_Zc_Scan 7.5deg ; Time to wait before looking for zero cross
; - Scan for zero cross 22.5deg , Nominal, with some motor variations
;
; Motor startup:
; There is a startup phase and an initial run phase, before normal bemf commutation run begins.
;
;**** **** **** **** ****
; Select the ESC and mode to use (or unselect all for use with external batch compile file);
;#define BLUESERIES_12A_MAIN
;#define BLUESERIES_12A_TAIL
;#define BLUESERIES_12A_MULTI
;#define BLUESERIES_20A_MAIN
;#define BLUESERIES_20A_TAIL
;#define BLUESERIES_20A_MULTI
;#define BLUESERIES_30A_MAIN
;#define BLUESERIES_30A_TAIL
;#define BLUESERIES_30A_MULTI
;#define BLUESERIES_40A_MAIN
;#define BLUESERIES_40A_TAIL
;#define BLUESERIES_40A_MULTI
;#define BLUESERIES_60A_MAIN
;#define BLUESERIES_60A_TAIL
;#define BLUESERIES_60A_MULTI
;#define BLUESERIES_70A_MAIN
;#define BLUESERIES_70A_TAIL
;#define BLUESERIES_70A_MULTI
;#define HK_UBEC_6A_MAIN
;#define HK_UBEC_6A_TAIL
;#define HK_UBEC_6A_MULTI
;#define HK_UBEC_10A_MAIN
;#define HK_UBEC_10A_TAIL
;#define HK_UBEC_10A_MULTI
;#define HK_UBEC_20A_MAIN
;#define HK_UBEC_20A_TAIL
;#define HK_UBEC_20A_MULTI
;#define HK_UBEC_30A_MAIN
;#define HK_UBEC_30A_TAIL
;#define HK_UBEC_30A_MULTI
;#define HK_UBEC_40A_MAIN
;#define HK_UBEC_40A_TAIL
;#define HK_UBEC_40A_MULTI
;#define SUPERSIMPLE_18A_MAIN
;#define SUPERSIMPLE_18A_TAIL
;#define SUPERSIMPLE_18A_MULTI
;#define SUPERSIMPLE_20A_MAIN
;#define SUPERSIMPLE_20A_TAIL
;#define SUPERSIMPLE_20A_MULTI
;#define SUPERSIMPLE_30A_MAIN
;#define SUPERSIMPLE_30A_TAIL
;#define SUPERSIMPLE_30A_MULTI
;#define SUPERSIMPLE_40A_MAIN
;#define SUPERSIMPLE_40A_TAIL
;#define SUPERSIMPLE_40A_MULTI
;#define MULTISTAR_10Av2_MAIN
;#define MULTISTAR_10Av2_TAIL
;#define MULTISTAR_10Av2_MULTI
;#define MULTISTAR_15A_MAIN ; Inverted input
;#define MULTISTAR_15A_TAIL
;#define MULTISTAR_15A_MULTI
;#define MULTISTAR_20A_MAIN ; Inverted input
;#define MULTISTAR_20A_TAIL
;#define MULTISTAR_20A_MULTI
;#define MULTISTAR_20A_NFET_MAIN ; Inverted input
;#define MULTISTAR_20A_NFET_TAIL
;#define MULTISTAR_20A_NFET_MULTI
;#define MULTISTAR_20Av2_MAIN
;#define MULTISTAR_20Av2_TAIL
;#define MULTISTAR_20Av2_MULTI
;#define MULTISTAR_30A_MAIN ; Inverted input
;#define MULTISTAR_30A_TAIL
;#define MULTISTAR_30A_MULTI
;#define MULTISTAR_40Av2_MAIN
;#define MULTISTAR_40Av2_TAIL
;#define MULTISTAR_40Av2_MULTI
;#define MULTISTAR_45A_MAIN ; Inverted input
;#define MULTISTAR_45A_TAIL
;#define MULTISTAR_45A_MULTI
;#define MYSTERY_12A_MAIN
;#define MYSTERY_12A_TAIL
;#define MYSTERY_12A_MULTI
;#define MYSTERY_30A_MAIN
;#define MYSTERY_30A_TAIL
;#define MYSTERY_30A_MULTI
;#define MYSTERY_40A_MAIN
;#define MYSTERY_40A_TAIL
;#define MYSTERY_40A_MULTI
;#define SUNRISE_HIMULTI_20A_MAIN ; Inverted input
;#define SUNRISE_HIMULTI_20A_TAIL
;#define SUNRISE_HIMULTI_20A_MULTI
;#define SUNRISE_HIMULTI_30A_MAIN ; Inverted input
;#define SUNRISE_HIMULTI_30A_TAIL
;#define SUNRISE_HIMULTI_30A_MULTI
;#define SUNRISE_HIMULTI_40A_MAIN ; Inverted input
;#define SUNRISE_HIMULTI_40A_TAIL
;#define SUNRISE_HIMULTI_40A_MULTI
;#define RCTIMER_40A_MAIN
;#define RCTIMER_40A_TAIL
;#define RCTIMER_40A_MULTI
;#define RCTIMER_NFS_30A_MAIN ; ICP1 as input
;#define RCTIMER_NFS_30A_TAIL
;#define RCTIMER_NFS_30A_MULTI
;#define YEP_7A_MAIN
;#define YEP_7A_TAIL
;#define YEP_7A_MULTI
;#define AFRO_12A_MAIN ; ICP1 as input
;#define AFRO_12A_TAIL
;#define AFRO_12A_MULTI
;#define AFRO_20A_MAIN ; ICP1 as input
;#define AFRO_20A_TAIL
;#define AFRO_20A_MULTI
;#define AFRO_20A_HV_MAIN ; ICP1 as input
;#define AFRO_20A_HV_TAIL
;#define AFRO_20A_HV_MULTI
;#define AFRO_30A_MAIN ; ICP1 as input
;#define AFRO_30A_TAIL
;#define AFRO_30A_MULTI
;#define SUNRISE_BLHELI_SLIM_20A_MAIN
;#define SUNRISE_BLHELI_SLIM_20A_TAIL
;#define SUNRISE_BLHELI_SLIM_20A_MULTI
;#define SUNRISE_BLHELI_SLIM_30A_MAIN
;#define SUNRISE_BLHELI_SLIM_30A_TAIL
;#define SUNRISE_BLHELI_SLIM_30A_MULTI
;#define DYS_SN20A_MAIN ; ICP1 as input
;#define DYS_SN20A_TAIL
;#define DYS_SN20A_MULTI
;#define TBS_CUBE_20A_MAIN ; ICP1 as input
;#define TBS_CUBE_20A_TAIL
;#define TBS_CUBE_20A_MULTI
;#define ZTW_SPIDER_LITE_18Av2_MAIN
;#define ZTW_SPIDER_LITE_18Av2_TAIL
;#define ZTW_SPIDER_LITE_18Av2_MULTI
;**** **** **** **** ****
; ESC selection statements
#if defined(BLUESERIES_12A_MAIN)
.EQU MODE = 0 ; Choose mode. Set to 0 for main motor
.INCLUDE "BlueSeries_12A.inc" ; Select BlueSeries 12A pinout
#endif
#if defined(BLUESERIES_12A_TAIL)
.EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
.INCLUDE "BlueSeries_12A.inc" ; Select BlueSeries 12A pinout
#endif
#if defined(BLUESERIES_12A_MULTI)
.EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
.INCLUDE "BlueSeries_12A.inc" ; Select BlueSeries 12A pinout
#endif
#if defined(BLUESERIES_20A_MAIN)
.EQU MODE = 0 ; Choose mode. Set to 0 for main motor
.INCLUDE "BlueSeries_20A.inc" ; Select BlueSeries 20A pinout
#endif
#if defined(BLUESERIES_20A_TAIL)
.EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
.INCLUDE "BlueSeries_20A.inc" ; Select BlueSeries 20A pinout
#endif
#if defined(BLUESERIES_20A_MULTI)
.EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
.INCLUDE "BlueSeries_20A.inc" ; Select BlueSeries 20A pinout
#endif
#if defined(BLUESERIES_30A_MAIN)
.EQU MODE = 0 ; Choose mode. Set to 0 for main motor
.INCLUDE "BlueSeries_30A.inc" ; Select BlueSeries 30A pinout
#endif
#if defined(BLUESERIES_30A_TAIL)
.EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
.INCLUDE "BlueSeries_30A.inc" ; Select BlueSeries 30A pinout
#endif
#if defined(BLUESERIES_30A_MULTI)
.EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
.INCLUDE "BlueSeries_30A.inc" ; Select BlueSeries 30A pinout
#endif
#if defined(BLUESERIES_40A_MAIN)
.EQU MODE = 0 ; Choose mode. Set to 0 for main motor
.INCLUDE "BlueSeries_40A.inc" ; Select BlueSeries 40A pinout
#endif
#if defined(BLUESERIES_40A_TAIL)
.EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
.INCLUDE "BlueSeries_40A.inc" ; Select BlueSeries 40A pinout
#endif
#if defined(BLUESERIES_40A_MULTI)
.EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
.INCLUDE "BlueSeries_40A.inc" ; Select BlueSeries 40A pinout
#endif
#if defined(BLUESERIES_60A_MAIN)
.EQU MODE = 0 ; Choose mode. Set to 0 for main motor
.INCLUDE "BlueSeries_60A.inc" ; Select BlueSeries 60A pinout
#endif
#if defined(BLUESERIES_60A_TAIL)
.EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
.INCLUDE "BlueSeries_60A.inc" ; Select BlueSeries 60A pinout
#endif
#if defined(BLUESERIES_60A_MULTI)
.EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
.INCLUDE "BlueSeries_60A.inc" ; Select BlueSeries 60A pinout
#endif
#if defined(BLUESERIES_70A_MAIN)
.EQU MODE = 0 ; Choose mode. Set to 0 for main motor
.INCLUDE "BlueSeries_70A.inc" ; Select BlueSeries 70A pinout
#endif
#if defined(BLUESERIES_70A_TAIL)
.EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
.INCLUDE "BlueSeries_70A.inc" ; Select BlueSeries 70A pinout
#endif
#if defined(BLUESERIES_70A_MULTI)
.EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
.INCLUDE "BlueSeries_70A.inc" ; Select BlueSeries 70A pinout
#endif
#if defined(HK_UBEC_6A_MAIN)
.EQU MODE = 0 ; Choose mode. Set to 0 for main motor
.INCLUDE "HK_UBEC_6A.inc" ; Select Hobbyking UBEC 6A pinout
#endif
#if defined(HK_UBEC_6A_TAIL)
.EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
.INCLUDE "HK_UBEC_6A.inc" ; Select Hobbyking UBEC 6A pinout
#endif
#if defined(HK_UBEC_6A_MULTI)
.EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
.INCLUDE "HK_UBEC_6A.inc" ; Select Hobbyking UBEC 6A pinout
#endif
#if defined(HK_UBEC_10A_MAIN)
.EQU MODE = 0 ; Choose mode. Set to 0 for main motor
.INCLUDE "HK_UBEC_10A.inc" ; Select Hobbyking UBEC 10A pinout
#endif
#if defined(HK_UBEC_10A_TAIL)
.EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
.INCLUDE "HK_UBEC_10A.inc" ; Select Hobbyking UBEC 10A pinout
#endif
#if defined(HK_UBEC_10A_MULTI)
.EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
.INCLUDE "HK_UBEC_10A.inc" ; Select Hobbyking UBEC 10A pinout
#endif
#if defined(HK_UBEC_20A_MAIN)
.EQU MODE = 0 ; Choose mode. Set to 0 for main motor
.INCLUDE "HK_UBEC_20A.inc" ; Select Hobbyking UBEC 20A pinout
#endif
#if defined(HK_UBEC_20A_TAIL)
.EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
.INCLUDE "HK_UBEC_20A.inc" ; Select Hobbyking UBEC 20A pinout
#endif
#if defined(HK_UBEC_20A_MULTI)
.EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
.INCLUDE "HK_UBEC_20A.inc" ; Select Hobbyking UBEC 20A pinout
#endif
#if defined(HK_UBEC_30A_MAIN)
.EQU MODE = 0 ; Choose mode. Set to 0 for main motor
.INCLUDE "HK_UBEC_30A.inc" ; Select Hobbyking UBEC 30A pinout
#endif
#if defined(HK_UBEC_30A_TAIL)
.EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
.INCLUDE "HK_UBEC_30A.inc" ; Select Hobbyking UBEC 30A pinout
#endif
#if defined(HK_UBEC_30A_MULTI)
.EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
.INCLUDE "HK_UBEC_30A.inc" ; Select Hobbyking UBEC 30A pinout
#endif
#if defined(HK_UBEC_40A_MAIN)
.EQU MODE = 0 ; Choose mode. Set to 0 for main motor
.INCLUDE "HK_UBEC_40A.inc" ; Select Hobbyking UBEC 40A pinout
#endif
#if defined(HK_UBEC_40A_TAIL)
.EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
.INCLUDE "HK_UBEC_40A.inc" ; Select Hobbyking UBEC 40A pinout
#endif
#if defined(HK_UBEC_40A_MULTI)
.EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
.INCLUDE "HK_UBEC_40A.inc" ; Select Hobbyking UBEC 40A pinout
#endif
#if defined(SUPERSIMPLE_18A_MAIN)
.EQU MODE = 0 ; Choose mode. Set to 0 for main motor
.INCLUDE "SuperSimple_18A.inc" ; Select SuperSimple 18A pinout
#endif
#if defined(SUPERSIMPLE_18A_TAIL)
.EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
.INCLUDE "SuperSimple_18A.inc" ; Select SuperSimple 18A pinout
#endif
#if defined(SUPERSIMPLE_18A_MULTI)
.EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
.INCLUDE "SuperSimple_18A.inc" ; Select SuperSimple 18A pinout
#endif
#if defined(SUPERSIMPLE_20A_MAIN)
.EQU MODE = 0 ; Choose mode. Set to 0 for main motor
.INCLUDE "SuperSimple_20A.inc" ; Select SuperSimple 20A pinout
#endif
#if defined(SUPERSIMPLE_20A_TAIL)
.EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
.INCLUDE "SuperSimple_20A.inc" ; Select SuperSimple 20A pinout
#endif
#if defined(SUPERSIMPLE_20A_MULTI)
.EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
.INCLUDE "SuperSimple_20A.inc" ; Select SuperSimple 20A pinout
#endif
#if defined(SUPERSIMPLE_30A_MAIN)
.EQU MODE = 0 ; Choose mode. Set to 0 for main motor
.INCLUDE "SuperSimple_30A.inc" ; Select SuperSimple 30A pinout
#endif
#if defined(SUPERSIMPLE_30A_TAIL)
.EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
.INCLUDE "SuperSimple_30A.inc" ; Select SuperSimple 30A pinout
#endif
#if defined(SUPERSIMPLE_30A_MULTI)
.EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
.INCLUDE "SuperSimple_30A.inc" ; Select SuperSimple 30A pinout
#endif
#if defined(SUPERSIMPLE_40A_MAIN)
.EQU MODE = 0 ; Choose mode. Set to 0 for main motor
.INCLUDE "SuperSimple_40A.inc" ; Select SuperSimple 40A pinout
#endif
#if defined(SUPERSIMPLE_40A_TAIL)
.EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
.INCLUDE "SuperSimple_40A.inc" ; Select SuperSimple 40A pinout
#endif
#if defined(SUPERSIMPLE_40A_MULTI)
.EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
.INCLUDE "SuperSimple_40A.inc" ; Select SuperSimple 40A pinout
#endif
#if defined(MULTISTAR_10Av2_MAIN)
.EQU MODE = 0 ; Choose mode. Set to 0 for main motor
.INCLUDE "Multistar_10Av2.inc" ; Select Multistar 10A v2 pinout
#endif
#if defined(MULTISTAR_10Av2_TAIL)
.EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
.INCLUDE "Multistar_10Av2.inc" ; Select Multistar 10A v2 pinout
#endif
#if defined(MULTISTAR_10Av2_MULTI)
.EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
.INCLUDE "Multistar_10Av2.inc" ; Select Multistar 10A v2 pinout
#endif
#if defined(MULTISTAR_15A_MAIN)
.EQU MODE = 0 ; Choose mode. Set to 0 for main motor
.INCLUDE "Multistar_15A.inc" ; Select Multistar 15A pinout
#endif
#if defined(MULTISTAR_15A_TAIL)
.EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
.INCLUDE "Multistar_15A.inc" ; Select Multistar 15A pinout
#endif
#if defined(MULTISTAR_15A_MULTI)
.EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
.INCLUDE "Multistar_15A.inc" ; Select Multistar 15A pinout
#endif
#if defined(MULTISTAR_20A_MAIN)
.EQU MODE = 0 ; Choose mode. Set to 0 for main motor
.INCLUDE "Multistar_20A.inc" ; Select Multistar 20A pinout
#endif
#if defined(MULTISTAR_20A_TAIL)
.EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
.INCLUDE "Multistar_20A.inc" ; Select Multistar 20A pinout
#endif
#if defined(MULTISTAR_20A_MULTI)
.EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
.INCLUDE "Multistar_20A.inc" ; Select Multistar 20A pinout
#endif
#if defined(MULTISTAR_20A_NFET_MAIN)
.EQU MODE = 0 ; Choose mode. Set to 0 for main motor
.INCLUDE "Multistar_20A_NFET.inc" ; Select Multistar 20A NFET pinout
#endif
#if defined(MULTISTAR_20A_NFET_TAIL)
.EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
.INCLUDE "Multistar_20A_NFET.inc" ; Select Multistar 20A NFET pinout
#endif
#if defined(MULTISTAR_20A_NFET_MULTI)
.EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
.INCLUDE "Multistar_20A_NFET.inc" ; Select Multistar 20A NFET pinout
#endif
#if defined(MULTISTAR_20Av2_MAIN)
.EQU MODE = 0 ; Choose mode. Set to 0 for main motor
.INCLUDE "Multistar_20Av2.inc" ; Select Multistar 20A v2 pinout
#endif
#if defined(MULTISTAR_20Av2_TAIL)
.EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
.INCLUDE "Multistar_20Av2.inc" ; Select Multistar 20A v2 pinout
#endif
#if defined(MULTISTAR_20Av2_MULTI)
.EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
.INCLUDE "Multistar_20Av2.inc" ; Select Multistar 20A v2 pinout
#endif
#if defined(MULTISTAR_30A_MAIN)
.EQU MODE = 0 ; Choose mode. Set to 0 for main motor
.INCLUDE "Multistar_30A.inc" ; Select Multistar 30A pinout
#endif
#if defined(MULTISTAR_30A_TAIL)
.EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
.INCLUDE "Multistar_30A.inc" ; Select Multistar 30A pinout
#endif
#if defined(MULTISTAR_30A_MULTI)
.EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
.INCLUDE "Multistar_30A.inc" ; Select Multistar 30A pinout
#endif
#if defined(MULTISTAR_40Av2_MAIN)
.EQU MODE = 0 ; Choose mode. Set to 0 for main motor
.INCLUDE "Multistar_40Av2.inc" ; Select Multistar 40A v2 pinout
#endif
#if defined(MULTISTAR_40Av2_TAIL)
.EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
.INCLUDE "Multistar_40Av2.inc" ; Select Multistar 40A v2 pinout
#endif
#if defined(MULTISTAR_40Av2_MULTI)
.EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
.INCLUDE "Multistar_40Av2.inc" ; Select Multistar 40A v2 pinout
#endif
#if defined(MULTISTAR_45A_MAIN)
.EQU MODE = 0 ; Choose mode. Set to 0 for main motor
.INCLUDE "Multistar_45A.inc" ; Select Multistar 45A pinout
#endif
#if defined(MULTISTAR_45A_TAIL)
.EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
.INCLUDE "Multistar_45A.inc" ; Select Multistar 45A pinout
#endif
#if defined(MULTISTAR_45A_MULTI)
.EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
.INCLUDE "Multistar_45A.inc" ; Select Multistar 45A pinout
#endif
#if defined(MYSTERY_12A_MAIN)
.EQU MODE = 0 ; Choose mode. Set to 0 for main motor
.INCLUDE "Mystery_12A.inc" ; Select Mystery 12A pinout
#endif
#if defined(MYSTERY_12A_TAIL)
.EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
.INCLUDE "Mystery_12A.inc" ; Select Mystery 12A pinout
#endif
#if defined(MYSTERY_12A_MULTI)
.EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
.INCLUDE "Mystery_12A.inc" ; Select Mystery 12A pinout
#endif
#if defined(MYSTERY_30A_MAIN)
.EQU MODE = 0 ; Choose mode. Set to 0 for main motor
.INCLUDE "Mystery_30A.inc" ; Select Mystery 30A pinout
#endif
#if defined(MYSTERY_30A_TAIL)
.EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
.INCLUDE "Mystery_30A.inc" ; Select Mystery 30A pinout
#endif
#if defined(MYSTERY_30A_MULTI)
.EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
.INCLUDE "Mystery_30A.inc" ; Select Mystery 30A pinout
#endif
#if defined(MYSTERY_40A_MAIN)
.EQU MODE = 0 ; Choose mode. Set to 0 for main motor
.INCLUDE "Mystery_40A.inc" ; Select Mystery 40A pinout
#endif
#if defined(MYSTERY_40A_TAIL)
.EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
.INCLUDE "Mystery_40A.inc" ; Select Mystery 40A pinout
#endif
#if defined(MYSTERY_40A_MULTI)
.EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
.INCLUDE "Mystery_40A.inc" ; Select Mystery 40A pinout
#endif
#if defined(SUNRISE_HIMULTI_20A_MAIN)
.EQU MODE = 0 ; Choose mode. Set to 0 for main motor
.INCLUDE "Sunrise_HiMulti_20A.inc" ; Select Sunrise HiMulti 20A pinout
#endif
#if defined(SUNRISE_HIMULTI_20A_TAIL)
.EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
.INCLUDE "Sunrise_HiMulti_20A.inc" ; Select Sunrise HiMulti 20A pinout
#endif
#if defined(SUNRISE_HIMULTI_20A_MULTI)
.EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
.INCLUDE "Sunrise_HiMulti_20A.inc" ; Select Sunrise HiMulti 20A pinout
#endif
#if defined(SUNRISE_HIMULTI_30A_MAIN)
.EQU MODE = 0 ; Choose mode. Set to 0 for main motor
.INCLUDE "Sunrise_HiMulti_30A.inc" ; Select Sunrise HiMulti 30A pinout
#endif
#if defined(SUNRISE_HIMULTI_30A_TAIL)
.EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
.INCLUDE "Sunrise_HiMulti_30A.inc" ; Select Sunrise HiMulti 30A pinout
#endif
#if defined(SUNRISE_HIMULTI_30A_MULTI)
.EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
.INCLUDE "Sunrise_HiMulti_30A.inc" ; Select Sunrise HiMulti 30A pinout
#endif
#if defined(SUNRISE_HIMULTI_40A_MAIN)
.EQU MODE = 0 ; Choose mode. Set to 0 for main motor
.INCLUDE "Sunrise_HiMulti_40A.inc" ; Select Sunrise HiMulti 40A pinout
#endif
#if defined(SUNRISE_HIMULTI_40A_TAIL)
.EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
.INCLUDE "Sunrise_HiMulti_40A.inc" ; Select Sunrise HiMulti 40A pinout
#endif
#if defined(SUNRISE_HIMULTI_40A_MULTI)
.EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
.INCLUDE "Sunrise_HiMulti_40A.inc" ; Select Sunrise HiMulti 40A pinout
#endif
#if defined(RCTIMER_40A_MAIN)
.EQU MODE = 0 ; Choose mode. Set to 0 for main motor
.INCLUDE "RCTimer_40A.inc" ; Select RCTimer 40A pinout
#endif
#if defined(RCTIMER_40A_TAIL)
.EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
.INCLUDE "RCTimer_40A.inc" ; Select RCTimer 40A pinout
#endif
#if defined(RCTIMER_40A_MULTI)
.EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
.INCLUDE "RCTimer_40A.inc" ; Select RCTimer 40A pinout
#endif
#if defined(RCTIMER_NFS_30A_MAIN)
.EQU MODE = 0 ; Choose mode. Set to 0 for main motor
.INCLUDE "RCTimer_NFS_30A.inc" ; Select RCTimer NFS 30A pinout
#endif
#if defined(RCTIMER_NFS_30A_TAIL)
.EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
.INCLUDE "RCTimer_NFS_30A.inc" ; Select RCTimer NFS 30A pinout
#endif
#if defined(RCTIMER_NFS_30A_MULTI)
.EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
.INCLUDE "RCTimer_NFS_30A.inc" ; Select RCTimer NFS 30A pinout
#endif
#if defined(YEP_7A_MAIN)
.EQU MODE = 0 ; Choose mode. Set to 0 for main motor
.INCLUDE "YEP_7A.inc" ; Select YEP 7A pinout
#endif
#if defined(YEP_7A_TAIL)
.EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
.INCLUDE "YEP_7A.inc" ; Select YEP 7A pinout
#endif
#if defined(YEP_7A_MULTI)
.EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
.INCLUDE "YEP_7A.inc" ; Select YEP 7A pinout
#endif
#if defined(AFRO_12A_MAIN)
.EQU MODE = 0 ; Choose mode. Set to 0 for main motor
.INCLUDE "AFRO_12A.inc" ; Select AFRO 12A pinout
#endif
#if defined(AFRO_12A_TAIL)
.EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
.INCLUDE "AFRO_12A.inc" ; Select AFRO 12A pinout
#endif
#if defined(AFRO_12A_MULTI)
.EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
.INCLUDE "AFRO_12A.inc" ; Select AFRO 12A pinout
#endif
#if defined(AFRO_20A_MAIN)
.EQU MODE = 0 ; Choose mode. Set to 0 for main motor
.INCLUDE "AFRO_20A.inc" ; Select AFRO 20A pinout
#endif
#if defined(AFRO_20A_TAIL)
.EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
.INCLUDE "AFRO_20A.inc" ; Select AFRO 20A pinout
#endif
#if defined(AFRO_20A_MULTI)
.EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
.INCLUDE "AFRO_20A.inc" ; Select AFRO 20A pinout
#endif
#if defined(AFRO_20A_HV_MAIN)
.EQU MODE = 0 ; Choose mode. Set to 0 for main motor
.INCLUDE "AFRO_20A_HV.inc" ; Select AFRO 20A HV pinout
#endif
#if defined(AFRO_20A_HV_TAIL)
.EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
.INCLUDE "AFRO_20A_HV.inc" ; Select AFRO 20A HV pinout
#endif
#if defined(AFRO_20A_HV_MULTI)
.EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
.INCLUDE "AFRO_20A_HV.inc" ; Select AFRO 20A HV pinout
#endif
#if defined(AFRO_30A_MAIN)
.EQU MODE = 0 ; Choose mode. Set to 0 for main motor
.INCLUDE "AFRO_30A.inc" ; Select AFRO 30A pinout
#endif
#if defined(AFRO_30A_TAIL)
.EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
.INCLUDE "AFRO_30A.inc" ; Select AFRO 30A pinout
#endif
#if defined(AFRO_30A_MULTI)
.EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
.INCLUDE "AFRO_30A.inc" ; Select AFRO 30A pinout
#endif
#if defined(SUNRISE_BLHELI_SLIM_20A_MAIN)
.EQU MODE = 0 ; Choose mode. Set to 0 for main motor
.INCLUDE "Sunrise_BLHeli_Slim_20A.inc" ; Select Sunrise BLHeli slim 20A pinout
#endif
#if defined(SUNRISE_BLHELI_SLIM_20A_TAIL)
.EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
.INCLUDE "Sunrise_BLHeli_Slim_20A.inc" ; Select Sunrise BLHeli slim 20A pinout
#endif
#if defined(SUNRISE_BLHELI_SLIM_20A_MULTI)
.EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
.INCLUDE "Sunrise_BLHeli_Slim_20A.inc" ; Select Sunrise BLHeli slim 20A pinout
#endif
#if defined(SUNRISE_BLHELI_SLIM_30A_MAIN)
.EQU MODE = 0 ; Choose mode. Set to 0 for main motor
.INCLUDE "Sunrise_BLHeli_Slim_30A.inc" ; Select Sunrise BLHeli slim 30A pinout
#endif
#if defined(SUNRISE_BLHELI_SLIM_30A_TAIL)
.EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
.INCLUDE "Sunrise_BLHeli_Slim_30A.inc" ; Select Sunrise BLHeli slim 30A pinout
#endif
#if defined(SUNRISE_BLHELI_SLIM_30A_MULTI)
.EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
.INCLUDE "Sunrise_BLHeli_Slim_30A.inc" ; Select Sunrise BLHeli slim 30A pinout
#endif
#if defined(DYS_SN20A_MAIN)
.EQU MODE = 0 ; Choose mode. Set to 0 for main motor
.INCLUDE "DYS_SN20A.inc" ; Select DYS SN20A pinout
#endif
#if defined(DYS_SN20A_TAIL)
.EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
.INCLUDE "DYS_SN20A.inc" ; Select DYS SN20A pinout
#endif
#if defined(DYS_SN20A_MULTI)
.EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
.INCLUDE "DYS_SN20A.inc" ; Select DYS SN20A pinout
#endif
#if defined(TBS_CUBE_20A_MAIN)
.EQU MODE = 0 ; Choose mode. Set to 0 for main motor
.INCLUDE "TBS_CUBE_20A.inc" ; Select TBS CUBE 20A pinout
#endif
#if defined(TBS_CUBE_20A_TAIL)
.EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
.INCLUDE "TBS_CUBE_20A.inc" ; Select TBS CUBE 20A pinout
#endif
#if defined(TBS_CUBE_20A_MULTI)
.EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
.INCLUDE "TBS_CUBE_20A.inc" ; Select TBS CUBE 20A pinout
#endif
#if defined(ZTW_SPIDER_LITE_18Av2_MAIN)
.EQU MODE = 0 ; Choose mode. Set to 0 for main motor
.INCLUDE "ZTW_Spider_Lite_18Av2.inc" ; Select ZTW Spider Lite 18Av2 pinout
#endif
#if defined(ZTW_SPIDER_LITE_18Av2_TAIL)
.EQU MODE = 1 ; Choose mode. Set to 1 for tail motor
.INCLUDE "ZTW_Spider_Lite_18Av2.inc" ; Select ZTW Spider Lite 18Av2 pinout
#endif
#if defined(ZTW_SPIDER_LITE_18Av2_MULTI)
.EQU MODE = 2 ; Choose mode. Set to 2 for multirotor
.INCLUDE "ZTW_Spider_Lite_18Av2.inc" ; Select ZTW Spider Lite 18Av2 pinout
#endif
;**** **** **** **** ****
; TX programming defaults
;
; Parameter dependencies:
; - Governor P gain, I gain and Range is only used if one of the three governor modes is selected
; - Governor setup target is only used if Setup governor mode is selected (or closed loop mode is on for multi)
;
; Main
.EQU DEFAULT_PGM_MAIN_P_GAIN = 7 ; 1=0.13 2=0.17 3=0.25 4=0.38 5=0.50 6=0.75 7=1.00 8=1.5 9=2.0 10=3.0 11=4.0 12=6.0 13=8.0
.EQU DEFAULT_PGM_MAIN_I_GAIN = 7 ; 1=0.13 2=0.17 3=0.25 4=0.38 5=0.50 6=0.75 7=1.00 8=1.5 9=2.0 10=3.0 11=4.0 12=6.0 13=8.0
.EQU DEFAULT_PGM_MAIN_GOVERNOR_MODE = 1 ; 1=Tx 2=Arm 3=Setup 4=Off
.EQU DEFAULT_PGM_MAIN_GOVERNOR_RANGE = 1 ; 1=High 2=Middle 3=Low
.EQU DEFAULT_PGM_MAIN_LOW_VOLTAGE_LIM = 4 ; 1=Off 2=3.0V/c 3=3.1V/c 4=3.2V/c 5=3.3V/c 6=3.4V/c
.EQU DEFAULT_PGM_MAIN_COMM_TIMING = 3 ; 1=Low 2=MediumLow 3=Medium 4=MediumHigh 5=High
.IF DAMPED_MODE_ENABLE == 1
.EQU DEFAULT_PGM_MAIN_PWM_FREQ = 2 ; 1=High 2=Low 3=DampedLight
.ELSE
.EQU DEFAULT_PGM_MAIN_PWM_FREQ = 2 ; 1=High 2=Low
.ENDIF
.EQU DEFAULT_PGM_MAIN_DEMAG_COMP = 1 ; 1=Disabled 2=Low 3=High
.EQU DEFAULT_PGM_MAIN_DIRECTION = 1 ; 1=Normal 2=Reversed
.EQU DEFAULT_PGM_MAIN_RCP_PWM_POL = 1 ; 1=Positive 2=Negative
.EQU DEFAULT_PGM_MAIN_GOV_SETUP_TARGET = 180; Target for governor in setup mode. Corresponds to 70% throttle
.EQU DEFAULT_PGM_MAIN_REARM_START = 0 ; 1=Enabled 0=Disabled
.EQU DEFAULT_PGM_MAIN_BEEP_STRENGTH = 120; Beep strength
.EQU DEFAULT_PGM_MAIN_BEACON_STRENGTH = 200; Beacon strength
.EQU DEFAULT_PGM_MAIN_BEACON_DELAY = 4 ; 1=1m 2=2m 3=5m 4=10m 5=Infinite
; Tail
.EQU DEFAULT_PGM_TAIL_GAIN = 3 ; 1=0.75 2=0.88 3=1.00 4=1.12 5=1.25
.EQU DEFAULT_PGM_TAIL_IDLE_SPEED = 4 ; 1=Low 2=MediumLow 3=Medium 4=MediumHigh 5=High
.EQU DEFAULT_PGM_TAIL_COMM_TIMING = 3 ; 1=Low 2=MediumLow 3=Medium 4=MediumHigh 5=High
.IF DAMPED_MODE_ENABLE == 1
.EQU DEFAULT_PGM_TAIL_PWM_FREQ = 3 ; 1=High 2=Low 3=DampedLight
.ELSE
.EQU DEFAULT_PGM_TAIL_PWM_FREQ = 1 ; 1=High 2=Low
.ENDIF
.EQU DEFAULT_PGM_TAIL_DEMAG_COMP = 1 ; 1=Disabled 2=Low 3=High
.EQU DEFAULT_PGM_TAIL_DIRECTION = 1 ; 1=Normal 2=Reversed 3=Bidirectional
.EQU DEFAULT_PGM_TAIL_RCP_PWM_POL = 1 ; 1=Positive 2=Negative
.EQU DEFAULT_PGM_TAIL_BEEP_STRENGTH = 250; Beep strength
.EQU DEFAULT_PGM_TAIL_BEACON_STRENGTH = 250; Beacon strength
.EQU DEFAULT_PGM_TAIL_BEACON_DELAY = 4 ; 1=1m 2=2m 3=5m 4=10m 5=Infinite
.EQU DEFAULT_PGM_TAIL_PWM_DITHER = 3 ; 1=Off 2=7 3=15 4=31 5=63
; Multi
.EQU DEFAULT_PGM_MULTI_P_GAIN = 9 ; 1=0.13 2=0.17 3=0.25 4=0.38 5=0.50 6=0.75 7=1.00 8=1.5 9=2.0 10=3.0 11=4.0 12=6.0 13=8.0
.EQU DEFAULT_PGM_MULTI_I_GAIN = 9 ; 1=0.13 2=0.17 3=0.25 4=0.38 5=0.50 6=0.75 7=1.00 8=1.5 9=2.0 10=3.0 11=4.0 12=6.0 13=8.0
.EQU DEFAULT_PGM_MULTI_GOVERNOR_MODE = 4 ; 1=HiRange 2=MidRange 3=LoRange 4=Off
.EQU DEFAULT_PGM_MULTI_GAIN = 3 ; 1=0.75 2=0.88 3=1.00 4=1.12 5=1.25
.EQU DEFAULT_PGM_MULTI_COMM_TIMING = 3 ; 1=Low 2=MediumLow 3=Medium 4=MediumHigh 5=High
.IF DAMPED_MODE_ENABLE == 1
.EQU DEFAULT_PGM_MULTI_PWM_FREQ = 3 ; 1=High 2=Low 3=DampedLight
.ELSE
.EQU DEFAULT_PGM_MULTI_PWM_FREQ = 1 ; 1=High 2=Low
.ENDIF
.EQU DEFAULT_PGM_MULTI_DEMAG_COMP = 2 ; 1=Disabled 2=Low 3=High
.EQU DEFAULT_PGM_MULTI_DIRECTION = 1 ; 1=Normal 2=Reversed 3=Bidirectional
.EQU DEFAULT_PGM_MULTI_RCP_PWM_POL = 1 ; 1=Positive 2=Negative
.EQU DEFAULT_PGM_MULTI_BEEP_STRENGTH = 40 ; Beep strength
.EQU DEFAULT_PGM_MULTI_BEACON_STRENGTH = 80 ; Beacon strength
.EQU DEFAULT_PGM_MULTI_BEACON_DELAY = 4 ; 1=1m 2=2m 3=5m 4=10m 5=Infinite
.EQU DEFAULT_PGM_MULTI_PWM_DITHER = 3 ; 1=Off 2=7 3=15 4=31 5=63
; Common
.EQU DEFAULT_PGM_ENABLE_TX_PROGRAM = 1 ; 1=Enabled 0=Disabled
.EQU DEFAULT_PGM_PPM_MIN_THROTTLE = 37 ; 4*37+1000=1148
.EQU DEFAULT_PGM_PPM_MAX_THROTTLE = 208; 4*208+1000=1832
.EQU DEFAULT_PGM_PPM_CENTER_THROTTLE = 122; 4*122+1000=1488 (used in bidirectional mode)
.EQU DEFAULT_PGM_BEC_VOLTAGE_HIGH = 0 ; 0=Low 1= High
.EQU DEFAULT_PGM_ENABLE_TEMP_PROT = 0 ; 1=Enabled 0=Disabled
.EQU DEFAULT_PGM_ENABLE_POWER_PROT = 1 ; 1=Enabled 0=Disabled
.EQU DEFAULT_PGM_ENABLE_PWM_INPUT = 0 ; 1=Enabled 0=Disabled
;**** **** **** **** ****
; Constant definitions for main
.IF MODE == 0
.EQU GOV_SPOOLRATE = 2 ; Number of steps for governor requested pwm per 32ms
.EQU RCP_TIMEOUT_PPM = 10 ; Number of timer2H overflows (about 32ms) before considering rc pulse lost
.EQU RCP_TIMEOUT = 64 ; Number of timer2L overflows (about 128us) before considering rc pulse lost
.EQU RCP_SKIP_RATE = 32 ; Number of timer2L overflows (about 128us) before reenabling rc pulse detection
.EQU RCP_MIN = 0 ; This is minimum RC pulse length
.EQU RCP_MAX = 255 ; This is maximum RC pulse length
.EQU RCP_VALIDATE = 2 ; Require minimum this pulse length to validate RC pulse
.EQU RCP_STOP = 1 ; Stop motor at or below this pulse length
.EQU RCP_STOP_LIMIT = 250 ; Stop motor if this many timer2H overflows (~32ms) are below stop limit
.EQU PWM_START = 50 ; PWM used as max power during start
.EQU COMM_TIME_MIN = 1 ; Minimum time (in us) for commutation wait
.EQU TEMP_CHECK_RATE = 8 ; Number of adc conversions for each check of temperature (the other conversions are used for voltage)
.ENDIF
; Constant definitions for tail
.IF MODE == 1
.EQU GOV_SPOOLRATE = 1 ; Number of steps for governor requested pwm per 32ms
.EQU RCP_TIMEOUT_PPM = 10 ; Number of timer2H overflows (about 32ms) before considering rc pulse lost
.EQU RCP_TIMEOUT = 24 ; Number of timer2L overflows (about 128us) before considering rc pulse lost
.EQU RCP_SKIP_RATE = 6 ; Number of timer2L overflows (about 128us) before reenabling rc pulse detection
.EQU RCP_MIN = 0 ; This is minimum RC pulse length
.EQU RCP_MAX = 255 ; This is maximum RC pulse length
.EQU RCP_VALIDATE = 2 ; Require minimum this pulse length to validate RC pulse
.EQU RCP_STOP = 1 ; Stop motor at or below this pulse length
.EQU RCP_STOP_LIMIT = 130 ; Stop motor if this many timer2H overflows (~32ms) are below stop limit
.EQU PWM_START = 50 ; PWM used as max power during start
.EQU COMM_TIME_MIN = 1 ; Minimum time (in us) for commutation wait
.EQU TEMP_CHECK_RATE = 8 ; Number of adc conversions for each check of temperature (the other conversions are used for voltage)
.ENDIF
; Constant definitions for multi
.IF MODE == 2
.EQU GOV_SPOOLRATE = 1 ; Number of steps for governor requested pwm per 32ms
.EQU RCP_TIMEOUT_PPM = 10 ; Number of timer2H overflows (about 32ms) before considering rc pulse lost
.EQU RCP_TIMEOUT = 24 ; Number of timer2L overflows (about 128us) before considering rc pulse lost
.EQU RCP_SKIP_RATE = 6 ; Number of timer2L overflows (about 128us) before reenabling rc pulse detection
.EQU RCP_MIN = 0 ; This is minimum RC pulse length
.EQU RCP_MAX = 255 ; This is maximum RC pulse length
.EQU RCP_VALIDATE = 2 ; Require minimum this pulse length to validate RC pulse
.EQU RCP_STOP = 1 ; Stop motor at or below this pulse length
.EQU RCP_STOP_LIMIT = 250 ; Stop motor if this many timer2H overflows (~32ms) are below stop limit
.EQU PWM_START = 50 ; PWM used as max power during start
.EQU COMM_TIME_MIN = 1 ; Minimum time (in us) for commutation wait
.EQU TEMP_CHECK_RATE = 8 ; Number of adc conversions for each check of temperature (the other conversions are used for voltage)
.ENDIF
;**** **** **** **** ****
; Register definitions
.DEF Mul_Res_L = R0 ; Reserved for mul instruction
.DEF Mul_Res_H = R1 ; Reserved for mul instruction
.DEF Zero = R2 ; Register variable initialized to 0, always at 0
.DEF I_Sreg = R3 ; Status register saved in interrupts
.DEF II_Sreg = R4 ; Status register saved in nested interrupts (pwm interrupts from timer2)
.DEF Current_Pwm_Limited = R5 ; Current_Pwm_Limited is allocated to a register for fast access
.DEF Next_Wt_L = R14 ; Next wait value (lo byte)
.DEF Next_Wt_H = R15 ; Next wait value (hi byte)
.DEF Temp1 = R16 ; Main temporary
.DEF Temp2 = R17 ; Main temporary (Temp1/2 must be two consecutive registers)
.DEF Temp3 = R18 ; Main temporary
.DEF Temp4 = R19 ; Main temporary
.DEF Temp5 = R6 ; Main temporary (limited operations)
.DEF Temp6 = R7 ; Main temporary (limited operations)
.DEF Temp7 = R8 ; Main temporary (limited operations)
.DEF Temp8 = R9 ; Main temporary (limited operations)
.DEF I_Temp1 = R20 ; Interrupt temporary
.DEF I_Temp2 = R21 ; Interrupt temporary
.DEF I_Temp3 = R10 ; Interrupt temporary (limited operations)
.DEF I_Temp4 = R11 ; Interrupt temporary (limited operations)
.DEF I_Temp5 = R12 ; Interrupt temporary (limited operations)
.DEF I_Temp6 = R13 ; Interrupt temporary (limited operations)
.DEF Flags0 = R22 ; State flags. Reset upon init_start
.EQU OC1A_PENDING = 0 ; Timer1 output compare pending flag
.EQU RCP_MEAS_PWM_FREQ = 1 ; Measure RC pulse pwm frequency
.EQU PWM_ON = 2 ; Set in on part of pwm cycle
.EQU DEMAG_ENABLED = 3 ; Set when demag compensation is enabled (above a min speed and throttle)
.EQU DEMAG_DETECTED = 4 ; Set when excessive demag time is detected
.EQU DEMAG_CUT_POWER = 5 ; Set when demag compensation cuts power
.EQU GOV_ACTIVE = 6 ; Set when governor is active
.EQU DIR_CHANGE_BRAKE = 7 ; Set when braking before direction change
.DEF Flags1 = R23 ; State flags. Reset upon init_start
.EQU MOTOR_SPINNING = 0 ; Set when in motor is spinning
.EQU STARTUP_PHASE = 1 ; Set when in startup phase
.EQU INITIAL_RUN_PHASE = 2 ; Set when in initial run phase, before synchronized run is achieved
.EQU ADC_READ_TEMP = 3 ; Set when ADC input shall be set to read temperature
.EQU COMP_TIMED_OUT = 4 ; Set when comparator reading timed out
.EQU SKIP_DAMP_ON = 5 ; Set when turning damping fet on is skipped
.EQU HIGH_RPM = 6 ; Set when motor rpm is high (Comm_Period4x_H less than 2)
; = 7
.DEF Flags2 = R24 ; State flags. NOT reset upon init_start
.EQU RCP_UPDATED = 0 ; New RC pulse length value available
.EQU RCP_EDGE_NO = 1 ; RC pulse edge no. 0=rising, 1=falling
.EQU PGM_PWMOFF_DAMPED = 2 ; Programmed pwm off damped mode
.EQU PGM_PWM_HIGH_FREQ = 3 ; Progremmed pwm high frequency
.EQU RCP_INT_NESTED_ENABLED = 4 ; Set when RC pulse interrupt is enabled around nested interrupts
.EQU RCP_PPM = 5 ; RC pulse ppm type input (set also when oneshot is set)
.EQU RCP_PPM_ONESHOT125 = 6 ; RC pulse ppm type input is OneShot125
.EQU RCP_DIR_REV = 7 ; RC pulse direction in bidirectional mode
.DEF Flags3 = R25 ; State flags. NOT reset upon init_start
.EQU RCP_PWM_FREQ_1KHZ = 0 ; RC pulse pwm frequency is 1kHz
.EQU RCP_PWM_FREQ_2KHZ = 1 ; RC pulse pwm frequency is 2kHz
.EQU RCP_PWM_FREQ_4KHZ = 2 ; RC pulse pwm frequency is 4kHz
.EQU RCP_PWM_FREQ_8KHZ = 3 ; RC pulse pwm frequency is 8kHz
.EQU RCP_PWM_FREQ_12KHZ = 4 ; RC pulse pwm frequency is 12kHz
.EQU PGM_DIR_REV = 5 ; Programmed direction. 0=normal, 1=reversed
.EQU PGM_RCP_PWM_POL = 6 ; Programmed RC pulse pwm polarity. 0=positive, 1=negative
.EQU FULL_THROTTLE_RANGE = 7 ; When set full throttle range is used (1000-2000us) and stored calibration values are ignored
; Here the general temporary register XYZ are placed (R26-R31)
; XH: General temporary used by main routines
; XL: General temporary used by interrupt routines
; Y: General temporary used by timer2 pwm interrupt routine
; Z: Address of current PWM FET ON routine (eg: pwm_afet_on)
;**** **** **** **** ****
; RAM definitions
.DSEG ; Data segment
.ORG SRAM_START
Timer0_Int_Cnt: .BYTE 1 ; Timer0 interrupt counter
Requested_Pwm: .BYTE 1 ; Requested pwm (from RC pulse value)
Governor_Req_Pwm: .BYTE 1 ; Governor requested pwm (sets governor target)
Current_Pwm: .BYTE 1 ; Current pwm
Current_Pwm_Lim_Dith: .BYTE 1 ; Current pwm that is limited and dithered (applied to the motor output)
Rcp_Prev_Edge_L: .BYTE 1 ; RC pulse previous edge timer3 timestamp (lo byte)
Rcp_Prev_Edge_H: .BYTE 1 ; RC pulse previous edge timer3 timestamp (hi byte)
Rcp_Outside_Range_Cnt: .BYTE 1 ; RC pulse outside range counter (incrementing)
Rcp_Timeout_Cntd: .BYTE 1 ; RC pulse timeout counter (decrementing)
Rcp_Skip_Cntd: .BYTE 1 ; RC pulse skip counter (decrementing)
Initial_Arm: .BYTE 1 ; Variable that is set during the first arm sequence after power on
Power_On_Wait_Cnt_L: .BYTE 1 ; Power on wait counter (lo byte)
Power_On_Wait_Cnt_H: .BYTE 1 ; Power on wait counter (hi byte)
Startup_Cnt: .BYTE 1 ; Startup phase commutations counter (incrementing)
Startup_Zc_Timeout_Cntd: .BYTE 1 ; Startup zero cross timeout counter (decrementing)
Initial_Run_Rot_Cnt: .BYTE 1 ; Initial run rotations counter (incrementing)
Stall_Cnt: .BYTE 1 ; Counts start/run attempts that resulted in stall. Reset upon a proper stop
Demag_Detected_Metric: .BYTE 1 ; Metric used to gauge demag event frequency
Demag_Pwr_Off_Thresh: .BYTE 1 ; Metric threshold above which power is cut
Low_Rpm_Pwr_Slope: .BYTE 1 ; Sets the slope of power increase for low rpms
Timer2_X: .BYTE 1 ; Timer 2 extended byte
Prev_Comm_L: .BYTE 1 ; Previous commutation timer timestamp (lo byte)
Prev_Comm_H: .BYTE 1 ; Previous commutation timer timestamp (hi byte)
Prev_Comm_X: .BYTE 1 ; Previous commutation timer3 timestamp (ext byte)
Prev_Prev_Comm_L: .BYTE 1 ; Pre-previous commutation timer timestamp (lo byte)
Prev_Prev_Comm_H: .BYTE 1 ; Pre-previous commutation timer timestamp (hi byte)
Comm_Period4x_L: .BYTE 1 ; Timer3 counts between the last 4 commutations (lo byte)
Comm_Period4x_H: .BYTE 1 ; Timer3 counts between the last 4 commutations (hi byte)
Comm_Diff: .BYTE 1 ; Timer3 count difference between the last two commutations
Comm_Phase: .BYTE 1 ; Current commutation phase
Comparator_Read_Cnt: .BYTE 1 ; Number of comparator reads done
Gov_Target_L: .BYTE 1 ; Governor target (lo byte)
Gov_Target_H: .BYTE 1 ; Governor target (hi byte)
Gov_Integral_L: .BYTE 1 ; Governor integral error (lo byte)
Gov_Integral_H: .BYTE 1 ; Governor integral error (hi byte)
Gov_Integral_X: .BYTE 1 ; Governor integral error (ex byte)
Gov_Proportional_L: .BYTE 1 ; Governor proportional error (lo byte)
Gov_Proportional_H: .BYTE 1 ; Governor proportional error (hi byte)
Gov_Prop_Pwm: .BYTE 1 ; Governor calculated new pwm based upon proportional error
Gov_Arm_Target: .BYTE 1 ; Governor arm target value
Wt_Advance_L: .BYTE 1 ; Timer3 counts for commutation advance timing (lo byte)
Wt_Advance_H: .BYTE 1 ; Timer3 counts for commutation advance timing (hi byte)
Wt_Zc_Scan_L: .BYTE 1 ; Timer3 counts from commutation to zero cross scan (lo byte)
Wt_Zc_Scan_H: .BYTE 1 ; Timer3 counts from commutation to zero cross scan (hi byte)
Wt_Zc_Timeout_L: .BYTE 1 ; Timer3 counts for zero cross scan timeout (lo byte)
Wt_Zc_Timeout_H: .BYTE 1 ; Timer3 counts for zero cross scan timeout (hi byte)
Wt_Comm_L: .BYTE 1 ; Timer3 counts from zero cross to commutation (lo byte)
Wt_Comm_H: .BYTE 1 ; Timer3 counts from zero cross to commutation (hi byte)
Rcp_PrePrev_Edge_L: .BYTE 1 ; RC pulse pre previous edge pca timestamp (lo byte)
Rcp_PrePrev_Edge_H: .BYTE 1 ; RC pulse pre previous edge pca timestamp (hi byte)
Rcp_Edge_L: .BYTE 1 ; RC pulse edge pca timestamp (lo byte)
Rcp_Edge_H: .BYTE 1 ; RC pulse edge pca timestamp (hi byte)
Rcp_Prev_Period_L: .BYTE 1 ; RC pulse previous period (lo byte)
Rcp_Prev_Period_H: .BYTE 1 ; RC pulse previous period (hi byte)
Rcp_Period_Diff_Accepted: .BYTE 1 ; RC pulse period difference acceptable
New_Rcp: .BYTE 1 ; New RC pulse value in pca counts
Prev_Rcp_Pwm_Freq: .BYTE 1 ; Previous RC pulse pwm frequency (used during pwm frequency measurement)
Curr_Rcp_Pwm_Freq: .BYTE 1 ; Current RC pulse pwm frequency (used during pwm frequency measurement)
Rcp_Stop_Cnt: .BYTE 1 ; Counter for RC pulses below stop value (lo byte)
Auto_Bailout_Armed: .BYTE 1 ; Set when auto rotation bailout is armed
Pwm_Limit: .BYTE 1 ; Maximum allowed pwm
Pwm_Limit_Spoolup: .BYTE 1 ; Maximum allowed pwm during spoolup of main
Pwm_Limit_By_Rpm: .BYTE 1 ; Maximum allowed pwm for low or high rpms
Pwm_Spoolup_Beg: .BYTE 1 ; Pwm to begin main spoolup with
Pwm_Motor_Idle: .BYTE 1 ; Motor idle speed pwm
Pwm_Prev_Edge: .BYTE 1 ; Timestamp from timer 2 when pwm toggles on or off
Pwm_Dither_Decoded: .BYTE 1 ; Decoded pwm dither value
Pwm_Dither_Excess_Power: .BYTE 1 ; Excess power (above max) from pwm dither
Random: .BYTE 1 ; Random number from LFSR
Spoolup_Limit_Cnt: .BYTE 1 ; Interrupt count for spoolup limit
Spoolup_Limit_Skip: .BYTE 1 ; Interrupt skips for spoolup limit increment (1=no skips, 2=skip one etc)
Main_Spoolup_Time_3x: .BYTE 1 ; Main spoolup time x3
Main_Spoolup_Time_10x: .BYTE 1 ; Main spoolup time x10
Main_Spoolup_Time_15x: .BYTE 1 ; Main spoolup time x15
Lipo_Adc_Limit_L: .BYTE 1 ; Low voltage limit adc value (lo byte)
Lipo_Adc_Limit_H: .BYTE 1 ; Low voltage limit adc value (hi byte)
Adc_Conversion_Cnt: .BYTE 1 ; Adc conversion counter
Current_Average_Temp_Adc: .BYTE 1 ; Current average temp ADC reading (lo byte of ADC, assuming hi byte is 0)
Ppm_Throttle_Gain: .BYTE 1 ; Gain to be applied to RCP value for PPM input
Beep_Strength: .BYTE 1 ; Strength of beeps
Tx_Pgm_Func_No: .BYTE 1 ; Function number when doing programming by tx
Tx_Pgm_Paraval_No: .BYTE 1 ; Parameter value number when doing programming by tx
Tx_Pgm_Beep_No: .BYTE 1 ; Beep number when doing programming by tx
DampingFET: .BYTE 1 ; Port position of fet used for damping
; The variables below must be in this sequence
Pgm_Gov_P_Gain: .BYTE 1 ; Programmed governor P gain
Pgm_Gov_I_Gain: .BYTE 1 ; Programmed governor I gain
Pgm_Gov_Mode: .BYTE 1 ; Programmed governor mode
Pgm_Low_Voltage_Lim: .BYTE 1 ; Programmed low voltage limit
Pgm_Motor_Gain: .BYTE 1 ; Programmed motor gain
Pgm_Motor_Idle: .BYTE 1 ; Programmed motor idle speed
Pgm_Startup_Pwr: .BYTE 1 ; Programmed startup power
Pgm_Pwm_Freq: .BYTE 1 ; Programmed pwm frequency
Pgm_Direction: .BYTE 1 ; Programmed rotation direction
Pgm_Input_Pol: .BYTE 1 ; Programmed input pwm polarity
Initialized_L_Dummy: .BYTE 1 ; Place holder
Initialized_H_Dummy: .BYTE 1 ; Place holder
Pgm_Enable_TX_Program: .BYTE 1 ; Programmed enable/disable value for TX programming
Pgm_Main_Rearm_Start: .BYTE 1 ; Programmed enable/disable re-arming main every start
Pgm_Gov_Setup_Target: .BYTE 1 ; Programmed main governor setup target
_Pgm_Startup_Rpm: .BYTE 1 ; Programmed startup rpm (unused - place holder)
_Pgm_Startup_Accel: .BYTE 1 ; Programmed startup acceleration (unused - place holder)
_Pgm_Volt_Comp: .BYTE 1 ; Place holder
Pgm_Comm_Timing: .BYTE 1 ; Programmed commutation timing
_Pgm_Damping_Force: .BYTE 1 ; Programmed damping force (unused - place holder)
Pgm_Gov_Range: .BYTE 1 ; Programmed governor range
Pgm_Startup_Method: .BYTE 1 ; Programmed startup method
Pgm_Ppm_Min_Throttle: .BYTE 1 ; Programmed throttle minimum
Pgm_Ppm_Max_Throttle: .BYTE 1 ; Programmed throttle maximum
Pgm_Beep_Strength: .BYTE 1 ; Programmed beep strength
Pgm_Beacon_Strength: .BYTE 1 ; Programmed beacon strength
Pgm_Beacon_Delay: .BYTE 1 ; Programmed beacon delay
_Pgm_Throttle_Rate: .BYTE 1 ; Programmed throttle rate (unused - place holder)
Pgm_Demag_Comp: .BYTE 1 ; Programmed demag compensation
Pgm_BEC_Voltage_High: .BYTE 1 ; Programmed BEC voltage
Pgm_Ppm_Center_Throttle: .BYTE 1 ; Programmed throttle center (in bidirectional mode)
Pgm_Main_Spoolup_Time: .BYTE 1 ; Programmed main spoolup time
Pgm_Enable_Temp_Prot: .BYTE 1 ; Programmed temperature protection enable
Pgm_Enable_Power_Prot: .BYTE 1 ; Programmed low rpm power protection enable
Pgm_Enable_Pwm_Input: .BYTE 1 ; Programmed PWM input signal enable
Pgm_Pwm_Dither: .BYTE 1 ; Programmed output PWM dither
; The sequence of the variables below is no longer of importance
Pgm_Gov_P_Gain_Decoded: .BYTE 1 ; Programmed governor decoded P gain
Pgm_Gov_I_Gain_Decoded: .BYTE 1 ; Programmed governor decoded I gain
Pgm_Startup_Pwr_Decoded: .BYTE 1 ; Programmed startup power decoded
.EQU SRAM_BYTES = 255 ; Bytes used in SRAM. Used for number of bytes to reset
;**** **** **** **** ****
.ESEG ; Eeprom segment
.ORG 0
.EQU EEPROM_FW_MAIN_REVISION = 14 ; Main revision of the firmware
.EQU EEPROM_FW_SUB_REVISION = 4 ; Sub revision of the firmware
.EQU EEPROM_LAYOUT_REVISION = 20 ; Revision of the EEPROM layout
Eep_FW_Main_Revision: .DB EEPROM_FW_MAIN_REVISION ; EEPROM firmware main revision number
Eep_FW_Sub_Revision: .DB EEPROM_FW_SUB_REVISION ; EEPROM firmware sub revision number
Eep_Layout_Revision: .DB EEPROM_LAYOUT_REVISION ; EEPROM layout revision number
.IF MODE == 0
Eep_Pgm_Gov_P_Gain: .DB DEFAULT_PGM_MAIN_P_GAIN ; EEPROM copy of programmed governor P gain
Eep_Pgm_Gov_I_Gain: .DB DEFAULT_PGM_MAIN_I_GAIN ; EEPROM copy of programmed governor I gain
Eep_Pgm_Gov_Mode: .DB DEFAULT_PGM_MAIN_GOVERNOR_MODE ; EEPROM copy of programmed governor mode
Eep_Pgm_Low_Voltage_Lim: .DB DEFAULT_PGM_MAIN_LOW_VOLTAGE_LIM ; EEPROM copy of programmed low voltage limit
_Eep_Pgm_Motor_Gain: .DB 0xFF
_Eep_Pgm_Motor_Idle: .DB 0xFF
Eep_Pgm_Startup_Pwr: .DB DEFAULT_PGM_MAIN_STARTUP_PWR ; EEPROM copy of programmed startup power
Eep_Pgm_Pwm_Freq: .DB DEFAULT_PGM_MAIN_PWM_FREQ ; EEPROM copy of programmed pwm frequency
Eep_Pgm_Direction: .DB DEFAULT_PGM_MAIN_DIRECTION ; EEPROM copy of programmed rotation direction
Eep_Pgm_Input_Pol: .DB DEFAULT_PGM_MAIN_RCP_PWM_POL ; EEPROM copy of programmed input polarity
Eep_Initialized_L: .DB 0xA5 ; EEPROM initialized signature low byte
Eep_Initialized_H: .DB 0x5A ; EEPROM initialized signature high byte
Eep_Enable_TX_Program: .DB DEFAULT_PGM_ENABLE_TX_PROGRAM ; EEPROM TX programming enable
Eep_Main_Rearm_Start: .DB DEFAULT_PGM_MAIN_REARM_START ; EEPROM re-arming main enable
Eep_Pgm_Gov_Setup_Target: .DB DEFAULT_PGM_MAIN_GOV_SETUP_TARGET ; EEPROM main governor setup target
_Eep_Pgm_Startup_Rpm: .DB 0xFF
_Eep_Pgm_Startup_Accel: .DB 0xFF
_Eep_Pgm_Volt_Comp: .DB 0xFF
Eep_Pgm_Comm_Timing: .DB DEFAULT_PGM_MAIN_COMM_TIMING ; EEPROM copy of programmed commutation timing
_Eep_Pgm_Damping_Force: .DB 0xFF
Eep_Pgm_Gov_Range: .DB DEFAULT_PGM_MAIN_GOVERNOR_RANGE ; EEPROM copy of programmed governor range
_Eep_Pgm_Startup_Method: .DB 0xFF
Eep_Pgm_Ppm_Min_Throttle: .DB DEFAULT_PGM_PPM_MIN_THROTTLE ; EEPROM copy of programmed minimum throttle (final value is 4x+1000=1148)
Eep_Pgm_Ppm_Max_Throttle: .DB DEFAULT_PGM_PPM_MAX_THROTTLE ; EEPROM copy of programmed minimum throttle (final value is 4x+1000=1832)
Eep_Pgm_Beep_Strength: .DB DEFAULT_PGM_MAIN_BEEP_STRENGTH ; EEPROM copy of programmed beep strength
Eep_Pgm_Beacon_Strength: .DB DEFAULT_PGM_MAIN_BEACON_STRENGTH ; EEPROM copy of programmed beacon strength
Eep_Pgm_Beacon_Delay: .DB DEFAULT_PGM_MAIN_BEACON_DELAY ; EEPROM copy of programmed beacon delay
_Eep_Pgm_Throttle_Rate: .DB 0xFF
Eep_Pgm_Demag_Comp: .DB DEFAULT_PGM_MAIN_DEMAG_COMP ; EEPROM copy of programmed demag compensation
Eep_Pgm_BEC_Voltage_High: .DB DEFAULT_PGM_BEC_VOLTAGE_HIGH ; EEPROM copy of programmed BEC voltage
_Eep_Pgm_Ppm_Center_Throttle: .DB 0xFF
Eep_Pgm_Main_Spoolup_Time: .DB DEFAULT_PGM_MAIN_SPOOLUP_TIME ; EEPROM copy of programmed main spoolup time
Eep_Pgm_Temp_Prot_Enable: .DB DEFAULT_PGM_ENABLE_TEMP_PROT ; EEPROM copy of programmed temperature protection enable
Eep_Pgm_Enable_Power_Prot: .DB DEFAULT_PGM_ENABLE_POWER_PROT ; EEPROM copy of programmed low rpm power protection enable
Eep_Pgm_Enable_Pwm_Input: .DB DEFAULT_PGM_ENABLE_PWM_INPUT ; EEPROM copy of programmed PWM input signal enable
_Eep_Pgm_Pwm_Dither: .DB 0xFF
.ENDIF
.IF MODE == 1
_Eep_Pgm_Gov_P_Gain: .DB 0xFF
_Eep_Pgm_Gov_I_Gain: .DB 0xFF
_Eep_Pgm_Gov_Mode: .DB 0xFF
_Eep_Pgm_Low_Voltage_Lim: .DB 0xFF
Eep_Pgm_Motor_Gain: .DB DEFAULT_PGM_TAIL_GAIN ; EEPROM copy of programmed tail gain
Eep_Pgm_Motor_Idle: .DB DEFAULT_PGM_TAIL_IDLE_SPEED ; EEPROM copy of programmed tail idle speed
Eep_Pgm_Startup_Pwr: .DB DEFAULT_PGM_TAIL_STARTUP_PWR ; EEPROM copy of programmed startup power
Eep_Pgm_Pwm_Freq: .DB DEFAULT_PGM_TAIL_PWM_FREQ ; EEPROM copy of programmed pwm frequency
Eep_Pgm_Direction: .DB DEFAULT_PGM_TAIL_DIRECTION ; EEPROM copy of programmed rotation direction
Eep_Pgm_Input_Pol: .DB DEFAULT_PGM_TAIL_RCP_PWM_POL ; EEPROM copy of programmed input polarity
Eep_Initialized_L: .DB 0x5A ; EEPROM initialized signature low byte
Eep_Initialized_H: .DB 0xA5 ; EEPROM initialized signature high byte
Eep_Enable_TX_Program: .DB DEFAULT_PGM_ENABLE_TX_PROGRAM ; EEPROM TX programming enable
_Eep_Main_Rearm_Start: .DB 0xFF
_Eep_Pgm_Gov_Setup_Target: .DB 0xFF
_Eep_Pgm_Startup_Rpm: .DB 0xFF
_Eep_Pgm_Startup_Accel: .DB 0xFF
_Eep_Pgm_Volt_Comp: .DB 0xFF
Eep_Pgm_Comm_Timing: .DB DEFAULT_PGM_TAIL_COMM_TIMING ; EEPROM copy of programmed commutation timing
_Eep_Pgm_Damping_Force: .DB 0xFF
_Eep_Pgm_Gov_Range: .DB 0xFF
_Eep_Pgm_Startup_Method: .DB 0xFF
Eep_Pgm_Ppm_Min_Throttle: .DB DEFAULT_PGM_PPM_MIN_THROTTLE ; EEPROM copy of programmed minimum throttle (final value is 4x+1000=1148)
Eep_Pgm_Ppm_Max_Throttle: .DB DEFAULT_PGM_PPM_MAX_THROTTLE ; EEPROM copy of programmed minimum throttle (final value is 4x+1000=1832)
Eep_Pgm_Beep_Strength: .DB DEFAULT_PGM_TAIL_BEEP_STRENGTH ; EEPROM copy of programmed beep strength
Eep_Pgm_Beacon_Strength: .DB DEFAULT_PGM_TAIL_BEACON_STRENGTH ; EEPROM copy of programmed beacon strength
Eep_Pgm_Beacon_Delay: .DB DEFAULT_PGM_TAIL_BEACON_DELAY ; EEPROM copy of programmed beacon delay
_Eep_Pgm_Throttle_Rate: .DB 0xFF
Eep_Pgm_Demag_Comp: .DB DEFAULT_PGM_TAIL_DEMAG_COMP ; EEPROM copy of programmed demag compensation
Eep_Pgm_BEC_Voltage_High: .DB DEFAULT_PGM_BEC_VOLTAGE_HIGH ; EEPROM copy of programmed BEC voltage
Eep_Pgm_Ppm_Center_Throttle: .DB DEFAULT_PGM_PPM_CENTER_THROTTLE ; EEPROM copy of programmed center throttle (final value is 4x+1000=1488)
_Eep_Pgm_Main_Spoolup_Time: .DB 0xFF
Eep_Pgm_Temp_Prot_Enable: .DB DEFAULT_PGM_ENABLE_TEMP_PROT ; EEPROM copy of programmed temperature protection enable
Eep_Pgm_Enable_Power_Prot: .DB DEFAULT_PGM_ENABLE_POWER_PROT ; EEPROM copy of programmed low rpm power protection enable
Eep_Pgm_Enable_Pwm_Input: .DB DEFAULT_PGM_ENABLE_PWM_INPUT ; EEPROM copy of programmed PWM input signal enable
Eep_Pgm_Pwm_Dither: .DB DEFAULT_PGM_TAIL_PWM_DITHER ; EEPROM copy of programmed output PWM dither
.ENDIF
.IF MODE == 2
Eep_Pgm_Gov_P_Gain: .DB DEFAULT_PGM_MULTI_P_GAIN ; EEPROM copy of programmed closed loop P gain
Eep_Pgm_Gov_I_Gain: .DB DEFAULT_PGM_MULTI_I_GAIN ; EEPROM copy of programmed closed loop I gain
Eep_Pgm_Gov_Mode: .DB DEFAULT_PGM_MULTI_GOVERNOR_MODE ; EEPROM copy of programmed closed loop mode
_Eep_Pgm_Low_Voltage_Lim: .DB 0xFF
Eep_Pgm_Motor_Gain: .DB DEFAULT_PGM_MULTI_GAIN ; EEPROM copy of programmed tail gain
_Eep_Pgm_Motor_Idle: .DB 0xFF ; EEPROM copy of programmed tail idle speed
Eep_Pgm_Startup_Pwr: .DB DEFAULT_PGM_MULTI_STARTUP_PWR ; EEPROM copy of programmed startup power
Eep_Pgm_Pwm_Freq: .DB DEFAULT_PGM_MULTI_PWM_FREQ ; EEPROM copy of programmed pwm frequency
Eep_Pgm_Direction: .DB DEFAULT_PGM_MULTI_DIRECTION ; EEPROM copy of programmed rotation direction
Eep_Pgm_Input_Pol: .DB DEFAULT_PGM_MULTI_RCP_PWM_POL ; EEPROM copy of programmed input polarity
Eep_Initialized_L: .DB 0x55 ; EEPROM initialized signature low byte
Eep_Initialized_H: .DB 0xAA ; EEPROM initialized signature high byte
Eep_Enable_TX_Program: .DB DEFAULT_PGM_ENABLE_TX_PROGRAM ; EEPROM TX programming enable
_Eep_Main_Rearm_Start: .DB 0xFF
_Eep_Pgm_Gov_Setup_Target: .DB 0xFF
_Eep_Pgm_Startup_Rpm: .DB 0xFF
_Eep_Pgm_Startup_Accel: .DB 0xFF
_Eep_Pgm_Volt_Comp: .DB 0xFF
Eep_Pgm_Comm_Timing: .DB DEFAULT_PGM_MULTI_COMM_TIMING ; EEPROM copy of programmed commutation timing
_Eep_Pgm_Damping_Force: .DB 0xFF
_Eep_Pgm_Gov_Range: .DB 0xFF
_Eep_Pgm_Startup_Method: .DB 0xFF
Eep_Pgm_Ppm_Min_Throttle: .DB DEFAULT_PGM_PPM_MIN_THROTTLE ; EEPROM copy of programmed minimum throttle (final value is 4x+1000=1148)
Eep_Pgm_Ppm_Max_Throttle: .DB DEFAULT_PGM_PPM_MAX_THROTTLE ; EEPROM copy of programmed minimum throttle (final value is 4x+1000=1832)
Eep_Pgm_Beep_Strength: .DB DEFAULT_PGM_MULTI_BEEP_STRENGTH ; EEPROM copy of programmed beep strength
Eep_Pgm_Beacon_Strength: .DB DEFAULT_PGM_MULTI_BEACON_STRENGTH ; EEPROM copy of programmed beacon strength
Eep_Pgm_Beacon_Delay: .DB DEFAULT_PGM_MULTI_BEACON_DELAY ; EEPROM copy of programmed beacon delay
_Eep_Pgm_Throttle_Rate: .DB 0xFF
Eep_Pgm_Demag_Comp: .DB DEFAULT_PGM_MULTI_DEMAG_COMP ; EEPROM copy of programmed demag compensation
Eep_Pgm_BEC_Voltage_High: .DB DEFAULT_PGM_BEC_VOLTAGE_HIGH ; EEPROM copy of programmed BEC voltage
Eep_Pgm_Ppm_Center_Throttle: .DB DEFAULT_PGM_PPM_CENTER_THROTTLE ; EEPROM copy of programmed center throttle (final value is 4x+1000=1488)
_Eep_Pgm_Main_Spoolup_Time: .DB 0xFF
Eep_Pgm_Temp_Prot_Enable: .DB DEFAULT_PGM_ENABLE_TEMP_PROT ; EEPROM copy of programmed temperature protection enable
Eep_Pgm_Enable_Power_Prot: .DB DEFAULT_PGM_ENABLE_POWER_PROT ; EEPROM copy of programmed low rpm power protection enable
Eep_Pgm_Enable_Pwm_Input: .DB DEFAULT_PGM_ENABLE_PWM_INPUT ; EEPROM copy of programmed PWM input signal enable
Eep_Pgm_Pwm_Dither: .DB DEFAULT_PGM_MULTI_PWM_DITHER ; EEPROM copy of programmed output PWM dither
.ENDIF
Eep_Dummy: .DB 0xFF ; EEPROM address for safety reason
.ORG 0x60
Eep_Name: .DB " " ; Name tag (16 Bytes)
;**** **** **** **** ****
.CSEG ; Code segment
.ORG 0
Interrupt_Table_Definition ; ATmega interrupts
;**** **** **** **** ****
; Table definitions
GOV_GAIN_TABLE: .DB 0x02, 0x03, 0x04, 0x06, 0x08, 0x0C, 0x10, 0x18, 0x20, 0x30, 0x40, 0x60, 0x80, 0 ; Padded zero for an even number
STARTUP_POWER_TABLE: .DB 0x04, 0x06, 0x08, 0x0C, 0x10, 0x18, 0x20, 0x30, 0x40, 0x60, 0x80, 0xA0, 0xC0, 0 ; Padded zero for an even number
PWM_DITHER_TABLE: .DB 0x00, 0x07, 0x0F, 0x1F, 0x3F, 0 ; Padded zero for an even number
.IF MODE == 0
.IF DAMPED_MODE_ENABLE == 1
TX_PGM_PARAMS_MAIN: .DB 13, 13, 4, 3, 6, 13, 5, 3, 3, 2, 2, 0 ; Padded zero for an even number
.ENDIF
.IF DAMPED_MODE_ENABLE == 0
TX_PGM_PARAMS_MAIN: .DB 13, 13, 4, 3, 6, 13, 5, 2, 3, 2, 2, 0 ; Padded zero for an even number
.ENDIF
.ENDIF
.IF MODE == 1
.IF DAMPED_MODE_ENABLE == 1
TX_PGM_PARAMS_TAIL: .DB 5, 5, 13, 5, 3, 5, 3, 3, 2, 0 ; Padded zero for an even number
.ENDIF
.IF DAMPED_MODE_ENABLE == 0
TX_PGM_PARAMS_TAIL: .DB 5, 5, 13, 5, 2, 5, 3, 3, 2, 0 ; Padded zero for an even number
.ENDIF
.ENDIF
.IF MODE == 2
.IF DAMPED_MODE_ENABLE == 1
TX_PGM_PARAMS_MULTI: .DB 13, 13, 4, 5, 13, 5, 3, 5, 3, 3, 2, 0 ; Padded zero for an even number
.ENDIF
.IF DAMPED_MODE_ENABLE == 0
TX_PGM_PARAMS_MULTI: .DB 13, 13, 4, 5, 13, 5, 2, 5, 3, 3, 2, 0 ; Padded zero for an even number
.ENDIF
.ENDIF
;**** **** **** **** **** **** **** **** **** **** **** **** ****
;
; Timer2 interrupt routine
;
; Assumptions: Z register must be set to desired pwm_nfet_on label
; Requirements: I_Temp variables can NOT be used
;
;**** **** **** **** **** **** **** **** **** **** **** **** ****
t2_int: ; Used for pwm control
in II_Sreg, SREG
; Check if pwm is on
sbrc Flags0, PWM_ON ; Is pwm on?
rjmp t2_int_pwm_off
; Pwm on cycle
tst Current_Pwm_Limited
breq t2_int_pwm_on_exit
ijmp ; Jump to pwm on routines. Z should be set to one of the pwm_nfet_on labels
t2_int_pwm_on_exit:
; Set timer for coming on cycle length
mov YL, Current_Pwm_Limited ; Load current pwm
com YL ; com is 255-x
sec
sbrc Flags2, PGM_PWM_HIGH_FREQ ; Use half the time when pwm frequency is high
ror YL
Set_TCNT2 YL ; Write start point for timer
; Set other variables
sts Pwm_Prev_Edge, YL ; Set timestamp
sbr Flags0, (1<= 128 ; "Negative", 1's complement
sbrc Flags1, SKIP_DAMP_ON
rjmp t2_int_pwm_off_damp_done
sbrc Flags0, DEMAG_CUT_POWER
rjmp t2_int_pwm_off_damp_done
Damping_FET_on YL ; Damping fet on
ldi YL, PFETON_DELAY
com YL
dec YL
brne PC-1
t2_int_pwm_off_damp_done:
All_nFETs_Off ; Switch off all nfets
.ENDIF
t2_int_pwm_off_exit:
sts Pwm_Prev_Edge, Zero ; Set timestamp to zero
out SREG, II_Sreg
reti
t2_int_pwm_off_fullpower_exit:
Set_TCNT2 Zero ; Write start point for timer
T2_Clear_Int_Flag YL ; Clear interrupt flag
sbr Flags0, (1<= 1 ; Tail or multi
; Boost pwm during direct start
mov XL, Flags1
andi XL, ((1<= 1 ; Tail or multi
; Set current_pwm_limited
lds I_Temp1, Current_Pwm ; Default not limited
lds XL, Pwm_Limit ; Check against limit
cp I_Temp1, XL
brcs PC+2 ; If current pwm below limit - branch
mov I_Temp1, XL ; Limit pwm
.IF MODE == 2 ; Multi
; Limit pwm for low rpms
lds XL, Pwm_Limit_By_Rpm ; Check against limit
cp I_Temp1, XL
brcs PC+2 ; If current pwm below limit - branch
mov I_Temp1, XL ; Limit pwm
.ENDIF
mov Current_Pwm_Limited, I_Temp1
; Dither
lds XL, Pwm_Dither_Decoded ; Load pwm dither
tst XL
brne PC+2 ; If active - branch
rjmp t0_int_current_pwm_no_dither
mov I_Temp2, I_Temp1
sub I_Temp2, XL ; Calculate pwm minus dither value
brcc t0_int_current_pwm_full_dither; If pwm more than dither value, then do full dither
mov XL, I_Temp1 ; Set dither level to current pwm
ldi I_Temp2, 0 ; Set pwm minus dither
t0_int_current_pwm_full_dither:
mov I_Temp4, XL ; Store dither value in I_Temp4
clc
rol XL ; Shift left once
mov I_Temp3, XL
lds XL, Random ; Load random number
com XL ; Invert to create proper DC bias in random code
and I_Temp3, XL ; And with double dither value
add I_Temp3, I_Temp2 ; Add pwm minus dither
brcs t0_int_current_pwm_dither_max_excess_power ; If dither cause power above max - branch and increase excess
lds XL, Pwm_Dither_Excess_Power ; Get excess power
cp XL, Zero ; Decrement excess power
breq PC+2
dec XL
add I_Temp3, XL ; Add excess power from previous cycles
sts Pwm_Dither_Excess_Power, XL
brcs t0_int_current_pwm_dither_max_power; If dither cause power above max - branch
mov I_Temp1, I_Temp3
rjmp t0_int_current_pwm_no_dither
t0_int_current_pwm_dither_max_excess_power:
lds XL, Pwm_Dither_Excess_Power
cp I_Temp4, XL ; Limit excess power to one above in order to always reach max power
brcs PC+2
inc XL
sts Pwm_Dither_Excess_Power, XL
t0_int_current_pwm_dither_max_power:
ldi I_Temp1, 255 ; Set power to max
t0_int_current_pwm_no_dither:
sts Current_Pwm_Lim_Dith, I_Temp1
.IF DAMPED_MODE_ENABLE == 1
; Skip damping fet switching for high throttle
cbr Flags1, (1<= 1 ; Tail or multi
cpi I_Temp2, 3
brne PC+3 ; No - branch
lds I_Temp3, Pgm_Ppm_Center_Throttle ; Center throttle value is in 4us units
.ENDIF
rcp_int_ppm_calculate:
ldi XL, 250 ; Add 1000us to minimum
add I_Temp3, XL
mov XL, Zero
adc XL, Zero
sub I_Temp5, I_Temp3 ; Subtract minimum
sbc I_Temp6, XL
in I_Temp1, SREG
andi I_Temp1, (1<= 1 ; Tail or multi
cpi I_Temp2, 3 ; Check if bidirectional operation
brne rcp_int_ppm_bidir_dir_set ; No - branch
tst I_Temp1
breq rcp_int_ppm_bidir_fwd ; If result is positive - branch
rcp_int_ppm_bidir_rev:
sbrc Flags2, RCP_DIR_REV
rjmp rcp_int_ppm_bidir_dir_set ; If same direction - branch
sbr Flags2, (1<= 1 ; Tail or multi
cpi I_Temp2, 3 ; Check if bidirectional operation
brne rcp_int_ppm_unidir_neg ; No - branch
ldi XL, 0xFF ; Change sign - invert and subtract minus one
com I_Temp5
com I_Temp6
sub I_Temp5, XL
sbc I_Temp6, XL
rjmp rcp_int_ppm_neg_checked
rcp_int_ppm_unidir_neg:
.ENDIF
ldi I_Temp1, RCP_MIN ; Yes - set to minimum
ldi I_Temp2, 0
rjmp rcp_int_pwm_divide_done
rcp_int_ppm_neg_checked:
.IF MODE >= 1 ; Tail or multi
cpi I_Temp2, 3 ; Check if bidirectional operation
brne rcp_int_ppm_bidir_done ; No - branch
lsl I_Temp5 ; Multiply value by 2
rol I_Temp6
ldi XL, 10 ; Subtract deadband
sub I_Temp5, XL
sbc I_Temp6, Zero
brcc rcp_int_ppm_bidir_done
ldi XL, RCP_MIN
mov I_Temp5, XL
mov I_Temp6, Zero
rcp_int_ppm_bidir_done:
.ENDIF
ldi XL, RCP_MAX ; Check that RC pulse is within legal range (max 255)
cp I_Temp5, XL
cpc I_Temp6, Zero
brcs rcp_int_ppm_max_checked
ldi I_Temp1, RCP_MAX
ldi I_Temp2, 0
rjmp rcp_int_pwm_divide_done
rcp_int_ppm_max_checked:
lds XL, Ppm_Throttle_Gain ; Multiply throttle value by gain
mul I_Temp5, XL
mov I_Temp1, Mul_Res_H ; Transfer result
lsl Mul_Res_L ; Multiply result by 2 (unity gain is 128)
rol I_Temp1
ldi I_Temp2, 0
brcs rcp_int_ppm_limit_after_mult
rjmp rcp_int_limited
rcp_int_ppm_limit_after_mult:
ldi I_Temp1, RCP_MAX
ldi I_Temp2, 0
rjmp rcp_int_limited
rcp_int_pwm_divide:
lsr I_Temp2 ; Divide by 2
ror I_Temp1
rcp_int_pwm_divide_done:
sbrs Flags3, RCP_PWM_FREQ_12KHZ ; Is RC input pwm frequency 12kHz?
rjmp rcp_int_check_legal_range
tst I_Temp2 ; Yes - check that value is not more than 255
breq PC+2
ldi I_Temp1, RCP_MAX
mov XL, I_Temp1 ; Multiply by 1.5
lsr XL
add I_Temp1, XL
adc I_Temp2, Zero
rcp_int_check_legal_range:
; Check that RC pulse is within legal range
cpi I_Temp1, RCP_MAX
cpc I_Temp2, Zero
brcs rcp_int_limited
ldi I_Temp1, RCP_MAX
rcp_int_limited:
; RC pulse value accepted
sts New_Rcp, I_Temp1 ; Store new pulse length
sbr Flags2, (1<= 1 ; Tail or multi
; If not supported, then exit
rjmp measure_lipo_exit
.ENDIF
.IF MODE == 0 ; Main
; Set commutation to BpFET on
xcall comm5comm6
; Start adc
Start_Adc XH
; Wait for ADC reference to settle, and then start again
xcall wait1ms
Start_Adc XH
; Wait for ADC conversion to complete
measure_lipo_wait_adc:
Get_Adc_Status XH
sbrc XH, ADSC
rjmp measure_lipo_wait_adc
; Read ADC result
Read_Adc_Result Temp1, Temp2
; Stop ADC
Stop_Adc XH
; Switch power off
xcall switch_power_off
; Set limit step
ldi Temp3, ADC_LIMIT_L
sts Lipo_Adc_Limit_L, Temp3
tst Temp3
brne PC+2
rjmp measure_lipo_exit ; Exit if disabled
ldi Temp4, ADC_LIMIT_H
sts Lipo_Adc_Limit_H, Temp4
mov Temp6, Temp4 ; Divide 3.0V value by 2
lsr Temp6
mov Temp5, Temp3
lsr Temp5
add Temp5, Temp3 ; Calculate 1.5*3.0V=4.5V value
adc Temp6, Temp4
mov Temp3, Temp5 ; Copy step
mov Temp4, Temp6
measure_lipo_cell_loop:
; Check voltage against xS lower limit
cp Temp1, Temp3 ; Voltage above limit?
cpc Temp2, Temp4
brcs measure_lipo_adjust ; No - branch
; Set xS voltage limit
lds Temp7, Lipo_Adc_Limit_L
ldi XH, ADC_LIMIT_L
add XH, Temp7
sts Lipo_Adc_Limit_L, XH
lds Temp7, Lipo_Adc_Limit_H
ldi XH, ADC_LIMIT_H
adc XH, Temp7
sts Lipo_Adc_Limit_H, XH
; Set (x+1)S lower limit
add Temp3, Temp5 ; Add step
adc Temp4, Temp6
rjmp measure_lipo_cell_loop ; Check for one more battery cell
measure_lipo_adjust:
lds Temp7, Lipo_Adc_Limit_L
lds Temp8, Lipo_Adc_Limit_H
; Calculate 3.125%
lds Temp2, Lipo_Adc_Limit_H
lsr Temp2
lds Temp1, Lipo_Adc_Limit_L
ror Temp1 ; After this 50%
lsr Temp2
ror Temp1 ; After this 25%
; Divide three times to get to 3.125%
ldi Temp3, 3
measure_lipo_divide_loop:
lsr Temp2
ror Temp1
dec Temp3
brne measure_lipo_divide_loop
; Add the programmed number of 0.1V (or 3.125% increments)
lds Temp3, Pgm_Low_Voltage_Lim ; Load programmed limit
dec Temp3
brne measure_lipo_limit_on ; Is low voltage limiting on?
sts Lipo_Adc_Limit_L, Zero ; No - set limit to zero
sts Lipo_Adc_Limit_H, Zero
rjmp measure_lipo_exit
measure_lipo_limit_on:
dec Temp3
breq measure_lipo_update
measure_lipo_add_loop:
add Temp7, Temp1 ; Add 3.125%
adc Temp8, Temp2
dec Temp3
brne measure_lipo_add_loop
measure_lipo_update:
; Set ADC limit
sts Lipo_Adc_Limit_L, Temp7
sts Lipo_Adc_Limit_H, Temp8
.ENDIF
measure_lipo_exit:
ret
;**** **** **** **** **** **** **** **** **** **** **** **** ****
;
; Check temperature, power supply voltage and limit power
;
; No assumptions
;
; Used to limit main motor power in order to maintain the required voltage
;
;**** **** **** **** **** **** **** **** **** **** **** **** ****
check_temp_voltage_and_limit_power:
; Load programmed low voltage limit
lds Temp3, Pgm_Low_Voltage_Lim ; Store in Temp3
; Wait for ADC conversion to complete
Get_Adc_Status XH
sbrc XH, ADSC
rjmp check_temp_voltage_and_limit_power
; Read ADC result
Read_Adc_Result Temp1, Temp2
; Stop ADC
Stop_Adc XH
lds XH, Adc_Conversion_Cnt ; Increment conversion counter
inc XH
sts Adc_Conversion_Cnt, XH
cpi XH, TEMP_CHECK_RATE ; Is conversion count equal to temp rate?
brcs check_voltage_start ; No - check voltage
sts Adc_Conversion_Cnt, Zero ; Yes - temperature check. Reset counter
lds XH, Pgm_Enable_Temp_Prot ; Is temp protection enabled?
tst XH
breq temp_check_exit ; No - branch
tst Temp2 ; Is temperature ADC reading below 256?
breq temp_average_inc_dec ; Yes - proceed
lds XH, Current_Average_Temp_Adc ; No - increment average
cpi XH, 0xFF
breq temp_average_updated ; Already max - no change
rjmp temp_average_inc ; Increment
temp_average_inc_dec:
lds XH, Current_Average_Temp_Adc ; Check if current temp ADC is above or below average
cp Temp1, XH
breq temp_average_updated ; Equal - no change
brcc temp_average_inc ; Above - increment average
tst XH ; Below - decrement average if average is not already zero
breq temp_average_updated
temp_average_dec:
dec XH ; Decrement average
rjmp temp_average_updated
temp_average_inc:
inc XH ; Increment average
breq temp_average_dec
temp_average_updated:
lds Temp1, Pwm_Limit
sts Current_Average_Temp_Adc, XH
cpi XH, TEMP_LIMIT ; Is temp ADC above first limit?
brcc temp_check_set_limit ; Yes - exit
ldi Temp1, 192 ; No - limit pwm
cpi XH, (TEMP_LIMIT-TEMP_LIMIT_STEP) ; Is temp ADC above second limit
brcc temp_check_set_limit ; Yes - exit
ldi Temp1, 128 ; No - limit pwm
cpi XH, (TEMP_LIMIT-2*TEMP_LIMIT_STEP) ; Is temp ADC above third limit
brcc temp_check_set_limit ; Yes - exit
ldi Temp1, 64 ; No - limit pwm
cpi XH, (TEMP_LIMIT-3*TEMP_LIMIT_STEP) ; Is temp ADC above final limit
brcc temp_check_set_limit ; Yes - exit
ldi Temp1, 0 ; No - limit pwm
temp_check_set_limit:
sts Pwm_Limit, Temp1 ; Set pwm limit
temp_check_exit:
Set_Adc_Ip_Volt ; Select adc input for next conversion
ret
check_voltage_start:
.IF MODE == 0 ; Main
; Check if low voltage limiting is enabled
cpi Temp3, 1 ; Is low voltage limit disabled?
breq check_voltage_good ; Yes - voltage declared good
; Check if ADC is saturated
cpi Temp1, 0xFF
ldi XH, 3
cpc Temp2, XH
brcc check_voltage_good ; ADC saturated, can not make judgement
ldi XH, ADC_LIMIT_L ; Is low voltage limit zero (ESC does not support it)?
tst XH
breq check_voltage_good ; Yes - voltage declared good
; Check voltage against limit
lds XH, Lipo_Adc_Limit_L
cp Temp1, XH
lds XH, Lipo_Adc_Limit_H
cpc Temp2, XH
brcc check_voltage_good ; If voltage above limit - branch
; Decrease pwm limit
lds XH, Pwm_Limit
tst XH
breq check_voltage_lim ; If limit zero - branch
dec XH ; Decrement limit
sts Pwm_Limit, XH
rjmp check_voltage_lim
check_voltage_good:
; Increase pwm limit
lds XH, Pwm_Limit
cpi XH, 0xFF
breq check_voltage_lim ; If limit max - branch
inc XH ; Increment limit
sts Pwm_Limit, XH
check_voltage_lim:
lds Temp1, Pwm_Limit ; Set limit
lds XH, Current_Pwm
sub XH, Temp1
brcc check_voltage_spoolup_lim ; If current pwm above limit - branch and limit
lds Temp1, Current_Pwm ; Set current pwm (no limiting)
check_voltage_spoolup_lim:
; Slow spoolup
lds XH, Pwm_Limit_Spoolup
cp Temp1, XH
brcs check_voltage_exit ; If current pwm below limit - branch
lds Temp1, Pwm_Limit_Spoolup
lds XH, Pwm_Limit_Spoolup ; Check if spoolup limit is max
cpi XH, 0xFF
breq check_voltage_exit ; If max - branch
lds XH, Pwm_Limit_Spoolup ; Set pwm limit to spoolup limit during ramp (to avoid governor integral buildup)
sts Pwm_Limit, XH
check_voltage_exit:
mov Current_Pwm_Limited, Temp1
sts Current_Pwm_Lim_Dith, Temp1
.ENDIF
.IF MODE == 1 ; Tail
; Increase pwm limit
lds XH, Pwm_Limit
inc XH
breq check_voltage_lim ; If limit max - branch
sts Pwm_Limit, XH ; Increment limit
check_voltage_lim:
.ENDIF
.IF MODE == 2 ; Multi
; Increase pwm limit
lds Temp2, Pwm_Limit
ldi XH, 16
add Temp2, XH
brcc PC+2 ; If not max - branch
ldi Temp2, 255
sts Pwm_Limit, Temp2 ; Increment limit
; Set current pwm limited if closed loop mode
lds XH, Pgm_Gov_Mode ; Governor mode?
cpi XH, 4
breq check_voltage_pwm_done ; No - branch
lds Temp1, Pwm_Limit ; Set limit
lds XH, Current_Pwm
sub XH, Temp1
brcc check_voltage_low_rpm ; If current pwm above limit - branch and limit
lds Temp1, Current_Pwm ; Set current pwm (no limiting)
check_voltage_low_rpm:
; Limit pwm for low rpms
lds XH, Pwm_Limit_By_Rpm ; Check against limit
cp Temp1, XH
brcs PC+2 ; If current pwm below limit - branch
mov Temp1, XH ; Limit pwm
mov Current_Pwm_Limited, Temp1
sts Current_Pwm_Lim_Dith, Temp1
check_voltage_pwm_done:
.ENDIF
; Set adc mux for next conversion
lds XH, Adc_Conversion_Cnt ; Is next conversion for temperature?
cpi XH, (TEMP_CHECK_RATE-1)
brne check_voltage_ret
Set_Adc_Ip_Temp ; Select temp sensor for next conversion
check_voltage_ret:
ret
;**** **** **** **** **** **** **** **** **** **** **** **** ****
;
; Set startup PWM routine
;
; No assumptions
;
; Used for pwm control during startup
;
;**** **** **** **** **** **** **** **** **** **** **** **** ****
set_startup_pwm:
; Adjust startup power
ldi Temp1, PWM_START ; Set power
cli ; Disable interrupts in order to avoid interference with mul ops in interrupt routines
lds XH, Pgm_Startup_Pwr_Decoded ; Multiply startup power by programmed value
mul Temp1, XH
mov Temp1, Mul_Res_H ; Transfer result
lsl Mul_Res_L ; Multiply result by 2 (unity gain is 128)
rol Temp1
sei
lds XH, Pwm_Limit ; Check against limit
cp Temp1, XH
brcs startup_pwm_set_pwm ; If pwm below limit - branch
lds Temp1, Pwm_Limit ; Limit pwm
startup_pwm_set_pwm:
; Set pwm variables
sts Requested_Pwm, Temp1 ; Update requested pwm
sts Current_Pwm, Temp1 ; Update current pwm
mov Current_Pwm_Limited, Temp1 ; Update limited version of current pwm
sts Current_Pwm_Lim_Dith, Temp1
sts Pwm_Spoolup_Beg, Temp1 ; Update spoolup beginning pwm
ret
;**** **** **** **** **** **** **** **** **** **** **** **** ****
;
; Initialize timing routine
;
; No assumptions
;
; Part of initialization before motor start
;
;**** **** **** **** **** **** **** **** **** **** **** **** ****
initialize_timing:
sts Comm_Period4x_L, Zero ; Set commutation period registers
ldi XH, 0xF0
sts Comm_Period4x_H, XH
ret
;**** **** **** **** **** **** **** **** **** **** **** **** ****
;
; Calculate next commutation timing routine
;
; No assumptions
;
; Called immediately after each commutation
; Also sets up timer 1 to wait advance timing
;
;**** **** **** **** **** **** **** **** **** **** **** **** ****
calc_next_comm_timing: ; Entry point for run phase
; Read commutation time
cli ; Disable interrupts while reading timer 1
Read_TCNT1L Temp1
Read_TCNT1H Temp2
lds Temp3, Timer2_X
sei
; Calculate this commutation time
lds Temp4, Prev_Comm_L
lds Temp5, Prev_Comm_H
sts Prev_Comm_L, Temp1 ; Store timestamp as previous commutation
sts Prev_Comm_H, Temp2
sub Temp1, Temp4 ; Calculate the new commutation time
sbc Temp2, Temp5
sbrc Flags1, STARTUP_PHASE
rjmp calc_next_comm_startup
sbrc Flags1, HIGH_RPM ; Branch if high rpm
rjmp calc_next_comm_timing_fast
rjmp calc_next_comm_normal
calc_next_comm_startup:
lds Temp6, Prev_Comm_X
sts Prev_Comm_X, Temp3 ; Store extended timestamp as previous commutation
sbc Temp3, Temp6 ; Calculate the new extended commutation time
tst Temp3
breq PC+3
ldi Temp1, 0xFF
ldi Temp2, 0xFF
lds Temp7, Prev_Prev_Comm_L
lds Temp8, Prev_Prev_Comm_H
sts Prev_Prev_Comm_L, Temp4
sts Prev_Prev_Comm_H, Temp5
sub Temp5, Temp8 ; Calculate previous commutation time (hi byte only)
sub Temp2, Temp5 ; Calculate the difference between the two previous commutation times (hi bytes only)
sts Comm_Diff, Temp2
lds Temp1, Prev_Comm_L ; Reload this commutation time
lds Temp2, Prev_Comm_H
sub Temp1, Temp7 ; Calculate the new commutation time based upon the two last commutations (to reduce sensitivity to offset)
sbc Temp2, Temp8
lds Temp3, Comm_Period4x_L ; Average with previous and save
lds Temp4, Comm_Period4x_H
lsr Temp4
ror Temp3
add Temp1, Temp3
adc Temp2, Temp4
brcc PC+3
ldi Temp1, 0xFF
ldi Temp2, 0xFF
sts Comm_Period4x_L, Temp1
sts Comm_Period4x_H, Temp2
rjmp calc_new_wait_times_setup
calc_next_comm_normal:
; Calculate new commutation time
lds Temp3, Comm_Period4x_L ; Comm_Period4x(-l-h) holds the time of 4 commutations
lds Temp4, Comm_Period4x_H
movw Temp5, Temp3 ; Copy variables
ldi XH, 4 ; Divide Comm_Period4x 4 times as default
mov Temp7, XH
ldi XH, 2 ; Divide new commutation time 2 times as default
mov Temp8, XH
cpi Temp4, 0x04
brcs PC+3
dec Temp7 ; Reduce averaging time constant for low speeds
dec Temp8
cpi Temp4, 0x08
brcs PC+3
dec Temp7 ; Reduce averaging time constant more for even lower speeds
dec Temp8
calc_next_comm_avg_period_div:
lsr Temp6 ; Divide by 2
ror Temp5
dec Temp7
brne calc_next_comm_avg_period_div
sub Temp3, Temp5 ; Subtract a fraction
sbc Temp4, Temp6
tst Temp8 ; Divide new time
breq calc_next_comm_new_period_div_done
calc_next_comm_new_period_div:
lsr Temp2 ; Divide by 2
ror Temp1
dec Temp8
brne calc_next_comm_new_period_div
calc_next_comm_new_period_div_done:
add Temp3, Temp1 ; Add the divided new time
adc Temp4, Temp2
sts Comm_Period4x_L, Temp3 ; Store Comm_Period4x_X
sts Comm_Period4x_H, Temp4
brcc calc_new_wait_times_setup; If period larger than 0xffff - go to slow case
ldi Temp4, 0xFF
sts Comm_Period4x_L, Temp4 ; Set commutation period registers to very slow timing (0xffff)
sts Comm_Period4x_H, Temp4
calc_new_wait_times_setup:
; Set high rpm bit (if above 156k erpm)
cpi Temp4, 2
brcc PC+2
sbr Flags1, (1<= 1 ; Tail or multi
cpi XH, 3
breq decode_params_dir_set
.ENDIF
cbr Flags3, (1<= 1 ; Tail or multi
lds XH, Pgm_Direction ; Check if bidirectional operation
cpi XH, 3
brne PC+2
rjmp program_by_tx_checked ; Disable tx programming if bidirectional operation
.ENDIF
xcall wait3ms
lds XH, Pgm_Enable_TX_Program; Start programming mode entry if enabled
cpi XH, 1 ; Is TX programming enabled?
brcc arming_initial_arm_check ; Yes - proceed
rjmp program_by_tx_checked ; No - branch
arming_initial_arm_check:
lds XH, Initial_Arm ; Yes - check if it is initial arm sequence
cpi XH, 1 ; Is it the initial arm sequence?
brcc arming_ppm_check ; Yes - proceed
rjmp program_by_tx_checked ; No - branch
arming_ppm_check:
sbrc Flags2, RCP_PPM
rjmp throttle_high_cal_start ; If flag is set (PPM) - branch
; PWM tx program entry
lds XH, New_Rcp ; Load new RC pulse value
cpi XH, RCP_MAX ; Is RC pulse max?
brcc program_by_tx_entry_pwm ; Yes - proceed
rjmp program_by_tx_checked ; No - branch
program_by_tx_entry_pwm:
cli ; Disable all interrupts
xcall beep_f4
sei ; Enable all interrupts
xcall wait100ms
lds XH, New_Rcp ; Load new RC pulse value
cpi XH, RCP_STOP ; Below stop?
brcc program_by_tx_entry_pwm ; No - start over
program_by_tx_entry_wait_pwm:
cli ; Disable all interrupts
xcall beep_f1
xcall wait10ms
xcall beep_f1
sei ; Enable all interrupts
xcall wait100ms
lds XH, New_Rcp ; Load new RC pulse value
cpi XH, RCP_MAX ; At or above max?
brcs program_by_tx_entry_wait_pwm ; No - start over
rjmp program_by_tx ; Yes - enter programming mode
; PPM throttle calibration and tx program entry
throttle_high_cal_start:
.IF MODE <= 1 ; Main or tail
ldi XH, 8 ; Set 3 seconds wait time
.ELSE
ldi XH, 3 ; Set 1 second wait time
.ENDIF
mov Temp8, XH
throttle_high_cal:
sbr Flags3, (1<= 1 ; Tail or multi
lds XH, Pgm_Direction ; Check if bidirectional operation
subi XH, 3
breq wait_for_power_on_check_timeout ; Do not wait if bidirectional operation
.ENDIF
xcall wait100ms ; Wait to see if start pulse was only a glitch
wait_for_power_on_check_timeout:
lds XH, Rcp_Timeout_Cntd ; Load RC pulse timeout counter value
tst XH
brne PC+2 ; If it is not zero - proceed
rjmp init_no_signal ; If it is zero (pulses missing) - go back to detect input signal
;**** **** **** **** **** **** **** **** **** **** **** **** ****
;
; Start entry point
;
;**** **** **** **** **** **** **** **** **** **** **** **** ****
init_start:
cli
xcall switch_power_off
sts Requested_Pwm, Zero ; Set requested pwm to zero
sts Governor_Req_Pwm, Zero ; Set governor requested pwm to zero
sts Current_Pwm, Zero ; Set current pwm to zero
mov Current_Pwm_Limited, Zero; Set limited current pwm to zero
sts Current_Pwm_Lim_Dith, Zero
sts Pwm_Dither_Excess_Power, Zero
sei
lds XH, Pgm_Motor_Idle ; Set idle pwm to programmed value
lsl XH
sts Pwm_Motor_Idle, XH
sts Gov_Target_L, Zero ; Set target to zero
sts Gov_Target_H, Zero
sts Gov_Integral_L, Zero ; Set integral to zero
sts Gov_Integral_H, Zero
sts Gov_Integral_X, Zero
sts Adc_Conversion_Cnt, Zero
ldi Flags0, 0 ; Clear flags0
ldi Flags1, 0 ; Clear flags1
sts Demag_Detected_Metric, Zero ; Clear demag metric
;**** **** **** **** ****
; Motor start beginning
;**** **** **** **** ****
ldi XH, TEMP_CHECK_RATE ; Make sure a temp reading is done
sts Adc_Conversion_Cnt, XH
Set_Adc_Ip_Temp
xcall wait1ms
Start_Adc XH
read_initial_temp:
Get_Adc_Status XH
sbrc XH, ADSC
rjmp read_initial_temp
Read_Adc_Result Temp1, Temp2 ; Read initial temperature
Stop_Adc XH
tst Temp2
breq PC+2 ; Is reading below 256?
ldi Temp1, 0xFF ; No - set average temperature value to 255
sts Current_Average_Temp_Adc, Temp1 ; Set initial average temp ADC reading
xcall check_temp_voltage_and_limit_power
ldi XH, TEMP_CHECK_RATE ; Make sure a temp reading is done next time
sts Adc_Conversion_Cnt, XH
Set_Adc_Ip_Temp
; Set up start operating conditions
lds Temp7, Pgm_Pwm_Freq ; Store setting in Temp7
ldi XH, 2 ; Set nondamped low frequency pwm mode
sts Pgm_Pwm_Freq, XH
xcall decode_parameters ; (Decode_parameters uses Temp1 and Temp8)
sts Pgm_Pwm_Freq, Temp7 ; Restore settings
; Set max allowed power
cli ; Disable interrupts to avoid that Requested_Pwm is overwritten
ldi XH, 0xFF ; Set pwm limit to max
sts Pwm_Limit, XH
xcall set_startup_pwm
lds XH, Requested_Pwm
sts Pwm_Limit, XH
sts Pwm_Limit_Spoolup, XH
sts Pwm_Limit_By_Rpm, XH
sei
ldi XH, 1 ; Set low pwm again after calling set_startup_pwm
sts Requested_Pwm, XH
sts Current_Pwm, XH
mov Current_Pwm_Limited, XH
sts Current_Pwm_Lim_Dith, XH
sts Spoolup_Limit_Skip, XH
lds XH, Auto_Bailout_Armed
sts Spoolup_Limit_Cnt, XH
; Begin startup sequence
lds XH, Pgm_Direction ; Check if bidirectional operation
cpi XH, 3
brne init_start_bidir_done
cbr Flags3, (1<= 1 ; Tail or multi
lds XH, Pgm_Direction ; Check if bidirectional operation
cpi XH, 3
brne run6_check_speed
sbrc Flags3, PGM_DIR_REV ; Check if actual rotation direction
rjmp run6_check_dir_rev
sbrc Flags2, RCP_DIR_REV ; Matches force direction
rjmp run6_check_dir_change
rjmp run6_check_speed
run6_check_dir_rev:
sbrs Flags2, RCP_DIR_REV
rjmp run6_check_dir_change
rjmp run6_check_speed
run6_check_dir_change:
sbrc Flags0, DIR_CHANGE_BRAKE
rjmp run6_check_speed
sbr Flags0, (1<= 1 ; Tail or multi
sbrs Flags0, DIR_CHANGE_BRAKE ; If it is not a direction change - stop
rjmp run_to_wait_for_power_on
cbr Flags0, (1<= 1 ; Tail or multi
sbrs Flags2, RCP_PPM
rjmp jmp_wait_for_power_on ; If flag is not set (PWM) - branch
lds XH, Stall_Cnt
cpi XH, 5
brcs jmp_wait_for_power_on
rjmp init_no_signal
jmp_wait_for_power_on:
rjmp wait_for_power_on ; Go back to wait for power on
.ENDIF
;**** **** **** **** **** **** **** **** **** **** **** **** ****
.INCLUDE "BLHeliTxPgm.inc" ; Include source code for programming the ESC with the TX
;**** **** **** **** **** **** **** **** **** **** **** **** ****
reset:
rjmp pgm_start
.EXIT