Startup behaviour fixes (#1306)

* Reduce PPS max to 20V to avoid instability

Some PSU's cant actually run at 21V

* Creating a rough draft of a "pre start check" concept

* Newer alpine

* Cleaning up MHP detection

* Cleanup comments

* PID: Run prestart based on ADC IRQ rather than times

* MHP30: Far better startup for detecting tip gain

* Newer alpine for github CI
This commit is contained in:
Ben V. Brown
2022-06-16 20:21:46 +10:00
committed by GitHub
parent f5cb42c9d7
commit 3bb1b7bc32
9 changed files with 98 additions and 73 deletions

View File

@@ -14,6 +14,8 @@ RUN apk add --no-cache gcc-riscv-none-elf gcc-arm-none-eabi newlib-riscv-none-el
# Install Python3 packages # Install Python3 packages
RUN python3 -m pip install bdflib black RUN python3 -m pip install bdflib black
# Git trust
RUN git config --global --add safe.directory /build/source
COPY . /build/source COPY . /build/source
COPY ./ci /build/ci COPY ./ci /build/ci

View File

@@ -86,6 +86,10 @@ enum StatusLED {
}; };
void setStatusLED(const enum StatusLED state); void setStatusLED(const enum StatusLED state);
// preStartChecks are run until they return 0
// By the PID, after each ADC sample comes in
// For example, on the MHP30 this is used to figure out the resistance of the hotplate
uint8_t preStartChecks();
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -13,13 +13,15 @@
#include <IRQ.h> #include <IRQ.h>
WS2812<GPIOA_BASE, WS2812_Pin, 1> ws2812; WS2812<GPIOA_BASE, WS2812_Pin, 1> ws2812;
volatile uint16_t PWMSafetyTimer = 0; volatile uint16_t PWMSafetyTimer = 0;
volatile uint8_t pendingPWM = 0; volatile uint8_t pendingPWM = 0;
uint16_t totalPWM = 255; uint16_t totalPWM = 255;
const uint16_t powerPWM = 255; const uint16_t powerPWM = 255;
uint16_t tipSenseResistancex10Ohms = 0;
volatile bool tipMeasurementOccuring = false;
history<uint16_t, PID_TIM_HZ> rawTempFilter = {{0}, 0, 0};
history<uint16_t, PID_TIM_HZ> rawTempFilter = {{0}, 0, 0}; void resetWatchdog() { HAL_IWDG_Refresh(&hiwdg); }
void resetWatchdog() { HAL_IWDG_Refresh(&hiwdg); }
#ifdef TEMP_NTC #ifdef TEMP_NTC
// Lookup table for the NTC // Lookup table for the NTC
@@ -208,7 +210,8 @@ uint16_t getHandleTemperature(uint8_t sample) {
uint16_t getTipInstantTemperature() { return getADC(2); } uint16_t getTipInstantTemperature() { return getADC(2); }
uint16_t getTipRawTemp(uint8_t refresh) { uint16_t getTipRawTemp(uint8_t refresh) {
if (refresh) { if (refresh && (tipMeasurementOccuring == false)) {
uint16_t lastSample = getTipInstantTemperature(); uint16_t lastSample = getTipInstantTemperature();
rawTempFilter.update(lastSample); rawTempFilter.update(lastSample);
return lastSample; return lastSample;
@@ -348,69 +351,82 @@ void setPlatePullup(bool pullingUp) {
HAL_GPIO_Init(PLATE_SENSOR_PULLUP_GPIO_Port, &GPIO_InitStruct); HAL_GPIO_Init(PLATE_SENSOR_PULLUP_GPIO_Port, &GPIO_InitStruct);
} }
uint16_t tipSenseResistancex10Ohms = 0; void performTipMeasurementStep(bool start) {
bool isTipDisconnected() { static uint16_t adcReadingPD1Set = 0;
static bool lastTipDisconnectedState = true; static TickType_t lastMeas = 0;
static uint16_t adcReadingPD1Set = 0; // Inter state that performs the steps to measure the resistor on the tip
static TickType_t lastMeas = 0; // Return 1 if a measurement is ongoing
// We want to perform our startup measurements of the tip resistance until we detect one fitted
// Step 1; if not setup, we turn on pullup and then wait
if (tipMeasurementOccuring == false && (start || tipSenseResistancex10Ohms == 0 || lastMeas == 0)) {
tipMeasurementOccuring = true;
tipSenseResistancex10Ohms = 0;
lastMeas = xTaskGetTickCount();
adcReadingPD1Set = 0;
setPlatePullup(true);
return;
}
// Wait 100ms for settle time
if ((xTaskGetTickCount() - lastMeas) < (TICKS_100MS)) {
return;
}
lastMeas = xTaskGetTickCount();
// We are sensing the resistance
if (adcReadingPD1Set == 0) {
// We will record the reading for PD1 being set
adcReadingPD1Set = getADC(3);
setPlatePullup(false);
return;
}
// Taking reading two
uint16_t adcReadingPD1Cleared = getADC(3);
uint32_t a = ((int)adcReadingPD1Set - (int)adcReadingPD1Cleared);
a *= 10000;
uint32_t b = ((int)adcReadingPD1Cleared + (32768 - (int)adcReadingPD1Set));
if (b) {
tipSenseResistancex10Ohms = a / b;
} else {
tipSenseResistancex10Ohms = adcReadingPD1Set = lastMeas = 0;
}
if (tipSenseResistancex10Ohms > 1100 || tipSenseResistancex10Ohms < 900) {
tipSenseResistancex10Ohms = 0; // out of range
adcReadingPD1Set = 0;
lastMeas = 0;
return;
}
tipMeasurementOccuring = false;
}
bool isTipDisconnected() {
static bool lastDisconnectedState = false;
// For the MHP30 we want to include a little extra logic in here // For the MHP30 we want to include a little extra logic in here
// As when the tip is first connected we want to measure the ~100 ohm resistor on the base of the tip // As when the tip is first connected we want to measure the ~100 ohm resistor on the base of the tip
// And likewise if its removed we want to clear that measurement // And likewise if its removed we want to clear that measurement
/* /*
* plate_sensor_res = ((adc5_value_PD1_set - adc5_value_PD1_cleared) / (adc5_value_PD1_cleared + 4096 - adc5_value_PD1_set)) * 1000.0; * plate_sensor_res = ((adc5_value_PD1_set - adc5_value_PD1_cleared) / (adc5_value_PD1_cleared + 4096 - adc5_value_PD1_set)) * 1000.0;
* */ * */
if (tipMeasurementOccuring) {
bool tipDisconnected = getADC(2) > (4090 * 8); performTipMeasurementStep(false);
// We have to handle here that this ^ will trip while measuring the gain resistor return true; // We fake no tip disconnection during the measurement cycle to mask it
if (xTaskGetTickCount() - lastMeas < (TICKS_100MS * 2 + (TICKS_100MS / 2))) {
tipDisconnected = false;
} }
if (tipDisconnected != lastTipDisconnectedState) { // If we are too close to the top, most likely disconnected tip
if (tipDisconnected) { bool tipDisconnected = getTipInstantTemperature() > (4090 * 8);
// Tip is now disconnected if (tipDisconnected == false && lastDisconnectedState == true) {
tipSenseResistancex10Ohms = 0; // zero out the resistance // Tip is now disconnected
adcReadingPD1Set = 0; performTipMeasurementStep(true);
lastMeas = 0;
}
lastTipDisconnectedState = tipDisconnected;
} }
if (!tipDisconnected) { lastDisconnectedState = tipDisconnected;
if (tipSenseResistancex10Ohms == 0) {
if (lastMeas == 0) {
lastMeas = xTaskGetTickCount();
setPlatePullup(true);
} else if (xTaskGetTickCount() - lastMeas > (TICKS_100MS)) {
lastMeas = xTaskGetTickCount();
// We are sensing the resistance
if (adcReadingPD1Set == 0) {
// We will record the reading for PD1 being set
adcReadingPD1Set = getADC(3);
setPlatePullup(false);
} else {
// We have taken reading one
uint16_t adcReadingPD1Cleared = getADC(3);
uint32_t a = ((int)adcReadingPD1Set - (int)adcReadingPD1Cleared);
a *= 10000;
uint32_t b = ((int)adcReadingPD1Cleared + (32768 - (int)adcReadingPD1Set));
if (b) {
tipSenseResistancex10Ohms = a / b;
} else {
tipSenseResistancex10Ohms = adcReadingPD1Set = lastMeas = 0;
}
if (tipSenseResistancex10Ohms > 1100 || tipSenseResistancex10Ohms < 900) {
tipSenseResistancex10Ohms = 0; // out of range
adcReadingPD1Set = 0;
lastMeas = 0;
}
}
}
return true; // we fake tip being disconnected until this is measured
}
}
return tipDisconnected; return tipDisconnected;
} }
uint8_t preStartChecks() {
performTipMeasurementStep(false);
return tipMeasurementOccuring ? 1 : 0;
}
void setBuzzer(bool on) { void setBuzzer(bool on) {
if (on) { if (on) {
htim3.Instance->CCR2 = 128; htim3.Instance->CCR2 = 128;

View File

@@ -10,7 +10,8 @@
#include "configuration.h" #include "configuration.h"
extern uint16_t tipSenseResistancex10Ohms; extern uint16_t tipSenseResistancex10Ohms;
uint32_t TipThermoModel::convertuVToDegC(uint32_t tipuVDelta) { uint32_t TipThermoModel::convertuVToDegC(uint32_t tipuVDelta) {
// For the MHP30, we are mimicing the original code and using the resistor fitted to the base of the heater head, this is measured in the isTipDisconnected() function // For the MHP30, we are mimicing the original code and using the resistor fitted to the base of the heater head,
// this is measured at boot in pid task and in the disconnected tip check if tip is removed
if (tipSenseResistancex10Ohms > 900 && tipSenseResistancex10Ohms <= 1100) { if (tipSenseResistancex10Ohms > 900 && tipSenseResistancex10Ohms <= 1100) {
int32_t a = ((tipSenseResistancex10Ohms / 10) + 300) * (3300000 - tipuVDelta); int32_t a = ((tipSenseResistancex10Ohms / 10) + 300) * (3300000 - tipuVDelta);
int32_t b = a / 1000000; int32_t b = a / 1000000;

View File

@@ -282,4 +282,5 @@ bool isTipDisconnected() {
return tipTemp > tipDisconnectedThres; return tipTemp > tipDisconnectedThres;
} }
void setStatusLED(const enum StatusLED state) {} void setStatusLED(const enum StatusLED state) {}
uint8_t preStartChecks() { return 0; }

View File

@@ -90,3 +90,5 @@ bool isTipDisconnected() {
} }
void setStatusLED(const enum StatusLED state) {} void setStatusLED(const enum StatusLED state) {}
uint8_t preStartChecks() { return 0; }

View File

@@ -124,7 +124,7 @@
#define POWER_LIMIT_STEPS 5 // #define POWER_LIMIT_STEPS 5 //
#define OP_AMP_GAIN_STAGE OP_AMP_GAIN_STAGE_PINECIL // Uses TS100 resistors #define OP_AMP_GAIN_STAGE OP_AMP_GAIN_STAGE_PINECIL // Uses TS100 resistors
#define TEMP_uV_LOOKUP_HAKKO // Use Hakko lookup table #define TEMP_uV_LOOKUP_HAKKO // Use Hakko lookup table
#define USB_PD_VMAX 21 // Maximum voltage for PD to negotiate #define USB_PD_VMAX 20 // Maximum voltage for PD to negotiate
#define PID_TIM_HZ (8) // Tick rate of the PID loop #define PID_TIM_HZ (8) // Tick rate of the PID loop
#define MAX_TEMP_C 450 // Max soldering temp selectable °C #define MAX_TEMP_C 450 // Max soldering temp selectable °C
#define MAX_TEMP_F 850 // Max soldering temp selectable °F #define MAX_TEMP_F 850 // Max soldering temp selectable °F

View File

@@ -172,7 +172,7 @@ static void gui_drawBatteryIcon() {
} }
static void gui_solderingTempAdjust() { static void gui_solderingTempAdjust() {
uint32_t lastChange = xTaskGetTickCount(); uint32_t lastChange = xTaskGetTickCount();
currentTempTargetDegC = 0; currentTempTargetDegC = 0; // Turn off header while adjusting temp
uint32_t autoRepeatTimer = 0; uint32_t autoRepeatTimer = 0;
uint8_t autoRepeatAcceleration = 0; uint8_t autoRepeatAcceleration = 0;
bool waitForRelease = false; bool waitForRelease = false;
@@ -511,12 +511,8 @@ static void gui_solderingMode(uint8_t jumpToSleep) {
boostModeOn = false; boostModeOn = false;
break; break;
case BUTTON_BOTH: case BUTTON_BOTH:
// exit
return;
break;
case BUTTON_B_LONG: case BUTTON_B_LONG:
return; // exit on back long hold return; // exit on back long hold
break;
case BUTTON_F_LONG: case BUTTON_F_LONG:
// if boost mode is enabled turn it on // if boost mode is enabled turn it on
if (getSettingValue(SettingsOptions::BoostTemp)) if (getSettingValue(SettingsOptions::BoostTemp))
@@ -665,8 +661,6 @@ static void gui_solderingMode(uint8_t jumpToSleep) {
// If we have tripped thermal runaway, turn off heater and show warning // If we have tripped thermal runaway, turn off heater and show warning
if (heaterThermalRunaway) { if (heaterThermalRunaway) {
currentTempTargetDegC = 0; // heater control off currentTempTargetDegC = 0; // heater control off
// TODO WARNING
warnUser(translatedString(Tr->WarningThermalRunaway), 10 * TICKS_SECOND); warnUser(translatedString(Tr->WarningThermalRunaway), 10 * TICKS_SECOND);
heaterThermalRunaway = false; heaterThermalRunaway = false;
return; return;

View File

@@ -39,21 +39,26 @@ void startPIDTask(void const *argument __unused) {
pidTaskNotification = xTaskGetCurrentTaskHandle(); pidTaskNotification = xTaskGetCurrentTaskHandle();
uint32_t PIDTempTarget = 0; uint32_t PIDTempTarget = 0;
// Pre-seed the adc filters // Pre-seed the adc filters
for (int i = 0; i < 128; i++) { for (int i = 0; i < 32; i++) {
osDelay(5); ulTaskNotifyTake(pdTRUE, 5);
TipThermoModel::getTipInC(true); TipThermoModel::getTipInC(true);
getInputVoltageX10(getSettingValue(SettingsOptions::VoltageDiv), 1); getInputVoltageX10(getSettingValue(SettingsOptions::VoltageDiv), 1);
} }
while (preStartChecks() != 0) {
ulTaskNotifyTake(pdTRUE, 2000);
}
int32_t x10WattsOut = 0; int32_t x10WattsOut = 0;
for (;;) { for (;;) {
x10WattsOut = 0; x10WattsOut = 0;
// This is a call to block this thread until the ADC does its samples // This is a call to block this thread until the ADC does its samples
if (ulTaskNotifyTake(pdTRUE, 2000)) { if (ulTaskNotifyTake(pdTRUE, TICKS_SECOND * 2)) {
// Do the reading here to keep the temp calculations churning along // Do the reading here to keep the temp calculations churning along
uint32_t currentTipTempInC = TipThermoModel::getTipInC(true); uint32_t currentTipTempInC = TipThermoModel::getTipInC(true);
PIDTempTarget = currentTempTargetDegC; PIDTempTarget = currentTempTargetDegC;
if (PIDTempTarget) { if (PIDTempTarget > 0) {
// Cap the max set point to 450C // Cap the max set point to 450C
if (PIDTempTarget > (450)) { if (PIDTempTarget > (450)) {
// Maximum allowed output // Maximum allowed output