From b05f36a025f6074113c86f9e5041b6fab58f94cf Mon Sep 17 00:00:00 2001 From: bowman Date: Wed, 22 Jul 2026 19:25:44 -0700 Subject: [PATCH] fix: widen tip PWM pipeline to uint16_t to fix HS-02 high-power output On the Fnirsi HS-02 the tip PWM period (powerPWM) is 395, but the watts-to-PWM pipeline was typed uint8_t end to end: X10WattsToPWM() -> uint8_t (clamps to powerPWM=395, then truncates) setTipPWM(const uint8_t pulse) Any demand that scaled the PWM value above 255 wrapped modulo 256, so the duty cycle collapsed. Concretely a full-power request of 395 truncated to 139, i.e. ~35% duty. This is why a power limit of <=90 W reached the setpoint from cold but 100 W only delivered ~40-60 W. Widen the value path to uint16_t (X10WattsToPWM return, setTipPWM pulse across all BSPs, plus PWMToX10Watts / shouldBeUsingFastPWMMode). The internally scaled value still fits uint8_t pendingPWM, and every other device has powerPWM <= 255 so they are unaffected. --- source/Core/BSP/BSP.h | 2 +- source/Core/BSP/Fnirsi/BSP.cpp | 2 +- source/Core/BSP/MHP30/BSP.cpp | 2 +- source/Core/BSP/Miniware/BSP.cpp | 2 +- source/Core/BSP/Pinecil/IRQ.cpp | 2 +- source/Core/BSP/Pinecilv2/IRQ.cpp | 2 +- source/Core/BSP/Sequre/BSP.cpp | 2 +- source/Core/Inc/power.hpp | 2 +- source/Core/Src/power.cpp | 8 ++++---- 9 files changed, 12 insertions(+), 12 deletions(-) diff --git a/source/Core/BSP/BSP.h b/source/Core/BSP/BSP.h index 37508597c7..22d4862e33 100644 --- a/source/Core/BSP/BSP.h +++ b/source/Core/BSP/BSP.h @@ -36,7 +36,7 @@ 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(const uint8_t pulse, const bool shouldUseFastModePWM); +void setTipPWM(const uint16_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 diff --git a/source/Core/BSP/Fnirsi/BSP.cpp b/source/Core/BSP/Fnirsi/BSP.cpp index 8858fab678..eabe77bd81 100644 --- a/source/Core/BSP/Fnirsi/BSP.cpp +++ b/source/Core/BSP/Fnirsi/BSP.cpp @@ -99,7 +99,7 @@ static void switchToFastPWM(void) { TIM4->PSC = 3999; // 8kHz -> 125uS per tick } -void setTipPWM(const uint8_t pulse, const bool shouldUseFastModePWM) { +void setTipPWM(const uint16_t pulse, const bool shouldUseFastModePWM) { PWMSafetyTimer = 20; // This is decremented in the handler for PWM so that the tip pwm is // disabled if the PID task is not scheduled often enough. diff --git a/source/Core/BSP/MHP30/BSP.cpp b/source/Core/BSP/MHP30/BSP.cpp index aa88f28e8f..e05acfef2f 100644 --- a/source/Core/BSP/MHP30/BSP.cpp +++ b/source/Core/BSP/MHP30/BSP.cpp @@ -251,7 +251,7 @@ uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample) { } return sum * 4 / divisor; } -void setTipPWM(const uint8_t pulse, const bool shouldUseFastModePWM) { +void setTipPWM(const uint16_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 efb52edc56..904c6cd562 100644 --- a/source/Core/BSP/Miniware/BSP.cpp +++ b/source/Core/BSP/Miniware/BSP.cpp @@ -118,7 +118,7 @@ static void switchToSlowPWM(void) { htimADC.Instance->PSC = 2690 * 2; } -void setTipPWM(const uint8_t pulse, const bool shouldUseFastModePWM) { +void setTipPWM(const uint16_t pulse, const bool shouldUseFastModePWM) { PWMSafetyTimer = 20; // This is decremented in the handler for PWM so that the tip pwm is // disabled if the PID task is not scheduled often enough. fastPWM = shouldUseFastModePWM; diff --git a/source/Core/BSP/Pinecil/IRQ.cpp b/source/Core/BSP/Pinecil/IRQ.cpp index e8f93df22e..faf0bf7f02 100644 --- a/source/Core/BSP/Pinecil/IRQ.cpp +++ b/source/Core/BSP/Pinecil/IRQ.cpp @@ -84,7 +84,7 @@ void switchToSlowPWM(void) { TIMER_CH0CV(TIMER1) = powerPWM + holdoffTicks / 2; TIMER_PSC(TIMER1) = 36000; } -void setTipPWM(const uint8_t pulse, const bool shouldUseFastModePWM) { +void setTipPWM(const uint16_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; diff --git a/source/Core/BSP/Pinecilv2/IRQ.cpp b/source/Core/BSP/Pinecilv2/IRQ.cpp index 1fbb4e1c9c..a1ecfb3aaa 100644 --- a/source/Core/BSP/Pinecilv2/IRQ.cpp +++ b/source/Core/BSP/Pinecilv2/IRQ.cpp @@ -157,7 +157,7 @@ void switchToSlowPWM(void) { BL_WR_REG(TIMER_BASE, TIMER_TCDR, tmpVal); } -void setTipPWM(const uint8_t pulse, const bool shouldUseFastModePWM) { +void setTipPWM(const uint16_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. diff --git a/source/Core/BSP/Sequre/BSP.cpp b/source/Core/BSP/Sequre/BSP.cpp index 32daec13ff..6024b06d05 100644 --- a/source/Core/BSP/Sequre/BSP.cpp +++ b/source/Core/BSP/Sequre/BSP.cpp @@ -89,7 +89,7 @@ static void switchToFastPWM(void) { htim2.Instance->PSC = 1500; } -void setTipPWM(const uint8_t pulse, const bool shouldUseFastModePWM) { +void setTipPWM(const uint16_t pulse, const bool shouldUseFastModePWM) { PWMSafetyTimer = 20; // 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; diff --git a/source/Core/Inc/power.hpp b/source/Core/Inc/power.hpp index 432ad16695..1eb5b2f39a 100644 --- a/source/Core/Inc/power.hpp +++ b/source/Core/Inc/power.hpp @@ -24,5 +24,5 @@ extern expMovingAverage x10WattHistory; uint32_t availableW10(uint8_t sample); void setTipX10Watts(int32_t mw); -uint8_t X10WattsToPWM(int32_t milliWatts, uint8_t sample = 0); +uint16_t X10WattsToPWM(int32_t milliWatts, uint8_t sample = 0); #endif /* POWER_HPP_ */ diff --git a/source/Core/Src/power.cpp b/source/Core/Src/power.cpp index 708014ed1a..ed0be2d809 100644 --- a/source/Core/Src/power.cpp +++ b/source/Core/Src/power.cpp @@ -9,13 +9,13 @@ #include #include -static int32_t PWMToX10Watts(uint8_t pwm, uint8_t sample); +static int32_t PWMToX10Watts(uint16_t pwm, uint8_t sample); const int fastPWMChangeoverPoint = 128; const int fastPWMChangeoverTolerance = 16; expMovingAverage x10WattHistory = {0}; -bool shouldBeUsingFastPWMMode(const uint8_t pwmTicks) { +bool shouldBeUsingFastPWMMode(const uint16_t pwmTicks) { // Determine if we should use slow or fast PWM mode // Crossover between modes set around the midpoint of the PWM control point static bool lastPWMWasFast = true; @@ -56,7 +56,7 @@ uint32_t availableW10(uint8_t sample) { // availableMilliWattsX10 is now an accurate representation return availableWattsX10; } -uint8_t X10WattsToPWM(int32_t x10Watts, uint8_t sample) { +uint16_t X10WattsToPWM(int32_t x10Watts, uint8_t sample) { // Scale input x10Watts to the pwm range available if (x10Watts <= 0) { // keep the battery voltage updating the filter @@ -74,7 +74,7 @@ uint8_t X10WattsToPWM(int32_t x10Watts, uint8_t sample) { return pwm; } -static int32_t PWMToX10Watts(uint8_t pwm, uint8_t sample) { +static int32_t PWMToX10Watts(uint16_t pwm, uint8_t sample) { uint32_t maxMW = availableW10(sample); // Get the milliwatts for the max pwm period // Then convert pwm into percentage of powerPWM to get the percentage of the max mw return (((uint32_t)pwm) * maxMW) / powerPWM;