aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorBen V. Brown <[email protected]>2019-07-13 22:54:07 +1000
committerBen V. Brown <[email protected]>2019-07-13 22:54:07 +1000
commitc5409f4f1b62e64426c06a6017db9ef6ca3bdccb (patch)
tree5fb24e53fffd4e64de0ca1e06ac63365af4961f1
parent74b225ceaabfba9368a82e34b406f33dde0ae18d (diff)
downloadIronOS-c5409f4f1b62e64426c06a6017db9ef6ca3bdccb.tar.gz
IronOS-c5409f4f1b62e64426c06a6017db9ef6ca3bdccb.zip
Ts80 Tuned a bit better, Ts100 WiP
-rw-r--r--workspace/TS100/inc/hardware.h2
-rw-r--r--workspace/TS100/inc/power.hpp15
-rw-r--r--workspace/TS100/src/Setup.c26
-rw-r--r--workspace/TS100/src/hardware.cpp (renamed from workspace/TS100/src/hardware.c)49
-rw-r--r--workspace/TS100/src/main.cpp129
-rw-r--r--workspace/TS100/src/power.cpp78
-rw-r--r--workspace/TS100A/.cproject4
-rw-r--r--workspace/TS100A/.project4
8 files changed, 165 insertions, 142 deletions
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 <history.hpp>
-
+#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<uint32_t, oscillationPeriod> 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
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<uint16_t, PID_TIM_HZ*4> 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<int32_t> tempError = { { 0 }, 0, 0 };
+ // Tip temp reading filter
+ history<int32_t, PID_TIM_HZ / 4> 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 <Settings.h>
#include <hardware.h>
-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
-history<uint32_t, oscillationPeriod> milliWattHistory = { { 0 }, 0, 0 };
+// 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.
-void setupPower(uint8_t res) {
- tipResistance = res;
-}
+#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<uint32_t, oscillationPeriod> milliWattHistory = { { 0 }, 0, 0 };
-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.
+ // 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;
+ //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
+
+ // 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 == 0)
+ if (milliWatts < 10) // no pint driving tip
return 0;
- int32_t v = getInputVoltageX10(divisor, sample); // 100 = 10v
- int32_t availableMilliWatts = v * v / tipResistance;
- //int32_t pwm = ((powerPWM * totalPWM / powerPWM) * milliWatts) / availableMilliWatts;
- int32_t pwm = (totalPWM * milliWatts) / availableMilliWatts;
+ //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 @@
<tool command="arm-atollic-eabi-gcc -c" commandLinePattern="${COMMAND} ${INPUTS} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT}" errorParsers="org.eclipse.cdt.core.GCCErrorParser" id="com.atollic.truestudio.exe.release.toolchain.gcc.45651038" name="C Compiler" superClass="com.atollic.truestudio.exe.release.toolchain.gcc">
<option id="com.atollic.truestudio.gcc.symbols.defined.1383071182" name="Defined symbols" superClass="com.atollic.truestudio.gcc.symbols.defined" useByScannerDiscovery="false" valueType="definedSymbols">
<listOptionValue builtIn="false" value="STM32F103T8Ux"/>
- <listOptionValue builtIn="false" value="MODEL_TS80"/>
+ <listOptionValue builtIn="false" value="MODEL_TS100"/>
<listOptionValue builtIn="false" value="STM32F1"/>
<listOptionValue builtIn="false" value="STM32"/>
<listOptionValue builtIn="false" value="USE_HAL_DRIVER"/>
@@ -96,7 +96,7 @@
<tool command="arm-atollic-eabi-g++ -c" commandLinePattern="${COMMAND} ${INPUTS} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT}" errorParsers="org.eclipse.cdt.core.GCCErrorParser" id="com.atollic.truestudio.exe.release.toolchain.gpp.93636755" name="C++ Compiler" superClass="com.atollic.truestudio.exe.release.toolchain.gpp">
<option id="com.atollic.truestudio.gpp.symbols.defined.552082963" name="Defined symbols" superClass="com.atollic.truestudio.gpp.symbols.defined" useByScannerDiscovery="false" valueType="definedSymbols">
<listOptionValue builtIn="false" value="STM32F103T8Ux"/>
- <listOptionValue builtIn="false" value="MODEL_TS80"/>
+ <listOptionValue builtIn="false" value="MODEL_TS100"/>
<listOptionValue builtIn="false" value="STM32F1"/>
<listOptionValue builtIn="false" value="STM32"/>
<listOptionValue builtIn="false" value="USE_HAL_DRIVER"/>
diff --git a/workspace/TS100A/.project b/workspace/TS100A/.project
index 1719ed01..daf70f52 100644
--- a/workspace/TS100A/.project
+++ b/workspace/TS100A/.project
@@ -221,9 +221,9 @@
<locationURI>PARENT-1-PROJECT_LOC/TS100/src/gui.cpp</locationURI>
</link>
<link>
- <name>src/hardware.c</name>
+ <name>src/hardware.cpp</name>
<type>1</type>
- <locationURI>PARENT-1-PROJECT_LOC/TS100/src/hardware.c</locationURI>
+ <locationURI>PARENT-1-PROJECT_LOC/TS100/src/hardware.cpp</locationURI>
</link>
<link>
<name>src/main.cpp</name>