diff --git a/workspace/TS100/Core/Inc/Settings.h b/workspace/TS100/Core/Inc/Settings.h index 4460ff67..dd918168 100644 --- a/workspace/TS100/Core/Inc/Settings.h +++ b/workspace/TS100/Core/Inc/Settings.h @@ -44,9 +44,7 @@ typedef struct { uint8_t customTipGain; // Tip gain value if custom tuned, or 0 if using a // tipType param -#ifdef MODEL_TS80 uint8_t pidPowerLimit; -#endif uint8_t version; // Used to track if a reset is needed on firmware upgrade uint32_t padding; // This is here for in case we are not an even divisor so // that nothing gets cut off diff --git a/workspace/TS100/Core/Inc/power.hpp b/workspace/TS100/Core/Inc/power.hpp index 10e327f2..94d329a4 100644 --- a/workspace/TS100/Core/Inc/power.hpp +++ b/workspace/TS100/Core/Inc/power.hpp @@ -18,22 +18,21 @@ // Once we have feed-forward temp estimation we should be able to better tune this. #ifdef MODEL_TS100 -const uint16_t tipMass = 450; // divide here so division is compile-time. +const int32_t tipMass = 3500; // divide here so division is compile-time. const uint8_t tipResistance = 85; //x10 ohms, 8.5 typical for ts100, 4.5 typical for ts80 #endif #ifdef MODEL_TS80 -const uint16_t tipMass = 450; +const uint32_t tipMass = 4500; const uint8_t tipResistance = 45; //x10 ohms, 8.5 typical for ts100, 4.5 typical for ts80 #endif -const uint8_t oscillationPeriod = 6 * PID_TIM_HZ; // I term look back value -extern history milliWattHistory; - -int32_t tempToMilliWatts(int32_t rawTemp); -void setTipMilliWatts(int32_t mw); -uint8_t milliWattsToPWM(int32_t milliWatts, uint8_t divisor, - uint8_t sample = 0); -int32_t PWMToMilliWatts(uint8_t pwm, uint8_t divisor, uint8_t sample = 0); +const uint8_t oscillationPeriod = 8*PID_TIM_HZ; // I term look back value +extern history x10WattHistory; +int32_t tempToX10Watts(int32_t rawTemp); +void setTipX10Watts(int32_t mw); +uint8_t X10WattsToPWM(int32_t milliWatts, uint8_t sample = 0); +int32_t PWMToX10Watts(uint8_t pwm, uint8_t sample = 0); +uint32_t availableW10(uint8_t sample) ; #endif /* POWER_HPP_ */ diff --git a/workspace/TS100/Core/Src/GUIThread.cpp b/workspace/TS100/Core/Src/GUIThread.cpp index 37908567..41b78814 100644 --- a/workspace/TS100/Core/Src/GUIThread.cpp +++ b/workspace/TS100/Core/Src/GUIThread.cpp @@ -502,9 +502,9 @@ static void gui_solderingMode(uint8_t jumpToSleep) { if (systemSettings.detailedSoldering) { OLED::setFont(1); OLED::print(SolderingAdvancedPowerPrompt); // Power: - OLED::printNumber(milliWattHistory[0] / 1000, 2); + OLED::printNumber(x10WattHistory[0] / 10, 2); OLED::print(SymbolDot); - OLED::printNumber(milliWattHistory[0] / 100 % 10, 1); + OLED::printNumber(x10WattHistory[0] % 10, 1); OLED::print(SymbolWatts); if (systemSettings.sensitivity && systemSettings.SleepTime) { @@ -514,6 +514,9 @@ static void gui_solderingMode(uint8_t jumpToSleep) { OLED::setCursor(0, 8); OLED::print(SleepingTipAdvancedString); + //OLED::printNumber( + // TipThermoModel::convertTipRawADCTouV(getTipRawTemp(0)), 5); // Draw the tip temp out finally + gui_drawTipTemp(true); OLED::print(SymbolSpace); printVoltage(); @@ -535,14 +538,10 @@ static void gui_solderingMode(uint8_t jumpToSleep) { OLED::print(SymbolSpace); // Draw heating/cooling symbols - OLED::drawHeatSymbol( - milliWattsToPWM(milliWattHistory[0], - systemSettings.voltageDiv)); + OLED::drawHeatSymbol(X10WattsToPWM(x10WattHistory[0])); } else { // Draw heating/cooling symbols - OLED::drawHeatSymbol( - milliWattsToPWM(milliWattHistory[0], - systemSettings.voltageDiv)); + OLED::drawHeatSymbol(X10WattsToPWM(x10WattHistory[0])); // We draw boost arrow if boosting, or else gap temp <-> heat // indicator if (boostModeOn) @@ -645,13 +644,17 @@ void showDebugMenu(void) { break; case 6: //Raw Tip - OLED::printNumber(TipThermoModel::convertTipRawADCTouV(getTipRawTemp(0)), 6); + { + uint32_t temp = systemSettings.CalibrationOffset; + systemSettings.CalibrationOffset = 0; + OLED::printNumber( + TipThermoModel::convertTipRawADCTouV(getTipRawTemp(1)), 6); + systemSettings.CalibrationOffset = temp; + } break; case 7: //Temp in C - OLED::printNumber( - TipThermoModel::convertTipRawADCToDegC(getTipRawTemp(0)), - 5); + OLED::printNumber(TipThermoModel::getTipInC(1), 5); break; case 8: //Handle Temp diff --git a/workspace/TS100/Core/Src/Settings.cpp b/workspace/TS100/Core/Src/Settings.cpp index c196890f..e8011e6e 100644 --- a/workspace/TS100/Core/Src/Settings.cpp +++ b/workspace/TS100/Core/Src/Settings.cpp @@ -106,13 +106,14 @@ void resetSettings() { systemSettings.descriptionScrollSpeed = 0; // default to slow #ifdef MODEL_TS100 - - systemSettings.CalibrationOffset = 650; // the adc offset in uV + systemSettings.CalibrationOffset = 300; // the adc offset in uV + systemSettings.pidPowerLimit=70; // Sets the max pwm power limit #endif #ifdef MODEL_TS80 systemSettings.pidPowerLimit=24; // Sets the max pwm power limit - systemSettings.CalibrationOffset = 650; // the adc offset in uV + + systemSettings.CalibrationOffset = 300; // the adc offset in uV #endif saveSettings(); // Save defaults } diff --git a/workspace/TS100/Core/Src/TipThermoModel.cpp b/workspace/TS100/Core/Src/TipThermoModel.cpp index 31af262a..168216e2 100644 --- a/workspace/TS100/Core/Src/TipThermoModel.cpp +++ b/workspace/TS100/Core/Src/TipThermoModel.cpp @@ -256,6 +256,6 @@ uint32_t TipThermoModel::getTipInC(bool sampleNow) { uint32_t TipThermoModel::getTipInF(bool sampleNow) { uint32_t currentTipTempInF = TipThermoModel::convertTipRawADCToDegF( getTipRawTemp(sampleNow)); - currentTipTempInF += convertCtoF(getHandleTemperature() / 10); //Add handle offset - return currentTipTempInF; + currentTipTempInF += convertCtoF(getHandleTemperature() / 10); //Add handle offset + return currentTipTempInF; } diff --git a/workspace/TS100/Core/Src/gui.cpp b/workspace/TS100/Core/Src/gui.cpp index 42ce89b6..f9f484e7 100644 --- a/workspace/TS100/Core/Src/gui.cpp +++ b/workspace/TS100/Core/Src/gui.cpp @@ -581,8 +581,9 @@ static void setTipOffset() { OLED::clearScreen(); OLED::setCursor(0, 0); OLED::drawCheckbox(true); + OLED::printNumber(systemSettings.CalibrationOffset,4); OLED::refresh(); - osDelay(1000); + osDelay(1200); } //Provide the user the option to tune their own tip if custom is selected diff --git a/workspace/TS100/Core/Src/hardware.cpp b/workspace/TS100/Core/Src/hardware.cpp index fa10da38..080705b2 100644 --- a/workspace/TS100/Core/Src/hardware.cpp +++ b/workspace/TS100/Core/Src/hardware.cpp @@ -27,7 +27,6 @@ uint16_t getHandleTemperature() { return result; } - uint16_t getTipInstantTemperature() { uint16_t sum = 0; // 12 bit readings * 8 -> 15 bits uint16_t readings[8]; @@ -42,23 +41,15 @@ uint16_t getTipInstantTemperature() { readings[5] = hadc2.Instance->JDR2; readings[6] = hadc2.Instance->JDR3; readings[7] = hadc2.Instance->JDR4; - uint8_t minID = 0, maxID = 0; + for (int i = 0; i < 8; i++) { - if (readings[i] < readings[minID]) - minID = i; - else if (readings[i] > readings[maxID]) - maxID = i; + sum += readings[i]; } - for (int i = 0; i < 8; i++) { - if (i != maxID) - sum += readings[i]; - } - sum += readings[minID]; //Duplicate the min to make up for the missing max value return sum; // 8x over sample } //2 second filter (ADC is PID_TIM_HZ Hz) -history rawTempFilter = { { 0 }, 0, 0 }; +history rawTempFilter = { { 0 }, 0, 0 }; uint16_t getTipRawTemp(uint8_t refresh) { if (refresh) { @@ -354,7 +345,6 @@ void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim) { } } - void vApplicationIdleHook(void) { HAL_IWDG_Refresh(&hiwdg); } diff --git a/workspace/TS100/Core/Src/main.cpp b/workspace/TS100/Core/Src/main.cpp index b9f11573..9568b97a 100644 --- a/workspace/TS100/Core/Src/main.cpp +++ b/workspace/TS100/Core/Src/main.cpp @@ -47,7 +47,7 @@ int main(void) { HAL_Init(); Setup_HAL(); // Setup all the HAL objects HAL_IWDG_Refresh(&hiwdg); - setTipMilliWatts(0); // force tip off + setTipX10Watts(0); // force tip off FRToSI2C::init(&hi2c1); OLED::initialize(); // start up the LCD OLED::setFont(0); // default to bigger font @@ -106,7 +106,7 @@ void startPIDTask(void const *argument __unused) { * We take the current tip temperature & evaluate the next step for the tip * control PWM. */ - setTipMilliWatts(0); // disable the output driver if the output is set to be off + setTipX10Watts(0); // disable the output driver if the output is set to be off #ifdef MODEL_TS80 idealQCVoltage = calculateMaxVoltage(systemSettings.cutoutSetting); #endif @@ -118,7 +118,7 @@ void startPIDTask(void const *argument __unused) { #else #endif - history tempError = { { 0 }, 0, 0 }; + history tempError = { { 0 }, 0, 0 }; currentTempTargetDegC = 0; // Force start with no output (off). If in sleep / soldering this will // be over-ridden rapidly pidTaskNotification = xTaskGetCurrentTaskHandle(); @@ -145,7 +145,7 @@ void startPIDTask(void const *argument __unused) { tempError.update(tError); // Now for the PID! - int32_t milliWattsOut = 0; + int32_t x10WattsOut = 0; // P term - total power needed to hit target temp next cycle. // thermal mass = 1690 milliJ/*C for my tip. @@ -154,17 +154,17 @@ void startPIDTask(void const *argument __unused) { // This is necessary because of the temp noise and thermal lag in the system. // Once we have feed-forward temp estimation we should be able to better tune this. - int32_t milliWattsNeeded = tempToMilliWatts( - tempError.average()); + int32_t x10WattsNeeded = tempToX10Watts(tError); +// tempError.average()); // note that milliWattsNeeded is sometimes negative, this counters overshoot // from I term's inertia. - milliWattsOut += milliWattsNeeded; + x10WattsOut += x10WattsNeeded; // I term - energy needed to compensate for heat loss. // We track energy put into the system over some window. // Assuming the temp is stable, energy in = energy transfered. // (If it isn't, P will dominate). - milliWattsOut += milliWattHistory.average(); + x10WattsOut += x10WattHistory.average(); // D term - use sudden temp change to counter fast cooling/heating. // In practice, this provides an early boost if temp is dropping @@ -172,7 +172,7 @@ void startPIDTask(void const *argument __unused) { // basically: temp - lastTemp // Unfortunately, our temp signal is too noisy to really help. - setTipMilliWatts(milliWattsOut); + setTipX10Watts(x10WattsOut); } else { #ifdef MODEL_TS80 @@ -180,15 +180,15 @@ void startPIDTask(void const *argument __unused) { // This is purely guesswork :'( as everyone implements stuff differently if (xTaskGetTickCount() - lastPowerPulse < 10) { // for the first 100mS turn on for a bit - setTipMilliWatts(2500); // typically its around 5W to hold the current temp, so this wont raise temp much + setTipX10Watts(25); // typically its around 5W to hold the current temp, so this wont raise temp much } else - setTipMilliWatts(0); + setTipX10Watts(0); //Then wait until the next 0.5 seconds if (xTaskGetTickCount() - lastPowerPulse > 50) { lastPowerPulse = xTaskGetTickCount(); } #else - setTipMilliWatts(0); + setTipX10Watts(0); #endif } @@ -197,7 +197,6 @@ void startPIDTask(void const *argument __unused) { asm("bkpt"); //ADC interrupt timeout - setTipMilliWatts(0); setTipPWM(0); } } diff --git a/workspace/TS100/Core/Src/power.cpp b/workspace/TS100/Core/Src/power.cpp index b5f7490a..a762a8cc 100644 --- a/workspace/TS100/Core/Src/power.cpp +++ b/workspace/TS100/Core/Src/power.cpp @@ -12,33 +12,30 @@ const uint16_t powerPWM = 255; const uint16_t totalPWM = 255 + 17; //htim2.Init.Period, the full PWM cycle -history milliWattHistory = { { 0 }, 0, 0 }; +history x10WattHistory = { { 0 }, 0, 0 }; -int32_t tempToMilliWatts(int32_t rawTemp) { +int32_t tempToX10Watts(int32_t rawTemp) { // mass is in milliJ/*C, rawC is raw per degree C // returns milliWatts needed to raise/lower a mass by rawTemp // degrees in one cycle. - int32_t milliJoules = tipMass*10 * rawTemp; + int32_t milliJoules = tipMass * rawTemp; return milliJoules; } -void setTipMilliWatts(int32_t mw) { - //Enforce Max Watts Limiter # TODO - - int32_t output = milliWattsToPWM(mw, systemSettings.voltageDiv , 1); +void setTipX10Watts(int32_t mw) { + int32_t output = X10WattsToPWM(mw, 1); setTipPWM(output); - uint32_t actualMilliWatts = PWMToMilliWatts(output, - systemSettings.voltageDiv , 0); + uint32_t actualMilliWatts = PWMToX10Watts(output, 0); - milliWattHistory.update(actualMilliWatts); + x10WattHistory.update(actualMilliWatts); } -int32_t availableW10(uint8_t divisor, uint8_t sample) { +uint32_t availableW10(uint8_t sample) { //P = V^2 / R, v*v = v^2 * 100 // R = R*10 // P therefore is in V^2*100/R*10 = W*10. - int32_t v = getInputVoltageX10(divisor, sample); // 100 = 10v - int32_t availableWattsX10 = (v * v) / tipResistance; + uint32_t v = getInputVoltageX10(systemSettings.voltageDiv, sample); // 100 = 10v + uint32_t availableWattsX10 = (v * v) / tipResistance; //However, 100% duty cycle is not possible as there is a dead time while the ADC takes a reading //Therefore need to scale available milliwats by this @@ -50,27 +47,23 @@ int32_t availableW10(uint8_t divisor, uint8_t sample) { return availableWattsX10; } -uint8_t milliWattsToPWM(int32_t milliWatts, uint8_t divisor, uint8_t sample) { - - // Scale input milliWatts to the pwm rate - if (milliWatts < 10) // no pint driving tip +uint8_t X10WattsToPWM(int32_t milliWatts, uint8_t sample) { + // Scale input milliWatts to the pwm range available + if (milliWatts < 1) return 0; - + // if (milliWatts > (int(systemSettings.pidPowerLimit) * 10)) +// milliWatts = (int(systemSettings.pidPowerLimit) * 10); //Calculate desired milliwatts as a percentage of availableW10 - int32_t pwm = (powerPWM * milliWatts) / availableW10(divisor, sample); + uint32_t pwm = (powerPWM * milliWatts) / availableW10(sample); if (pwm > powerPWM) { pwm = powerPWM; //constrain to max PWM counter, shouldnt be possible, but small cost for safety to avoid wraps - } else if (pwm < 0) { //cannot go negative - pwm = 0; } return pwm; } -int32_t PWMToMilliWatts(uint8_t pwm, uint8_t divisor, uint8_t sample) { - int32_t maxMW = availableW10(divisor, sample); //Get the milliwatts for the max pwm period +int32_t PWMToX10Watts(uint8_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 - int32_t res = (pwm * maxMW) / powerPWM; - if (res < 0) - res = 0; - return res; + return (((uint32_t) pwm) * maxMW) / powerPWM; + }