Skip to content

Commit

Permalink
Firmware revision 10 (patch 2)
Browse files Browse the repository at this point in the history
Temperature protection improvements
Support for 100% duty cycle driver mode via FULL_DUTY
Assume VOLT_MUL as percentage for extra resolution
  • Loading branch information
neoxic committed Mar 23, 2024
1 parent 51b96a1 commit 1d0ccb9
Show file tree
Hide file tree
Showing 10 changed files with 52 additions and 41 deletions.
34 changes: 17 additions & 17 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,31 +48,31 @@ endfunction()
add_subdirectory(boot)

add_target(AIKON1 STM32G071 DEAD_TIME=35 COMP_MAP=213 IO_PA6)
add_target(AIRBOT1 AT32F421 DEAD_TIME=66 COMP_MAP=321 SENS_MAP=0xA3A6 VOLT_MUL=74 CURR_MUL=30 LED_MAP=0xAFB3B4)
add_target(AIRBOT2 STM32F051 DEAD_TIME=26 COMP_MAP=321 SENS_MAP=0xA3 VOLT_MUL=74 IO_PA2)
add_target(AIRBOT1 AT32F421 DEAD_TIME=66 COMP_MAP=321 SENS_MAP=0xA3A6 VOLT_MUL=738 CURR_MUL=30 LED_MAP=0xAFB3B4)
add_target(AIRBOT2 STM32F051 DEAD_TIME=26 COMP_MAP=321 SENS_MAP=0xA3 VOLT_MUL=738 IO_PA2)
add_target(DYS1 STM32F051 DEAD_TIME=26 COMP_MAP=123 LED_MAP=0xAFB3B4 LED_INV IO_PA2)
add_target(EMAX1 STM32F051 DEAD_TIME=26 COMP_MAP=123 IO_PA2)
add_target(ESCAPE1 STM32G071 DEAD_TIME=35 COMP_MAP=123 SENS_MAP=0xA5A4 VOLT_MUL=110 CURR_MUL=30 LED_WS2812 IO_PA2 IO_AUX)
add_target(ESCAPE2 STM32G071 DEAD_TIME=19 COMP_MAP=123 SENS_MAP=0xA6 VOLT_MUL=110 USE_BEC IO_PA2 IO_AUX)
add_target(ESCAPE3 AT32F421 DEAD_TIME=36 COMP_MAP=123 SENS_MAP=0xA6 VOLT_MUL=110 USE_BEC IO_AUX)
add_target(FLYCOLOR1 STM32F051 DEAD_TIME=26 COMP_MAP=123 SENS_MAP=0xA6 VOLT_MUL=110 LED_MAP=0xB5B4B3 IO_PA2)
add_target(FLYCOLOR2 STM32G071 DEAD_TIME=35 COMP_MAP=123 SENS_MAP=0xA6 VOLT_MUL=110 LED_MAP=0xB8)
add_target(HAKRC1 STM32F051 DEAD_TIME=26 COMP_MAP=213 SENS_MAP=0xA3 VOLT_MUL=110 LED_MAP=0xAFB5B3 LED_INV)
add_target(HAKRC2 AT32F421 DEAD_TIME=66 COMP_MAP=213 SENS_MAP=0xA3 VOLT_MUL=110 LED_MAP=0xAFB5B3 LED_INV)
add_target(HGLRC1 STM32F051 DEAD_TIME=26 COMP_MAP=123 SENS_MAP=0xA6 VOLT_MUL=210 IO_PA2)
add_target(IFLIGHT1 STM32F051 DEAD_TIME=26 COMP_MAP=321 SENS_MAP=0xA3A6 VOLT_MUL=110 CURR_MUL=20 LED_MAP=0xB8B5B3 LED_INV)
add_target(IFLIGHT2 STM32G071 DEAD_TIME=35 COMP_MAP=213 SENS_MAP=0xA5A4 VOLT_MUL=110 CURR_MUL=20 LED_WS2812 IO_PA6)
add_target(IFLIGHT3 STM32G071 DEAD_TIME=35 COMP_MAP=132 SENS_MAP=0xA0 VOLT_MUL=110 LED_WS2812)
add_target(LUMENIER1 GD32F350 DEAD_TIME=57 COMP_MAP=321 SENS_MAP=0xA3 VOLT_MUL=110)
add_target(NEUTRONRC1 STM32G071 DEAD_TIME=35 COMP_MAP=123 SENS_MAP=0xA6A4 VOLT_MUL=210 CURR_MUL=50 LED_WS2812)
add_target(ESCAPE1 STM32G071 DEAD_TIME=35 COMP_MAP=123 SENS_MAP=0xA5A4 VOLT_MUL=1100 CURR_MUL=30 LED_WS2812 IO_PA2 IO_AUX)
add_target(ESCAPE2 STM32G071 DEAD_TIME=19 COMP_MAP=123 SENS_MAP=0xA6 VOLT_MUL=1100 USE_BEC IO_PA2 IO_AUX)
add_target(ESCAPE3 AT32F421 DEAD_TIME=36 COMP_MAP=123 SENS_MAP=0xA6 VOLT_MUL=1100 USE_BEC IO_AUX)
add_target(FLYCOLOR1 STM32F051 DEAD_TIME=26 COMP_MAP=123 SENS_MAP=0xA6 VOLT_MUL=1100 LED_MAP=0xB5B4B3 IO_PA2)
add_target(FLYCOLOR2 STM32G071 DEAD_TIME=35 COMP_MAP=123 SENS_MAP=0xA6 VOLT_MUL=1100 LED_MAP=0xB8)
add_target(HAKRC1 STM32F051 DEAD_TIME=26 COMP_MAP=213 SENS_MAP=0xA3 VOLT_MUL=1100 LED_MAP=0xAFB5B3 LED_INV)
add_target(HAKRC2 AT32F421 DEAD_TIME=66 COMP_MAP=213 SENS_MAP=0xA3 VOLT_MUL=1100 LED_MAP=0xAFB5B3 LED_INV)
add_target(HGLRC1 STM32F051 DEAD_TIME=26 COMP_MAP=123 SENS_MAP=0xA6 VOLT_MUL=2100 IO_PA2)
add_target(IFLIGHT1 STM32F051 DEAD_TIME=26 COMP_MAP=321 SENS_MAP=0xA3A6 VOLT_MUL=1100 CURR_MUL=20 LED_MAP=0xB8B5B3 LED_INV)
add_target(IFLIGHT2 STM32G071 DEAD_TIME=35 COMP_MAP=213 SENS_MAP=0xA5A4 VOLT_MUL=1100 CURR_MUL=20 LED_WS2812 IO_PA6)
add_target(IFLIGHT3 STM32G071 DEAD_TIME=35 COMP_MAP=132 SENS_MAP=0xA0 VOLT_MUL=1100 LED_WS2812)
add_target(LUMENIER1 GD32F350 DEAD_TIME=57 COMP_MAP=321 SENS_MAP=0xA3 VOLT_MUL=1100)
add_target(NEUTRONRC1 STM32G071 DEAD_TIME=35 COMP_MAP=123 SENS_MAP=0xA6A4 VOLT_MUL=2100 CURR_MUL=50 LED_WS2812)
add_target(NEUTRONRC2 AT32F421 DEAD_TIME=66 COMP_MAP=321)
add_target(NEUTRONRC3 STM32G071 DEAD_TIME=35 COMP_MAP=123)
add_target(NEUTRONRC4 AT32F421 DEAD_TIME=66 COMP_MAP=321 INVERTED_HIGH)
add_target(SKYSTARS1 GD32E230 DEAD_TIME=40 COMP_MAP=321 SENS_MAP=0xA3 VOLT_MUL=110 LED_MAP=0xB5B3AF)
add_target(SKYSTARS1 GD32E230 DEAD_TIME=40 COMP_MAP=321 SENS_MAP=0xA3 VOLT_MUL=1100 LED_MAP=0xB5B3AF)
add_target(TMOTOR1 STM32F051 DEAD_TIME=26 COMP_MAP=132 IO_PA2)
add_target(TMOTOR2 STM32F051 DEAD_TIME=26 COMP_MAP=321)
add_target(TMOTOR3 STM32G071 DEAD_TIME=35 COMP_MAP=231 IO_PA6)

