From 3f69dbd5a3644f6cf020810e6f10c433f70c341b Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Wed, 3 Jul 2019 15:32:02 +1000 Subject: [PATCH 1/6] Rework debug menu --- Translation Editor/fontTables.py | 0 Translation Editor/make_translation.py | 27 ++++++++++++++++++++++++++ workspace/TS100/inc/Translation.h | 1 + workspace/TS100/inc/history.hpp | 2 +- workspace/TS100/src/main.cpp | 15 ++------------ 5 files changed, 31 insertions(+), 14 deletions(-) mode change 100644 => 100755 Translation Editor/fontTables.py mode change 100644 => 100755 Translation Editor/make_translation.py diff --git a/Translation Editor/fontTables.py b/Translation Editor/fontTables.py old mode 100644 new mode 100755 diff --git a/Translation Editor/make_translation.py b/Translation Editor/make_translation.py old mode 100644 new mode 100755 index 7ec28c92..07d90c4d --- a/Translation Editor/make_translation.py +++ b/Translation Editor/make_translation.py @@ -115,6 +115,23 @@ def getTipModelEnumTS100(): constants.append("User") return constants +def getDebugMenuHeaders(): + constants = [] + constants.append("DateHere") + constants.append("Heap: ") + constants.append("HWMG: ") + constants.append("HWMP: ") + constants.append("HWMM: ") + constants.append("Time: ") + constants.append("Move: ") + constants.append("RTip: ") + constants.append("CTip: ") + constants.append("Vin: ") + constants.append("THan: ") + constants.append("Model: ") + constants.append("Tres: ") + return constants + def getLetterCounts(defs, lang): textList = [] @@ -160,6 +177,7 @@ def getLetterCounts(defs, lang): constants = getConstants() for x in constants: textList.append(x[1]) + textList.extend(getDebugMenuHeaders()) textList.extend(getTipModelEnumTS100()) textList.extend(getTipModelEnumTS80()) @@ -343,6 +361,15 @@ def writeLanguage(languageCode, defs, f): f.write(to_unicode("};\n\n")) + # -- Debugging Menu + + + + f.write(to_unicode("const char* DebugMenu[] = {\n")) + for c in getDebugMenuHeaders(): + f.write(to_unicode("\t \"" + convStr(symbolConversionTable, c) + "\","+ "//{} \n".format(c))) + f.write(to_unicode("};\n\n")) + # ----- Menu Options # Menu type diff --git a/workspace/TS100/inc/Translation.h b/workspace/TS100/inc/Translation.h index ec1f6b83..c6d015b9 100644 --- a/workspace/TS100/inc/Translation.h +++ b/workspace/TS100/inc/Translation.h @@ -67,4 +67,5 @@ extern const char* SymbolDC; extern const char* SymbolCellCount; extern const char* SymbolVersionNumber; +extern const char* DebugMenu[]; #endif /* TRANSLATION_H_ */ diff --git a/workspace/TS100/inc/history.hpp b/workspace/TS100/inc/history.hpp index 856f6536..01f2a93d 100644 --- a/workspace/TS100/inc/history.hpp +++ b/workspace/TS100/inc/history.hpp @@ -11,7 +11,7 @@ #include // max size = 127 -template +template struct history { static const uint8_t size = SIZE; T buf[size]; diff --git a/workspace/TS100/src/main.cpp b/workspace/TS100/src/main.cpp index 076965b7..db45a89b 100644 --- a/workspace/TS100/src/main.cpp +++ b/workspace/TS100/src/main.cpp @@ -674,17 +674,6 @@ static void gui_solderingMode(uint8_t jumpToSleep) { } } -static const char *HEADERS[] = { -__DATE__, "Heap: ", "HWMG: ", "HWMP: ", "HWMM: ", "Time: ", "Move: ", "RTip: ", - "CTip: ", "Vin :", "THan: ", "Model: ", -#ifdef MODEL_TS80 - "QCV: ", "Tr ", -#else - "Tm ", "Ralim-", - -#endif - }; - void showVersion(void) { uint8_t screen = 0; ButtonState b; @@ -698,7 +687,7 @@ void showVersion(void) { OLED::print(SymbolVersionNumber); // Print version number #endif OLED::setCursor(0, 8); // second line - OLED::print(HEADERS[screen]); + OLED::print(DebugMenu[screen]); switch (screen) { case 1: OLED::printNumber(xPortGetFreeHeapSize(), 5); @@ -744,7 +733,7 @@ void showVersion(void) { #ifdef MODEL_TS80 OLED::printNumber(calculateTipR(), 5); #else - OLED::print("Tek.com"); + OLED::printNumber(8500,5)); #endif break; default: From f6affb67ca0c8ce3f2cddf3f1563cff01a008624 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Wed, 3 Jul 2019 15:32:49 +1000 Subject: [PATCH 2/6] Move Movement filter to history template --- workspace/TS100/src/main.cpp | 45 +++++++++++------------------------- 1 file changed, 14 insertions(+), 31 deletions(-) diff --git a/workspace/TS100/src/main.cpp b/workspace/TS100/src/main.cpp index db45a89b..c758cb2d 100644 --- a/workspace/TS100/src/main.cpp +++ b/workspace/TS100/src/main.cpp @@ -1045,12 +1045,11 @@ void startMOVTask(void const *argument __unused) { OLED::setRotation(systemSettings.OrientationMode & 1); lastMovementTime = 0; - int16_t datax[MOVFilter] = { 0 }; - int16_t datay[MOVFilter] = { 0 }; - int16_t dataz[MOVFilter] = { 0 }; - uint8_t currentPointer = 0; - int16_t tx = 0, ty = 0, tz = 0; - int32_t avgx = 0, avgy = 0, avgz = 0; + history datax = { { 0 }, 0, 0 }; + history datay = { { 0 }, 0, 0 }; + history dataz = { { 0 }, 0, 0 }; + + int16_t tempx = 0, tempy = 0, tempz = 0; if (systemSettings.sensitivity > 9) systemSettings.sensitivity = 9; #if ACCELDEBUG @@ -1062,10 +1061,10 @@ void startMOVTask(void const *argument __unused) { threshold -= systemSettings.sensitivity * 200; // 200 is the step size if (PCBVersion == 2) { - LIS2DH12::getAxisReadings(&tx, &ty, &tz); + LIS2DH12::getAxisReadings(&tempx, &tempy, &tempz); rotation = LIS2DH12::getOrientation(); } else if (PCBVersion == 1) { - MMA8652FC::getAxisReadings(&tx, &ty, &tz); + MMA8652FC::getAxisReadings(&tempx, &tempy, &tempz); rotation = MMA8652FC::getOrientation(); } if (systemSettings.OrientationMode == 2) { @@ -1073,37 +1072,21 @@ void startMOVTask(void const *argument __unused) { OLED::setRotation(rotation == ORIENTATION_LEFT_HAND); // link the data through } } - datax[currentPointer] = (int32_t) tx; - datay[currentPointer] = (int32_t) ty; - dataz[currentPointer] = (int32_t) tz; - currentPointer = (currentPointer + 1) % MOVFilter; - avgx = avgy = avgz = 0; - // calculate averages - for (uint8_t i = 0; i < MOVFilter; i++) { - avgx += datax[i]; - avgy += datay[i]; - avgz += dataz[i]; - } - avgx /= MOVFilter; - avgy /= MOVFilter; - avgz /= MOVFilter; + + datax.update(tempx); + datay.update(tempx); + dataz.update(tempx); // Sum the deltas - int32_t error = (abs(avgx - tx) + abs(avgy - ty) + abs(avgz - tz)); + int32_t error = (abs(datax.average() - tempx) + + abs(datay.average() - tempy) + abs(dataz.average() - tempz)); // So now we have averages, we want to look if these are different by more // than the threshold - - // If error has occurred then we update the tick timer + // If this has occurred then we update the tick timer if (error > threshold) { lastMovementTime = xTaskGetTickCount(); } - osDelay(100); // Slow down update rate -#ifdef MODEL_TS80 - if (currentlyActiveTemperatureTarget) { - seekQC(idealQCVoltage, systemSettings.voltageDiv); // Run the QC seek again to try and compensate for cable V drop - } -#endif } } From 74b225ceaabfba9368a82e34b406f33dde0ae18d Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Wed, 3 Jul 2019 15:33:00 +1000 Subject: [PATCH 3/6] Cleanup IRQ's --- workspace/TS100/src/main.cpp | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/workspace/TS100/src/main.cpp b/workspace/TS100/src/main.cpp index c758cb2d..43cf1128 100644 --- a/workspace/TS100/src/main.cpp +++ b/workspace/TS100/src/main.cpp @@ -1128,14 +1128,13 @@ bool showBootLogoIfavailable() { * runs again */ void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef *hadc) { + (void) hadc; BaseType_t xHigherPriorityTaskWoken = pdFALSE; - if (hadc == &hadc1) { - if (pidTaskNotification) { - vTaskNotifyGiveFromISR(pidTaskNotification, - &xHigherPriorityTaskWoken); - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); - } + if (pidTaskNotification) { + vTaskNotifyGiveFromISR(pidTaskNotification, &xHigherPriorityTaskWoken); + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } + } void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c __unused) { FRToSI2C::CpltCallback(); @@ -1147,13 +1146,9 @@ void HAL_I2C_MemTxCpltCallback(I2C_HandleTypeDef *hi2c __unused) { FRToSI2C::CpltCallback(); } void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c __unused) { - asm("bkpt"); - FRToSI2C::CpltCallback(); } void HAL_I2C_AbortCpltCallback(I2C_HandleTypeDef *hi2c __unused) { - //asm("bkpt"); - FRToSI2C::CpltCallback(); } void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c __unused) { @@ -1161,7 +1156,6 @@ void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c __unused) { } void vApplicationStackOverflowHook(xTaskHandle *pxTask __unused, signed portCHAR *pcTaskName __unused) { - asm("bkpt"); // We dont have a good way to handle a stack overflow at this point in time NVIC_SystemReset(); } From c5409f4f1b62e64426c06a6017db9ef6ca3bdccb Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sat, 13 Jul 2019 22:54:07 +1000 Subject: [PATCH 4/6] Ts80 Tuned a bit better, Ts100 WiP --- workspace/TS100/inc/hardware.h | 2 +- workspace/TS100/inc/power.hpp | 15 +- workspace/TS100/src/Setup.c | 26 ++-- .../TS100/src/{hardware.c => hardware.cpp} | 49 ++++--- workspace/TS100/src/main.cpp | 129 ++++++++---------- workspace/TS100/src/power.cpp | 80 +++++++---- workspace/TS100A/.cproject | 4 +- workspace/TS100A/.project | 4 +- 8 files changed, 166 insertions(+), 143 deletions(-) rename workspace/TS100/src/{hardware.c => hardware.cpp} (91%) diff --git a/workspace/TS100/inc/hardware.h b/workspace/TS100/inc/hardware.h index ecc142f2..561f1229 100644 --- a/workspace/TS100/inc/hardware.h +++ b/workspace/TS100/inc/hardware.h @@ -16,7 +16,7 @@ extern "C" { enum Orientation { ORIENTATION_LEFT_HAND = 0, ORIENTATION_RIGHT_HAND = 1, ORIENTATION_FLAT = 3 }; - +#define PID_TIM_HZ (16) #if defined(MODEL_TS100) + defined(MODEL_TS80) > 1 #error "Multiple models defined!" #elif defined(MODEL_TS100) + defined(MODEL_TS80) == 0 diff --git a/workspace/TS100/inc/power.hpp b/workspace/TS100/inc/power.hpp index c08e4cbc..87df47f2 100644 --- a/workspace/TS100/inc/power.hpp +++ b/workspace/TS100/inc/power.hpp @@ -2,23 +2,22 @@ * Power.hpp * * Created on: 28 Oct, 2018 - * Authors: Ben V. Brown, David Hilton + * Authors: Ben V. Brown, David Hilton (David's Idea) */ #include "stdint.h" #include - +#include "hardware.h" #ifndef POWER_HPP_ #define POWER_HPP_ -const uint8_t hz = 32;//PID loop rate -const uint8_t oscillationPeriod = 3.5 * hz; // dampening look back tuning +const uint8_t oscillationPeriod = 4 * PID_TIM_HZ; // I term look back value extern history milliWattHistory; -void setupPower(uint8_t resistance); -int32_t tempToMilliWatts(int32_t rawTemp, uint16_t mass, uint8_t rawC); +int32_t tempToMilliWatts(int32_t rawTemp, uint8_t rawC); 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 milliWattsToPWM(int32_t milliWatts, uint8_t divisor, + uint8_t sample = 0); +int32_t PWMToMilliWatts(uint8_t pwm, uint8_t divisor, uint8_t sample = 0); #endif /* POWER_HPP_ */ diff --git a/workspace/TS100/src/Setup.c b/workspace/TS100/src/Setup.c index 8108d1a5..50f742a3 100644 --- a/workspace/TS100/src/Setup.c +++ b/workspace/TS100/src/Setup.c @@ -262,9 +262,9 @@ static void MX_TIM3_Init(void) { htim3.Instance = TIM3; htim3.Init.Prescaler = 8; htim3.Init.CounterMode = TIM_COUNTERMODE_UP; - htim3.Init.Period = 100; // 10 Khz PWM freq + htim3.Init.Period = 400; // 5 Khz PWM freq htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV4; // 4mhz before div - htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; + htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;//Preload the ARR register (though we dont use this) HAL_TIM_Base_Init(&htim3); sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; @@ -279,7 +279,7 @@ static void MX_TIM3_Init(void) { HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig); sConfigOC.OCMode = TIM_OCMODE_PWM1; - sConfigOC.Pulse = 50; + sConfigOC.Pulse = 80;//80% duty cycle, that is AC coupled through the cap sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_ENABLE; HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, PWM_Out_CHANNEL); @@ -291,10 +291,10 @@ static void MX_TIM3_Init(void) { */ GPIO_InitStruct.Pin = PWM_Out_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;//We would like sharp rising edges HAL_GPIO_Init(PWM_Out_GPIO_Port, &GPIO_InitStruct); #ifdef MODEL_TS100 - // Remap TIM3_CH1 to be on pB4 + // Remap TIM3_CH1 to be on PB4 __HAL_AFIO_REMAP_TIM3_PARTIAL(); #else // No re-map required @@ -314,14 +314,17 @@ static void MX_TIM2_Init(void) { // Timer 2 is fairly slow as its being used to run the PWM and trigger the ADC // in the PWM off time. htim2.Instance = TIM2; - htim2.Init.Prescaler = 785; // pwm out is 10k from tim3, we want to run our PWM at around 10hz or slower on the output stage + htim2.Init.Prescaler = 2000; //1mhz tick rate/800 = 1.25 KHz tick rate + + // pwm out is 10k from tim3, we want to run our PWM at around 10hz or slower on the output stage // The input is 1mhz after the div/4, so divide this by 785 to give around 4Hz output change rate //Trade off is the slower the PWM output the slower we can respond and we gain temperature accuracy in settling time, //But it increases the time delay between the heat cycle and the measurement and calculate cycle htim2.Init.CounterMode = TIM_COUNTERMODE_UP; - htim2.Init.Period = 255 + 60; + htim2.Init.Period = 255 + 20; htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV4; // 4mhz before divide htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; + htim2.Init.RepetitionCounter=0; HAL_TIM_Base_Init(&htim2); sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; @@ -335,7 +338,8 @@ static void MX_TIM2_Init(void) { HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig); sConfigOC.OCMode = TIM_OCMODE_PWM1; - sConfigOC.Pulse = 255 + 50; //255 is the largest time period of the drive signal, and the 50 offsets this around 5ms afterwards + sConfigOC.Pulse = 255 + 10; + //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. * Assume ADC samples in 0.5ms @@ -344,11 +348,7 @@ static void MX_TIM2_Init(void) { sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_ENABLE; HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1); - - sConfigOC.OCMode = TIM_OCMODE_PWM1; - sConfigOC.Pulse = 0; - sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; - sConfigOC.OCFastMode = TIM_OCFAST_ENABLE; + sConfigOC.Pulse = 0;//default to entirely off HAL_TIM_OC_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_4); HAL_TIM_Base_Start_IT(&htim2); diff --git a/workspace/TS100/src/hardware.c b/workspace/TS100/src/hardware.cpp similarity index 91% rename from workspace/TS100/src/hardware.c rename to workspace/TS100/src/hardware.cpp index 63fb0703..daf0659e 100644 --- a/workspace/TS100/src/hardware.c +++ b/workspace/TS100/src/hardware.cpp @@ -10,6 +10,7 @@ #include "FreeRTOS.h" #include "stm32f1xx_hal.h" #include "cmsis_os.h" +#include "history.hpp" volatile uint16_t PWMSafetyTimer = 0; volatile int16_t CalibrationTempOffset = 0; uint16_t tipGainCalValue = 0; @@ -68,15 +69,31 @@ uint16_t ftoTipMeasurement(uint16_t temp) { } uint16_t getTipInstantTemperature() { - uint16_t sum; - sum = hadc1.Instance->JDR1; - sum += hadc1.Instance->JDR2; - sum += hadc1.Instance->JDR3; - sum += hadc1.Instance->JDR4; - sum += hadc2.Instance->JDR1; - sum += hadc2.Instance->JDR2; - sum += hadc2.Instance->JDR3; - sum += hadc2.Instance->JDR4; + uint16_t sum = 0; // 12 bit readings * 8 -> 15 bits + uint16_t readings[8]; + //Looking to reject the highest outlier readings. + //As on some hardware these samples can run into the op-amp recovery time + //Once this time is up the signal stabilises quickly, so no need to reject minimums + readings[0] = hadc1.Instance->JDR1; + readings[1] = hadc1.Instance->JDR2; + readings[2] = hadc1.Instance->JDR3; + readings[3] = hadc1.Instance->JDR4; + readings[4] = hadc2.Instance->JDR1; + 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; + } + 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 } /* @@ -117,15 +134,17 @@ uint16_t lookupTipDefaultCalValue(enum TipType tipID) { } #endif } +//2 second filter (ADC is PID_TIM_HZ Hz) +history rawTempFilter = { { 0 }, 0, 0 }; uint16_t getTipRawTemp(uint8_t refresh) { - static uint16_t lastSample = 0; - if (refresh) { - lastSample = getTipInstantTemperature(); + uint16_t lastSample = getTipInstantTemperature(); + rawTempFilter.update(lastSample); + return lastSample; + } else { + return rawTempFilter.average(); } - - return lastSample; } uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample) { @@ -237,8 +256,6 @@ void startQC(uint16_t divisor) { // Pre check that the input could be >5V already, and if so, dont both // negotiating as someone is feeding in hv uint16_t vin = getInputVoltageX10(divisor, 1); - if (vin > 150) - return; // Over voltage if (vin > 100) { QCMode = 1; // ALready at ~12V return; diff --git a/workspace/TS100/src/main.cpp b/workspace/TS100/src/main.cpp index 43cf1128..cc970019 100644 --- a/workspace/TS100/src/main.cpp +++ b/workspace/TS100/src/main.cpp @@ -271,36 +271,36 @@ static void gui_drawBatteryIcon() { // we need to calculate which of the 10 levels they are on uint8_t cellCount = systemSettings.cutoutSetting + 2; uint32_t cellV = getInputVoltageX10(systemSettings.voltageDiv, 0) - / cellCount; + / cellCount; // Should give us approx cell voltage X10 // Range is 42 -> 33 = 9 steps therefore we will use battery 1-10 if (cellV < 33) - cellV = 33; - cellV -= 33;// Should leave us a number of 0-9 + cellV = 33; + cellV -= 33; // Should leave us a number of 0-9 if (cellV > 9) - cellV = 9; + cellV = 9; OLED::drawBattery(cellV + 1); } else - OLED::drawSymbol(15); // Draw the DC Logo + OLED::drawSymbol(15); // Draw the DC Logo #else - // On TS80 we replace this symbol with the voltage we are operating on - // If <9V then show single digit, if not show duals - uint8_t V = getInputVoltageX10(systemSettings.voltageDiv, 0); - if (V % 10 >= 5) - V = V / 10 + 1; // round up - else - V = V / 10; - if (V >= 10) { - int16_t xPos = OLED::getCursorX(); - OLED::setFont(1); - OLED::printNumber(1, 1); - OLED::setCursor(xPos, 8); - OLED::printNumber(V % 10, 1); - OLED::setFont(0); - OLED::setCursor(xPos + 12, 0); // need to reset this as if we drew a wide char - } else { - OLED::printNumber(V, 1); - } + // On TS80 we replace this symbol with the voltage we are operating on + // If <9V then show single digit, if not show duals + uint8_t V = getInputVoltageX10(systemSettings.voltageDiv, 0); + if (V % 10 >= 5) + V = V / 10 + 1;// round up + else + V = V / 10; + if (V >= 10) { + int16_t xPos = OLED::getCursorX(); + OLED::setFont(1); + OLED::printNumber(1, 1); + OLED::setCursor(xPos, 8); + OLED::printNumber(V % 10, 1); + OLED::setFont(0); + OLED::setCursor(xPos + 12, 0); // need to reset this as if we drew a wide char + } else { + OLED::printNumber(V, 1); + } #endif } static void gui_solderingTempAdjust() { @@ -372,7 +372,7 @@ static void gui_solderingTempAdjust() { #ifdef MODEL_TS80 if (!OLED::getRotation()) #else - if (OLED::getRotation()) + if (OLED::getRotation()) #endif OLED::print(SymbolMinus); else @@ -388,7 +388,7 @@ static void gui_solderingTempAdjust() { #ifdef MODEL_TS80 if (!OLED::getRotation()) #else - if (OLED::getRotation()) + if (OLED::getRotation()) #endif OLED::print(SymbolPlus); else @@ -415,7 +415,7 @@ static int gui_SolderingSleepingMode() { || (xTaskGetTickCount() - lastButtonTime < 100)) return 0; // user moved or pressed a button, go back to soldering #ifdef MODEL_TS100 - if (checkVoltageForExit()) + if (checkVoltageForExit()) return 1; // return non-zero on error #endif if (systemSettings.temperatureInF) { @@ -682,9 +682,9 @@ void showVersion(void) { OLED::setCursor(0, 0); // Position the cursor at the 0,0 (top left) OLED::setFont(1); // small font #ifdef MODEL_TS100 - OLED::print(SymbolVersionNumber); // Print version number -#else OLED::print(SymbolVersionNumber); // Print version number +#else + OLED::print(SymbolVersionNumber); // Print version number #endif OLED::setCursor(0, 8); // second line OLED::print(DebugMenu[screen]); @@ -733,7 +733,7 @@ void showVersion(void) { #ifdef MODEL_TS80 OLED::printNumber(calculateTipR(), 5); #else - OLED::printNumber(8500,5)); + OLED::printNumber(8500, 5); #endif break; default: @@ -871,7 +871,7 @@ void startGUITask(void const *argument __unused) { #ifdef MODEL_TS80 if (!OLED::getRotation()) { #else - if (OLED::getRotation()) { + if (OLED::getRotation()) { #endif OLED::drawArea(12, 0, 84, 16, idleScreenBG); OLED::setCursor(0, 0); @@ -892,7 +892,7 @@ void startGUITask(void const *argument __unused) { #ifdef MODEL_TS80 if (!OLED::getRotation()) { #else - if (OLED::getRotation()) { + if (OLED::getRotation()) { #endif // in right handed mode we want to draw over the first part OLED::fillArea(55, 0, 41, 16, 0); // clear the area for the temp @@ -921,19 +921,16 @@ void startPIDTask(void const *argument __unused) { */ setTipMilliWatts(0); // disable the output driver if the output is set to be off #ifdef MODEL_TS80 - idealQCVoltage = calculateMaxVoltage(systemSettings.cutoutSetting); + idealQCVoltage = calculateMaxVoltage(systemSettings.cutoutSetting); #endif uint8_t rawC = ctoTipMeasurement(101) - ctoTipMeasurement(100); // 1*C change in raw. #ifdef MODEL_TS80 - //Set power management code to the tip resistance in ohms * 10 - setupPower(calculateTipR() / 100); - TickType_t lastPowerPulse = 0; -#else - setupPower(85); - + //Set power management code to the tip resistance in ohms * 10 + TickType_t lastPowerPulse = 0; #endif - history tempError = { { 0 }, 0, 0 }; + // Tip temp reading filter + history tempError = { { 0 }, 0, 0 }; currentlyActiveTemperatureTarget = 0; // Force start with no output (off). If in sleep / soldering this will // be over-ridden rapidly pidTaskNotification = xTaskGetCurrentTaskHandle(); @@ -947,9 +944,9 @@ void startPIDTask(void const *argument __unused) { if (currentlyActiveTemperatureTarget > ctoTipMeasurement(450)) { //Maximum allowed output currentlyActiveTemperatureTarget = ctoTipMeasurement(450); - } else if (currentlyActiveTemperatureTarget > 32400) { - //Cap to max adc reading - currentlyActiveTemperatureTarget = 32400; + } else if (currentlyActiveTemperatureTarget > 32700) { + //Cap to max adc reading (32768) + currentlyActiveTemperatureTarget = 32700; } // As we get close to our target, temp noise causes the system @@ -963,27 +960,15 @@ void startPIDTask(void const *argument __unused) { tempError.update(tError); // Now for the PID! - int32_t milliWattsOut = 0; // P term - total power needed to hit target temp next cycle. // thermal mass = 1690 milliJ/*C for my tip. // = Watts*Seconds to raise Temp from room temp to +100*C, divided by 100*C. - // we divide milliWattsNeeded by 20 to let the I term dominate near the set point. - // 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. -#ifdef MODEL_TS100 - const uint16_t mass = 2020 / 20; // divide here so division is compile-time. -#endif -#ifdef MODEL_TS80 - const uint16_t mass = 2020 / 50; -#endif - - int32_t milliWattsNeeded = tempToMilliWatts(tempError.average(), - mass, rawC); + int32_t milliWattsOut = tempToMilliWatts(tempError.average(), + rawC); // note that milliWattsNeeded is sometimes negative, this counters overshoot // from I term's inertia. - milliWattsOut += milliWattsNeeded; // I term - energy needed to compensate for heat loss. // We track energy put into the system over some window. @@ -991,11 +976,12 @@ void startPIDTask(void const *argument __unused) { // (If it isn't, P will dominate). milliWattsOut += milliWattHistory.average(); - // D term - use sudden temp change to counter fast cooling/heating. - // In practice, this provides an early boost if temp is dropping - // and counters extra power if the iron is no longer losing temp. - // basically: temp - lastTemp - // Unfortunately, our temp signal is too noisy to really help. + // Not Used: + // D term - use sudden temp change to counter fast cooling/heating. + // In practice, this provides an early boost if temp is dropping + // and counters extra power if the iron is no longer losing temp. + // basically: temp - lastTemp + // Unfortunately, our temp signal is too noisy to really help. setTipMilliWatts(milliWattsOut); } else { @@ -1005,9 +991,10 @@ 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(5000); // typically its around 5W to hold the current temp, so this wont raise temp much - } else + setTipMilliWatts(2000);// typically its around 5W to hold the current temp, so this wont raise temp much + } else { setTipMilliWatts(0); + } //Then wait until the next 0.5 seconds if (xTaskGetTickCount() - lastPowerPulse > 50) { lastPowerPulse = xTaskGetTickCount(); @@ -1019,7 +1006,6 @@ void startPIDTask(void const *argument __unused) { HAL_IWDG_Refresh(&hiwdg); } else { - asm("bkpt"); //ADC interrupt timeout setTipMilliWatts(0); @@ -1035,9 +1021,9 @@ void startMOVTask(void const *argument __unused) { #ifdef MODEL_TS80 startQC(systemSettings.voltageDiv); while (pidTaskNotification == 0) - osDelay(30); // To ensure we return after idealQCVoltage/tip resistance + osDelay(30); // To ensure we return after idealQCVoltage/tip resistance - seekQC(idealQCVoltage, systemSettings.voltageDiv); // this will move the QC output to the preferred voltage to start with + seekQC(idealQCVoltage, systemSettings.voltageDiv);// this will move the QC output to the preferred voltage to start with #else osDelay(250); // wait for accelerometer to stabilize @@ -1096,16 +1082,11 @@ void startMOVTask(void const *argument __unused) { bool showBootLogoIfavailable() { // check if the header is there (0xAA,0x55,0xF0,0x0D) // If so display logo - // TODO REDUCE STACK ON THIS ONE, USE DRAWING IN THE READ LOOP - uint16_t temp[98]; - - for (uint8_t i = 0; i < (98); i++) { - temp[i] = *(uint16_t *) (FLASH_LOGOADDR + (i * 2)); - } uint8_t temp8[98 * 2]; for (uint8_t i = 0; i < 98; i++) { - temp8[i * 2] = temp[i] >> 8; - temp8[i * 2 + 1] = temp[i] & 0xFF; + uint16_t temp = *(uint16_t *) (FLASH_LOGOADDR + (i * 2)); + temp8[i * 2] = temp >> 8; + temp8[i * 2 + 1] = temp & 0xFF; } if (temp8[0] != 0xAA) diff --git a/workspace/TS100/src/power.cpp b/workspace/TS100/src/power.cpp index d8bd0118..1182bf45 100644 --- a/workspace/TS100/src/power.cpp +++ b/workspace/TS100/src/power.cpp @@ -9,58 +9,84 @@ #include #include -uint8_t tipResistance = 85; //x10 ohms, 8.5 typical for ts100, 4.5 typical for ts80 const uint16_t powerPWM = 255; -const uint16_t totalPWM = 255 + 60; //htim2.Init.Period, the full PWM cycle +const uint16_t totalPWM = 255 + 30; //htim2.Init.Period, the full PWM cycle +// thermal mass = 1690 milliJ/*C for my tip. +// -> Wattsx10*Seconds to raise Temp from room temp to +100*C, divided by 100*C. +// we divide mass by 20 to let the I term dominate near the set point. +// 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. + +#ifdef MODEL_TS100 +const uint16_t tipMass = 2020 ; // 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 = 1000/4; +const uint8_t tipResistance = 46; //x10 ohms, 8.5 typical for ts100, 4.5 typical for ts80 + +#endif history milliWattHistory = { { 0 }, 0, 0 }; -void setupPower(uint8_t res) { - tipResistance = res; -} - -int32_t tempToMilliWatts(int32_t rawTemp, uint16_t mass, uint8_t rawC) { +int32_t tempToMilliWatts(int32_t rawTemp, uint8_t rawC) { // 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 = mass * rawTemp / rawC; - return milliJoules * hz; + int32_t milliJoules = tipMass * (rawTemp / rawC); + return milliJoules; } void setTipMilliWatts(int32_t mw) { //Enforce Max Watts Limiter # TODO - int32_t output = milliWattsToPWM(mw, systemSettings.voltageDiv / 10,1); + int32_t output = milliWattsToPWM(mw, systemSettings.voltageDiv / 10, 1); setTipPWM(output); - uint16_t actualMilliWatts = PWMToMilliWatts(output, - systemSettings.voltageDiv / 10); + uint32_t actualMilliWatts = PWMToMilliWatts(output, + systemSettings.voltageDiv / 10, 0); milliWattHistory.update(actualMilliWatts); } -uint8_t milliWattsToPWM(int32_t milliWatts, uint8_t divisor, uint8_t sample) { +int32_t availableW10(uint8_t divisor, uint8_t sample) { //P = V^2 / R, v*v = v^2 * 100 // R = R*10 - // P therefore is in V^2*10/R = W*10. - // Scale input milliWatts to the pwm rate - if (milliWatts == 0) - return 0; + // P therefore is in V^2*100/R*10 = W*10. int32_t v = getInputVoltageX10(divisor, sample); // 100 = 10v - int32_t availableMilliWatts = v * v / tipResistance; + int32_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 - //int32_t pwm = ((powerPWM * totalPWM / powerPWM) * milliWatts) / availableMilliWatts; - int32_t pwm = (totalPWM * milliWatts) / availableMilliWatts; + // avMw=(AvMw*powerPWM)/totalPWM. + availableWattsX10 = availableWattsX10 * powerPWM; + availableWattsX10 /= totalPWM; + + //availableMilliWattsX10 is now an accurate representation + 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 + return 0; + + //Calculate desired milliwatts as a percentage of availableW10 + int32_t pwm = (powerPWM * milliWatts) / availableW10(divisor, sample); if (pwm > powerPWM) { - pwm = powerPWM; - } else if (pwm < 0) { + 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) { - int32_t v = getInputVoltageX10(divisor, 0); - return pwm * (v * v / tipResistance) / (powerPWM * totalPWM / powerPWM); +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 + //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; } diff --git a/workspace/TS100A/.cproject b/workspace/TS100A/.cproject index 01717ce0..75bd2169 100644 --- a/workspace/TS100A/.cproject +++ b/workspace/TS100A/.cproject @@ -52,7 +52,7 @@