Merge pull request #1043 from Ralim/ralim/pid
PID complete rewrite with kudos to @sandmanRO and help from @discip
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
#include "BSP_Power.h"
|
#include "BSP_Power.h"
|
||||||
#include "BSP_QC.h"
|
#include "BSP_QC.h"
|
||||||
#include "Defines.h"
|
#include "Defines.h"
|
||||||
#include "Model_Config.h"
|
#include "configuration.h"
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
/*
|
/*
|
||||||
@@ -33,16 +33,13 @@ void BSPInit(void);
|
|||||||
// Called to reset the hardware watchdog unit
|
// Called to reset the hardware watchdog unit
|
||||||
void resetWatchdog();
|
void resetWatchdog();
|
||||||
// Accepts a output level of 0.. to use to control the tip output PWM
|
// Accepts a output level of 0.. to use to control the tip output PWM
|
||||||
void setTipPWM(uint8_t pulse);
|
void setTipPWM(const uint8_t pulse, const bool shouldUseFastModePWM);
|
||||||
// Returns the Handle temp in C, X10
|
// Returns the Handle temp in C, X10
|
||||||
uint16_t getHandleTemperature(uint8_t sample);
|
uint16_t getHandleTemperature(uint8_t sample);
|
||||||
// Returns the Tip temperature ADC reading in raw units
|
// Returns the Tip temperature ADC reading in raw units
|
||||||
uint16_t getTipRawTemp(uint8_t refresh);
|
uint16_t getTipRawTemp(uint8_t refresh);
|
||||||
// Returns the main DC input voltage, using the adjustable divisor + sample flag
|
// Returns the main DC input voltage, using the adjustable divisor + sample flag
|
||||||
uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample);
|
uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample);
|
||||||
// Switch to the most suitable PWM freq given the desired period;
|
|
||||||
// returns true if the switch was performed and totalPWM changed
|
|
||||||
bool tryBetterPWM(uint8_t pwm);
|
|
||||||
|
|
||||||
// Readers for the two buttons
|
// Readers for the two buttons
|
||||||
// !! Returns 1 if held down, 0 if released
|
// !! Returns 1 if held down, 0 if released
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
#include "BSP.h"
|
#include "BSP.h"
|
||||||
#include "I2C_Wrapper.hpp"
|
#include "I2C_Wrapper.hpp"
|
||||||
#include "Model_Config.h"
|
|
||||||
#include "Pins.h"
|
#include "Pins.h"
|
||||||
#include "Setup.h"
|
#include "Setup.h"
|
||||||
#include "TipThermoModel.h"
|
#include "TipThermoModel.h"
|
||||||
@@ -246,11 +245,7 @@ uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample) {
|
|||||||
}
|
}
|
||||||
return sum * 4 / divisor;
|
return sum * 4 / divisor;
|
||||||
}
|
}
|
||||||
bool tryBetterPWM(uint8_t pwm) {
|
void setTipPWM(const uint8_t pulse, const bool shouldUseFastModePWM) {
|
||||||
// We dont need this for the MHP30
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
void setTipPWM(uint8_t pulse) {
|
|
||||||
// We can just set the timer directly
|
// We can just set the timer directly
|
||||||
if (htim3.Instance->PSC > 20) {
|
if (htim3.Instance->PSC > 20) {
|
||||||
htim3.Instance->CCR1 = 0;
|
htim3.Instance->CCR1 = 0;
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
/*
|
|
||||||
* Model_Config.h
|
|
||||||
*
|
|
||||||
* Created on: 25 Jul 2020
|
|
||||||
* Author: Ralim
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BSP_MINIWARE_MODEL_CONFIG_H_
|
|
||||||
#define BSP_MINIWARE_MODEL_CONFIG_H_
|
|
||||||
/*
|
|
||||||
* Lookup for mapping features <-> Models
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef MODEL_MHP30
|
|
||||||
#error "No model defined!"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef MODEL_MHP30
|
|
||||||
#define ACCEL_MSA
|
|
||||||
#define POW_PD
|
|
||||||
#define TEMP_NTC
|
|
||||||
#define I2C_SOFT
|
|
||||||
#define BATTFILTERDEPTH 8
|
|
||||||
#define OLED_I2CBB
|
|
||||||
#define ACCEL_EXITS_ON_MOVEMENT
|
|
||||||
#endif
|
|
||||||
#ifdef ACCEL_EXITS_ON_MOVEMENT
|
|
||||||
#define NO_SLEEP_MODE
|
|
||||||
#endif
|
|
||||||
#endif /* BSP_MINIWARE_MODEL_CONFIG_H_ */
|
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
#ifndef BSP_MINIWARE_PINS_H_
|
#ifndef BSP_MINIWARE_PINS_H_
|
||||||
#define BSP_MINIWARE_PINS_H_
|
#define BSP_MINIWARE_PINS_H_
|
||||||
#include "Model_Config.h"
|
#include "configuration.h"
|
||||||
|
|
||||||
// MHP30 pin map
|
// MHP30 pin map
|
||||||
#define KEY_B_Pin GPIO_PIN_0
|
#define KEY_B_Pin GPIO_PIN_0
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
#include "BSP.h"
|
#include "BSP.h"
|
||||||
#include "BSP_Power.h"
|
#include "BSP_Power.h"
|
||||||
#include "Model_Config.h"
|
|
||||||
#include "Pins.h"
|
#include "Pins.h"
|
||||||
#include "QC3.h"
|
#include "QC3.h"
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
|
#include "configuration.h"
|
||||||
#include "fusb_user.h"
|
#include "fusb_user.h"
|
||||||
#include "fusbpd.h"
|
#include "fusbpd.h"
|
||||||
#include "int_n.h"
|
#include "int_n.h"
|
||||||
|
|||||||
@@ -5,11 +5,12 @@
|
|||||||
* Author: Ralim
|
* Author: Ralim
|
||||||
*/
|
*/
|
||||||
#include "BSP.h"
|
#include "BSP.h"
|
||||||
#include "Model_Config.h"
|
|
||||||
#include "Pins.h"
|
#include "Pins.h"
|
||||||
#include "QC3.h"
|
#include "QC3.h"
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
|
#include "configuration.h"
|
||||||
#include "stm32f1xx_hal.h"
|
#include "stm32f1xx_hal.h"
|
||||||
|
|
||||||
#ifdef POW_QC
|
#ifdef POW_QC
|
||||||
void QC_DPlusZero_Six() {
|
void QC_DPlusZero_Six() {
|
||||||
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_RESET); // pull down D+
|
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_RESET); // pull down D+
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
#ifndef BSP_MINIWARE_SOFTWARE_I2C_H_
|
#ifndef BSP_MINIWARE_SOFTWARE_I2C_H_
|
||||||
#define BSP_MINIWARE_SOFTWARE_I2C_H_
|
#define BSP_MINIWARE_SOFTWARE_I2C_H_
|
||||||
#include "BSP.h"
|
#include "BSP.h"
|
||||||
#include "Model_Config.h"
|
#include "configuration.h"
|
||||||
#include "stm32f1xx_hal.h"
|
#include "stm32f1xx_hal.h"
|
||||||
#ifdef I2C_SOFT
|
#ifdef I2C_SOFT
|
||||||
|
|
||||||
|
|||||||
156
source/Core/BSP/MHP30/configuration.h
Normal file
156
source/Core/BSP/MHP30/configuration.h
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
#ifndef CONFIGURATION_H_
|
||||||
|
#define CONFIGURATION_H_
|
||||||
|
#include "Settings.h"
|
||||||
|
#include "configuration.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
/**
|
||||||
|
* Configuration.h
|
||||||
|
* Define here your default pre settings for TS80 or TS100
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//============================= Default Settings ============================
|
||||||
|
//===========================================================================
|
||||||
|
/**
|
||||||
|
* Default soldering temp is 320.0 C
|
||||||
|
* Temperature the iron sleeps at - default 150.0 C
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define SLEEP_TEMP 150 // Default sleep temperature
|
||||||
|
#define BOOST_TEMP 420 // Default boost temp.
|
||||||
|
#define BOOST_MODE_ENABLED 1 // 0: Disable 1: Enable
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Blink the temperature on the cooling screen when its > 50C
|
||||||
|
*/
|
||||||
|
#define COOLING_TEMP_BLINK 0 // 0: Disable 1: Enable
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How many seconds/minutes we wait until going to sleep/shutdown.
|
||||||
|
* Values -> SLEEP_TIME * 10; i.e. 5*10 = 50 Seconds!
|
||||||
|
*/
|
||||||
|
#define SLEEP_TIME 5 // x10 Seconds
|
||||||
|
#define SHUTDOWN_TIME 10 // Minutes
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto start off for safety.
|
||||||
|
* Pissible values are:
|
||||||
|
* 0 - none
|
||||||
|
* 1 - Soldering Temperature
|
||||||
|
* 2 - Sleep Temperature
|
||||||
|
* 3 - Sleep Off Temperature
|
||||||
|
*/
|
||||||
|
#define AUTO_START_MODE 0 // Default to none
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Locking Mode
|
||||||
|
* When in soldering mode a long press on both keys toggle the lock of the buttons
|
||||||
|
* Possible values are:
|
||||||
|
* 0 - Desactivated
|
||||||
|
* 1 - Lock except boost
|
||||||
|
* 2 - Full lock
|
||||||
|
*/
|
||||||
|
#define LOCKING_MODE 0 // Default to desactivated for safety
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OLED Orientation
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#define ORIENTATION_MODE 0 // 0: Right 1:Left 2:Automatic - Default right
|
||||||
|
#define REVERSE_BUTTON_TEMP_CHANGE 0 // 0:Default 1:Reverse - Reverse the plus and minus button assigment for temperature change
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Temp change settings
|
||||||
|
*/
|
||||||
|
#define TEMP_CHANGE_SHORT_STEP 1 // Default temp change short step +1
|
||||||
|
#define TEMP_CHANGE_LONG_STEP 10 // Default temp change long step +10
|
||||||
|
#define TEMP_CHANGE_SHORT_STEP_MAX 50 // Temp change short step MAX value
|
||||||
|
#define TEMP_CHANGE_LONG_STEP_MAX 90 // Temp change long step MAX value
|
||||||
|
|
||||||
|
/* Power pulse for keeping power banks awake*/
|
||||||
|
#define POWER_PULSE_INCREMENT 1
|
||||||
|
#define POWER_PULSE_MAX 100 // x10 max watts
|
||||||
|
#define POWER_PULSE_WAIT_MAX 9 // 9*2.5s = 22.5 seconds
|
||||||
|
#define POWER_PULSE_DURATION_MAX 9 // 9*250ms = 2.25 seconds
|
||||||
|
|
||||||
|
#ifdef MODEL_TS100
|
||||||
|
#define POWER_PULSE_DEFAULT 0
|
||||||
|
#else
|
||||||
|
#define POWER_PULSE_DEFAULT 5
|
||||||
|
#endif
|
||||||
|
#define POWER_PULSE_WAIT_DEFAULT 4 // Default rate of the power pulse: 4*2500 = 10000 ms = 10 s
|
||||||
|
#define POWER_PULSE_DURATION_DEFAULT 1 // Default duration of the power pulse: 1*250 = 250 ms
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OLED Orientation Sensitivity on Automatic mode!
|
||||||
|
* Motion Sensitivity <0=Off 1=Least Sensitive 9=Most Sensitive>
|
||||||
|
*/
|
||||||
|
#define SENSITIVITY 7 // Default 7
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detailed soldering screen
|
||||||
|
* Detailed idle screen (off for first time users)
|
||||||
|
*/
|
||||||
|
#define DETAILED_SOLDERING 0 // 0: Disable 1: Enable - Default 0
|
||||||
|
#define DETAILED_IDLE 0 // 0: Disable 1: Enable - Default 0
|
||||||
|
|
||||||
|
#define THERMAL_RUNAWAY_TIME_SEC 20
|
||||||
|
#define THERMAL_RUNAWAY_TEMP_C 20
|
||||||
|
|
||||||
|
#define CUT_OUT_SETTING 0 // default to no cut-off voltage
|
||||||
|
#define RECOM_VOL_CELL 33 // Minimum voltage per cell (Recommended 3.3V (33))
|
||||||
|
#define TEMPERATURE_INF 0 // default to 0
|
||||||
|
#define DESCRIPTION_SCROLL_SPEED 0 // 0: Slow 1: Fast - default to slow
|
||||||
|
#define ANIMATION_LOOP 1 // 0: off 1: on
|
||||||
|
#define ANIMATION_SPEED settingOffSpeed_t::MEDIUM
|
||||||
|
|
||||||
|
#define OP_AMP_Rf_MHP30 268500 // 268.5 Kilo-ohms -> Measured
|
||||||
|
#define OP_AMP_Rin_MHP30 1600 // 1.6 Kilo-ohms -> Measured
|
||||||
|
|
||||||
|
#define OP_AMP_GAIN_STAGE_MHP30 (1 + (OP_AMP_Rf_MHP30 / OP_AMP_Rin_MHP30))
|
||||||
|
// Deriving the Voltage div:
|
||||||
|
// Vin_max = (3.3*(r1+r2))/(r2)
|
||||||
|
// vdiv = (32768*4)/(vin_max*10)
|
||||||
|
|
||||||
|
#ifndef MODEL_MHP30
|
||||||
|
#error "No model defined!"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MODEL_MHP30
|
||||||
|
#define SOLDERING_TEMP 200 // Default soldering temp is 200.0 °C
|
||||||
|
#define VOLTAGE_DIV 360 // Default for MHP30
|
||||||
|
#define PID_POWER_LIMIT 65 // Sets the max pwm power limit
|
||||||
|
#define CALIBRATION_OFFSET 0 // the adc offset in uV - MHP compensates automagically
|
||||||
|
#define POWER_LIMIT 65 // 65 watts default power limit
|
||||||
|
#define MAX_POWER_LIMIT 65 //
|
||||||
|
#define POWER_LIMIT_STEPS 1 //
|
||||||
|
#define OP_AMP_GAIN_STAGE OP_AMP_GAIN_STAGE_MHP30 //
|
||||||
|
#define USB_PD_VMAX 20 // Maximum voltage for PD to negotiate
|
||||||
|
#define MODEL_HAS_DCDC // Has inductor to current filter
|
||||||
|
#define PID_TIM_HZ (16) //
|
||||||
|
#define MAX_TEMP_C 300 // Max soldering temp selectable °C
|
||||||
|
#define MAX_TEMP_F 570 // Max soldering temp selectable °F
|
||||||
|
#define MIN_TEMP_C 10 // Min soldering temp selectable °C
|
||||||
|
#define MIN_TEMP_F 60 // Min soldering temp selectable °F
|
||||||
|
#define MIN_BOOST_TEMP_C 150 // The min settable temp for boost mode °C
|
||||||
|
#define MIN_BOOST_TEMP_F 300 // The min settable temp for boost mode °F
|
||||||
|
#define NO_DISPLAY_ROTATE // Disable OLED rotation by accel
|
||||||
|
#define SLEW_LIMIT 50 // Limit to 3.0 Watts per 64ms pid loop update rate slew rate
|
||||||
|
#define ACCEL_MSA
|
||||||
|
#define POW_PD
|
||||||
|
#define TEMP_NTC
|
||||||
|
#define I2C_SOFT
|
||||||
|
#define BATTFILTERDEPTH 8
|
||||||
|
#define OLED_I2CBB
|
||||||
|
#define ACCEL_EXITS_ON_MOVEMENT
|
||||||
|
|
||||||
|
#define HARDWARE_MAX_WATTAGE_X10 650
|
||||||
|
#define TIP_THERMAL_MASS 65 // TODO, needs refinement
|
||||||
|
#define tipResistance 60 // x10 ohms, ~6 typical
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ACCEL_EXITS_ON_MOVEMENT
|
||||||
|
#define NO_SLEEP_MODE
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "Model_Config.h"
|
#include "configuration.h"
|
||||||
#ifdef POW_PD
|
#ifdef POW_PD
|
||||||
#include "BSP.h"
|
#include "BSP.h"
|
||||||
#include "I2C_Wrapper.hpp"
|
#include "I2C_Wrapper.hpp"
|
||||||
|
|||||||
@@ -7,11 +7,12 @@
|
|||||||
|
|
||||||
#include "BSP.h"
|
#include "BSP.h"
|
||||||
#include "I2CBB.hpp"
|
#include "I2CBB.hpp"
|
||||||
#include "Model_Config.h"
|
|
||||||
#include "Pins.h"
|
#include "Pins.h"
|
||||||
#include "Setup.h"
|
#include "Setup.h"
|
||||||
|
#include "configuration.h"
|
||||||
#include "fusbpd.h"
|
#include "fusbpd.h"
|
||||||
#include <I2C_Wrapper.hpp>
|
#include <I2C_Wrapper.hpp>
|
||||||
|
|
||||||
void preRToSInit() {
|
void preRToSInit() {
|
||||||
/* Reset of all peripherals, Initializes the Flash interface and the Systick.
|
/* Reset of all peripherals, Initializes the Flash interface and the Systick.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
#include "BSP.h"
|
#include "BSP.h"
|
||||||
#include "I2C_Wrapper.hpp"
|
#include "I2C_Wrapper.hpp"
|
||||||
#include "Model_Config.h"
|
|
||||||
#include "Pins.h"
|
#include "Pins.h"
|
||||||
#include "Setup.h"
|
#include "Setup.h"
|
||||||
#include "TipThermoModel.h"
|
#include "TipThermoModel.h"
|
||||||
@@ -10,6 +9,7 @@
|
|||||||
#include "history.hpp"
|
#include "history.hpp"
|
||||||
#include "main.hpp"
|
#include "main.hpp"
|
||||||
#include <IRQ.h>
|
#include <IRQ.h>
|
||||||
|
|
||||||
volatile uint16_t PWMSafetyTimer = 0;
|
volatile uint16_t PWMSafetyTimer = 0;
|
||||||
volatile uint8_t pendingPWM = 0;
|
volatile uint8_t pendingPWM = 0;
|
||||||
|
|
||||||
@@ -21,9 +21,7 @@ uint16_t totalPWM; // htim2.Init.Period, the full PWM cycle
|
|||||||
|
|
||||||
static bool fastPWM;
|
static bool fastPWM;
|
||||||
|
|
||||||
// 2 second filter (ADC is PID_TIM_HZ Hz)
|
void resetWatchdog() { HAL_IWDG_Refresh(&hiwdg); }
|
||||||
history<uint16_t, PID_TIM_HZ> rawTempFilter = {{0}, 0, 0};
|
|
||||||
void resetWatchdog() { HAL_IWDG_Refresh(&hiwdg); }
|
|
||||||
#ifdef TEMP_NTC
|
#ifdef TEMP_NTC
|
||||||
// Lookup table for the NTC
|
// Lookup table for the NTC
|
||||||
// Stored as ADCReading,Temp in degC
|
// Stored as ADCReading,Temp in degC
|
||||||
@@ -135,48 +133,36 @@ uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample) {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setTipPWM(uint8_t pulse) {
|
|
||||||
PWMSafetyTimer = 10; // This is decremented in the handler for PWM so that the tip pwm is
|
|
||||||
// disabled if the PID task is not scheduled often enough.
|
|
||||||
|
|
||||||
pendingPWM = pulse;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void switchToFastPWM(void) {
|
static void switchToFastPWM(void) {
|
||||||
fastPWM = true;
|
// 10Hz
|
||||||
totalPWM = powerPWM + tempMeasureTicks * 2 + holdoffTicks;
|
fastPWM = true;
|
||||||
htim2.Instance->ARR = totalPWM;
|
totalPWM = powerPWM + tempMeasureTicks + holdoffTicks;
|
||||||
// ~3.5 Hz rate
|
htim2.Instance->ARR = totalPWM;
|
||||||
htim2.Instance->CCR1 = powerPWM + holdoffTicks * 2;
|
htim2.Instance->CCR1 = powerPWM + holdoffTicks;
|
||||||
// 2 MHz timer clock/2000 = 1 kHz tick rate
|
htim2.Instance->PSC = 2690;
|
||||||
htim2.Instance->PSC = 2000;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void switchToSlowPWM(void) {
|
static void switchToSlowPWM(void) {
|
||||||
fastPWM = false;
|
// 5Hz
|
||||||
totalPWM = powerPWM + tempMeasureTicks + holdoffTicks;
|
fastPWM = false;
|
||||||
htim2.Instance->ARR = totalPWM;
|
totalPWM = powerPWM + tempMeasureTicks / 2 + holdoffTicks / 2;
|
||||||
// ~1.84 Hz rate
|
htim2.Instance->ARR = totalPWM;
|
||||||
htim2.Instance->CCR1 = powerPWM + holdoffTicks;
|
htim2.Instance->CCR1 = powerPWM + holdoffTicks / 2;
|
||||||
// 2 MHz timer clock/4000 = 500 Hz tick rate
|
htim2.Instance->PSC = 2690 * 2;
|
||||||
htim2.Instance->PSC = 4000;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool tryBetterPWM(uint8_t pwm) {
|
void setTipPWM(const uint8_t pulse, const bool shouldUseFastModePWM) {
|
||||||
if (fastPWM && pwm == powerPWM) {
|
PWMSafetyTimer = 10; // This is decremented in the handler for PWM so that the tip pwm is
|
||||||
// maximum power for fast PWM reached, need to go slower to get more
|
// disabled if the PID task is not scheduled often enough.
|
||||||
switchToSlowPWM();
|
pendingPWM = pulse;
|
||||||
return true;
|
if (fastPWM != shouldUseFastModePWM) {
|
||||||
} else if (!fastPWM && pwm < 230) {
|
if (shouldUseFastModePWM) {
|
||||||
// 254 in fast PWM mode gives the same power as 239 in slow
|
switchToFastPWM();
|
||||||
// allow for some reasonable hysteresis by switching only when it goes
|
} else {
|
||||||
// below 230 (equivalent to 245 in fast mode)
|
switchToSlowPWM();
|
||||||
switchToFastPWM();
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// These are called by the HAL after the corresponding events from the system
|
// These are called by the HAL after the corresponding events from the system
|
||||||
// timers.
|
// timers.
|
||||||
|
|
||||||
|
|||||||
@@ -1,49 +0,0 @@
|
|||||||
/*
|
|
||||||
* Model_Config.h
|
|
||||||
*
|
|
||||||
* Created on: 25 Jul 2020
|
|
||||||
* Author: Ralim
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BSP_MINIWARE_MODEL_CONFIG_H_
|
|
||||||
#define BSP_MINIWARE_MODEL_CONFIG_H_
|
|
||||||
/*
|
|
||||||
* Lookup for mapping features <-> Models
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(MODEL_TS100) + defined(MODEL_TS80) + defined(MODEL_TS80P) > 1
|
|
||||||
#error "Multiple models defined!"
|
|
||||||
#elif defined(MODEL_TS100) + defined(MODEL_TS80) + defined(MODEL_TS80P) == 0
|
|
||||||
#error "No model defined!"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef MODEL_TS100
|
|
||||||
#define POW_DC
|
|
||||||
#define ACCEL_MMA
|
|
||||||
#define ACCEL_LIS
|
|
||||||
#define TEMP_TMP36
|
|
||||||
#define BATTFILTERDEPTH 32
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef MODEL_TS80
|
|
||||||
#define ACCEL_LIS
|
|
||||||
#define POW_QC
|
|
||||||
#define TEMP_TMP36
|
|
||||||
#define LIS_ORI_FLIP
|
|
||||||
#define OLED_FLIP
|
|
||||||
#define BATTFILTERDEPTH 8
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef MODEL_TS80P
|
|
||||||
#define ACCEL_LIS
|
|
||||||
#define ACCEL_MSA
|
|
||||||
#define POW_PD
|
|
||||||
#define POW_QC
|
|
||||||
#define TEMP_NTC
|
|
||||||
#define I2C_SOFT
|
|
||||||
#define LIS_ORI_FLIP
|
|
||||||
#define OLED_FLIP
|
|
||||||
#define BATTFILTERDEPTH 8
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* BSP_MINIWARE_MODEL_CONFIG_H_ */
|
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
#ifndef BSP_MINIWARE_PINS_H_
|
#ifndef BSP_MINIWARE_PINS_H_
|
||||||
#define BSP_MINIWARE_PINS_H_
|
#define BSP_MINIWARE_PINS_H_
|
||||||
#include "Model_Config.h"
|
#include "configuration.h"
|
||||||
|
|
||||||
#ifdef MODEL_TS100
|
#ifdef MODEL_TS100
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
#include "BSP.h"
|
#include "BSP.h"
|
||||||
#include "BSP_Power.h"
|
#include "BSP_Power.h"
|
||||||
#include "Model_Config.h"
|
|
||||||
#include "Pins.h"
|
#include "Pins.h"
|
||||||
#include "QC3.h"
|
#include "QC3.h"
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
|
#include "configuration.h"
|
||||||
#include "fusb_user.h"
|
#include "fusb_user.h"
|
||||||
#include "fusbpd.h"
|
#include "fusbpd.h"
|
||||||
#include "int_n.h"
|
#include "int_n.h"
|
||||||
|
|||||||
@@ -5,11 +5,12 @@
|
|||||||
* Author: Ralim
|
* Author: Ralim
|
||||||
*/
|
*/
|
||||||
#include "BSP.h"
|
#include "BSP.h"
|
||||||
#include "Model_Config.h"
|
|
||||||
#include "Pins.h"
|
#include "Pins.h"
|
||||||
#include "QC3.h"
|
#include "QC3.h"
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
|
#include "configuration.h"
|
||||||
#include "stm32f1xx_hal.h"
|
#include "stm32f1xx_hal.h"
|
||||||
|
|
||||||
#ifdef POW_QC
|
#ifdef POW_QC
|
||||||
void QC_DPlusZero_Six() {
|
void QC_DPlusZero_Six() {
|
||||||
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_RESET); // pull down D+
|
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_RESET); // pull down D+
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ DMA_HandleTypeDef hdma_i2c1_tx;
|
|||||||
IWDG_HandleTypeDef hiwdg;
|
IWDG_HandleTypeDef hiwdg;
|
||||||
TIM_HandleTypeDef htim2;
|
TIM_HandleTypeDef htim2;
|
||||||
TIM_HandleTypeDef htim3;
|
TIM_HandleTypeDef htim3;
|
||||||
#define ADC_FILTER_LEN 32
|
#define ADC_FILTER_LEN 4
|
||||||
#define ADC_SAMPLES 16
|
#define ADC_SAMPLES 16
|
||||||
uint16_t ADCReadings[ADC_SAMPLES]; // Used to store the adc readings for the handle cold junction temp
|
uint16_t ADCReadings[ADC_SAMPLES]; // Used to store the adc readings for the handle cold junction temp
|
||||||
|
|
||||||
@@ -326,7 +326,8 @@ static void MX_TIM2_Init(void) {
|
|||||||
// These values give a rate of around 3.5 Hz for "fast" mode and 1.84 Hz for "slow"
|
// These values give a rate of around 3.5 Hz for "fast" mode and 1.84 Hz for "slow"
|
||||||
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
|
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
|
||||||
// dummy value, will be reconfigured by BSPInit()
|
// dummy value, will be reconfigured by BSPInit()
|
||||||
htim2.Init.Period = 255 + 17 * 2;
|
htim2.Init.Period = powerPWM + 14 * 2;
|
||||||
|
|
||||||
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV4; // 8 MHz (x2 APB1) before divide
|
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV4; // 8 MHz (x2 APB1) before divide
|
||||||
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
|
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
|
||||||
htim2.Init.RepetitionCounter = 0;
|
htim2.Init.RepetitionCounter = 0;
|
||||||
@@ -344,7 +345,7 @@ static void MX_TIM2_Init(void) {
|
|||||||
|
|
||||||
sConfigOC.OCMode = TIM_OCMODE_PWM1;
|
sConfigOC.OCMode = TIM_OCMODE_PWM1;
|
||||||
// dummy value, will be reconfigured by BSPInit() in the BSP.cpp
|
// dummy value, will be reconfigured by BSPInit() in the BSP.cpp
|
||||||
sConfigOC.Pulse = 255 + 13 * 2; // 13 -> Delay of 7 ms
|
sConfigOC.Pulse = powerPWM + 14; // 13 -> Delay of 7 ms
|
||||||
// 255 is the largest time period of the drive signal, and then offset ADC sample to be a bit delayed after this
|
// 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.
|
* It takes 4 milliseconds for output to be stable after PWM turns off.
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
#ifndef BSP_MINIWARE_SOFTWARE_I2C_H_
|
#ifndef BSP_MINIWARE_SOFTWARE_I2C_H_
|
||||||
#define BSP_MINIWARE_SOFTWARE_I2C_H_
|
#define BSP_MINIWARE_SOFTWARE_I2C_H_
|
||||||
#include "BSP.h"
|
#include "BSP.h"
|
||||||
#include "Model_Config.h"
|
#include "configuration.h"
|
||||||
#include "stm32f1xx_hal.h"
|
#include "stm32f1xx_hal.h"
|
||||||
#ifdef I2C_SOFT
|
#ifdef I2C_SOFT
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
#pragma once
|
#ifndef CONFIGURATION_H_
|
||||||
#include "Model_Config.h"
|
#define CONFIGURATION_H_
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
/**
|
/**
|
||||||
* Configuration.h
|
* Configuration.h
|
||||||
* Define here your default pre settings for TS80 or TS100
|
* Define here your default pre settings for TS80(P) or TS100
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#define ORIENTATION_MODE 0 // 0: Right 1:Left 2:Automatic - Default right
|
#define ORIENTATION_MODE 0 // 0: Right 1:Left 2:Automatic - Default right
|
||||||
#define REVERSE_BUTTON_TEMP_CHANGE 0 // 0:Default 1:Reverse - Reverse the plus and minus button assigment for temperatur change
|
#define REVERSE_BUTTON_TEMP_CHANGE 0 // 0:Default 1:Reverse - Reverse the plus and minus button assigment for temperature change
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Temp change settings
|
* Temp change settings
|
||||||
@@ -114,14 +114,16 @@
|
|||||||
|
|
||||||
#define OP_AMP_GAIN_STAGE_TS80 (1 + (OP_AMP_Rf_TS80 / OP_AMP_Rin_TS80))
|
#define OP_AMP_GAIN_STAGE_TS80 (1 + (OP_AMP_Rf_TS80 / OP_AMP_Rin_TS80))
|
||||||
|
|
||||||
#define OP_AMP_Rf_MHP30 268500 // 268.5 Kilo-ohms -> Measured
|
|
||||||
#define OP_AMP_Rin_MHP30 1600 // 1.6 Kilo-ohms -> Measured
|
|
||||||
|
|
||||||
#define OP_AMP_GAIN_STAGE_MHP30 (1 + (OP_AMP_Rf_MHP30 / OP_AMP_Rin_MHP30))
|
|
||||||
// Deriving the Voltage div:
|
// Deriving the Voltage div:
|
||||||
// Vin_max = (3.3*(r1+r2))/(r2)
|
// Vin_max = (3.3*(r1+r2))/(r2)
|
||||||
// vdiv = (32768*4)/(vin_max*10)
|
// vdiv = (32768*4)/(vin_max*10)
|
||||||
|
|
||||||
|
#if defined(MODEL_TS100) + defined(MODEL_TS80) + defined(MODEL_TS80P) > 1
|
||||||
|
#error "Multiple models defined!"
|
||||||
|
#elif defined(MODEL_TS100) + defined(MODEL_TS80) + defined(MODEL_TS80P) == 0
|
||||||
|
#error "No model defined!"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef MODEL_TS100
|
#ifdef MODEL_TS100
|
||||||
#define SOLDERING_TEMP 320 // Default soldering temp is 320.0 °C
|
#define SOLDERING_TEMP 320 // Default soldering temp is 320.0 °C
|
||||||
#define VOLTAGE_DIV 467 // 467 - Default divider from schematic
|
#define VOLTAGE_DIV 467 // 467 - Default divider from schematic
|
||||||
@@ -140,26 +142,10 @@
|
|||||||
#define MIN_TEMP_F 60 // Min soldering temp selectable °F
|
#define MIN_TEMP_F 60 // Min soldering temp selectable °F
|
||||||
#define MIN_BOOST_TEMP_C 250 // The min settable temp for boost mode °C
|
#define MIN_BOOST_TEMP_C 250 // The min settable temp for boost mode °C
|
||||||
#define MIN_BOOST_TEMP_F 480 // The min settable temp for boost mode °F
|
#define MIN_BOOST_TEMP_F 480 // The min settable temp for boost mode °F
|
||||||
#endif
|
#define POW_DC
|
||||||
|
#define ACCEL_MMA
|
||||||
#ifdef MODEL_Pinecil
|
#define ACCEL_LIS
|
||||||
#define SOLDERING_TEMP 320 // Default soldering temp is 320.0 °C
|
#define TEMP_TMP36
|
||||||
#define VOLTAGE_DIV 467 // 467 - Default divider from schematic
|
|
||||||
#define CALIBRATION_OFFSET 900 // 900 - Default adc offset in uV
|
|
||||||
#define PID_POWER_LIMIT 70 // Sets the max pwm power limit
|
|
||||||
#define POWER_LIMIT 0 // 0 watts default limit
|
|
||||||
#define MAX_POWER_LIMIT 65 //
|
|
||||||
#define POWER_LIMIT_STEPS 5 //
|
|
||||||
#define OP_AMP_GAIN_STAGE OP_AMP_GAIN_STAGE_TS100 // 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 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
|
|
||||||
#define MIN_TEMP_F 60 // Min soldering temp selectable °F
|
|
||||||
#define MIN_BOOST_TEMP_C 250 // The min settable temp for boost mode °C
|
|
||||||
#define MIN_BOOST_TEMP_F 480 // The min settable temp for boost mode °F
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MODEL_TS80
|
#ifdef MODEL_TS80
|
||||||
@@ -180,6 +166,11 @@
|
|||||||
#define MIN_TEMP_F 60 // Min soldering temp selectable °F
|
#define MIN_TEMP_F 60 // Min soldering temp selectable °F
|
||||||
#define MIN_BOOST_TEMP_C 250 // The min settable temp for boost mode °C
|
#define MIN_BOOST_TEMP_C 250 // The min settable temp for boost mode °C
|
||||||
#define MIN_BOOST_TEMP_F 480 // The min settable temp for boost mode °F
|
#define MIN_BOOST_TEMP_F 480 // The min settable temp for boost mode °F
|
||||||
|
#define ACCEL_LIS
|
||||||
|
#define POW_QC
|
||||||
|
#define TEMP_TMP36
|
||||||
|
#define LIS_ORI_FLIP
|
||||||
|
#define OLED_FLIP
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MODEL_TS80P
|
#ifdef MODEL_TS80P
|
||||||
@@ -200,59 +191,31 @@
|
|||||||
#define MIN_TEMP_F 60 // Min soldering temp selectable °F
|
#define MIN_TEMP_F 60 // Min soldering temp selectable °F
|
||||||
#define MIN_BOOST_TEMP_C 250 // The min settable temp for boost mode °C
|
#define MIN_BOOST_TEMP_C 250 // The min settable temp for boost mode °C
|
||||||
#define MIN_BOOST_TEMP_F 480 // The min settable temp for boost mode °F
|
#define MIN_BOOST_TEMP_F 480 // The min settable temp for boost mode °F
|
||||||
|
#define ACCEL_LIS
|
||||||
#endif
|
#define ACCEL_MSA
|
||||||
|
#define POW_PD
|
||||||
#ifdef MODEL_MHP30
|
#define POW_QC
|
||||||
#define SOLDERING_TEMP 200 // Default soldering temp is 200.0 °C
|
#define TEMP_NTC
|
||||||
#define VOLTAGE_DIV 360 // Default for MHP30
|
#define I2C_SOFT
|
||||||
#define PID_POWER_LIMIT 65 // Sets the max pwm power limit
|
#define LIS_ORI_FLIP
|
||||||
#define CALIBRATION_OFFSET 0 // the adc offset in uV - MHP compensates automagically
|
#define OLED_FLIP
|
||||||
#define POWER_LIMIT 65 // 65 watts default power limit
|
|
||||||
#define MAX_POWER_LIMIT 65 //
|
|
||||||
#define POWER_LIMIT_STEPS 1 //
|
|
||||||
#define OP_AMP_GAIN_STAGE OP_AMP_GAIN_STAGE_MHP30 //
|
|
||||||
#define USB_PD_VMAX 20 // Maximum voltage for PD to negotiate
|
|
||||||
#define MODEL_HAS_DCDC // Has inductor to current filter
|
|
||||||
#define PID_TIM_HZ (16) //
|
|
||||||
#define THERMAL_MASS_OVERSHOOTS // We have overshoot so reverse direction of compensation
|
|
||||||
#define MAX_TEMP_C 300 // Max soldering temp selectable °C
|
|
||||||
#define MAX_TEMP_F 570 // Max soldering temp selectable °F
|
|
||||||
#define MIN_TEMP_C 10 // Min soldering temp selectable °C
|
|
||||||
#define MIN_TEMP_F 60 // Min soldering temp selectable °F
|
|
||||||
#define MIN_BOOST_TEMP_C 150 // The min settable temp for boost mode °C
|
|
||||||
#define MIN_BOOST_TEMP_F 300 // The min settable temp for boost mode °F
|
|
||||||
#define NO_DISPLAY_ROTATE // Disable OLED rotation by accel
|
|
||||||
#define SLEW_LIMIT 50 // Limit to 3.0 Watts per 64ms pid loop update rate slew rate
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MODEL_TS100
|
#ifdef MODEL_TS100
|
||||||
const int32_t tipMass = 65; // X10 watts to raise 1 deg C in 1 second
|
#define HARDWARE_MAX_WATTAGE_X10 750
|
||||||
const uint8_t tipResistance = 75; // x10 ohms, 7.5 typical for ts100 tips
|
#define TIP_THERMAL_MASS 65 // X10 watts to raise 1 deg C in 1 second
|
||||||
#endif
|
#define tipResistance 75 // x10 ohms, 7.5 typical for ts100 tips
|
||||||
|
|
||||||
#ifdef MODEL_Pinecil
|
|
||||||
const int32_t tipMass = 45; // X10 watts to raise 1 deg C in 1 second
|
|
||||||
const uint8_t tipResistance = 75; // x10 ohms, 7.5 typical for ts100 tips
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MODEL_TS80
|
#ifdef MODEL_TS80
|
||||||
const uint32_t tipMass = 40;
|
#define HARDWARE_MAX_WATTAGE_X10 180
|
||||||
const uint8_t tipResistance = 45; // x10 ohms, 4.5 typical for ts80 tips
|
#define TIP_THERMAL_MASS 40
|
||||||
|
#define tipResistance 45 // x10 ohms, 4.5 typical for ts80 tips
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MODEL_TS80P
|
#ifdef MODEL_TS80P
|
||||||
const uint32_t tipMass = 40;
|
#define HARDWARE_MAX_WATTAGE_X10 300
|
||||||
const uint8_t tipResistance = 45; // x10 ohms, 4.5 typical for ts80 tips
|
#define TIP_THERMAL_MASS 40
|
||||||
|
#define tipResistance 45 // x10 ohms, 4.5 typical for ts80 tips
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MODEL_MHP30
|
|
||||||
const uint32_t tipMass = 45; // TODO
|
|
||||||
const uint8_t tipResistance = 60; // x10 ohms, ~6 typical
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef POW_QC_20V
|
|
||||||
#define QC_SETTINGS_MAX 3
|
|
||||||
#else
|
|
||||||
#define QC_SETTINGS_MAX 2
|
|
||||||
#endif
|
#endif
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "Model_Config.h"
|
#include "configuration.h"
|
||||||
#ifdef POW_PD
|
#ifdef POW_PD
|
||||||
#include "BSP.h"
|
#include "BSP.h"
|
||||||
#include "I2CBB.hpp"
|
#include "I2CBB.hpp"
|
||||||
|
|||||||
@@ -7,11 +7,12 @@
|
|||||||
|
|
||||||
#include "BSP.h"
|
#include "BSP.h"
|
||||||
#include "I2CBB.hpp"
|
#include "I2CBB.hpp"
|
||||||
#include "Model_Config.h"
|
|
||||||
#include "Pins.h"
|
#include "Pins.h"
|
||||||
#include "Setup.h"
|
#include "Setup.h"
|
||||||
|
#include "configuration.h"
|
||||||
#include "fusbpd.h"
|
#include "fusbpd.h"
|
||||||
#include <I2C_Wrapper.hpp>
|
#include <I2C_Wrapper.hpp>
|
||||||
|
|
||||||
void preRToSInit() {
|
void preRToSInit() {
|
||||||
/* Reset of all peripherals, Initializes the Flash interface and the Systick.
|
/* Reset of all peripherals, Initializes the Flash interface and the Systick.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -12,14 +12,12 @@
|
|||||||
#include "main.hpp"
|
#include "main.hpp"
|
||||||
|
|
||||||
const uint16_t powerPWM = 255;
|
const uint16_t powerPWM = 255;
|
||||||
const uint8_t holdoffTicks = 25; // delay of 7 ms
|
const uint8_t holdoffTicks = 10;
|
||||||
const uint8_t tempMeasureTicks = 25;
|
const uint8_t tempMeasureTicks = 14;
|
||||||
|
|
||||||
uint16_t totalPWM; // htim2.Init.Period, the full PWM cycle
|
uint16_t totalPWM; // Total length of the cycle's ticks
|
||||||
|
|
||||||
// 2 second filter (ADC is PID_TIM_HZ Hz)
|
void resetWatchdog() { fwdgt_counter_reload(); }
|
||||||
history<uint16_t, PID_TIM_HZ> rawTempFilter = {{0}, 0, 0};
|
|
||||||
void resetWatchdog() { fwdgt_counter_reload(); }
|
|
||||||
|
|
||||||
uint16_t getHandleTemperature(uint8_t sample) {
|
uint16_t getHandleTemperature(uint8_t sample) {
|
||||||
#ifdef TEMP_TMP36
|
#ifdef TEMP_TMP36
|
||||||
|
|||||||
@@ -18,6 +18,9 @@ volatile uint16_t i2c_nbytes;
|
|||||||
volatile uint16_t i2c_write_dress;
|
volatile uint16_t i2c_write_dress;
|
||||||
volatile uint16_t i2c_read_dress;
|
volatile uint16_t i2c_read_dress;
|
||||||
volatile uint8_t i2c_process_flag = 0;
|
volatile uint8_t i2c_process_flag = 0;
|
||||||
|
static bool fastPWM;
|
||||||
|
static void switchToSlowPWM(void);
|
||||||
|
static void switchToFastPWM(void);
|
||||||
void ADC0_1_IRQHandler(void) {
|
void ADC0_1_IRQHandler(void) {
|
||||||
|
|
||||||
adc_interrupt_flag_clear(ADC0, ADC_INT_FLAG_EOIC);
|
adc_interrupt_flag_clear(ADC0, ADC_INT_FLAG_EOIC);
|
||||||
@@ -34,74 +37,58 @@ void ADC0_1_IRQHandler(void) {
|
|||||||
volatile uint16_t PWMSafetyTimer = 0;
|
volatile uint16_t PWMSafetyTimer = 0;
|
||||||
volatile uint8_t pendingPWM = 0;
|
volatile uint8_t pendingPWM = 0;
|
||||||
void TIMER1_IRQHandler(void) {
|
void TIMER1_IRQHandler(void) {
|
||||||
|
static bool lastPeriodWasFast = false;
|
||||||
|
|
||||||
if (timer_interrupt_flag_get(TIMER1, TIMER_INT_UP) == SET) {
|
if (timer_interrupt_flag_get(TIMER1, TIMER_INT_UP) == SET) {
|
||||||
timer_interrupt_flag_clear(TIMER1, TIMER_INT_UP);
|
timer_interrupt_flag_clear(TIMER1, TIMER_INT_UP);
|
||||||
// rollover turn on output if required
|
// rollover turn on output if required
|
||||||
if (PWMSafetyTimer && pendingPWM) {
|
|
||||||
timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_0, 50);
|
|
||||||
}
|
|
||||||
if (PWMSafetyTimer) {
|
if (PWMSafetyTimer) {
|
||||||
PWMSafetyTimer--;
|
PWMSafetyTimer--;
|
||||||
|
if (lastPeriodWasFast != fastPWM) {
|
||||||
|
if (fastPWM) {
|
||||||
|
switchToFastPWM();
|
||||||
|
} else {
|
||||||
|
switchToSlowPWM();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pendingPWM) {
|
||||||
|
timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_1, pendingPWM);
|
||||||
|
timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_0, 50);
|
||||||
|
} else {
|
||||||
|
timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_0, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (timer_interrupt_flag_get(TIMER1, TIMER_INT_CH1) == SET) {
|
if (timer_interrupt_flag_get(TIMER1, TIMER_INT_CH1) == SET) {
|
||||||
timer_interrupt_flag_clear(TIMER1, TIMER_INT_CH1);
|
timer_interrupt_flag_clear(TIMER1, TIMER_INT_CH1);
|
||||||
// This is triggered on pwm setpoint trigger; we want to copy the pending
|
|
||||||
// PWM value into the output control reg
|
|
||||||
|
|
||||||
timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_0, 0);
|
timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_0, 0);
|
||||||
if (pendingPWM) {
|
|
||||||
timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_1, pendingPWM);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setTipPWM(uint8_t pulse) {
|
void switchToFastPWM(void) {
|
||||||
|
fastPWM = true;
|
||||||
|
totalPWM = powerPWM + tempMeasureTicks + holdoffTicks;
|
||||||
|
TIMER_CAR(TIMER1) = (uint32_t)totalPWM;
|
||||||
|
|
||||||
|
// ~10Hz
|
||||||
|
TIMER_CH0CV(TIMER1) = powerPWM + holdoffTicks;
|
||||||
|
// 1 kHz tick rate
|
||||||
|
TIMER_PSC(TIMER1) = 18000;
|
||||||
|
}
|
||||||
|
|
||||||
|
void switchToSlowPWM(void) {
|
||||||
|
// 5Hz
|
||||||
|
fastPWM = false;
|
||||||
|
totalPWM = powerPWM + tempMeasureTicks / 2 + holdoffTicks / 2;
|
||||||
|
TIMER_CAR(TIMER1) = (uint32_t)totalPWM;
|
||||||
|
TIMER_CH0CV(TIMER1) = powerPWM + holdoffTicks / 2;
|
||||||
|
TIMER_PSC(TIMER1) = 36000;
|
||||||
|
}
|
||||||
|
void setTipPWM(const uint8_t pulse, const bool shouldUseFastModePWM) {
|
||||||
PWMSafetyTimer = 10; // This is decremented in the handler for PWM so that the tip pwm is
|
PWMSafetyTimer = 10; // This is decremented in the handler for PWM so that the tip pwm is
|
||||||
// disabled if the PID task is not scheduled often enough.
|
// disabled if the PID task is not scheduled often enough.
|
||||||
pendingPWM = pulse;
|
pendingPWM = pulse;
|
||||||
}
|
fastPWM = shouldUseFastModePWM;
|
||||||
|
|
||||||
static bool fastPWM;
|
|
||||||
static void switchToFastPWM(void) {
|
|
||||||
fastPWM = true;
|
|
||||||
totalPWM = powerPWM + tempMeasureTicks * 2;
|
|
||||||
TIMER_CAR(TIMER1) = (uint32_t)totalPWM;
|
|
||||||
|
|
||||||
// ~3.5 Hz rate
|
|
||||||
TIMER_CH0CV(TIMER1) = powerPWM + holdoffTicks * 2;
|
|
||||||
// 1 kHz tick rate
|
|
||||||
TIMER_PSC(TIMER1) = 12000;
|
|
||||||
/* generate an update event */
|
|
||||||
TIMER_SWEVG(TIMER1) |= (uint32_t)TIMER_SWEVG_UPG;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void switchToSlowPWM(void) {
|
|
||||||
fastPWM = false;
|
|
||||||
totalPWM = powerPWM + tempMeasureTicks;
|
|
||||||
TIMER_CAR(TIMER1) = (uint32_t)totalPWM;
|
|
||||||
// ~1.84 Hz rate
|
|
||||||
TIMER_CH0CV(TIMER1) = powerPWM + holdoffTicks;
|
|
||||||
// 500 Hz tick rate
|
|
||||||
TIMER_PSC(TIMER1) = 24000;
|
|
||||||
/* generate an update event */
|
|
||||||
TIMER_SWEVG(TIMER1) |= (uint32_t)TIMER_SWEVG_UPG;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool tryBetterPWM(uint8_t pwm) {
|
|
||||||
if (fastPWM && pwm == powerPWM) {
|
|
||||||
// maximum power for fast PWM reached, need to go slower to get more
|
|
||||||
switchToSlowPWM();
|
|
||||||
return true;
|
|
||||||
} else if (!fastPWM && pwm < 230) {
|
|
||||||
// 254 in fast PWM mode gives the same power as 239 in slow
|
|
||||||
// allow for some reasonable hysteresis by switching only when it goes
|
|
||||||
// below 230 (equivalent to 245 in fast mode)
|
|
||||||
switchToFastPWM();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EXTI5_9_IRQHandler(void) {
|
void EXTI5_9_IRQHandler(void) {
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
* Model_Config.h
|
|
||||||
*
|
|
||||||
* Created on: 25 Jul 2020
|
|
||||||
* Author: Ralim
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BSP_PINE64_MODEL_CONFIG_H_
|
|
||||||
#define BSP_PINE64_MODEL_CONFIG_H_
|
|
||||||
/*
|
|
||||||
* Lookup for mapping features <-> Models
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(MODEL_Pinecil) == 0
|
|
||||||
#error "No model defined!"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef MODEL_Pinecil
|
|
||||||
#define POW_PD
|
|
||||||
#define POW_QC
|
|
||||||
#define POW_DC
|
|
||||||
#define POW_QC_20V
|
|
||||||
#define ENABLE_QC2
|
|
||||||
#define TEMP_TMP36
|
|
||||||
#define ACCEL_BMA
|
|
||||||
#define ACCEL_SC7
|
|
||||||
#define HALL_SENSOR
|
|
||||||
#define HALL_SI7210
|
|
||||||
#define BATTFILTERDEPTH 32
|
|
||||||
#define DEBUG_UART_OUTPUT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* BSP_PINE64_MODEL_CONFIG_H_ */
|
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
#include "BSP.h"
|
#include "BSP.h"
|
||||||
#include "BSP_Power.h"
|
#include "BSP_Power.h"
|
||||||
#include "Model_Config.h"
|
|
||||||
#include "Pins.h"
|
#include "Pins.h"
|
||||||
#include "QC3.h"
|
#include "QC3.h"
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
|
#include "configuration.h"
|
||||||
#include "fusb_user.h"
|
#include "fusb_user.h"
|
||||||
#include "fusbpd.h"
|
#include "fusbpd.h"
|
||||||
#include "int_n.h"
|
#include "int_n.h"
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
#include "history.hpp"
|
#include "history.hpp"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#define ADC_NORM_SAMPLES 16
|
#define ADC_NORM_SAMPLES 16
|
||||||
#define ADC_FILTER_LEN 32
|
#define ADC_FILTER_LEN 4
|
||||||
uint16_t ADCReadings[ADC_NORM_SAMPLES]; // room for 32 lots of the pair of readings
|
uint16_t ADCReadings[ADC_NORM_SAMPLES]; // room for 32 lots of the pair of readings
|
||||||
|
|
||||||
// Functions
|
// Functions
|
||||||
@@ -264,17 +264,17 @@ void setup_timers() {
|
|||||||
/* initialize TIMER init parameter struct */
|
/* initialize TIMER init parameter struct */
|
||||||
timer_struct_para_init(&timer_initpara);
|
timer_struct_para_init(&timer_initpara);
|
||||||
/* TIMER1 configuration */
|
/* TIMER1 configuration */
|
||||||
timer_initpara.prescaler = 5000;
|
timer_initpara.prescaler = 30000;
|
||||||
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
|
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
|
||||||
timer_initpara.counterdirection = TIMER_COUNTER_UP;
|
timer_initpara.counterdirection = TIMER_COUNTER_UP;
|
||||||
timer_initpara.period = powerPWM + tempMeasureTicks;
|
timer_initpara.period = powerPWM + tempMeasureTicks + holdoffTicks;
|
||||||
timer_initpara.clockdivision = TIMER_CKDIV_DIV4;
|
timer_initpara.clockdivision = TIMER_CKDIV_DIV4;
|
||||||
timer_initpara.repetitioncounter = 0;
|
timer_initpara.repetitioncounter = 0;
|
||||||
timer_init(TIMER1, &timer_initpara);
|
timer_init(TIMER1, &timer_initpara);
|
||||||
|
|
||||||
/* CH0 configured to implement the PWM irq's for the output control*/
|
/* CH0 configured to implement the PWM irq's for the output control*/
|
||||||
timer_channel_output_struct_para_init(&timer_ocintpara);
|
timer_channel_output_struct_para_init(&timer_ocintpara);
|
||||||
timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH;
|
timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_LOW;
|
||||||
timer_ocintpara.outputstate = TIMER_CCX_ENABLE;
|
timer_ocintpara.outputstate = TIMER_CCX_ENABLE;
|
||||||
timer_channel_output_config(TIMER1, TIMER_CH_0, &timer_ocintpara);
|
timer_channel_output_config(TIMER1, TIMER_CH_0, &timer_ocintpara);
|
||||||
|
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ static void system_clock_108m_hxtal(void) {
|
|||||||
/* APB2 = AHB/1 */
|
/* APB2 = AHB/1 */
|
||||||
RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
|
RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
|
||||||
/* APB1 = AHB/2 */
|
/* APB1 = AHB/2 */
|
||||||
RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
|
RCU_CFG0 |= RCU_APB1_CKAHB_DIV4;
|
||||||
|
|
||||||
/* CK_PLL = (CK_PREDIV0) * 27 = 108 MHz */
|
/* CK_PLL = (CK_PREDIV0) * 27 = 108 MHz */
|
||||||
RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
|
RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
|
||||||
|
|||||||
151
source/Core/BSP/Pine64/configuration.h
Normal file
151
source/Core/BSP/Pine64/configuration.h
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
#ifndef CONFIGURATION_H_
|
||||||
|
#define CONFIGURATION_H_
|
||||||
|
#include "Settings.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
/**
|
||||||
|
* Configuration.h
|
||||||
|
* Define here your default pre settings for Pinecil
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//============================= Default Settings ============================
|
||||||
|
//===========================================================================
|
||||||
|
/**
|
||||||
|
* Default soldering temp is 320.0 C
|
||||||
|
* Temperature the iron sleeps at - default 150.0 C
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define SLEEP_TEMP 150 // Default sleep temperature
|
||||||
|
#define BOOST_TEMP 420 // Default boost temp.
|
||||||
|
#define BOOST_MODE_ENABLED 1 // 0: Disable 1: Enable
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Blink the temperature on the cooling screen when its > 50C
|
||||||
|
*/
|
||||||
|
#define COOLING_TEMP_BLINK 0 // 0: Disable 1: Enable
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How many seconds/minutes we wait until going to sleep/shutdown.
|
||||||
|
* Values -> SLEEP_TIME * 10; i.e. 5*10 = 50 Seconds!
|
||||||
|
*/
|
||||||
|
#define SLEEP_TIME 5 // x10 Seconds
|
||||||
|
#define SHUTDOWN_TIME 10 // Minutes
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto start off for safety.
|
||||||
|
* Pissible values are:
|
||||||
|
* 0 - none
|
||||||
|
* 1 - Soldering Temperature
|
||||||
|
* 2 - Sleep Temperature
|
||||||
|
* 3 - Sleep Off Temperature
|
||||||
|
*/
|
||||||
|
#define AUTO_START_MODE 0 // Default to none
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Locking Mode
|
||||||
|
* When in soldering mode a long press on both keys toggle the lock of the buttons
|
||||||
|
* Possible values are:
|
||||||
|
* 0 - Desactivated
|
||||||
|
* 1 - Lock except boost
|
||||||
|
* 2 - Full lock
|
||||||
|
*/
|
||||||
|
#define LOCKING_MODE 0 // Default to desactivated for safety
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OLED Orientation
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#define ORIENTATION_MODE 0 // 0: Right 1:Left 2:Automatic - Default right
|
||||||
|
#define REVERSE_BUTTON_TEMP_CHANGE 0 // 0:Default 1:Reverse - Reverse the plus and minus button assigment for temperature change
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Temp change settings
|
||||||
|
*/
|
||||||
|
#define TEMP_CHANGE_SHORT_STEP 1 // Default temp change short step +1
|
||||||
|
#define TEMP_CHANGE_LONG_STEP 10 // Default temp change long step +10
|
||||||
|
#define TEMP_CHANGE_SHORT_STEP_MAX 50 // Temp change short step MAX value
|
||||||
|
#define TEMP_CHANGE_LONG_STEP_MAX 90 // Temp change long step MAX value
|
||||||
|
|
||||||
|
/* Power pulse for keeping power banks awake*/
|
||||||
|
#define POWER_PULSE_INCREMENT 1
|
||||||
|
#define POWER_PULSE_MAX 100 // x10 max watts
|
||||||
|
#define POWER_PULSE_WAIT_MAX 9 // 9*2.5s = 22.5 seconds
|
||||||
|
#define POWER_PULSE_DURATION_MAX 9 // 9*250ms = 2.25 seconds
|
||||||
|
|
||||||
|
#ifdef MODEL_Pinecil
|
||||||
|
#define POWER_PULSE_DEFAULT 0
|
||||||
|
#else
|
||||||
|
#define POWER_PULSE_DEFAULT 5
|
||||||
|
#endif
|
||||||
|
#define POWER_PULSE_WAIT_DEFAULT 4 // Default rate of the power pulse: 4*2500 = 10000 ms = 10 s
|
||||||
|
#define POWER_PULSE_DURATION_DEFAULT 1 // Default duration of the power pulse: 1*250 = 250 ms
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OLED Orientation Sensitivity on Automatic mode!
|
||||||
|
* Motion Sensitivity <0=Off 1=Least Sensitive 9=Most Sensitive>
|
||||||
|
*/
|
||||||
|
#define SENSITIVITY 7 // Default 7
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detailed soldering screen
|
||||||
|
* Detailed idle screen (off for first time users)
|
||||||
|
*/
|
||||||
|
#define DETAILED_SOLDERING 0 // 0: Disable 1: Enable - Default 0
|
||||||
|
#define DETAILED_IDLE 0 // 0: Disable 1: Enable - Default 0
|
||||||
|
|
||||||
|
#define THERMAL_RUNAWAY_TIME_SEC 20
|
||||||
|
#define THERMAL_RUNAWAY_TEMP_C 20
|
||||||
|
|
||||||
|
#define CUT_OUT_SETTING 0 // default to no cut-off voltage
|
||||||
|
#define RECOM_VOL_CELL 33 // Minimum voltage per cell (Recommended 3.3V (33))
|
||||||
|
#define TEMPERATURE_INF 0 // default to 0
|
||||||
|
#define DESCRIPTION_SCROLL_SPEED 0 // 0: Slow 1: Fast - default to slow
|
||||||
|
#define ANIMATION_LOOP 1 // 0: off 1: on
|
||||||
|
#define ANIMATION_SPEED settingOffSpeed_t::MEDIUM
|
||||||
|
|
||||||
|
#define OP_AMP_Rf_Pinecil 750 * 1000 // 750 Kilo-ohms -> From schematic, R1
|
||||||
|
#define OP_AMP_Rin_Pinecil 2370 // 2.37 Kilo-ohms -> From schematic, R2
|
||||||
|
|
||||||
|
#define OP_AMP_GAIN_STAGE_PINECIL (1 + (OP_AMP_Rf_Pinecil / OP_AMP_Rin_Pinecil))
|
||||||
|
|
||||||
|
#if defined(MODEL_Pinecil) == 0
|
||||||
|
#error "No model defined!"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MODEL_Pinecil
|
||||||
|
#define SOLDERING_TEMP 320 // Default soldering temp is 320.0 °C
|
||||||
|
#define VOLTAGE_DIV 467 // 467 - Default divider from schematic
|
||||||
|
#define CALIBRATION_OFFSET 900 // 900 - Default adc offset in uV
|
||||||
|
#define PID_POWER_LIMIT 70 // Sets the max pwm power limit
|
||||||
|
#define POWER_LIMIT 0 // 0 watts default limit
|
||||||
|
#define MAX_POWER_LIMIT 65 //
|
||||||
|
#define POWER_LIMIT_STEPS 5 //
|
||||||
|
#define OP_AMP_GAIN_STAGE OP_AMP_GAIN_STAGE_PINECIL // Uses Pinecil 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 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
|
||||||
|
#define MIN_TEMP_F 60 // Min soldering temp selectable °F
|
||||||
|
#define MIN_BOOST_TEMP_C 250 // The min settable temp for boost mode °C
|
||||||
|
#define MIN_BOOST_TEMP_F 480 // The min settable temp for boost mode °F
|
||||||
|
|
||||||
|
#define POW_PD
|
||||||
|
#define POW_QC
|
||||||
|
#define POW_DC
|
||||||
|
#define POW_QC_20V
|
||||||
|
#define ENABLE_QC2
|
||||||
|
#define TEMP_TMP36
|
||||||
|
#define ACCEL_BMA
|
||||||
|
#define ACCEL_SC7
|
||||||
|
#define HALL_SENSOR
|
||||||
|
#define HALL_SI7210
|
||||||
|
#define DEBUG_UART_OUTPUT
|
||||||
|
|
||||||
|
#define HARDWARE_MAX_WATTAGE_X10 750
|
||||||
|
#define TIP_THERMAL_MASS 65 // X10 watts to raise 1 deg C in 1 second
|
||||||
|
#define tipResistance 75 // x10 ohms, 7.5 typical for Pinecil tips
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "Model_Config.h"
|
#include "configuration.h"
|
||||||
#ifdef POW_PD
|
#ifdef POW_PD
|
||||||
#include "BSP.h"
|
#include "BSP.h"
|
||||||
#include "I2C_Wrapper.hpp"
|
#include "I2C_Wrapper.hpp"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
* Created on: 13 Jun 2020
|
* Created on: 13 Jun 2020
|
||||||
* Author: Ralim
|
* Author: Ralim
|
||||||
*/
|
*/
|
||||||
#include "Model_Config.h"
|
#include "configuration.h"
|
||||||
#ifdef POW_PD
|
#ifdef POW_PD
|
||||||
#include "BSP.h"
|
#include "BSP.h"
|
||||||
#include "I2CBB.hpp"
|
#include "I2CBB.hpp"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
* Created on: 12 Jun 2020
|
* Created on: 12 Jun 2020
|
||||||
* Author: Ralim
|
* Author: Ralim
|
||||||
*/
|
*/
|
||||||
#include "Model_Config.h"
|
#include "configuration.h"
|
||||||
#ifdef I2C_SOFT
|
#ifdef I2C_SOFT
|
||||||
#include "FreeRTOS.h"
|
#include "FreeRTOS.h"
|
||||||
#include <I2CBB.hpp>
|
#include <I2CBB.hpp>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
#ifndef BSP_MINIWARE_I2CBB_HPP_
|
#ifndef BSP_MINIWARE_I2CBB_HPP_
|
||||||
#define BSP_MINIWARE_I2CBB_HPP_
|
#define BSP_MINIWARE_I2CBB_HPP_
|
||||||
#include "Model_Config.h"
|
#include "configuration.h"
|
||||||
#ifdef I2C_SOFT
|
#ifdef I2C_SOFT
|
||||||
#include "BSP.h"
|
#include "BSP.h"
|
||||||
#include "FreeRTOS.h"
|
#include "FreeRTOS.h"
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
#ifndef OLED_HPP_
|
#ifndef OLED_HPP_
|
||||||
#define OLED_HPP_
|
#define OLED_HPP_
|
||||||
#include "Font.h"
|
#include "Font.h"
|
||||||
#include "Model_Config.h"
|
#include "configuration.h"
|
||||||
#include <BSP.h>
|
#include <BSP.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|||||||
@@ -72,14 +72,11 @@ uint32_t TipThermoModel::convertFtoC(uint32_t degF) {
|
|||||||
uint32_t TipThermoModel::getTipInC(bool sampleNow) {
|
uint32_t TipThermoModel::getTipInC(bool sampleNow) {
|
||||||
int32_t currentTipTempInC = TipThermoModel::convertTipRawADCToDegC(getTipRawTemp(sampleNow));
|
int32_t currentTipTempInC = TipThermoModel::convertTipRawADCToDegC(getTipRawTemp(sampleNow));
|
||||||
currentTipTempInC += getHandleTemperature(sampleNow) / 10; // Add handle offset
|
currentTipTempInC += getHandleTemperature(sampleNow) / 10; // Add handle offset
|
||||||
// Power usage indicates that our tip temp is lower than our thermocouple temp.
|
|
||||||
// I found a number that doesn't unbalance the existing PID, causing overshoot.
|
// Power usage indicates that our tip temp is lower than our thermocouple temp.
|
||||||
// This could be tuned in concert with PID parameters...
|
// I found a number that doesn't unbalance the existing PID, causing overshoot.
|
||||||
#ifdef THERMAL_MASS_OVERSHOOTS
|
// This could be tuned in concert with PID parameters...
|
||||||
currentTipTempInC += x10WattHistory.average() / 25;
|
|
||||||
#else
|
|
||||||
currentTipTempInC -= x10WattHistory.average() / 25;
|
|
||||||
#endif
|
|
||||||
if (currentTipTempInC < 0)
|
if (currentTipTempInC < 0)
|
||||||
return 0;
|
return 0;
|
||||||
return currentTipTempInC;
|
return currentTipTempInC;
|
||||||
@@ -92,7 +89,7 @@ uint32_t TipThermoModel::getTipInF(bool sampleNow) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t TipThermoModel::getTipMaxInC() {
|
uint32_t TipThermoModel::getTipMaxInC() {
|
||||||
uint32_t maximumTipTemp = TipThermoModel::convertTipRawADCToDegC(0x7FFF - (21 * 5)); // back off approx 5 deg c from ADC max
|
uint32_t maximumTipTemp = TipThermoModel::convertTipRawADCToDegC(0x7FFF - (21 * 3)); // back off approx 5 deg c from ADC max
|
||||||
maximumTipTemp += getHandleTemperature(0) / 10; // Add handle offset
|
maximumTipTemp += getHandleTemperature(0) / 10; // Add handle offset
|
||||||
return maximumTipTemp - 1;
|
return maximumTipTemp - 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,8 @@
|
|||||||
const uint8_t wattHistoryFilter = 24; // I term look back weighting
|
const uint8_t wattHistoryFilter = 24; // I term look back weighting
|
||||||
extern expMovingAverage<uint32_t, wattHistoryFilter> x10WattHistory;
|
extern expMovingAverage<uint32_t, wattHistoryFilter> x10WattHistory;
|
||||||
|
|
||||||
int32_t tempToX10Watts(int32_t rawTemp);
|
uint32_t availableW10(uint8_t sample);
|
||||||
void setTipX10Watts(int32_t mw);
|
int32_t tempToX10Watts(int32_t rawTemp);
|
||||||
uint8_t X10WattsToPWM(int32_t milliWatts, uint8_t sample = 0);
|
void setTipX10Watts(int32_t mw);
|
||||||
|
uint8_t X10WattsToPWM(int32_t milliWatts, uint8_t sample = 0);
|
||||||
#endif /* POWER_HPP_ */
|
#endif /* POWER_HPP_ */
|
||||||
|
|||||||
@@ -7,9 +7,9 @@
|
|||||||
|
|
||||||
// Quick charge 3.0 supporting functions
|
// Quick charge 3.0 supporting functions
|
||||||
#include "QC3.h"
|
#include "QC3.h"
|
||||||
|
|
||||||
#include "BSP.h"
|
#include "BSP.h"
|
||||||
#include "cmsis_os.h"
|
#include "cmsis_os.h"
|
||||||
|
#include "configuration.h"
|
||||||
#include "stdint.h"
|
#include "stdint.h"
|
||||||
enum QCState {
|
enum QCState {
|
||||||
NOT_STARTED = 0, // Have not checked
|
NOT_STARTED = 0, // Have not checked
|
||||||
@@ -70,7 +70,7 @@ void seekQC(int16_t Vx10, uint16_t divisor) {
|
|||||||
// try and step towards the wanted value
|
// try and step towards the wanted value
|
||||||
|
|
||||||
// 1. Measure current voltage
|
// 1. Measure current voltage
|
||||||
int16_t vStart = getInputVoltageX10(divisor, 1);
|
int16_t vStart = getInputVoltageX10(divisor, 0);
|
||||||
int difference = Vx10 - vStart;
|
int difference = Vx10 - vStart;
|
||||||
|
|
||||||
// 2. calculate ideal steps (0.2V changes)
|
// 2. calculate ideal steps (0.2V changes)
|
||||||
@@ -94,7 +94,7 @@ void seekQC(int16_t Vx10, uint16_t divisor) {
|
|||||||
#ifdef ENABLE_QC2
|
#ifdef ENABLE_QC2
|
||||||
// Re-measure
|
// Re-measure
|
||||||
/* Disabled due to nothing to test and code space of around 1k*/
|
/* Disabled due to nothing to test and code space of around 1k*/
|
||||||
steps = vStart - getInputVoltageX10(divisor, 1);
|
steps = vStart - getInputVoltageX10(divisor, 0);
|
||||||
if (steps < 0)
|
if (steps < 0)
|
||||||
steps = -steps;
|
steps = -steps;
|
||||||
if (steps > 4) {
|
if (steps > 4) {
|
||||||
@@ -118,7 +118,7 @@ void seekQC(int16_t Vx10, uint16_t divisor) {
|
|||||||
void startQC(uint16_t divisor) {
|
void startQC(uint16_t divisor) {
|
||||||
// Pre check that the input could be >5V already, and if so, dont both
|
// Pre check that the input could be >5V already, and if so, dont both
|
||||||
// negotiating as someone is feeding in hv
|
// negotiating as someone is feeding in hv
|
||||||
if (getInputVoltageX10(divisor, 1) > 80) {
|
if (getInputVoltageX10(divisor, 0) > 80) {
|
||||||
QCTries = 11;
|
QCTries = 11;
|
||||||
QCMode = QCState::NO_QC;
|
QCMode = QCState::NO_QC;
|
||||||
return;
|
return;
|
||||||
@@ -160,7 +160,7 @@ void startQC(uint16_t divisor) {
|
|||||||
// Wait for frontend ADC to stabilise
|
// Wait for frontend ADC to stabilise
|
||||||
QCMode = QCState::QC_2;
|
QCMode = QCState::QC_2;
|
||||||
for (uint8_t i = 0; i < 10; i++) {
|
for (uint8_t i = 0; i < 10; i++) {
|
||||||
if (getInputVoltageX10(divisor, 1) > 80) {
|
if (getInputVoltageX10(divisor, 0) > 80) {
|
||||||
// yay we have at least QC2.0 or QC3.0
|
// yay we have at least QC2.0 or QC3.0
|
||||||
QCMode = QCState::QC_3; // We have at least QC2, pray for 3
|
QCMode = QCState::QC_3; // We have at least QC2, pray for 3
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -15,6 +15,12 @@
|
|||||||
#include <string.h> // for memset
|
#include <string.h> // for memset
|
||||||
bool sanitiseSettings();
|
bool sanitiseSettings();
|
||||||
|
|
||||||
|
#ifdef POW_QC_20V
|
||||||
|
#define QC_SETTINGS_MAX 3
|
||||||
|
#else
|
||||||
|
#define QC_SETTINGS_MAX 2
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This struct must be a multiple of 2 bytes as it is saved / restored from
|
* This struct must be a multiple of 2 bytes as it is saved / restored from
|
||||||
* flash in uint16_t chunks
|
* flash in uint16_t chunks
|
||||||
@@ -144,7 +150,7 @@ bool nextSettingValue(const enum SettingsOptions option) {
|
|||||||
} else {
|
} else {
|
||||||
systemSettings.settingsValues[(int)option] += constants.increment;
|
systemSettings.settingsValues[(int)option] += constants.increment;
|
||||||
}
|
}
|
||||||
return (constants.max - systemSettings.settingsValues[(int)option]) < constants.increment;
|
return (constants.max - systemSettings.settingsValues[(int)option]) <= constants.increment;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool prevSettingValue(const enum SettingsOptions option) {
|
bool prevSettingValue(const enum SettingsOptions option) {
|
||||||
|
|||||||
@@ -187,6 +187,8 @@ const menuitem UIMenu[] = {
|
|||||||
* Display orientation
|
* Display orientation
|
||||||
* Cooldown blink
|
* Cooldown blink
|
||||||
* Reverse Temp change buttons + -
|
* Reverse Temp change buttons + -
|
||||||
|
* Detailed IDLE
|
||||||
|
* Detailed Soldering
|
||||||
*/
|
*/
|
||||||
{SETTINGS_DESC(SettingsItemIndex::TemperatureUnit), settings_setTempF, settings_displayTempF,
|
{SETTINGS_DESC(SettingsItemIndex::TemperatureUnit), settings_setTempF, settings_displayTempF,
|
||||||
SettingsOptions::SettingsOptionsLength}, /* Temperature units, this has to be the first element in the array to work with the logic in settings_enterUIMenu() */
|
SettingsOptions::SettingsOptionsLength}, /* Temperature units, this has to be the first element in the array to work with the logic in settings_enterUIMenu() */
|
||||||
@@ -196,12 +198,14 @@ const menuitem UIMenu[] = {
|
|||||||
{SETTINGS_DESC(SettingsItemIndex::CooldownBlink), nullptr, settings_displayCoolingBlinkEnabled, SettingsOptions::CoolingTempBlink}, /*Cooling blink warning*/
|
{SETTINGS_DESC(SettingsItemIndex::CooldownBlink), nullptr, settings_displayCoolingBlinkEnabled, SettingsOptions::CoolingTempBlink}, /*Cooling blink warning*/
|
||||||
{SETTINGS_DESC(SettingsItemIndex::ScrollingSpeed), nullptr, settings_displayScrollSpeed, SettingsOptions::DescriptionScrollSpeed}, /*Scroll Speed for descriptions*/
|
{SETTINGS_DESC(SettingsItemIndex::ScrollingSpeed), nullptr, settings_displayScrollSpeed, SettingsOptions::DescriptionScrollSpeed}, /*Scroll Speed for descriptions*/
|
||||||
{SETTINGS_DESC(SettingsItemIndex::ReverseButtonTempChange), nullptr, settings_displayReverseButtonTempChangeEnabled,
|
{SETTINGS_DESC(SettingsItemIndex::ReverseButtonTempChange), nullptr, settings_displayReverseButtonTempChangeEnabled,
|
||||||
SettingsOptions::ReverseButtonTempChangeEnabled}, /* Reverse Temp change buttons + - */
|
SettingsOptions::ReverseButtonTempChangeEnabled}, /* Reverse Temp change buttons + - */
|
||||||
{SETTINGS_DESC(SettingsItemIndex::AnimSpeed), nullptr, settings_displayAnimationSpeed, SettingsOptions::AnimationSpeed}, /*Animation Speed adjustment */
|
{SETTINGS_DESC(SettingsItemIndex::AnimSpeed), nullptr, settings_displayAnimationSpeed, SettingsOptions::AnimationSpeed}, /*Animation Speed adjustment */
|
||||||
{SETTINGS_DESC(SettingsItemIndex::AnimLoop), nullptr, settings_displayAnimationLoop, SettingsOptions::AnimationLoop}, /*Animation Loop switch */
|
{SETTINGS_DESC(SettingsItemIndex::AnimLoop), nullptr, settings_displayAnimationLoop, SettingsOptions::AnimationLoop}, /*Animation Loop switch */
|
||||||
{SETTINGS_DESC(SettingsItemIndex::Brightness), nullptr, settings_displayBrightnessLevel, SettingsOptions::OLEDBrightness}, /*Brightness Level*/
|
{SETTINGS_DESC(SettingsItemIndex::Brightness), nullptr, settings_displayBrightnessLevel, SettingsOptions::OLEDBrightness}, /*Brightness Level*/
|
||||||
{SETTINGS_DESC(SettingsItemIndex::ColourInversion), nullptr, settings_displayInvertColor, SettingsOptions::OLEDInversion}, /*Invert screen colour*/
|
{SETTINGS_DESC(SettingsItemIndex::ColourInversion), nullptr, settings_displayInvertColor, SettingsOptions::OLEDInversion}, /*Invert screen colour*/
|
||||||
{0, nullptr, nullptr, SettingsOptions::SettingsOptionsLength} // end of menu marker. DO NOT REMOVE
|
{SETTINGS_DESC(SettingsItemIndex::AdvancedIdle), nullptr, settings_displayAdvancedIDLEScreens, SettingsOptions::DetailedIDLE}, /* Advanced idle screen*/
|
||||||
|
{SETTINGS_DESC(SettingsItemIndex::AdvancedSoldering), nullptr, settings_displayAdvancedSolderingScreens, SettingsOptions::DetailedSoldering}, /* Advanced soldering screen*/
|
||||||
|
{0, nullptr, nullptr, SettingsOptions::SettingsOptionsLength} // end of menu marker. DO NOT REMOVE
|
||||||
};
|
};
|
||||||
const menuitem PowerSavingMenu[] = {
|
const menuitem PowerSavingMenu[] = {
|
||||||
/*
|
/*
|
||||||
@@ -225,8 +229,6 @@ const menuitem advancedMenu[] = {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Power limit
|
* Power limit
|
||||||
* Detailed IDLE
|
|
||||||
* Detailed Soldering
|
|
||||||
* Calibrate Temperature
|
* Calibrate Temperature
|
||||||
* Calibrate Input V
|
* Calibrate Input V
|
||||||
* Reset Settings
|
* Reset Settings
|
||||||
@@ -237,8 +239,6 @@ const menuitem advancedMenu[] = {
|
|||||||
* Power Pulse Duration
|
* Power Pulse Duration
|
||||||
*/
|
*/
|
||||||
{SETTINGS_DESC(SettingsItemIndex::PowerLimit), nullptr, settings_displayPowerLimit, SettingsOptions::PowerLimit}, /*Power limit*/
|
{SETTINGS_DESC(SettingsItemIndex::PowerLimit), nullptr, settings_displayPowerLimit, SettingsOptions::PowerLimit}, /*Power limit*/
|
||||||
{SETTINGS_DESC(SettingsItemIndex::AdvancedIdle), nullptr, settings_displayAdvancedIDLEScreens, SettingsOptions::DetailedIDLE}, /* Advanced idle screen*/
|
|
||||||
{SETTINGS_DESC(SettingsItemIndex::AdvancedSoldering), nullptr, settings_displayAdvancedSolderingScreens, SettingsOptions::DetailedSoldering}, /* Advanced soldering screen*/
|
|
||||||
{SETTINGS_DESC(SettingsItemIndex::SettingsReset), settings_setResetSettings, settings_displayResetSettings, SettingsOptions::SettingsOptionsLength}, /*Resets settings*/
|
{SETTINGS_DESC(SettingsItemIndex::SettingsReset), settings_setResetSettings, settings_displayResetSettings, SettingsOptions::SettingsOptionsLength}, /*Resets settings*/
|
||||||
{SETTINGS_DESC(SettingsItemIndex::TemperatureCalibration), settings_setCalibrate, settings_displayCalibrate, SettingsOptions::SettingsOptionsLength}, /*Calibrate tip*/
|
{SETTINGS_DESC(SettingsItemIndex::TemperatureCalibration), settings_setCalibrate, settings_displayCalibrate, SettingsOptions::SettingsOptionsLength}, /*Calibrate tip*/
|
||||||
{SETTINGS_DESC(SettingsItemIndex::VoltageCalibration), settings_setCalibrateVIN, settings_displayCalibrateVIN, SettingsOptions::SettingsOptionsLength}, /*Voltage input cal*/
|
{SETTINGS_DESC(SettingsItemIndex::VoltageCalibration), settings_setCalibrateVIN, settings_displayCalibrateVIN, SettingsOptions::SettingsOptionsLength}, /*Voltage input cal*/
|
||||||
@@ -352,8 +352,12 @@ static bool settings_displayQCInputV(void) {
|
|||||||
|
|
||||||
static bool settings_displayPDNegTimeout(void) {
|
static bool settings_displayPDNegTimeout(void) {
|
||||||
printShortDescription(SettingsItemIndex::PDNegTimeout, 5);
|
printShortDescription(SettingsItemIndex::PDNegTimeout, 5);
|
||||||
OLED::printNumber(getSettingValue(SettingsOptions::PDNegTimeout), 2, FontStyle::LARGE);
|
auto value = getSettingValue(SettingsOptions::PDNegTimeout);
|
||||||
|
if (value == 0) {
|
||||||
|
OLED::print(translatedString(Tr->OffString), FontStyle::LARGE);
|
||||||
|
} else {
|
||||||
|
OLED::printNumber(value, 2, FontStyle::LARGE);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -409,7 +413,7 @@ static bool settings_displayShutdownTime(void) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
static bool settings_setTempF(void) {
|
static bool settings_setTempF(void) {
|
||||||
nextSettingValue(SettingsOptions::TemperatureInF);
|
bool res = nextSettingValue(SettingsOptions::TemperatureInF);
|
||||||
uint16_t BoostTemp = getSettingValue(SettingsOptions::BoostTemp);
|
uint16_t BoostTemp = getSettingValue(SettingsOptions::BoostTemp);
|
||||||
uint16_t SolderingTemp = getSettingValue(SettingsOptions::SolderingTemp);
|
uint16_t SolderingTemp = getSettingValue(SettingsOptions::SolderingTemp);
|
||||||
uint16_t SleepTemp = getSettingValue(SettingsOptions::SleepTemp);
|
uint16_t SleepTemp = getSettingValue(SettingsOptions::SleepTemp);
|
||||||
@@ -438,7 +442,7 @@ static bool settings_setTempF(void) {
|
|||||||
setSettingValue(SettingsOptions::SolderingTemp, SolderingTemp);
|
setSettingValue(SettingsOptions::SolderingTemp, SolderingTemp);
|
||||||
setSettingValue(SettingsOptions::SleepTemp, SleepTemp);
|
setSettingValue(SettingsOptions::SleepTemp, SleepTemp);
|
||||||
|
|
||||||
return false;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool settings_displayTempF(void) {
|
static bool settings_displayTempF(void) {
|
||||||
@@ -641,7 +645,7 @@ static void setTipOffset() {
|
|||||||
OLED::refresh();
|
OLED::refresh();
|
||||||
osDelay(100);
|
osDelay(100);
|
||||||
}
|
}
|
||||||
setoffset = TipThermoModel::convertTipRawADCTouV(offset / 16);
|
setoffset = TipThermoModel::convertTipRawADCTouV(offset / 16, true);
|
||||||
}
|
}
|
||||||
setSettingValue(SettingsOptions::CalibrationOffset, setoffset);
|
setSettingValue(SettingsOptions::CalibrationOffset, setoffset);
|
||||||
OLED::clearScreen();
|
OLED::clearScreen();
|
||||||
|
|||||||
@@ -10,26 +10,41 @@
|
|||||||
#include <power.hpp>
|
#include <power.hpp>
|
||||||
|
|
||||||
static int32_t PWMToX10Watts(uint8_t pwm, uint8_t sample);
|
static int32_t PWMToX10Watts(uint8_t pwm, uint8_t sample);
|
||||||
|
const int fastPWMChangeoverPoint = 128;
|
||||||
|
const int fastPWMChangeoverTolerance = 16;
|
||||||
|
|
||||||
expMovingAverage<uint32_t, wattHistoryFilter> x10WattHistory = {0};
|
expMovingAverage<uint32_t, wattHistoryFilter> x10WattHistory = {0};
|
||||||
|
|
||||||
|
bool shouldBeUsingFastPWMMode(const uint8_t pwmTicks) {
|
||||||
|
// Determine if we should use slow or fast PWM mode
|
||||||
|
// Crossover between modes set around the midpoint of the PWM control point
|
||||||
|
static bool lastPWMWasFast = true;
|
||||||
|
if (pwmTicks > (fastPWMChangeoverPoint + fastPWMChangeoverTolerance) && lastPWMWasFast) {
|
||||||
|
lastPWMWasFast = false;
|
||||||
|
} else if (pwmTicks < (fastPWMChangeoverPoint - fastPWMChangeoverTolerance) && !lastPWMWasFast) {
|
||||||
|
lastPWMWasFast = true;
|
||||||
|
}
|
||||||
|
return lastPWMWasFast;
|
||||||
|
}
|
||||||
|
|
||||||
int32_t tempToX10Watts(int32_t rawTemp) {
|
int32_t tempToX10Watts(int32_t rawTemp) {
|
||||||
// mass is in milliJ/*C, rawC is raw per degree C
|
// mass is in x10J/*C, rawC is raw per degree C
|
||||||
// returns milliWatts needed to raise/lower a mass by rawTemp
|
// returns x10Watts needed to raise/lower a mass by rawTemp
|
||||||
// degrees in one cycle.
|
// degrees in one cycle.
|
||||||
int32_t milliJoules = tipMass * rawTemp;
|
int32_t x10Watts = TIP_THERMAL_MASS * rawTemp;
|
||||||
return milliJoules;
|
return x10Watts;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setTipX10Watts(int32_t mw) {
|
void setTipX10Watts(int32_t mw) {
|
||||||
int32_t output = X10WattsToPWM(mw, 1);
|
int32_t outputPWMLevel = X10WattsToPWM(mw, 1);
|
||||||
setTipPWM(output);
|
const bool shouldUseFastPWM = shouldBeUsingFastPWMMode(outputPWMLevel);
|
||||||
uint32_t actualMilliWatts = PWMToX10Watts(output, 0);
|
setTipPWM(outputPWMLevel, shouldUseFastPWM);
|
||||||
|
uint32_t actualMilliWatts = PWMToX10Watts(outputPWMLevel, 0);
|
||||||
|
|
||||||
x10WattHistory.update(actualMilliWatts);
|
x10WattHistory.update(actualMilliWatts);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t availableW10(uint8_t sample) {
|
uint32_t availableW10(uint8_t sample) {
|
||||||
// P = V^2 / R, v*v = v^2 * 100
|
// P = V^2 / R, v*v = v^2 * 100
|
||||||
// R = R*10
|
// R = R*10
|
||||||
// P therefore is in V^2*100/R*10 = W*10.
|
// P therefore is in V^2*100/R*10 = W*10.
|
||||||
@@ -45,26 +60,21 @@ static uint32_t availableW10(uint8_t sample) {
|
|||||||
// availableMilliWattsX10 is now an accurate representation
|
// availableMilliWattsX10 is now an accurate representation
|
||||||
return availableWattsX10;
|
return availableWattsX10;
|
||||||
}
|
}
|
||||||
|
uint8_t X10WattsToPWM(int32_t x10Watts, uint8_t sample) {
|
||||||
uint8_t X10WattsToPWM(int32_t milliWatts, uint8_t sample) {
|
// Scale input x10Watts to the pwm range available
|
||||||
// Scale input milliWatts to the pwm range available
|
if (x10Watts < 0) {
|
||||||
if (milliWatts < 1) {
|
|
||||||
// keep the battery voltage updating the filter
|
// keep the battery voltage updating the filter
|
||||||
getInputVoltageX10(getSettingValue(SettingsOptions::VoltageDiv), sample);
|
getInputVoltageX10(getSettingValue(SettingsOptions::VoltageDiv), sample);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate desired milliwatts as a percentage of availableW10
|
// Calculate desired x10Watts as a percentage of availableW10
|
||||||
uint32_t pwm;
|
uint32_t pwm;
|
||||||
do {
|
pwm = (powerPWM * x10Watts) / availableW10(sample);
|
||||||
pwm = (powerPWM * milliWatts) / availableW10(sample);
|
if (pwm > powerPWM) {
|
||||||
if (pwm > powerPWM) {
|
// constrain to max PWM counter
|
||||||
// constrain to max PWM counter, shouldn't be possible,
|
pwm = powerPWM;
|
||||||
// but small cost for safety to avoid wraps
|
}
|
||||||
pwm = powerPWM;
|
|
||||||
}
|
|
||||||
} while (tryBetterPWM(pwm));
|
|
||||||
|
|
||||||
return pwm;
|
return pwm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,17 +12,18 @@
|
|||||||
#include "LIS2DH12.hpp"
|
#include "LIS2DH12.hpp"
|
||||||
#include "MMA8652FC.hpp"
|
#include "MMA8652FC.hpp"
|
||||||
#include "MSA301.h"
|
#include "MSA301.h"
|
||||||
#include "Model_Config.h"
|
|
||||||
#include "QC3.h"
|
#include "QC3.h"
|
||||||
#include "SC7A20.hpp"
|
#include "SC7A20.hpp"
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
#include "TipThermoModel.h"
|
#include "TipThermoModel.h"
|
||||||
#include "cmsis_os.h"
|
#include "cmsis_os.h"
|
||||||
|
#include "configuration.h"
|
||||||
#include "history.hpp"
|
#include "history.hpp"
|
||||||
#include "main.hpp"
|
#include "main.hpp"
|
||||||
#include "power.hpp"
|
#include "power.hpp"
|
||||||
#include "stdlib.h"
|
#include "stdlib.h"
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
|
|
||||||
#define MOVFilter 8
|
#define MOVFilter 8
|
||||||
uint8_t accelInit = 0;
|
uint8_t accelInit = 0;
|
||||||
TickType_t lastMovementTime = 0;
|
TickType_t lastMovementTime = 0;
|
||||||
|
|||||||
@@ -20,36 +20,36 @@ TaskHandle_t pidTaskNotification = NULL;
|
|||||||
uint32_t currentTempTargetDegC = 0; // Current temperature target in C
|
uint32_t currentTempTargetDegC = 0; // Current temperature target in C
|
||||||
int32_t powerSupplyWattageLimit = 0;
|
int32_t powerSupplyWattageLimit = 0;
|
||||||
bool heaterThermalRunaway = false;
|
bool heaterThermalRunaway = false;
|
||||||
|
|
||||||
|
static int32_t getPIDResultX10Watts(int32_t tError);
|
||||||
|
static void detectThermalRunaway(const int16_t currentTipTempInC, const int tError);
|
||||||
|
static void setOutputx10WattsViaFilters(int32_t x10Watts);
|
||||||
|
static int32_t getX10WattageLimits();
|
||||||
|
|
||||||
/* StartPIDTask function */
|
/* StartPIDTask function */
|
||||||
void startPIDTask(void const *argument __unused) {
|
void startPIDTask(void const *argument __unused) {
|
||||||
/*
|
/*
|
||||||
* We take the current tip temperature & evaluate the next step for the tip
|
* We take the current tip temperature & evaluate the next step for the tip
|
||||||
* control PWM.
|
* control PWM.
|
||||||
*/
|
*/
|
||||||
setTipX10Watts(0); // disable the output driver if the output is set to be off
|
setTipX10Watts(0); // disable the output at startup
|
||||||
TickType_t lastPowerPulseStart = 0;
|
|
||||||
TickType_t lastPowerPulseEnd = 0;
|
|
||||||
|
|
||||||
history<int32_t, PID_TIM_HZ> tempError = {{0}, 0, 0};
|
currentTempTargetDegC = 0; // Force start with no output (off). If in sleep / soldering this will
|
||||||
currentTempTargetDegC = 0; // Force start with no output (off). If in sleep / soldering this will
|
// be over-ridden rapidly
|
||||||
// be over-ridden rapidly
|
pidTaskNotification = xTaskGetCurrentTaskHandle();
|
||||||
pidTaskNotification = xTaskGetCurrentTaskHandle();
|
uint32_t PIDTempTarget = 0;
|
||||||
uint32_t PIDTempTarget = 0;
|
|
||||||
uint16_t tipTempCRunawayTemp = 0;
|
|
||||||
TickType_t runawaylastChangeTime = 0;
|
|
||||||
// Pre-seed the adc filters
|
// Pre-seed the adc filters
|
||||||
for (int i = 0; i < 64; i++) {
|
for (int i = 0; i < 128; i++) {
|
||||||
vTaskDelay(2);
|
vTaskDelay(5);
|
||||||
TipThermoModel::getTipInC(true);
|
TipThermoModel::getTipInC(true);
|
||||||
|
getInputVoltageX10(getSettingValue(SettingsOptions::VoltageDiv), 1);
|
||||||
}
|
}
|
||||||
#ifdef SLEW_LIMIT
|
int32_t x10WattsOut = 0;
|
||||||
int32_t x10WattsOutLast = 0;
|
|
||||||
#endif
|
|
||||||
for (;;) {
|
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
x10WattsOut = 0;
|
||||||
|
// This is a call to block this thread until the ADC does its samples
|
||||||
if (ulTaskNotifyTake(pdTRUE, 2000)) {
|
if (ulTaskNotifyTake(pdTRUE, 2000)) {
|
||||||
// This is a call to block this thread until the ADC does its samples
|
|
||||||
int32_t x10WattsOut = 0;
|
|
||||||
// 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;
|
||||||
@@ -63,116 +63,163 @@ void startPIDTask(void const *argument __unused) {
|
|||||||
if (PIDTempTarget > TipThermoModel::getTipMaxInC()) {
|
if (PIDTempTarget > TipThermoModel::getTipMaxInC()) {
|
||||||
PIDTempTarget = TipThermoModel::getTipMaxInC();
|
PIDTempTarget = TipThermoModel::getTipMaxInC();
|
||||||
}
|
}
|
||||||
// Convert the current tip to degree's C
|
int32_t tError = PIDTempTarget - currentTipTempInC;
|
||||||
|
|
||||||
// As we get close to our target, temp noise causes the system
|
|
||||||
// to be unstable. Use a rolling average to dampen it.
|
|
||||||
// We overshoot by roughly 1 degree C.
|
|
||||||
// This helps stabilize the display.
|
|
||||||
int32_t tError = PIDTempTarget - currentTipTempInC + 1;
|
|
||||||
tError = tError > INT16_MAX ? INT16_MAX : tError;
|
|
||||||
tError = tError < INT16_MIN ? INT16_MIN : tError;
|
|
||||||
tempError.update(tError);
|
|
||||||
|
|
||||||
// Now for the PID!
|
|
||||||
|
|
||||||
// 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.
|
|
||||||
|
|
||||||
int32_t x10WattsNeeded = tempToX10Watts(tError);
|
|
||||||
// note that milliWattsNeeded is sometimes negative, this counters overshoot
|
|
||||||
// from I term's inertia.
|
|
||||||
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).
|
|
||||||
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
|
|
||||||
// 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.
|
|
||||||
|
|
||||||
// Check for thermal runaway, where it has been x seconds with negligible (y) temp rise
|
|
||||||
// While trying to actively heat
|
|
||||||
if ((tError > THERMAL_RUNAWAY_TEMP_C)) {
|
|
||||||
// Temp error is high
|
|
||||||
int16_t delta = (int16_t)currentTipTempInC - (int16_t)tipTempCRunawayTemp;
|
|
||||||
if (delta < 0) {
|
|
||||||
delta = -delta;
|
|
||||||
}
|
|
||||||
if (delta > THERMAL_RUNAWAY_TEMP_C) {
|
|
||||||
// We have heated up more than the threshold, reset the timer
|
|
||||||
tipTempCRunawayTemp = currentTipTempInC;
|
|
||||||
runawaylastChangeTime = xTaskGetTickCount();
|
|
||||||
} else {
|
|
||||||
if ((xTaskGetTickCount() - runawaylastChangeTime) > (THERMAL_RUNAWAY_TIME_SEC * TICKS_SECOND)) {
|
|
||||||
// It has taken too long to rise
|
|
||||||
heaterThermalRunaway = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
tipTempCRunawayTemp = currentTipTempInC;
|
|
||||||
runawaylastChangeTime = xTaskGetTickCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
detectThermalRunaway(currentTipTempInC, tError);
|
||||||
|
x10WattsOut = getPIDResultX10Watts(tError);
|
||||||
} else {
|
} else {
|
||||||
tipTempCRunawayTemp = currentTipTempInC;
|
detectThermalRunaway(currentTipTempInC, 0);
|
||||||
runawaylastChangeTime = xTaskGetTickCount();
|
|
||||||
}
|
}
|
||||||
|
setOutputx10WattsViaFilters(x10WattsOut);
|
||||||
// If the user turns on the option of using an occasional pulse to keep the power bank on
|
|
||||||
if (getSettingValue(SettingsOptions::KeepAwakePulse)) {
|
|
||||||
const TickType_t powerPulseWait = powerPulseWaitUnit * getSettingValue(SettingsOptions::KeepAwakePulseWait);
|
|
||||||
if (xTaskGetTickCount() - lastPowerPulseStart > powerPulseWait) {
|
|
||||||
const TickType_t powerPulseDuration = powerPulseDurationUnit * getSettingValue(SettingsOptions::KeepAwakePulseDuration);
|
|
||||||
lastPowerPulseStart = xTaskGetTickCount();
|
|
||||||
lastPowerPulseEnd = lastPowerPulseStart + powerPulseDuration;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If current PID is less than the pulse level, check if we want to constrain to the pulse as the floor
|
|
||||||
if (x10WattsOut < getSettingValue(SettingsOptions::KeepAwakePulse) && xTaskGetTickCount() < lastPowerPulseEnd) {
|
|
||||||
x10WattsOut = getSettingValue(SettingsOptions::KeepAwakePulse);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Secondary safety check to forcefully disable header when within ADC noise of top of ADC
|
|
||||||
if (getTipRawTemp(0) > (0x7FFF - 32)) {
|
|
||||||
x10WattsOut = 0;
|
|
||||||
}
|
|
||||||
if (heaterThermalRunaway) {
|
|
||||||
x10WattsOut = 0;
|
|
||||||
}
|
|
||||||
if (getSettingValue(SettingsOptions::PowerLimit) && x10WattsOut > (getSettingValue(SettingsOptions::PowerLimit) * 10)) {
|
|
||||||
x10WattsOut = getSettingValue(SettingsOptions::PowerLimit) * 10;
|
|
||||||
}
|
|
||||||
if (powerSupplyWattageLimit && x10WattsOut > powerSupplyWattageLimit * 10) {
|
|
||||||
x10WattsOut = powerSupplyWattageLimit * 10;
|
|
||||||
}
|
|
||||||
#ifdef SLEW_LIMIT
|
|
||||||
if (x10WattsOut - x10WattsOutLast > SLEW_LIMIT) {
|
|
||||||
x10WattsOut = x10WattsOutLast + SLEW_LIMIT;
|
|
||||||
}
|
|
||||||
if (x10WattsOut < 0) {
|
|
||||||
x10WattsOut = 0;
|
|
||||||
}
|
|
||||||
x10WattsOutLast = x10WattsOut;
|
|
||||||
#endif
|
|
||||||
setTipX10Watts(x10WattsOut);
|
|
||||||
#ifdef DEBUG_UART_OUTPUT
|
|
||||||
log_system_state(x10WattsOut);
|
|
||||||
#endif
|
|
||||||
resetWatchdog();
|
|
||||||
} else {
|
} else {
|
||||||
// ADC interrupt timeout
|
// ADC interrupt timeout
|
||||||
setTipPWM(0);
|
setTipPWM(0, false);
|
||||||
}
|
}
|
||||||
|
#ifdef DEBUG_UART_OUTPUT
|
||||||
|
log_system_state(x10WattsOut);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class T = int32_t> struct Integrator {
|
||||||
|
T sum;
|
||||||
|
|
||||||
|
T update(const T val, const int32_t inertia, const int32_t gain, const int32_t rate, const int32_t limit) {
|
||||||
|
// Decay the old value. This is a simplified formula that still works with decent results
|
||||||
|
// Ideally we would have used an exponential decay but the computational effort required
|
||||||
|
// by exp function is just not justified here in respect to the outcome
|
||||||
|
sum = (sum * (100 - (inertia / rate))) / 100;
|
||||||
|
// Add the new value x integration interval ( 1 / rate)
|
||||||
|
sum += (gain * val) / rate;
|
||||||
|
|
||||||
|
// limit the output
|
||||||
|
if (sum > limit)
|
||||||
|
sum = limit;
|
||||||
|
else if (sum < -limit)
|
||||||
|
sum = -limit;
|
||||||
|
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set(T const val) { sum = val; }
|
||||||
|
|
||||||
|
T get(bool positiveOnly = true) const { return (positiveOnly) ? ((sum > 0) ? sum : 0) : sum; }
|
||||||
|
};
|
||||||
|
int32_t getPIDResultX10Watts(int32_t setpointDelta) {
|
||||||
|
static TickType_t lastCall = 0;
|
||||||
|
static Integrator<int32_t> powerStore = {0};
|
||||||
|
|
||||||
|
const int rate = 1000 / (xTaskGetTickCount() - lastCall);
|
||||||
|
lastCall = xTaskGetTickCount();
|
||||||
|
// Sandman note:
|
||||||
|
// PID Challenge - we have a small thermal mass that we to want heat up as fast as possible but we don't
|
||||||
|
// want to overshot excessively (if at all) the setpoint temperature. In the same time we have 'imprecise'
|
||||||
|
// instant temperature measurements. The nature of temperature reading imprecision is not necessarily
|
||||||
|
// related to the sensor (thermocouple) or DAQ system, that otherwise are fairly decent. The real issue is
|
||||||
|
// the thermal inertia. We basically read the temperature in the window between two heating sessions when
|
||||||
|
// the output is off. However, the heater temperature does not dissipate instantly into the tip mass so
|
||||||
|
// at any moment right after heating, the thermocouple would sense a temperature significantly higher than
|
||||||
|
// moments later. We could use longer delays but that would slow the PID loop and that would lead to other
|
||||||
|
// negative side effects. As a result, we can only rely on the I term but with a twist. Instead of a simple
|
||||||
|
// integrator we are going to use a self decaying integrator that acts more like a dual I term / P term
|
||||||
|
// rather than a plain I term. Depending on the circumstances, like when the delta temperature is large,
|
||||||
|
// it acts more like a P term whereas on closing to setpoint it acts increasingly closer to a plain I term.
|
||||||
|
// So in a sense, we have a bit of both.
|
||||||
|
// So there we go...
|
||||||
|
|
||||||
|
// P = (Thermal Mass) x (Delta Temperature ) / 1sec, where thermal mass is in X10 J / °C and
|
||||||
|
// delta temperature is in °C. The result is the power in X10 W needed to raise (or decrease!) the
|
||||||
|
// tip temperature with (Delta Temperature ) °C in 1 second.
|
||||||
|
// Note on powerStore. On update, if the value is provided in X10 (W) units then inertia shall be provided
|
||||||
|
// in X10 (J / °C) units as well. Also, powerStore is updated with a gain of 2. Where this comes from: The actual
|
||||||
|
// power CMOS is controlled by TIM3->CTR1 (that is software modulated - on/off - by TIM2-CTR4 interrupts). However,
|
||||||
|
// TIM3->CTR1 is configured with a duty cycle of 50% so, in real, we get only 50% of the presumed power output
|
||||||
|
// so we basically double the need (gain = 2) to get what we want.
|
||||||
|
return powerStore.update(TIP_THERMAL_MASS * setpointDelta, // the required power
|
||||||
|
TIP_THERMAL_MASS, // Inertia, smaller numbers increase dominance of the previous value
|
||||||
|
2, // gain
|
||||||
|
rate, // PID cycle frequency
|
||||||
|
getX10WattageLimits());
|
||||||
|
}
|
||||||
|
|
||||||
|
void detectThermalRunaway(const int16_t currentTipTempInC, const int tError) {
|
||||||
|
static uint16_t tipTempCRunawayTemp = 0;
|
||||||
|
static TickType_t runawaylastChangeTime = 0;
|
||||||
|
|
||||||
|
// Check for thermal runaway, where it has been x seconds with negligible (y) temp rise
|
||||||
|
// While trying to actively heat
|
||||||
|
if ((tError > THERMAL_RUNAWAY_TEMP_C)) {
|
||||||
|
// Temp error is high
|
||||||
|
int16_t delta = (int16_t)currentTipTempInC - (int16_t)tipTempCRunawayTemp;
|
||||||
|
if (delta < 0) {
|
||||||
|
delta = -delta;
|
||||||
|
}
|
||||||
|
if (delta > THERMAL_RUNAWAY_TEMP_C) {
|
||||||
|
// We have heated up more than the threshold, reset the timer
|
||||||
|
tipTempCRunawayTemp = currentTipTempInC;
|
||||||
|
runawaylastChangeTime = xTaskGetTickCount();
|
||||||
|
} else {
|
||||||
|
if ((xTaskGetTickCount() - runawaylastChangeTime) > (THERMAL_RUNAWAY_TIME_SEC * TICKS_SECOND)) {
|
||||||
|
// It has taken too long to rise
|
||||||
|
heaterThermalRunaway = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tipTempCRunawayTemp = currentTipTempInC;
|
||||||
|
runawaylastChangeTime = xTaskGetTickCount();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t getX10WattageLimits() {
|
||||||
|
int32_t limit = availableW10(0);
|
||||||
|
|
||||||
|
if (getSettingValue(SettingsOptions::PowerLimit) && limit > (getSettingValue(SettingsOptions::PowerLimit) * 10)) {
|
||||||
|
limit = getSettingValue(SettingsOptions::PowerLimit) * 10;
|
||||||
|
}
|
||||||
|
if (powerSupplyWattageLimit && limit > powerSupplyWattageLimit * 10) {
|
||||||
|
limit = powerSupplyWattageLimit * 10;
|
||||||
|
}
|
||||||
|
return limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setOutputx10WattsViaFilters(int32_t x10WattsOut) {
|
||||||
|
static TickType_t lastPowerPulseStart = 0;
|
||||||
|
static TickType_t lastPowerPulseEnd = 0;
|
||||||
|
#ifdef SLEW_LIMIT
|
||||||
|
static int32_t x10WattsOutLast = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// If the user turns on the option of using an occasional pulse to keep the power bank on
|
||||||
|
if (getSettingValue(SettingsOptions::KeepAwakePulse)) {
|
||||||
|
const TickType_t powerPulseWait = powerPulseWaitUnit * getSettingValue(SettingsOptions::KeepAwakePulseWait);
|
||||||
|
if (xTaskGetTickCount() - lastPowerPulseStart > powerPulseWait) {
|
||||||
|
const TickType_t powerPulseDuration = powerPulseDurationUnit * getSettingValue(SettingsOptions::KeepAwakePulseDuration);
|
||||||
|
lastPowerPulseStart = xTaskGetTickCount();
|
||||||
|
lastPowerPulseEnd = lastPowerPulseStart + powerPulseDuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If current PID is less than the pulse level, check if we want to constrain to the pulse as the floor
|
||||||
|
if (x10WattsOut < getSettingValue(SettingsOptions::KeepAwakePulse) && xTaskGetTickCount() < lastPowerPulseEnd) {
|
||||||
|
x10WattsOut = getSettingValue(SettingsOptions::KeepAwakePulse);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Secondary safety check to forcefully disable header when within ADC noise of top of ADC
|
||||||
|
if (getTipRawTemp(0) > (0x7FFF - 32)) {
|
||||||
|
x10WattsOut = 0;
|
||||||
|
}
|
||||||
|
if (heaterThermalRunaway) {
|
||||||
|
x10WattsOut = 0;
|
||||||
|
}
|
||||||
|
#ifdef SLEW_LIMIT
|
||||||
|
if (x10WattsOut - x10WattsOutLast > SLEW_LIMIT) {
|
||||||
|
x10WattsOut = x10WattsOutLast + SLEW_LIMIT;
|
||||||
|
}
|
||||||
|
if (x10WattsOut < 0) {
|
||||||
|
x10WattsOut = 0;
|
||||||
|
}
|
||||||
|
x10WattsOutLast = x10WattsOut;
|
||||||
|
#endif
|
||||||
|
setTipX10Watts(x10WattsOut);
|
||||||
|
resetWatchdog();
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user