# Experimental targets
add_target(_SPIN32 STSPIN32F0 DEAD_TIME=26 ANALOG) # Sensored drive using STEVAL_SPIN3201 board
add_target(_G431 STM32G431 DEAD_TIME=180 COMP_MAP=132 SENS_MAP=0xBFA6 VOLT_MUL=160 CURR_MUL=100 USE_HSE=8 USE_PB1)
add_target(_G431 STM32G431 DEAD_TIME=180 COMP_MAP=132 SENS_MAP=0xBFA6 VOLT_MUL=1600 CURR_MUL=100 USE_HSE=8 USE_PB1)
2 changes: 1 addition & 1 deletion mcu/AT32F421/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,6 @@ void dma1_channel1_isr(void) {
#endif
if (ain) x = buf[i++];
int r = 4914000 / buf[i + 1];
int t = ((buf[i] * r >> 12) - 1280) * 10 / 43 + 25;
int t = ((buf[i] * r >> 12) - 1280) * 40 / 43 + 100;
adcdata(t, v * r >> 12, c * r >> 12, x * r >> 12);
}
2 changes: 1 addition & 1 deletion mcu/GD32E230/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,6 @@ void dma1_channel1_isr(void) {
#endif
if (ain) x = buf[i++];
int r = 4914000 / buf[i + 1];
int t = (1450 - (buf[i] * r >> 12)) * 10 / 43 + 25;
int t = (1450 - (buf[i] * r >> 12)) * 40 / 43 + 100;
adcdata(t, v * r >> 12, c * r >> 12, x * r >> 12);
}
2 changes: 1 addition & 1 deletion mcu/GD32F350/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,6 @@ void dma1_channel1_isr(void) {
#endif
if (ain) x = buf[i++];
int r = 4914000 / buf[i + 1];
int t = (1440 - (buf[i] * r >> 12)) * 100 / 408 + 25;
int t = (1440 - (buf[i] * r >> 12)) * 400 / 408 + 100;
adcdata(t, v * r >> 12, c * r >> 12, x * r >> 12);
}
2 changes: 1 addition & 1 deletion mcu/STM32F051/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,6 @@ void dma1_channel1_isr(void) {
if (ain) x = buf[i++];
#endif
int r = ST_VREFINT_CAL * 3300 / buf[i + 1];
int t = (buf[i] * r / 3300 - ST_TSENSE_CAL1_30C) * 80 / (ST_TSENSE_CAL2_110C - ST_TSENSE_CAL1_30C) + 30;
int t = (buf[i] * r / 3300 - ST_TSENSE_CAL1_30C) * 320 / (ST_TSENSE_CAL2_110C - ST_TSENSE_CAL1_30C) + 120;
adcdata(t, v * r >> 12, c * r >> 12, x * r >> 12);
}
2 changes: 1 addition & 1 deletion mcu/STM32G071/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,6 @@ void dma1_channel4_7_dmamux_isr(void) {
#endif
if (ain) x = buf[i++];
int r = ST_VREFINT_CAL * 3000 / buf[i + 1];
int t = (buf[i] * r / 3000 - ST_TSENSE_CAL1_30C) * 100 / (ST_TSENSE_CAL2_130C - ST_TSENSE_CAL1_30C) + 30;
int t = (buf[i] * r / 3000 - ST_TSENSE_CAL1_30C) * 400 / (ST_TSENSE_CAL2_130C - ST_TSENSE_CAL1_30C) + 120;
adcdata(t, v * r >> 12, c * r >> 12, x * r >> 12);
}
2 changes: 1 addition & 1 deletion mcu/STM32G431/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ static void adcdma(void) {
#endif
if (ain) x = buf[i++];
int r = ST_VREFINT_CAL * 3000 / buf[i + 1];
int t = (buf[i] * r / 3000 - ST_TSENSE_CAL1_30C) * 100 / (ST_TSENSE_CAL2_130C - ST_TSENSE_CAL1_30C) + 30;
int t = (buf[i] * r / 3000 - ST_TSENSE_CAL1_30C) * 400 / (ST_TSENSE_CAL2_130C - ST_TSENSE_CAL1_30C) + 120;
adcdata(t, v * r >> 12, c * r >> 12, x * r >> 12);
}

