diff --git a/source/Core/BSP/BSP_Power.h b/source/Core/BSP/BSP_Power.h index a924a1ec..02ce36f7 100644 --- a/source/Core/BSP/BSP_Power.h +++ b/source/Core/BSP/BSP_Power.h @@ -16,6 +16,13 @@ extern "C" { // Can be used to check any details for the power system void power_check(); +// Returns the tip resistance in x10 ohms, so 7.5 = 75; 14=140 etc +uint8_t getTipResitanceX10(); + +// Called when device is idle to allow measuring tip resistance +void startMeasureTipResistance(); +void FinishMeasureTipResistance(); + #ifdef __cplusplus } #endif diff --git a/source/Core/BSP/Magic/BSP.cpp b/source/Core/BSP/Magic/BSP.cpp index 4325569d..f4bc5772 100644 --- a/source/Core/BSP/Magic/BSP.cpp +++ b/source/Core/BSP/Magic/BSP.cpp @@ -223,3 +223,47 @@ bool isTipDisconnected() { void setStatusLED(const enum StatusLED state) { // Dont have one } + +uint8_t lastTipResistance = 75; // default safe +uint32_t lastTipReadinguV = 0; +uint8_t getTipResitanceX10() { + // Return tip resistance in x10 ohms + // We can measure this using the op-amp + return lastTipResistance; +} +void startMeasureTipResistance() { + + if (isTipDisconnected()) { + return; + } + + // We want to calculate lastTipResistance + // If tip is connected, and the tip is cold and the tip is not being heated + // We can use the GPIO to inject a small current into the tip and measure this + // The gpio is 5.1k -> diode -> tip -> gnd + // Which is around 0.65mA this will induce: + // 6 ohm tip -> 3.9mV (Real world ~= 3320) + // 8 ohm tip -> 5.2mV (Real world ~= 4500) + // Which is definitely measureable + // Taking shortcuts here as we know we only really have to pick apart 6 and 8 ohm tips + // These are reported as 60 and 75 respectively + lastTipReadinguV = TipThermoModel::convertTipRawADCTouV(getTipRawTemp(0)); + gpio_write(TIP_RESISTANCE_SENSE, 1); + // Wait for next ADC measurement +} + +void FinishMeasureTipResistance() { + gpio_write(TIP_RESISTANCE_SENSE, 0); + if (isTipDisconnected()) { + return; + } + // read the tip uV with the current source on + uint32_t newReading = (TipThermoModel::convertTipRawADCTouV(getTipRawTemp(0))); + if (newReading < lastTipReadinguV) { + return; + } + // newReading -= lastTipReadinguV; + MSG("Tip Delta %lu, %lu %lu \r\n", newReading - lastTipReadinguV, newReading, lastTipReadinguV); + newReading -= lastTipReadinguV; + lastTipReadinguV = newReading; +} \ No newline at end of file diff --git a/source/Core/BSP/Magic/IRQ.cpp b/source/Core/BSP/Magic/IRQ.cpp index d7b6dcef..9e2eefe6 100644 --- a/source/Core/BSP/Magic/IRQ.cpp +++ b/source/Core/BSP/Magic/IRQ.cpp @@ -23,6 +23,7 @@ history ADC_Vin; history ADC_Temp; history ADC_Tip; + void adc_fifo_irq(void) { if (ADC_GetIntStatus(ADC_INT_FIFO_READY) == SET) { bool wakePID = false; diff --git a/source/Core/BSP/Magic/Setup.cpp b/source/Core/BSP/Magic/Setup.cpp index c843f669..3753dd6f 100644 --- a/source/Core/BSP/Magic/Setup.cpp +++ b/source/Core/BSP/Magic/Setup.cpp @@ -29,8 +29,9 @@ void hardware_init() { gpio_set_mode(TMP36_INPUT_Pin, GPIO_INPUT_MODE); gpio_set_mode(TIP_TEMP_Pin, GPIO_INPUT_MODE); gpio_set_mode(VIN_Pin, GPIO_INPUT_MODE); - gpio_set_mode(TIP_RESISTANCE_SENSE, GPIO_INPUT_MODE); - + gpio_set_mode(TIP_RESISTANCE_SENSE, GPIO_OUTPUT_PP_MODE); + gpio_write(TIP_RESISTANCE_SENSE, 0); + MSG("Magic Starting\r\n"); setup_timer_scheduler(); setup_adc(); setup_pwm(); diff --git a/source/Core/BSP/Magic/configuration.h b/source/Core/BSP/Magic/configuration.h index c98a566a..5684486f 100644 --- a/source/Core/BSP/Magic/configuration.h +++ b/source/Core/BSP/Magic/configuration.h @@ -116,17 +116,17 @@ #ifdef MODEL_Magic #define ADC_VDD_MV 3200 // ADC max reading millivolts #define SOLDERING_TEMP 320 // Default soldering temp is 320.0 °C -#define VOLTAGE_DIV 600 // 290 - Default divider from schematic -#define CALIBRATION_OFFSET 900 // 900 - Default adc offset in uV +#define VOLTAGE_DIV 600 // 600 - Default divider from schematic +#define CALIBRATION_OFFSET 800 // 900 - Default adc offset in uV #define MIN_CALIBRATION_OFFSET 100 // Min value for calibration -#define PID_POWER_LIMIT 70 // Sets the max pwm power limit +#define PID_POWER_LIMIT 220 // Sets the max pwm power limit #define POWER_LIMIT 0 // 0 watts default limit -#define MAX_POWER_LIMIT 70 // +#define MAX_POWER_LIMIT 220 // #define POWER_LIMIT_STEPS 5 // #define OP_AMP_GAIN_STAGE OP_AMP_GAIN_STAGE_PINECIL // Uses TS100 resistors #define TEMP_uV_LOOKUP_HAKKO // Use Hakko lookup table #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 (10) // Tick rate of the PID loop #define MAX_TEMP_C 450 // Max soldering temp selectable °C #define MAX_TEMP_F 850 // Max soldering temp selectable °F #define MIN_TEMP_C 10 // Min soldering temp selectable °C diff --git a/source/Core/Drivers/USBPD.cpp b/source/Core/Drivers/USBPD.cpp index d2d37777..98e99b7e 100644 --- a/source/Core/Drivers/USBPD.cpp +++ b/source/Core/Drivers/USBPD.cpp @@ -13,9 +13,6 @@ #ifndef USB_PD_VMAX #error Max PD Voltage must be defined #endif -#ifndef TIP_RESISTANCE -#error Tip resistance must be defined -#endif void ms_delay(uint32_t delayms) { // Convert ms -> ticks @@ -98,10 +95,10 @@ bool pdbs_dpm_evaluate_capability(const pd_msg *capabilities, pd_msg *request) { #ifdef MODEL_HAS_DCDC // If this device has step down DC/DC inductor to smooth out current spikes // We can instead ignore resistance and go for max voltage we can accept - min_resistance_ohmsx10 = TIP_RESISTANCE; + min_resistance_ohmsx10 = getTipResitanceX10(); #endif // Fudge of 0.5 ohms to round up a little to account for other losses - if (min_resistance_ohmsx10 <= (TIP_RESISTANCE + 5)) { + if (min_resistance_ohmsx10 <= (getTipResitanceX10() + 5)) { // This is a valid power source we can select as if ((voltage_mv > bestIndexVoltage) || bestIndex == 0xFF) { // Higher voltage and valid, select this instead @@ -124,7 +121,7 @@ bool pdbs_dpm_evaluate_capability(const pd_msg *capabilities, pd_msg *request) { // Using the current and tip resistance, calculate the ideal max voltage // if this is range, then we will work with this voltage // if this is not in range; then max_voltage can be safely selected - int ideal_voltage_mv = (TIP_RESISTANCE * max_current); + int ideal_voltage_mv = (getTipResitanceX10() * max_current); if (ideal_voltage_mv > max_voltage) { ideal_voltage_mv = max_voltage; // constrain } @@ -186,7 +183,7 @@ void pdbs_dpm_get_sink_capability(pd_msg *cap, const bool isPD3) { // if (requested_voltage_mv != 5000) { // voltage = requested_voltage_mv; // } - // uint16_t current = (voltage) / TIP_RESISTANCE; // In centi-amps + // uint16_t current = (voltage) / getTipResitanceX10(); // In centi-amps // /* Add a PDO for the desired power. */ // cap->obj[numobj++] = PD_PDO_TYPE_FIXED | PD_PDO_SNK_FIXED_VOLTAGE_SET(PD_MV2PDV(voltage)) | PD_PDO_SNK_FIXED_CURRENT_SET(current); diff --git a/source/Core/Src/power.cpp b/source/Core/Src/power.cpp index e7037882..a394d951 100644 --- a/source/Core/Src/power.cpp +++ b/source/Core/Src/power.cpp @@ -49,7 +49,7 @@ uint32_t availableW10(uint8_t sample) { // R = R*10 // P therefore is in V^2*100/R*10 = W*10. uint32_t v = getInputVoltageX10(getSettingValue(SettingsOptions::VoltageDiv), sample); // 100 = 10v - uint32_t availableWattsX10 = (v * v) / TIP_RESISTANCE; + uint32_t availableWattsX10 = (v * v) / getTipResitanceX10(); // 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 diff --git a/source/Core/Threads/PIDThread.cpp b/source/Core/Threads/PIDThread.cpp index 65cce4db..b061d2d6 100644 --- a/source/Core/Threads/PIDThread.cpp +++ b/source/Core/Threads/PIDThread.cpp @@ -45,12 +45,15 @@ void startPIDTask(void const *argument __unused) { TipThermoModel::getTipInC(true); getInputVoltageX10(getSettingValue(SettingsOptions::VoltageDiv), 1); } - int32_t x10WattsOut = 0; - + int32_t x10WattsOut = 0; + bool measuringTipResistance = false; for (;;) { x10WattsOut = 0; // This is a call to block this thread until the ADC does its samples if (ulTaskNotifyTake(pdTRUE, 2000)) { + if (measuringTipResistance) { + FinishMeasureTipResistance(); + } // Do the reading here to keep the temp calculations churning along uint32_t currentTipTempInC = TipThermoModel::getTipInC(true); PIDTempTarget = currentTempTargetDegC; @@ -72,6 +75,11 @@ void startPIDTask(void const *argument __unused) { detectThermalRunaway(currentTipTempInC, 0); } setOutputx10WattsViaFilters(x10WattsOut); + // If the output is off, take tip measurement reading + if (x10WattsOut == 0 && PIDTempTarget == 0) { + startMeasureTipResistance(); + measuringTipResistance = true; + } } else { // ADC interrupt timeout setTipPWM(0, false);