From a57449ed0fb0166eecce68a82e5adee6cd6233c7 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Tue, 14 Sep 2021 21:48:37 +1000 Subject: [PATCH] Retiming all the PWM's --- source/Core/BSP/BSP.h | 5 +- source/Core/BSP/MHP30/BSP.cpp | 6 +- source/Core/BSP/Miniware/BSP.cpp | 56 +++++------- source/Core/BSP/Miniware/Setup.cpp | 5 +- source/Core/BSP/Pine64/BSP.cpp | 4 +- source/Core/BSP/Pine64/IRQ.cpp | 89 ++++++++----------- source/Core/BSP/Pine64/Setup.cpp | 6 +- .../Common/Source/system_gd32vf103.c | 2 +- 8 files changed, 71 insertions(+), 102 deletions(-) diff --git a/source/Core/BSP/BSP.h b/source/Core/BSP/BSP.h index e0739c60..fce1fe2e 100644 --- a/source/Core/BSP/BSP.h +++ b/source/Core/BSP/BSP.h @@ -33,16 +33,13 @@ void BSPInit(void); // Called to reset the hardware watchdog unit void resetWatchdog(); // Accepts a output level of 0.. to use to control the tip output PWM -void setTipPWM(uint8_t pulse); +void setTipPWM(const uint8_t pulse, const bool shouldUseFastModePWM); // Returns the Handle temp in C, X10 uint16_t getHandleTemperature(uint8_t sample); // Returns the Tip temperature ADC reading in raw units uint16_t getTipRawTemp(uint8_t refresh); // Returns the main DC input voltage, using the adjustable divisor + sample flag uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample); -// Switch to the most suitable PWM freq given the desired period; -// returns true if the switch was performed and totalPWM changed -bool tryBetterPWM(uint8_t pwm); // Readers for the two buttons // !! Returns 1 if held down, 0 if released diff --git a/source/Core/BSP/MHP30/BSP.cpp b/source/Core/BSP/MHP30/BSP.cpp index 4757f3d3..ffff19ee 100644 --- a/source/Core/BSP/MHP30/BSP.cpp +++ b/source/Core/BSP/MHP30/BSP.cpp @@ -246,11 +246,7 @@ uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample) { } return sum * 4 / divisor; } -bool tryBetterPWM(uint8_t pwm) { - // We dont need this for the MHP30 - return false; -} -void setTipPWM(uint8_t pulse) { +void setTipPWM(const uint8_t pulse, const bool shouldUseFastModePWM) { // We can just set the timer directly if (htim3.Instance->PSC > 20) { htim3.Instance->CCR1 = 0; diff --git a/source/Core/BSP/Miniware/BSP.cpp b/source/Core/BSP/Miniware/BSP.cpp index 7a75d989..397ec521 100644 --- a/source/Core/BSP/Miniware/BSP.cpp +++ b/source/Core/BSP/Miniware/BSP.cpp @@ -135,48 +135,36 @@ uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample) { return res; } -void setTipPWM(uint8_t pulse) { - PWMSafetyTimer = 10; // This is decremented in the handler for PWM so that the tip pwm is - // disabled if the PID task is not scheduled often enough. - - pendingPWM = pulse; -} - static void switchToFastPWM(void) { - fastPWM = true; - totalPWM = powerPWM + tempMeasureTicks * 2 + holdoffTicks; - htim2.Instance->ARR = totalPWM; - // ~3.5 Hz rate - htim2.Instance->CCR1 = powerPWM + holdoffTicks * 2; - // 2 MHz timer clock/2000 = 1 kHz tick rate - htim2.Instance->PSC = 2000; + // 10Hz + fastPWM = true; + totalPWM = powerPWM + tempMeasureTicks + holdoffTicks; + htim2.Instance->ARR = totalPWM; + htim2.Instance->CCR1 = powerPWM + holdoffTicks; + htim2.Instance->PSC = 2690; } static void switchToSlowPWM(void) { - fastPWM = false; - totalPWM = powerPWM + tempMeasureTicks + holdoffTicks; - htim2.Instance->ARR = totalPWM; - // ~1.84 Hz rate - htim2.Instance->CCR1 = powerPWM + holdoffTicks; - // 2 MHz timer clock/4000 = 500 Hz tick rate - htim2.Instance->PSC = 4000; + // 5Hz + fastPWM = false; + totalPWM = powerPWM + tempMeasureTicks / 2 + holdoffTicks / 2; + htim2.Instance->ARR = totalPWM; + htim2.Instance->CCR1 = powerPWM + holdoffTicks / 2; + htim2.Instance->PSC = 2690 * 2; } -bool tryBetterPWM(uint8_t pwm) { - if (fastPWM && pwm == powerPWM) { - // maximum power for fast PWM reached, need to go slower to get more - switchToSlowPWM(); - return true; - } else if (!fastPWM && pwm < 230) { - // 254 in fast PWM mode gives the same power as 239 in slow - // allow for some reasonable hysteresis by switching only when it goes - // below 230 (equivalent to 245 in fast mode) - switchToFastPWM(); - return true; +void setTipPWM(const uint8_t pulse, const bool shouldUseFastModePWM) { + PWMSafetyTimer = 10; // This is decremented in the handler for PWM so that the tip pwm is + // disabled if the PID task is not scheduled often enough. + pendingPWM = pulse; + if (fastPWM != shouldUseFastModePWM) { + if (shouldUseFastModePWM) { + switchToFastPWM(); + } else { + switchToSlowPWM(); + } } - return false; } - // These are called by the HAL after the corresponding events from the system // timers. diff --git a/source/Core/BSP/Miniware/Setup.cpp b/source/Core/BSP/Miniware/Setup.cpp index 9532503e..93b7a6e6 100644 --- a/source/Core/BSP/Miniware/Setup.cpp +++ b/source/Core/BSP/Miniware/Setup.cpp @@ -326,7 +326,8 @@ static void MX_TIM2_Init(void) { // These values give a rate of around 3.5 Hz for "fast" mode and 1.84 Hz for "slow" htim2.Init.CounterMode = TIM_COUNTERMODE_UP; // dummy value, will be reconfigured by BSPInit() - htim2.Init.Period = 255 + 17 * 2; + htim2.Init.Period = powerPWM + 14 * 2; + htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV4; // 8 MHz (x2 APB1) before divide htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; htim2.Init.RepetitionCounter = 0; @@ -344,7 +345,7 @@ static void MX_TIM2_Init(void) { sConfigOC.OCMode = TIM_OCMODE_PWM1; // dummy value, will be reconfigured by BSPInit() in the BSP.cpp - sConfigOC.Pulse = 255 + 13 * 2; // 13 -> Delay of 7 ms + sConfigOC.Pulse = powerPWM + 14; // 13 -> Delay of 7 ms // 255 is the largest time period of the drive signal, and then offset ADC sample to be a bit delayed after this /* * It takes 4 milliseconds for output to be stable after PWM turns off. diff --git a/source/Core/BSP/Pine64/BSP.cpp b/source/Core/BSP/Pine64/BSP.cpp index a1978bd3..a4526712 100644 --- a/source/Core/BSP/Pine64/BSP.cpp +++ b/source/Core/BSP/Pine64/BSP.cpp @@ -12,8 +12,8 @@ #include "main.hpp" const uint16_t powerPWM = 255; -const uint8_t holdoffTicks = 25; // delay of 7 ms -const uint8_t tempMeasureTicks = 25; +const uint8_t holdoffTicks = 10; +const uint8_t tempMeasureTicks = 14; uint16_t totalPWM; // htim2.Init.Period, the full PWM cycle diff --git a/source/Core/BSP/Pine64/IRQ.cpp b/source/Core/BSP/Pine64/IRQ.cpp index 9285bb16..e0fff8f4 100644 --- a/source/Core/BSP/Pine64/IRQ.cpp +++ b/source/Core/BSP/Pine64/IRQ.cpp @@ -18,6 +18,9 @@ volatile uint16_t i2c_nbytes; volatile uint16_t i2c_write_dress; volatile uint16_t i2c_read_dress; volatile uint8_t i2c_process_flag = 0; +static bool fastPWM; +static void switchToSlowPWM(void); +static void switchToFastPWM(void); void ADC0_1_IRQHandler(void) { adc_interrupt_flag_clear(ADC0, ADC_INT_FLAG_EOIC); @@ -34,74 +37,58 @@ void ADC0_1_IRQHandler(void) { volatile uint16_t PWMSafetyTimer = 0; volatile uint8_t pendingPWM = 0; void TIMER1_IRQHandler(void) { + static bool lastPeriodWasFast = false; if (timer_interrupt_flag_get(TIMER1, TIMER_INT_UP) == SET) { timer_interrupt_flag_clear(TIMER1, TIMER_INT_UP); // rollover turn on output if required - if (PWMSafetyTimer && pendingPWM) { - timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_0, 50); - } if (PWMSafetyTimer) { PWMSafetyTimer--; + if (lastPeriodWasFast != fastPWM) { + if (fastPWM) { + switchToFastPWM(); + } else { + switchToSlowPWM(); + } + } + if (pendingPWM) { + timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_1, pendingPWM); + timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_0, 50); + } else { + timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_0, 0); + } } } if (timer_interrupt_flag_get(TIMER1, TIMER_INT_CH1) == SET) { timer_interrupt_flag_clear(TIMER1, TIMER_INT_CH1); - // This is triggered on pwm setpoint trigger; we want to copy the pending - // PWM value into the output control reg - timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_0, 0); - if (pendingPWM) { - timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_1, pendingPWM); - } } } -void setTipPWM(uint8_t pulse) { +void switchToFastPWM(void) { + fastPWM = true; + totalPWM = powerPWM + tempMeasureTicks + holdoffTicks; + TIMER_CAR(TIMER1) = (uint32_t)totalPWM; + + // ~10Hz + TIMER_CH0CV(TIMER1) = powerPWM + holdoffTicks; + // 1 kHz tick rate + TIMER_PSC(TIMER1) = 18000; +} + +void switchToSlowPWM(void) { + // 5Hz + fastPWM = false; + totalPWM = powerPWM + tempMeasureTicks / 2 + holdoffTicks / 2; + TIMER_CAR(TIMER1) = (uint32_t)totalPWM; + TIMER_CH0CV(TIMER1) = powerPWM + holdoffTicks / 2; + TIMER_PSC(TIMER1) = 36000; +} +void setTipPWM(const uint8_t pulse, const bool shouldUseFastModePWM) { PWMSafetyTimer = 10; // This is decremented in the handler for PWM so that the tip pwm is // disabled if the PID task is not scheduled often enough. pendingPWM = pulse; -} - -static bool fastPWM; -static void switchToFastPWM(void) { - fastPWM = true; - totalPWM = powerPWM + tempMeasureTicks * 2; - TIMER_CAR(TIMER1) = (uint32_t)totalPWM; - - // ~3.5 Hz rate - TIMER_CH0CV(TIMER1) = powerPWM + holdoffTicks * 2; - // 1 kHz tick rate - TIMER_PSC(TIMER1) = 12000; - /* generate an update event */ - TIMER_SWEVG(TIMER1) |= (uint32_t)TIMER_SWEVG_UPG; -} - -static void switchToSlowPWM(void) { - fastPWM = false; - totalPWM = powerPWM + tempMeasureTicks; - TIMER_CAR(TIMER1) = (uint32_t)totalPWM; - // ~1.84 Hz rate - TIMER_CH0CV(TIMER1) = powerPWM + holdoffTicks; - // 500 Hz tick rate - TIMER_PSC(TIMER1) = 24000; - /* generate an update event */ - TIMER_SWEVG(TIMER1) |= (uint32_t)TIMER_SWEVG_UPG; -} - -bool tryBetterPWM(uint8_t pwm) { - if (fastPWM && pwm == powerPWM) { - // maximum power for fast PWM reached, need to go slower to get more - switchToSlowPWM(); - return true; - } else if (!fastPWM && pwm < 230) { - // 254 in fast PWM mode gives the same power as 239 in slow - // allow for some reasonable hysteresis by switching only when it goes - // below 230 (equivalent to 245 in fast mode) - switchToFastPWM(); - return true; - } - return false; + fastPWM = shouldUseFastModePWM; } void EXTI5_9_IRQHandler(void) { diff --git a/source/Core/BSP/Pine64/Setup.cpp b/source/Core/BSP/Pine64/Setup.cpp index 826dbdc4..0b683036 100644 --- a/source/Core/BSP/Pine64/Setup.cpp +++ b/source/Core/BSP/Pine64/Setup.cpp @@ -12,7 +12,7 @@ #include "history.hpp" #include #define ADC_NORM_SAMPLES 16 -#define ADC_FILTER_LEN 32 +#define ADC_FILTER_LEN 4 uint16_t ADCReadings[ADC_NORM_SAMPLES]; // room for 32 lots of the pair of readings // Functions @@ -264,10 +264,10 @@ void setup_timers() { /* initialize TIMER init parameter struct */ timer_struct_para_init(&timer_initpara); /* TIMER1 configuration */ - timer_initpara.prescaler = 5000; + timer_initpara.prescaler = 30000; timer_initpara.alignedmode = TIMER_COUNTER_EDGE; timer_initpara.counterdirection = TIMER_COUNTER_UP; - timer_initpara.period = powerPWM + tempMeasureTicks; + timer_initpara.period = powerPWM + tempMeasureTicks + holdoffTicks; timer_initpara.clockdivision = TIMER_CKDIV_DIV4; timer_initpara.repetitioncounter = 0; timer_init(TIMER1, &timer_initpara); diff --git a/source/Core/BSP/Pine64/Vendor/SoC/gd32vf103/Common/Source/system_gd32vf103.c b/source/Core/BSP/Pine64/Vendor/SoC/gd32vf103/Common/Source/system_gd32vf103.c index fcb8786c..b34e55a4 100644 --- a/source/Core/BSP/Pine64/Vendor/SoC/gd32vf103/Common/Source/system_gd32vf103.c +++ b/source/Core/BSP/Pine64/Vendor/SoC/gd32vf103/Common/Source/system_gd32vf103.c @@ -118,7 +118,7 @@ static void system_clock_108m_hxtal(void) { /* APB2 = AHB/1 */ RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; /* APB1 = AHB/2 */ - RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + RCU_CFG0 |= RCU_APB1_CKAHB_DIV4; /* CK_PLL = (CK_PREDIV0) * 27 = 108 MHz */ RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);