Expand Down
2 changes: 1 addition & 1 deletion mcu/STSPIN32F0/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,6 @@ void dma1_channel1_isr(void) {
int i = 0;
int x = ain ? buf[i++] : 0;
int r = ST_VREFINT_CAL * 3300 / buf[i + 1];
int t = (buf[i] * r / 3300 - ST_TSENSE_CAL1_30C) * 80 / (ST_TSENSE_CAL2_110C - ST_TSENSE_CAL1_30C) + 30;
int t = (buf[i] * r / 3300 - ST_TSENSE_CAL1_30C) * 320 / (ST_TSENSE_CAL2_110C - ST_TSENSE_CAL1_30C) + 120;
adcdata(t, 0, 0, x * r >> 12);
}
2 changes: 1 addition & 1 deletion src/defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
#endif

#ifndef VOLT_MUL
#define VOLT_MUL 0 // %/10
#define VOLT_MUL 0 // %
#endif
#ifndef CURR_MUL
#define CURR_MUL 0 // mA/mV
Expand Down
43 changes: 27 additions & 16 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,24 +41,24 @@ const Cfg cfgdata = {
.duty_drag = DUTY_DRAG, // Drag brake amount (%) [0..100]
.throt_mode = THROT_MODE, // Throttle mode (0 - forward, 1 - forward/reverse, 2 - forward/brake/reverse)
.throt_set = THROT_SET, // Preset throttle (%) [0..100]
.throt_cal = THROT_CAL, // Throttle calibration
.throt_min = THROT_MIN, // Minimum throttle (us)
.throt_mid = THROT_MID, // Middle throttle (us)
.throt_max = THROT_MAX, // Maximum throttle (us)
.throt_cal = THROT_CAL, // Automatic throttle calibration
.throt_min = THROT_MIN, // Minimum throttle setpoint (us)
.throt_mid = THROT_MID, // Middle throttle setpoint (us)
.throt_max = THROT_MAX, // Maximum throttle setpoint (us)
.input_mode = INPUT_MODE, // Input mode (0 - servo/Oneshot125/DSHOT, 1 - analog, 2 - serial, 3 - iBUS, 4 - SBUS/SBUS2, 5 - CRSF)
.input_chid = INPUT_CHID, // Serial channel ID [0 - off, 1..14 - iBUS, 1..16 - SBUS/SBUS2/CRSF]
.telem_mode = TELEM_MODE, // Telemetry mode (0 - KISS, 1 - KISS auto, 2 - iBUS, 3 - S.Port, 4 - CRSF)
.telem_phid = TELEM_PHID, // Telemetry physical ID [0 - off, 1..3 - iBUS, 1..28 - S.Port, 1..4 - SBUS2]
.telem_poles = TELEM_POLES, // Number of motor poles for RPM telemetry [2..100]
.prot_temp = PROT_TEMP, // Temperature threshold (C) [0 - off, 60..140]
.prot_volt = PROT_VOLT, // Low voltage cutoff per battery cell (V/10) [0 - off, 28..38]
.prot_cells = PROT_CELLS, // Number of battery cells [0 - auto, 1..12]
.prot_cells = PROT_CELLS, // Number of battery cells [0 - auto, 1..16]
.prot_curr = PROT_CURR, // Maximum current (A) [0..255]
.music = MUSIC, // Startup music
.volume = VOLUME, // Sound volume (%) [0..100]
.beacon = BEACON, // Beacon volume (%) [0..100]
.bec = BEC, // BEC voltage control
.led = LED, // LED bits
.bec = BEC, // BEC voltage control [0..3]
.led = LED, // LED on/off bits [0..15]
};

