Skip to content

Commit c308fe8

Browse files
authored
Pinecil v2 tune via PID (#1827)
* Start PWM after adc irq fully done * Filter len 4 * Use comparitor 2 on timer for wrap around * Update IRQ.cpp * Tip measurements are uint16_t Update BSP.cpp Update BSP.cpp * WiP PID move pid tuning to config Update PIDThread.cpp * Handle PWM Timer gitchy comparitor * Tuning * Dampen with Kd * Cleaning up * Use TemperatureType_t for getTipTemp() * Add small rolling average to user GUI temp to reduce flicker * Trigger PID when adc is skipped (will use old values)
1 parent 9c7ad43 commit c308fe8

File tree

16 files changed

+271
-178
lines changed

16 files changed

+271
-178
lines changed

source/Core/BSP/BSP_Power.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,8 @@ void power_check();
1919
// Returns the tip resistance in x10 ohms, so 7.5 = 75; 14=140 etc
2020
uint8_t getTipResistanceX10();
2121

22-
uint8_t getTipThermalMass();
23-
uint8_t getTipInertia();
24-
22+
uint16_t getTipThermalMass();
23+
uint16_t getTipInertia();
2524

2625
#ifdef __cplusplus
2726
}

source/Core/BSP/MHP30/BSP.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,7 @@ uint64_t getDeviceID() {
472472

473473
uint8_t preStartChecksDone() { return 1; }
474474

475-
uint8_t getTipThermalMass() { return TIP_THERMAL_MASS; }
476-
uint8_t getTipInertia() { return TIP_THERMAL_MASS; }
475+
uint16_t getTipThermalMass() { return TIP_THERMAL_MASS; }
476+
uint16_t getTipInertia() { return TIP_THERMAL_MASS; }
477477

478478
void showBootLogo(void) { BootLogo::handleShowingLogo((uint8_t *)FLASH_LOGOADDR); }

source/Core/BSP/Miniware/BSP.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,7 @@ bool isTipShorted() { return tipShorted; }
396396
#else
397397
bool isTipShorted() { return false; }
398398
#endif
399-
uint8_t getTipThermalMass() {
399+
uint16_t getTipThermalMass() {
400400
#ifdef TIP_RESISTANCE_SENSE_Pin
401401
if (lastTipResistance >= 80) {
402402
return TIP_THERMAL_MASS;
@@ -406,7 +406,7 @@ uint8_t getTipThermalMass() {
406406
return TIP_THERMAL_MASS;
407407
#endif
408408
}
409-
uint8_t getTipInertia() {
409+
uint16_t getTipInertia() {
410410
#ifdef TIP_RESISTANCE_SENSE_Pin
411411
if (lastTipResistance >= 80) {
412412
return TIP_THERMAL_MASS;

source/Core/BSP/Pinecil/BSP.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ uint8_t getTipResistanceX10() { return TIP_RESISTANCE; }
9797
bool isTipShorted() { return false; }
9898
uint8_t preStartChecksDone() { return 1; }
9999

100-
uint8_t getTipThermalMass() { return TIP_THERMAL_MASS; }
101-
uint8_t getTipInertia() { return TIP_THERMAL_MASS; }
100+
uint16_t getTipThermalMass() { return TIP_THERMAL_MASS; }
101+
uint16_t getTipInertia() { return TIP_THERMAL_MASS; }
102102

103103
void showBootLogo(void) { BootLogo::handleShowingLogo((uint8_t *)FLASH_LOGOADDR); }

source/Core/BSP/Pinecilv2/BSP.cpp

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -160,18 +160,8 @@ uint8_t getTipResistanceX10() {
160160
return lastTipResistance;
161161
}
162162

163-
uint8_t getTipThermalMass() {
164-
if (lastTipResistance >= 80) {
165-
return 65;
166-
}
167-
return 45;
168-
}
169-
uint8_t getTipInertia() {
170-
if (lastTipResistance >= 80) {
171-
return 90;
172-
}
173-
return 10;
174-
}
163+
uint16_t getTipThermalMass() { return 120; }
164+
uint16_t getTipInertia() { return 750; }
175165
// We want to calculate lastTipResistance
176166
// If tip is connected, and the tip is cold and the tip is not being heated
177167
// We can use the GPIO to inject a small current into the tip and measure this
@@ -180,7 +170,7 @@ uint8_t getTipInertia() {
180170
// Which is around 0.54mA this will induce:
181171
// 6 ohm tip -> 3.24mV (Real world ~= 3320)
182172
// 8 ohm tip -> 4.32mV (Real world ~= 4500)
183-
// Which is definitely measureable
173+
// Which is definitely measurable
184174
// Taking shortcuts here as we know we only really have to pick apart 6 and 8 ohm tips
185175
// These are reported as 60 and 75 respectively
186176
void performTipResistanceSampleReading() {

source/Core/BSP/Pinecilv2/IRQ.cpp

Lines changed: 46 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,17 @@ extern "C" {
1919
}
2020
void start_PWM_output(void);
2121

22-
#define ADC_Filter_Smooth 1
22+
#define ADC_Filter_Smooth 4 /* This basically smooths over one PWM cycle / set of readings */
2323
history<uint16_t, ADC_Filter_Smooth> ADC_Vin;
2424
history<uint16_t, ADC_Filter_Smooth> ADC_Temp;
2525
history<uint16_t, ADC_Filter_Smooth> ADC_Tip;
26-
volatile uint8_t ADCBurstCounter = 0;
27-
void adc_fifo_irq(void) {
26+
27+
// IRQ is called at the end of the 8 set readings, pop these from the FIFO and send to filters
28+
void adc_fifo_irq(void) {
2829
if (ADC_GetIntStatus(ADC_INT_FIFO_READY) == SET) {
2930
// Read out all entries in the fifo
3031
while (ADC_Get_FIFO_Count()) {
31-
ADCBurstCounter++;
32-
volatile uint32_t reading = ADC_Read_FIFO();
32+
uint32_t reading = ADC_Read_FIFO();
3333
// As per manual, 26 bit reading; lowest 16 are the ADC
3434
uint16_t sample = reading & 0xFFFF;
3535
uint8_t source = (reading >> 21) & 0b11111;
@@ -43,23 +43,16 @@ void adc_fifo_irq(void) {
4343
case VIN_ADC_CHANNEL:
4444
ADC_Vin.update(sample);
4545
break;
46-
4746
default:
4847
break;
4948
}
5049
}
51-
52-
if (ADCBurstCounter >= 8) {
53-
ADCBurstCounter = 0;
54-
start_PWM_output();
55-
56-
// unblock the PID controller thread
57-
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
58-
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
59-
if (pidTaskNotification) {
60-
vTaskNotifyGiveFromISR(pidTaskNotification, &xHigherPriorityTaskWoken);
61-
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
62-
}
50+
// unblock the PID controller thread
51+
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
52+
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
53+
if (pidTaskNotification) {
54+
vTaskNotifyGiveFromISR(pidTaskNotification, &xHigherPriorityTaskWoken);
55+
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
6356
}
6457
}
6558
}
@@ -100,16 +93,43 @@ void start_PWM_output(void) {
10093
PWM_Channel_Disable(PWM_Channel);
10194
switchToFastPWM();
10295
}
103-
TIMER_Enable(TIMER_CH0);
10496
}
10597

10698
// Timer 0 is used to co-ordinate the ADC and the output PWM
10799
void timer0_comp0_callback(void) {
108-
TIMER_Disable(TIMER_CH0);
109-
ADC_Start();
100+
if (PWM_Channel_Is_Enabled(PWM_Channel)) {
101+
// So there appears to be a bug _somewhere_ where sometimes the comparator doesn't fire
102+
// Its not re-occurring with specific values, so suspect its a weird bug
103+
// For now, we just skip the cycle and throw away the ADC readings. Its a waste but
104+
// It stops stupid glitches in readings, i'd take slight instability from the time jump
105+
// Over the readings we get that are borked as the header is left on
106+
// <Ralim 2023/10/14>
107+
PWM_Channel_Disable(PWM_Channel);
108+
// MSG("ALERT PWM Glitch\r\n");
109+
// Triger the PID now instead
110+
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
111+
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
112+
if (pidTaskNotification) {
113+
vTaskNotifyGiveFromISR(pidTaskNotification, &xHigherPriorityTaskWoken);
114+
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
115+
}
116+
}
117+
} else {
118+
ADC_Start();
119+
}
120+
TIMER_ClearIntStatus(TIMER_CH0, TIMER_COMP_ID_0);
121+
}
122+
void timer0_comp1_callback(void) {
123+
// Trigged at end of output cycle; turn off the tip PWM
124+
PWM_Channel_Disable(PWM_Channel);
125+
TIMER_ClearIntStatus(TIMER_CH0, TIMER_COMP_ID_1);
110126
}
111-
void timer0_comp1_callback(void) { PWM_Channel_Disable(PWM_Channel); } // Trigged at end of output cycle; turn off the tip PWM
112127

128+
void timer0_comp2_callback(void) {
129+
// Triggered at end of timer cycle; re-start the tip driver
130+
start_PWM_output();
131+
TIMER_ClearIntStatus(TIMER_CH0, TIMER_COMP_ID_2);
132+
}
113133
void switchToFastPWM(void) {
114134
inFastPWMMode = true;
115135
holdoffTicks = 10;
@@ -119,8 +139,8 @@ void switchToFastPWM(void) {
119139

120140
// ~10Hz
121141
TIMER_SetCompValue(TIMER_CH0, TIMER_COMP_ID_0, powerPWM + holdoffTicks);
122-
// Set divider to 10 ~= 10.5Hz
123142

143+
// Set divider to 10 ~= 10.5Hz
124144
uint32_t tmpVal = BL_RD_REG(TIMER_BASE, TIMER_TCDR);
125145

126146
tmpVal = BL_SET_REG_BITS_VAL(tmpVal, TIMER_TCDR2, 10);
@@ -139,7 +159,7 @@ void switchToSlowPWM(void) {
139159
// Adjust ADC
140160
TIMER_SetCompValue(TIMER_CH0, TIMER_COMP_ID_0, powerPWM + holdoffTicks);
141161

142-
// Set divider to 22
162+
// Set divider for ~ 5Hz
143163

144164
uint32_t tmpVal = BL_RD_REG(TIMER_BASE, TIMER_TCDR);
145165

@@ -193,5 +213,6 @@ uint16_t getADCHandleTemp(uint8_t sample) { return ADC_Temp.average(); }
193213

194214
uint16_t getADCVin(uint8_t sample) { return ADC_Vin.average(); }
195215

196-
// Returns either average or instant value. When sample is set the samples from the injected ADC are copied to the filter and then the raw reading is returned
216+
// Returns the current raw tip reading after any cleanup filtering
217+
// For Pinecil V2 we dont do any rolling filtering other than just averaging all 4 readings in the adc snapshot
197218
uint16_t getTipRawTemp(uint8_t sample) { return ADC_Tip.average() >> 1; }

source/Core/BSP/Pinecilv2/Setup.cpp

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ void setup_adc(void) {
102102

103103
adc_cfg.clkDiv = ADC_CLK_DIV_4;
104104
adc_cfg.vref = ADC_VREF_3P2V;
105-
adc_cfg.resWidth = ADC_DATA_WIDTH_14_WITH_64_AVERAGE;
105+
adc_cfg.resWidth = ADC_DATA_WIDTH_14_WITH_16_AVERAGE;
106106
adc_cfg.inputMode = ADC_INPUT_SINGLE_END;
107107
adc_cfg.v18Sel = ADC_V18_SEL_1P72V;
108108
adc_cfg.v11Sel = ADC_V11_SEL_1P1V;
@@ -111,7 +111,7 @@ void setup_adc(void) {
111111
adc_cfg.chopMode = ADC_CHOP_MOD_AZ_ON;
112112
adc_cfg.biasSel = ADC_BIAS_SEL_MAIN_BANDGAP;
113113
adc_cfg.vcm = ADC_PGA_VCM_1P6V;
114-
adc_cfg.offsetCalibEn = ENABLE;
114+
adc_cfg.offsetCalibEn = DISABLE;
115115
adc_cfg.offsetCalibVal = 0;
116116

117117
ADC_Disable();
@@ -120,7 +120,7 @@ void setup_adc(void) {
120120

121121
ADC_Init(&adc_cfg);
122122
adc_fifo_cfg.dmaEn = DISABLE;
123-
adc_fifo_cfg.fifoThreshold = ADC_FIFO_THRESHOLD_8;
123+
adc_fifo_cfg.fifoThreshold = ADC_FIFO_THRESHOLD_8; // Triger FIFO when all 8 measurements are done
124124
ADC_FIFO_Cfg(&adc_fifo_cfg);
125125
ADC_MIC_Bias_Disable();
126126
ADC_Tsen_Disable();
@@ -138,26 +138,29 @@ void setup_timer_scheduler() {
138138
TIMER_Disable(TIMER_CH0);
139139

140140
TIMER_CFG_Type cfg = {
141-
TIMER_CH0, // Channel
142-
TIMER_CLKSRC_32K, // Clock source
143-
TIMER_PRELOAD_TRIG_COMP0, // Trigger; reset after trigger 0
144-
TIMER_COUNT_PRELOAD, // Counter mode
145-
22, // Clock div
146-
(uint16_t)(powerPWM + holdoffTicks), // CH0 compare (adc)
147-
0, // CH1 compare (pwm out)
148-
0, // CH2 compare not used
149-
0, // Preload
141+
TIMER_CH0, // Channel
142+
TIMER_CLKSRC_32K, // Clock source
143+
TIMER_PRELOAD_TRIG_COMP2, // Trigger; reset after trigger 0
144+
TIMER_COUNT_PRELOAD, // Counter mode
145+
22, // Clock div
146+
(uint16_t)(powerPWM + holdoffTicks), // CH0 compare (adc)
147+
(uint16_t)(powerPWM), // CH1 compare (pwm out)
148+
(uint16_t)(powerPWM + holdoffTicks + tempMeasureTicks), // CH2 compare end of cycle
149+
0, // Preload
150150
};
151151
TIMER_Init(&cfg);
152152

153153
Timer_Int_Callback_Install(TIMER_CH0, TIMER_INT_COMP_0, timer0_comp0_callback);
154154
Timer_Int_Callback_Install(TIMER_CH0, TIMER_INT_COMP_1, timer0_comp1_callback);
155+
Timer_Int_Callback_Install(TIMER_CH0, TIMER_INT_COMP_2, timer0_comp2_callback);
155156

156157
TIMER_ClearIntStatus(TIMER_CH0, TIMER_COMP_ID_0);
157158
TIMER_ClearIntStatus(TIMER_CH0, TIMER_COMP_ID_1);
159+
TIMER_ClearIntStatus(TIMER_CH0, TIMER_COMP_ID_2);
158160

159161
TIMER_IntMask(TIMER_CH0, TIMER_INT_COMP_0, UNMASK);
160162
TIMER_IntMask(TIMER_CH0, TIMER_INT_COMP_1, UNMASK);
163+
TIMER_IntMask(TIMER_CH0, TIMER_INT_COMP_2, UNMASK);
161164
CPU_Interrupt_Enable(TIMER_CH0_IRQn);
162165
TIMER_Enable(TIMER_CH0);
163166
}

0 commit comments

Comments
 (0)