__attribute__((__section__(".cfg")))
Expand All @@ -68,7 +68,7 @@ int throt, ertm, erpm, temp, volt, curr, csum, dshotval, beepval = -1;
char analog, telreq, telmode, flipdir, beacon, dshotext;
volatile uint32_t tickms;

static int step, sine, sync, ival;
static int step, sine, sync, ival, tval;
static char prep, accl, tick, reverse, ready, brushed;

static void reset(void) {
Expand Down Expand Up @@ -159,11 +159,16 @@ static void nextstep(void) {
int a = step - 1;
int b = a < 120 ? a + 240 : a - 120;
int c = a < 240 ? a + 120 : a - 240;
int p = cfg.sine_power << 3;
if (cfg.prot_temp) { // Temperature threshold
int q = max(120 - (tval - (cfg.prot_temp << 2)), 60); // 50% power reduction at 15C above threshold
if (p > q) p = q;
}
TIM1_CR1 = TIM_CR1_CEN | TIM_CR1_ARPE | TIM_CR1_UDIS;
TIM1_ARR = CLK_KHZ / 24 - 1;
TIM1_CCR1 = DEAD_TIME + (sinedata[a] * cfg.sine_power >> 4);
TIM1_CCR2 = DEAD_TIME + (sinedata[b] * cfg.sine_power >> 4);
TIM1_CCR3 = DEAD_TIME + (sinedata[c] * cfg.sine_power >> 4);
TIM1_CCR1 = DEAD_TIME + (sinedata[a] * p >> 7);
TIM1_CCR2 = DEAD_TIME + (sinedata[b] * p >> 7);
TIM1_CCR3 = DEAD_TIME + (sinedata[c] * p >> 7);
TIM1_CR1 = TIM_CR1_CEN | TIM_CR1_ARPE;
if (prep) return;
TIM1_CCMR1 = TIM_CCMR1_OC1PE | TIM_CCMR1_OC1M_PWM1 | TIM_CCMR1_OC2PE | TIM_CCMR1_OC2M_PWM1;
Expand Down Expand Up @@ -449,8 +454,8 @@ void adcdata(int t, int v, int c, int x) {
if (!ready) z += c >> 1;
c = 0;
}
temp = smooth(&st, max(t, 0), 10); // C
volt = smooth(&sv, v * VOLT_MUL / 100, 7); // V/100
temp = max((tval = smooth(&st, t, 10)) >> 2, 0); // C
volt = smooth(&sv, v * VOLT_MUL / 1000, 7); // V/100
curr = smooth(&sc, c * CURR_MUL / 10, 4); // A/100
if (!analog) return;
throt = scale(smooth(&sx, x, 5), ANALOG_MIN, ANALOG_MAX, cfg.throt_set * 20, 2000); // Analog throttle
Expand Down Expand Up @@ -634,6 +639,10 @@ void main(void) {
arr = scale(erpm, 30000, 60000, arr, CLK_KHZ / cfg.freq_max); // Variable PWM frequency
}
int maxduty = scale(erpm, 0, cfg.duty_ramp * 1000, cfg.duty_spup * 20, 2000);
if (cfg.prot_temp) { // Temperature threshold
int q = max(2000 - (tval - (cfg.prot_temp << 2)) * 25, 500); // 75% power reduction at 15C above threshold
if (maxduty > q) maxduty = q;
}
if ((newduty -= choke) < 0) newduty = 0;
if (newduty > maxduty) newduty = maxduty;
int a = accl ? 0 : cfg.duty_rate;
Expand All @@ -642,7 +651,11 @@ void main(void) {
if (++r == 8) r = 0;
if (curduty >= newduty || (curduty += b) > newduty) curduty = newduty; // Acceleration slew rate limiting
}
#ifdef FULL_DUTY // Allow 100% duty cycle
int ccr = scale(curduty, 0, 2000, running && cfg.damp ? DEAD_TIME : 0, arr--);
#else
int ccr = scale(curduty, 0, 2000, running && cfg.damp ? DEAD_TIME : 0, brushed ? arr - (CLK_MHZ * 3 >> 1) : arr);
#endif
TIM1_CR1 = TIM_CR1_CEN | TIM_CR1_ARPE | TIM_CR1_UDIS;
TIM1_ARR = arr;
TIM1_CCR1 = ccr;
Expand Down Expand Up @@ -686,8 +699,6 @@ void main(void) {
if (tick & 15) continue; // 16kHz -> 1kHz
if (volt >= cfg.prot_volt * cells * 10) v = 0;
else if (++v == 3000) reset(); // Low voltage cutoff after 3s
int t = cfg.prot_temp ? clamp((temp - cfg.prot_temp) * 100, 0, 1500) : 0; // 25% power cap @ 15C above threshold
int u = cfg.prot_curr ? calcpid(&curpid, curr, cfg.prot_curr * 100) >> 10 : 0; // Current PID control
choke = clamp(choke + u, t, 2000);
choke = cfg.prot_curr ? clamp(choke + (calcpid(&curpid, curr, cfg.prot_curr * 100) >> 10), 0, 2000) : 0; // Current-based PID control
}
}

0 comments on commit 1d0ccb9

Please sign in to comment.