From 86944cc58a57254a3a81ce73a32c3026e4678e53 Mon Sep 17 00:00:00 2001 From: Tobias Frost Date: Fri, 21 Dec 2018 10:26:40 +0100 Subject: [PATCH 01/22] erste version rising protection (ungetested) --- Maiskolben_TFT/Maiskolben_TFT.ino | 50 +++++++++++++++++++++++++++++++ Maiskolben_TFT/definitions.h | 10 +++++-- 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/Maiskolben_TFT/Maiskolben_TFT.ino b/Maiskolben_TFT/Maiskolben_TFT.ino index f22c917..c79f1b2 100644 --- a/Maiskolben_TFT/Maiskolben_TFT.ino +++ b/Maiskolben_TFT/Maiskolben_TFT.ino @@ -234,6 +234,7 @@ void setup(void) { tft.setCursor(46,120); tft.print("HW Revision "); tft.print(revision); + //Allow Options to be set at startup delay(100); attachInterrupt(digitalPinToInterrupt(SW_STBY), optionMenu, LOW); @@ -638,6 +639,10 @@ void display(void) { case NO_TIP: tft.print(F("Error: No tip connected\nTip slipped out?")); break; + case FAILED_TO_HEAT: + tft.print(F("Error: Heating\nTemp not increasing.")); + break; + } tft.setTextSize(2); tft.setTextColor(YELLOW, BLACK); @@ -838,12 +843,19 @@ void display(void) { } void compute(void) { + static int16_t rising_protection_milestone_temperature = 0; + static int16_t rising_protection_timeout = WATCH_TEMP_PERIOD; + static int16_t rising_rebound_timeout = WATCH_TEMP_PERIOD; + static bool rising_protection_target_reached = false; + #ifndef USE_TFT_RESET setStandbyLayoff(!digitalRead(STBY_NO)); //do not measure while heater is active, potential is not neccessary == GND #endif cur_t = getTemperature(); if (off) { target_t = 0; + rising_protection_milestone_temperature = 0; + rising_protection_timeout = WATCH_TEMP_PERIOD; if (cur_t < adc_offset + TEMP_RISE) { threshold_counter = TEMP_UNDER_THRESHOLD; //reset counter } @@ -856,6 +868,44 @@ void compute(void) { if (cur_t-last_measured <= -30 && last_measured != 999) { setError(EXCESSIVE_FALL); //decrease of more than 30 degree is uncommon, short of ring and gnd is possible. } + + // if target_t has been lowered, make sure that we also lower that milestone temperature + if (target_t < rising_protection_milestone_temperature) { + rising_protection_milestone_temperature = target_t; + } + + // ensure that the temperature is actually rising when it should. + if(target_t - cur_t > WATCH_TEMP_DEACTIVATE ) { + // temperature is lower than setpoint by WATCH_TEMP_DEACTIVATE °C. + if (rising_protection_target_reached) { + // if previously we've been at target, e.g cleaning the tip might drop the temp significantly in a short time. + // so we need to temporarily suspend the protection and also continue it with a lower milestone. + if(rising_rebound_timeout) { rising_rebound_timeout--; } + else { + // rebound timeout expired, arm protection again. + rising_protection_milestone_temperature = cur_t + WATCH_TEMP_INCREASE; + rising_protection_target_reached = false; + } + } else { + // target was previously not reached, see if next milestone has been reached. + if (cur_t >= rising_protection_milestone_temperature + WATCH_TEMP_INCREASE) { + rising_protection_milestone_temperature = cur_t + WATCH_TEMP_INCREASE; // Yes, raise the bar. + rising_protection_timeout = WATCH_TEMP_PERIOD; // and give a new time window. + } else { + rising_protection_timeout--; // milestone not reached. + } + } + } else { + // we are near the target, time to disarm the protection.. + rising_protection_timeout = WATCH_TEMP_PERIOD; + rising_protection_target_reached = true; + } + + if(0 == rising_protection_timeout) { + // milestone not reached, E-STOP. + setError(FAILED_TO_HEAT); + } + if (cur_t < adc_offset + TEMP_RISE) { if (threshold_counter == 0) { setError(NOT_HEATING); //temperature is not reached in desired time, short of sensor and gnd too? diff --git a/Maiskolben_TFT/definitions.h b/Maiskolben_TFT/definitions.h index 58c2385..5f276eb 100644 --- a/Maiskolben_TFT/definitions.h +++ b/Maiskolben_TFT/definitions.h @@ -19,10 +19,15 @@ #define STANDBY_TIMEOUT 240 // seconds without any significant temperature drop, if exceeded it will standby #define OFF_TIMEOUT 900 // seconds in standby before turning off -#define TEMP_RISE 30 //threshold temperature, that must be exceeded delta in given time: +#define TEMP_RISE 30 //threshold temperature, that must be exceeded delta in given time: (from cold to ~70°C) #define TEMP_UNDER_THRESHOLD 80 // x (TIME_COMPUTE_IN_MS + DELAY_BEFORE_MEASURE) #define THRES_MAX_DECEED 2 //max times the threshold temperature may be undercut by the current temperature +#define WATCH_TEMP_PERIOD (750/20) // Time allowed (in meas cycles ~20ms) to raise temperature +#define WATCH_TEMP_REBOUND (1000/20) // Time after, when target has been reached previously, the temp may drop without re-arming the protection +#define WATCH_TEMP_INCREASE 10 // by this degrees. +#define WATCH_TEMP_DEACTIVATE 50 // deacticate the watching when we are this near the target (in °C) -- to avoid that loads + //Temperature in degree to rise at least in given time #define TEMP_MIN_RISE 10 //Time in that the temperature must rise by the set temperature @@ -96,7 +101,8 @@ typedef enum ERROR_TYPE { NOT_HEATING, NO_TIP, BATTERY_LOW, - USB_ONLY + USB_ONLY, + FAILED_TO_HEAT } error_type; const unsigned char power_cord [] PROGMEM = { From afa4ae69345bde9c2692a0d2e0a86b2246fd5cfc Mon Sep 17 00:00:00 2001 From: Tobias Frost Date: Sat, 22 Dec 2018 09:15:53 +0100 Subject: [PATCH 02/22] FAST_BOOT feature Define "FAST_BOOT" and the boot screen will be only shown briefly. To enter the options menu, you can press the button already when you turn on the Maiskolben (or while the Maiskolben splash screen is showing.) --- Maiskolben_TFT/Maiskolben_TFT.ino | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Maiskolben_TFT/Maiskolben_TFT.ino b/Maiskolben_TFT/Maiskolben_TFT.ino index c79f1b2..f89dcfb 100644 --- a/Maiskolben_TFT/Maiskolben_TFT.ino +++ b/Maiskolben_TFT/Maiskolben_TFT.ino @@ -12,6 +12,9 @@ */ //#define USE_TFT_RESET +/* show splash screen only a short time; to enter options, press power button when turning the maiskolben on. */ +#define FAST_BOOT + /* * If red is blue and blue is red change this * If not sure, leave commented, you will be shown a setup screen @@ -222,6 +225,9 @@ void setup(void) { if (force_menu) optionMenu(); else { updateRevision(); +#ifdef FAST_BOOT + attachInterrupt(digitalPinToInterrupt(SW_STBY), optionMenu, LOW); +#endif tft.drawBitmap(0, 20, maiskolben, 160, 64, YELLOW); tft.setCursor(20,86); tft.setTextColor(YELLOW); @@ -235,13 +241,17 @@ void setup(void) { tft.print("HW Revision "); tft.print(revision); +#ifdef FAST_BOOT //Allow Options to be set at startup + delay(200); +#else delay(100); attachInterrupt(digitalPinToInterrupt(SW_STBY), optionMenu, LOW); for (int i = 0; i < 10 && !menu_dismissed; i++) { digitalWrite(HEAT_LED, i % 2); delay(250); } +#endif detachInterrupt(digitalPinToInterrupt(SW_STBY)); } /* From 1adbf12710be070717a0e9b2a57a61b4b357bb19 Mon Sep 17 00:00:00 2001 From: Tobias Frost Date: Sat, 22 Dec 2018 10:20:50 +0100 Subject: [PATCH 03/22] In loop() it should be ifdef ADC_TEST, not ifndef... --- Maiskolben_TFT/Maiskolben_TFT.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Maiskolben_TFT/Maiskolben_TFT.ino b/Maiskolben_TFT/Maiskolben_TFT.ino index f89dcfb..90bbc75 100644 --- a/Maiskolben_TFT/Maiskolben_TFT.ino +++ b/Maiskolben_TFT/Maiskolben_TFT.ino @@ -975,7 +975,7 @@ void loop(void) { if (sendNext <= millis()) { sendNext += 100; -#ifndef TEST_ADC +#ifdef TEST_ADC Serial.print(stored[0]); Serial.print(";"); Serial.print(stored[1]); @@ -1001,8 +1001,8 @@ void loop(void) { Serial.print(v_c2); Serial.print(";"); Serial.println(v); -#endif Serial.flush(); +#endif display(); } if (Serial.available()) { From dd886f3c286f265a764f320371356cab60188eba Mon Sep 17 00:00:00 2001 From: Tobias Frost Date: Sat, 22 Dec 2018 10:24:49 +0100 Subject: [PATCH 04/22] Move the up and down triangles a tad to the left (they were cut on my display) --- Maiskolben_TFT/Maiskolben_TFT.ino | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Maiskolben_TFT/Maiskolben_TFT.ino b/Maiskolben_TFT/Maiskolben_TFT.ino index 90bbc75..32d0c91 100644 --- a/Maiskolben_TFT/Maiskolben_TFT.ino +++ b/Maiskolben_TFT/Maiskolben_TFT.ino @@ -684,17 +684,17 @@ void display(void) { if (stby || stby_layoff) { old_stby = true; tft.setTextColor(YELLOW, BLACK); - tft.print(F("STBY ")); + tft.print(F("STBY ")); } else { old_stby = false; set_t_old = set_t; tft.setTextColor(WHITE, BLACK); - tft.write(' '); + //tft.write(' '); printTemp(set_t); tft.write(247); tft.write(fahrenheit?'F':'C'); - tft.fillTriangle(149, 50, 159, 50, 154, 38, (set_t < TEMP_MAX) ? WHITE : GRAY); - tft.fillTriangle(149, 77, 159, 77, 154, 90, (set_t > TEMP_MIN) ? WHITE : GRAY); + tft.fillTriangle(140, 50, 150, 50, 145, 38, (set_t < TEMP_MAX) ? WHITE : GRAY); + tft.fillTriangle(140, 77, 150, 77, 145, 90, (set_t > TEMP_MIN) ? WHITE : GRAY); } } if (!off) { @@ -737,7 +737,7 @@ void display(void) { if (temperature < TEMP_COLD) { tft.print(F("COLD ")); } else { - tft.write(' '); + //tft.write(' '); printTemp(temperature); tft.write(247); tft.write(fahrenheit?'F':'C'); From fc77a1ae4255506b9d72707a33ab8943ea9dfaa5 Mon Sep 17 00:00:00 2001 From: Tobias Frost Date: Sat, 22 Dec 2018 10:35:30 +0100 Subject: [PATCH 05/22] Use the real voltage for power calculation, do not assume min of 15V. --- Maiskolben_TFT/Maiskolben_TFT.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Maiskolben_TFT/Maiskolben_TFT.ino b/Maiskolben_TFT/Maiskolben_TFT.ino index 32d0c91..a00b6ab 100644 --- a/Maiskolben_TFT/Maiskolben_TFT.ino +++ b/Maiskolben_TFT/Maiskolben_TFT.ino @@ -756,7 +756,7 @@ void display(void) { tft.setTextColor(YELLOW, BLACK); tft.setCursor(122,5); tft.setTextSize(2); - int power = min(15,v)*min(15,v)/4.8*pwm/255; + int power =v*v/4.8*pwm/255; if (power < 10) tft.write(' '); tft.print(power); tft.write('W'); From 83a6a96c95165334cb26a9811732c61d494763cf Mon Sep 17 00:00:00 2001 From: Tobias Frost Date: Sat, 22 Dec 2018 10:56:01 +0100 Subject: [PATCH 06/22] Define macro COLOR(r,g,b) to easy color defintions out of RGB components, regardless of the scaling of the LCD. --- Maiskolben_TFT/Maiskolben_TFT.ino | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/Maiskolben_TFT/Maiskolben_TFT.ino b/Maiskolben_TFT/Maiskolben_TFT.ino index a00b6ab..8628d3e 100644 --- a/Maiskolben_TFT/Maiskolben_TFT.ino +++ b/Maiskolben_TFT/Maiskolben_TFT.ino @@ -75,15 +75,18 @@ TFT_ILI9163C tft = TFT_ILI9163C(TFT_CS, TFT_DC, STBY_NO); #else TFT_ILI9163C tft = TFT_ILI9163C(TFT_CS, TFT_DC); #endif -#define BLACK 0x0000 -#define BLUE 0x001F -#define RED 0xF800 -#define GREEN 0x07E0 -#define CYAN 0x07FF -#define MAGENTA 0xF81F -#define YELLOW 0xFFE0 -#define WHITE 0xFFFF -#define GRAY 0x94B2 + +#define COLOR(r,g,b) ((((r &0xFFu)>>3u)<<11u) + (((g&0xFFu)>>2u)<<5u) + ((b&0xFFu)>>3u)) + +#define BLACK COLOR(0,0,0) +#define BLUE COLOR(0,0,255) +#define RED COLOR(255,20,20) +#define GREEN COLOR(0, 255, 0) +#define CYAN COLOR(0, 255, 255) +#define MAGENTA COLOR(255, 0, 255) +#define YELLOW COLOR(255, 255, 0) +#define WHITE COLOR(255,255,255) +#define GRAY COLOR(144,148,140) PID heaterPID(&cur_td, &pid_val, &set_td, kp, ki, kd, DIRECT); From cfbb807537a87a731e17df3c01302dc5242dc813 Mon Sep 17 00:00:00 2001 From: Tobias Frost Date: Sat, 22 Dec 2018 10:58:14 +0100 Subject: [PATCH 07/22] Do not enter standby mode when the soldering iron is off. (Bikeshedding, I know, but I find it confusing when the soldering iron is off and press short on that it enters standby mode, but without heating it to standby temperature) --- Maiskolben_TFT/Maiskolben_TFT.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Maiskolben_TFT/Maiskolben_TFT.ino b/Maiskolben_TFT/Maiskolben_TFT.ino index 8628d3e..572ca15 100644 --- a/Maiskolben_TFT/Maiskolben_TFT.ino +++ b/Maiskolben_TFT/Maiskolben_TFT.ino @@ -513,7 +513,7 @@ void timer_sw_poll(void) { cnt_off_press = min(201, cnt_off_press+1); } else { if (cnt_off_press > 0 && cnt_off_press <= 100) { - setStandby(!stby); + if (!off) setStandby(!stby); } cnt_off_press = 0; } From b16b7bcb638001057940ab9c3655cb3868ee2664 Mon Sep 17 00:00:00 2001 From: Tobias Frost Date: Sat, 22 Dec 2018 10:59:50 +0100 Subject: [PATCH 08/22] Be able to turn the soldering iron on with only a short press on the power button. --- Maiskolben_TFT/Maiskolben_TFT.ino | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Maiskolben_TFT/Maiskolben_TFT.ino b/Maiskolben_TFT/Maiskolben_TFT.ino index 572ca15..7e94db3 100644 --- a/Maiskolben_TFT/Maiskolben_TFT.ino +++ b/Maiskolben_TFT/Maiskolben_TFT.ino @@ -514,6 +514,10 @@ void timer_sw_poll(void) { } else { if (cnt_off_press > 0 && cnt_off_press <= 100) { if (!off) setStandby(!stby); + if (off) { + setStandby(false); + setOff(false); + } } cnt_off_press = 0; } From 110fd4074ffbcea84109716c6a67cfc58d99dc34 Mon Sep 17 00:00:00 2001 From: Tobias Frost Date: Sat, 22 Dec 2018 11:01:53 +0100 Subject: [PATCH 09/22] Tuning the protection parameter for the RT-11 tip (the biggest I have in my stock, and therefore the slowest to heat) --- Maiskolben_TFT/definitions.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Maiskolben_TFT/definitions.h b/Maiskolben_TFT/definitions.h index 5f276eb..cd4a682 100644 --- a/Maiskolben_TFT/definitions.h +++ b/Maiskolben_TFT/definitions.h @@ -23,9 +23,9 @@ #define TEMP_UNDER_THRESHOLD 80 // x (TIME_COMPUTE_IN_MS + DELAY_BEFORE_MEASURE) #define THRES_MAX_DECEED 2 //max times the threshold temperature may be undercut by the current temperature -#define WATCH_TEMP_PERIOD (750/20) // Time allowed (in meas cycles ~20ms) to raise temperature +#define WATCH_TEMP_PERIOD (1500/20) // Time allowed (in meas cycles ~20ms) to raise temperature #define WATCH_TEMP_REBOUND (1000/20) // Time after, when target has been reached previously, the temp may drop without re-arming the protection -#define WATCH_TEMP_INCREASE 10 // by this degrees. +#define WATCH_TEMP_INCREASE 5 // by this degrees. #define WATCH_TEMP_DEACTIVATE 50 // deacticate the watching when we are this near the target (in °C) -- to avoid that loads //Temperature in degree to rise at least in given time From a389a9ce617a94ef2f723a3604e62e5033fbe116 Mon Sep 17 00:00:00 2001 From: Tobias Frost Date: Sat, 22 Dec 2018 11:59:40 +0100 Subject: [PATCH 10/22] Tweak displaying the input voltage and use defines for cell voltages (incomplete for the parts my hardware does not support) --- Maiskolben_TFT/Maiskolben_TFT.ino | 29 +++++++++++++++++++---------- Maiskolben_TFT/definitions.h | 16 ++++++++++++---- 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/Maiskolben_TFT/Maiskolben_TFT.ino b/Maiskolben_TFT/Maiskolben_TFT.ino index 7e94db3..964e6c4 100644 --- a/Maiskolben_TFT/Maiskolben_TFT.ino +++ b/Maiskolben_TFT/Maiskolben_TFT.ino @@ -15,6 +15,9 @@ /* show splash screen only a short time; to enter options, press power button when turning the maiskolben on. */ #define FAST_BOOT +/* display the input voltage (define to true to show, to false to hide */ +#define SHOW_INPUT_VOLTS true + /* * If red is blue and blue is red change this * If not sure, leave commented, you will be shown a setup screen @@ -798,15 +801,21 @@ void display(void) { power_source_old = power_source; } if (power_source == POWER_CORD) { - /*if (v > v_c3) { - tft.setTextSize(2); - tft.setTextColor(GREEN, BLACK); - tft.setCursor(0,5); - tft.print(v); + if (SHOW_INPUT_VOLTS) { + tft.drawBitmap(0, 5, power_cord, 24, 9, tft.Color565(max(0, min(255, ((NUM_CELLS*MAX_VOLTS_PER_CELL)-v)*112)), max(0, min(255, (v-NUM_CELLS*MIN_VOLTS_PER_CELL)*112)), 0)); + tft.setTextSize(1); + tft.setTextColor(tft.Color565(max(0, min(255, ((NUM_CELLS*MAX_VOLTS_PER_CELL)-v)*112)), max(0, min(255, (v-(NUM_CELLS*MIN_VOLTS_PER_CELL))*112)), 0), BLACK); + tft.setCursor(25,5); + tft.print(v,1); tft.print("V "); - } else {*/ - tft.drawBitmap(0, 5, power_cord, 24, 9, tft.Color565(max(0, min(255, (14.5-v)*112)), max(0, min(255, (v-11)*112)), 0)); - //} + if ( v > NUM_CELLS*MAX_CHARGE_PER_CELL) { + tft.setTextColor(WHITE,BLACK); + tft.print(v_c3 + 0.3 ); // 0,3 for the shottky diode + tft.print("Vbat"); + } + } else { + tft.drawBitmap(0, 5, power_cord, 24, 9, tft.Color565(max(0, min(255, ((NUM_CELLS*MAX_VOLTS_PER_CELL)-v)*112)), max(0, min(255, (v-NUM_CELLS*MIN_VOLTS_PER_CELL)*112)), 0)); + } } else if (power_source == POWER_LIPO || power_source == POWER_CHARGING) { float volt[] = {v_c1, v_c2-v_c1, v_c3-v_c2}; uint8_t volt_disp[] = {max(1,min(16,(volt[0]-3.0)*14.2)), max(1,min(16,(volt[1]-3.0)*14.2)), max(1,min(16,(volt[2]-3.0)*14.2))}; @@ -817,11 +826,11 @@ void display(void) { } } for (uint8_t i = 0; i < 3; i++) { - if (volt[i] < 3.20) { + if (volt[i] < MIN_VOLTS_PER_CELL) { setError(BATTERY_LOW); tft.fillRect(13, 7+14*i, volt_disp[i], 8, blink?RED:BLACK); } else { - tft.fillRect(13, 7+14*i, volt_disp[i], 8, tft.Color565(250-min(250, max(0, (volt[i]-3.4)*1000.0)), max(0,min(250, (volt[i]-3.15)*1000.0)), 0)); + tft.fillRect(13, 7+14*i, volt_disp[i], 8, tft.Color565(250-min(250, max(0, (volt[i]-MIN_VOLTS_PER_CELL)*1000.0)), max(0,min(250, (volt[i]-MIN_VOLTS_PER_CELL)*1000.0)), 0)); } tft.fillRect(13+volt_disp[i], 7+14*i, 17-volt_disp[i], 8, BLACK); } diff --git a/Maiskolben_TFT/definitions.h b/Maiskolben_TFT/definitions.h index cd4a682..4ee580d 100644 --- a/Maiskolben_TFT/definitions.h +++ b/Maiskolben_TFT/definitions.h @@ -28,11 +28,19 @@ #define WATCH_TEMP_INCREASE 5 // by this degrees. #define WATCH_TEMP_DEACTIVATE 50 // deacticate the watching when we are this near the target (in °C) -- to avoid that loads -//Temperature in degree to rise at least in given time -#define TEMP_MIN_RISE 10 -//Time in that the temperature must rise by the set temperature -#define TEMP_RISE_TIME 1000 +// voltage ranges for the voltage display. +#define NUM_CELLS (4) +#if (true) // For LiFePO4, set to false. Be sure to read not below +#define MIN_VOLTS_PER_CELL (3.0) // LiIon: Usually discharged until 3.0 V/cell +#define MAX_VOLTS_PER_CELL (3.6) // LiIon: Nominal at 3.6V +#define MAX_CHARGE_PER_CELL (4.2) // When charged, full at 4.2 +#else +// NOTE: LiFePO4 needs an own BMS! Do not use the LiIon charging circuitry that might be on your Maiskolben! Ignoring this warning can cause your cell to explode and may cause fires! +#define MIN_VOLTS_PER_CELL (2.5) // LiFePo in my case, they can go down to 2.0V, my BMS will lockout at 2.1. The 2.5 are margin. +#define MAX_VOLTS_PER_CELL (3.2) // LiFePo: nominal voltage is 3.2V +#define MAX_CHARGE_PER_CELL (4.2) // When charged, full at 3.6V +#endif //#define OLD_PWM // RX 0 From 113c9d02cb976f6ffee6615d241a7a6ad2173162 Mon Sep 17 00:00:00 2001 From: Tobias Frost Date: Sat, 22 Dec 2018 11:59:56 +0100 Subject: [PATCH 11/22] Tune my PID parameters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I've replaced the output transitor with a ProFET, Infineon BTS420. This guy needs an higher integral part for the PID, or it is 4-5°C off. --- Maiskolben_TFT/definitions.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Maiskolben_TFT/definitions.h b/Maiskolben_TFT/definitions.h index 4ee580d..5b4e4a3 100644 --- a/Maiskolben_TFT/definitions.h +++ b/Maiskolben_TFT/definitions.h @@ -69,7 +69,7 @@ #endif #define kp 0.03 -#define ki 0.00001 +#define ki 0.00025 #define kd 0.0 #define TIME_COMPUTE_IN_MS 10 From 54647ead6f60def2a8c60014b819771d541ec2ea Mon Sep 17 00:00:00 2001 From: Tobias Frost Date: Sat, 22 Dec 2018 12:03:02 +0100 Subject: [PATCH 12/22] Speed up the voltage measurements (Especially when switching from external power to USB it takes quite long to recognize.)x --- Maiskolben_TFT/definitions.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Maiskolben_TFT/definitions.h b/Maiskolben_TFT/definitions.h index 5b4e4a3..b2bf576 100644 --- a/Maiskolben_TFT/definitions.h +++ b/Maiskolben_TFT/definitions.h @@ -73,7 +73,7 @@ #define kd 0.0 #define TIME_COMPUTE_IN_MS 10 -#define TIME_MEASURE_VOLTAGE_IN_MS 200 +#define TIME_MEASURE_VOLTAGE_IN_MS 50 #define TIME_SW_POLL_IN_MS 10 #define DELAY_BEFORE_MEASURE 10 #define DELAY_MAIN_LOOP 10 From 2d74eb96f7f74f6f9b3a718334a5f35a5a6a7fdf Mon Sep 17 00:00:00 2001 From: Tobias Frost Date: Sat, 22 Dec 2018 16:22:52 +0100 Subject: [PATCH 13/22] Tweak GUI a bit Print a battery symbol, dependent on charge level. Print it cyan when charging, print it green when fully charged. On Battery, print it colored from red to green, depending on charge level. Untested: If no battery is present, print the power chord symbol only (cannot test because my hardware is a bit f***ed up.) --- Maiskolben_TFT/Maiskolben_TFT.ino | 75 +++++++++++++++++++++++----- Maiskolben_TFT/definitions.h | 83 +++++++++++++++++++++++++++++-- 2 files changed, 143 insertions(+), 15 deletions(-) diff --git a/Maiskolben_TFT/Maiskolben_TFT.ino b/Maiskolben_TFT/Maiskolben_TFT.ino index 964e6c4..cf86acb 100644 --- a/Maiskolben_TFT/Maiskolben_TFT.ino +++ b/Maiskolben_TFT/Maiskolben_TFT.ino @@ -629,6 +629,36 @@ void printTemp(float t) { tft.print((int)t); } + +const unsigned char* get_battery_symbol(float v_bat, bool charging, uint8_t *red, uint8_t *green, uint8_t *percent_out ) { + uint8_t percent; + if (charging) { + float D_MAX = NUM_CELLS * (MAX_CHARGE_PER_CELL - MIN_VOLTS_PER_CELL); + float delta_v = (v_bat) - (NUM_CELLS * MIN_VOLTS_PER_CELL); + // Ladezustand + percent = min(100,max(0,(delta_v / D_MAX ) * 100.0)); + } else { + float D_MAX = NUM_CELLS * (MAX_VOLTS_PER_CELL - MIN_VOLTS_PER_CELL); + float delta_v = (v_bat) - (NUM_CELLS * MIN_VOLTS_PER_CELL); + // Ladezustand + percent = min(100,max(0,(delta_v / D_MAX ) * 100.0)); + } + + if (red && green) { + *green = ((float) percent) * 2.55; + *red = 255-*green; + } + + if (percent_out) { + *percent_out = percent; + } + + if(percent > 75) return battery_100; + if(percent > 50) return battery_50; + if(percent > 25) return battery_25; + return battery_0; +} + void display(void) { if (force_redraw) tft.fillScreen(BLACK); int16_t temperature = cur_t; //buffer volatile value @@ -801,20 +831,41 @@ void display(void) { power_source_old = power_source; } if (power_source == POWER_CORD) { - if (SHOW_INPUT_VOLTS) { - tft.drawBitmap(0, 5, power_cord, 24, 9, tft.Color565(max(0, min(255, ((NUM_CELLS*MAX_VOLTS_PER_CELL)-v)*112)), max(0, min(255, (v-NUM_CELLS*MIN_VOLTS_PER_CELL)*112)), 0)); - tft.setTextSize(1); - tft.setTextColor(tft.Color565(max(0, min(255, ((NUM_CELLS*MAX_VOLTS_PER_CELL)-v)*112)), max(0, min(255, (v-(NUM_CELLS*MIN_VOLTS_PER_CELL))*112)), 0), BLACK); - tft.setCursor(25,5); - tft.print(v,1); - tft.print("V "); - if ( v > NUM_CELLS*MAX_CHARGE_PER_CELL) { - tft.setTextColor(WHITE,BLACK); - tft.print(v_c3 + 0.3 ); // 0,3 for the shottky diode - tft.print("Vbat"); + uint8_t red = 0; + uint8_t green = 0; + uint8_t percent = 0; + tft.setTextSize(1); + tft.setCursor(30,5); + + if (v > (v_c3+1.5)) { + if (v_c3 > NUM_CELLS*MIN_VOLTS_PER_CELL) { + // on wall power, with battery present. + // we print a cyan symbol to indicate that we're (likely) charging, and a green one if completed. + const unsigned char *symbol = get_battery_symbol(v_c3+0.35, false, nullptr, nullptr, &percent); + uint16_t color = tft.Color565(red, green, 0); + if (percent > 98) { + color = GREEN; + } else { + color = CYAN; + } + tft.drawBitmap(0, 5, symbol, 24, 9 , color, BLACK); + } else { + tft.drawBitmap(0, 5, power_cord, 24, 9 , GREEN, BLACK); } + tft.setTextColor(WHITE,BLACK); + tft.print("DC "); tft.print(v,1); tft.print("V"); + tft.fillRect(77, 5, 45, 9, BLACK); } else { - tft.drawBitmap(0, 5, power_cord, 24, 9, tft.Color565(max(0, min(255, ((NUM_CELLS*MAX_VOLTS_PER_CELL)-v)*112)), max(0, min(255, (v-NUM_CELLS*MIN_VOLTS_PER_CELL)*112)), 0)); + // on battery. + const unsigned char *symbol = get_battery_symbol(v_c3+0.35, false, &red, &green, &percent); + uint16_t color = tft.Color565(red, green, 0); + tft.drawBitmap(0, 5, symbol, 24, 9 , color, BLACK); + tft.setTextColor(WHITE,BLACK); + tft.print("BAT: "); + tft.print(v_c3+0.35, 1); + tft.print("V "); + tft.print(percent); + tft.print("% "); } } else if (power_source == POWER_LIPO || power_source == POWER_CHARGING) { float volt[] = {v_c1, v_c2-v_c1, v_c3-v_c2}; diff --git a/Maiskolben_TFT/definitions.h b/Maiskolben_TFT/definitions.h index b2bf576..54cf8d8 100644 --- a/Maiskolben_TFT/definitions.h +++ b/Maiskolben_TFT/definitions.h @@ -31,15 +31,15 @@ // voltage ranges for the voltage display. #define NUM_CELLS (4) -#if (true) // For LiFePO4, set to false. Be sure to read not below +#if (false) // For LiFePO4, set to false. Be sure to read not below #define MIN_VOLTS_PER_CELL (3.0) // LiIon: Usually discharged until 3.0 V/cell #define MAX_VOLTS_PER_CELL (3.6) // LiIon: Nominal at 3.6V #define MAX_CHARGE_PER_CELL (4.2) // When charged, full at 4.2 #else // NOTE: LiFePO4 needs an own BMS! Do not use the LiIon charging circuitry that might be on your Maiskolben! Ignoring this warning can cause your cell to explode and may cause fires! -#define MIN_VOLTS_PER_CELL (2.5) // LiFePo in my case, they can go down to 2.0V, my BMS will lockout at 2.1. The 2.5 are margin. +#define MIN_VOLTS_PER_CELL (2.5) // LiFePo in my case, they can go down to 2.0V, my BMS wi4,2ll lockout at 2.1. The 2.75 are margin. #define MAX_VOLTS_PER_CELL (3.2) // LiFePo: nominal voltage is 3.2V -#define MAX_CHARGE_PER_CELL (4.2) // When charged, full at 3.6V +#define MAX_CHARGE_PER_CELL (3.6) // When charged, full at 3.6V #endif //#define OLD_PWM @@ -125,6 +125,83 @@ const unsigned char power_cord [] PROGMEM = { 0x00, 0x00, 0xC0 }; +const unsigned char battery_0 [] PROGMEM = { + 0b11111111, 0b11111111, 0b11111100, + 0b10000000, 0b00000000, 0b00000111, + 0b10000000, 0b00000000, 0b00000101, + 0b10000000, 0b00000000, 0b00000101, + 0b10000000, 0b00000000, 0b00000101, + 0b10000000, 0b00000000, 0b00000111, + 0b11111111, 0b11111111, 0b11111100, + 0,0,0, 0,0,0, +}; + + +const unsigned char battery_25 [] PROGMEM = { + 0b11111111, 0b11111111, 0b11111100, + 0b11111100, 0b00000000, 0b00000111, + 0b11111100, 0b00000000, 0b00000101, + 0b11111100, 0b00000000, 0b00000101, + 0b11111100, 0b00000000, 0b00000101, + 0b11111100, 0b00000000, 0b00000111, + 0b11111111, 0b11111111, 0b11111100, + 0,0,0, 0,0,0, +}; + +const unsigned char battery_50 [] PROGMEM = { + 0b11111111, 0b11111111, 0b11111100, + 0b11111111, 0b11100000, 0b00000111, + 0b11111111, 0b11100000, 0b00000101, + 0b11111111, 0b11100000, 0b00000101, + 0b11111111, 0b11100000, 0b00000101, + 0b11111111, 0b11100000, 0b00000111, + 0b11111111, 0b11111111, 0b11111100, + 0,0,0, 0,0,0, +}; + +const unsigned char battery_75 [] PROGMEM = { + 0b11111111, 0b11111111, 0b11111100, + 0b11111111, 0b11111111, 0b00000111, + 0b11111111, 0b11111111, 0b00000101, + 0b11111111, 0b11111111, 0b00000101, + 0b11111111, 0b11111111, 0b00000101, + 0b11111111, 0b11111111, 0b00000111, + 0b11111111, 0b11111111, 0b11111100, + 0,0,0, 0,0,0, +}; + +const unsigned char battery_100 [] PROGMEM = { + 0b11111111, 0b11111111, 0b11111100, + 0b11111111, 0b11111111, 0b11111111, + 0b11111111, 0b11111111, 0b11111101, + 0b11111111, 0b11111111, 0b11111101, + 0b11111111, 0b11111111, 0b11111101, + 0b11111111, 0b11111111, 0b11111111, + 0b11111111, 0b11111111, 0b11111100, + 0,0,0, 0,0,0, +}; + + +// 0b00000000, 0b00000000, 0b11000000 +// 0b00000000, 0b11111111, 0b11000000 +// 0b00000001, 0b11111111, 0b11011111 +// 0b00000011, 0b11111111, 0b11011111 +// 0b11111011, 0b11111111, 0b11000000 +// 0b00000011, 0b11111111, 0b11011111 +// 0b00000001, 0b11111111, 0b11011111 +// 0b00000000, 0b11111111, 0b11000000 +// 0b00000000, 0b00000000, 0b11000000 + +// 0123456701234567 01234567 +// ************** +// * *** +// * * * +// * *** +// ************** + + + + const unsigned char maiskolben [] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, From ca5fdf4ab196fd05ffe6b4bafc80a2545dc9ffff Mon Sep 17 00:00:00 2001 From: Tobias Frost Date: Sat, 22 Dec 2018 16:41:19 +0100 Subject: [PATCH 14/22] Small change in artwork for 100% full --- Maiskolben_TFT/definitions.h | 26 +++----------------------- 1 file changed, 3 insertions(+), 23 deletions(-) diff --git a/Maiskolben_TFT/definitions.h b/Maiskolben_TFT/definitions.h index 54cf8d8..1bce101 100644 --- a/Maiskolben_TFT/definitions.h +++ b/Maiskolben_TFT/definitions.h @@ -173,35 +173,15 @@ const unsigned char battery_75 [] PROGMEM = { const unsigned char battery_100 [] PROGMEM = { 0b11111111, 0b11111111, 0b11111100, 0b11111111, 0b11111111, 0b11111111, - 0b11111111, 0b11111111, 0b11111101, - 0b11111111, 0b11111111, 0b11111101, - 0b11111111, 0b11111111, 0b11111101, + 0b11111111, 0b11111111, 0b11111111, + 0b11111111, 0b11111111, 0b11111111, + 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111100, 0,0,0, 0,0,0, }; -// 0b00000000, 0b00000000, 0b11000000 -// 0b00000000, 0b11111111, 0b11000000 -// 0b00000001, 0b11111111, 0b11011111 -// 0b00000011, 0b11111111, 0b11011111 -// 0b11111011, 0b11111111, 0b11000000 -// 0b00000011, 0b11111111, 0b11011111 -// 0b00000001, 0b11111111, 0b11011111 -// 0b00000000, 0b11111111, 0b11000000 -// 0b00000000, 0b00000000, 0b11000000 - -// 0123456701234567 01234567 -// ************** -// * *** -// * * * -// * *** -// ************** - - - - const unsigned char maiskolben [] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, From aede67d5569ed9a2e8e8fb4f8768729608bb7b60 Mon Sep 17 00:00:00 2001 From: Tobias Frost Date: Sat, 22 Dec 2018 16:41:37 +0100 Subject: [PATCH 15/22] Tune PID --- Maiskolben_TFT/definitions.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Maiskolben_TFT/definitions.h b/Maiskolben_TFT/definitions.h index 1bce101..b0179a7 100644 --- a/Maiskolben_TFT/definitions.h +++ b/Maiskolben_TFT/definitions.h @@ -68,8 +68,8 @@ #define VIN A7 #endif -#define kp 0.03 -#define ki 0.00025 +#define kp 0.035 +#define ki 0.0002 #define kd 0.0 #define TIME_COMPUTE_IN_MS 10 From a705140470c3b66028b4bf1f5ee8510b5d821ea7 Mon Sep 17 00:00:00 2001 From: Tobias Frost Date: Sat, 22 Dec 2018 17:13:42 +0100 Subject: [PATCH 16/22] Fix for battery percentage .. --- Maiskolben_TFT/Maiskolben_TFT.ino | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Maiskolben_TFT/Maiskolben_TFT.ino b/Maiskolben_TFT/Maiskolben_TFT.ino index cf86acb..1633dba 100644 --- a/Maiskolben_TFT/Maiskolben_TFT.ino +++ b/Maiskolben_TFT/Maiskolben_TFT.ino @@ -653,9 +653,10 @@ const unsigned char* get_battery_symbol(float v_bat, bool charging, uint8_t *red *percent_out = percent; } - if(percent > 75) return battery_100; - if(percent > 50) return battery_50; - if(percent > 25) return battery_25; + if(percent >= 90) return battery_100; + if(percent >= 75) return battery_75; + if(percent >= 50) return battery_50; + if(percent >= 25) return battery_25; return battery_0; } From f19cae18bc781f73bad23534498ea114c3335e6e Mon Sep 17 00:00:00 2001 From: Tobias Frost Date: Sat, 22 Dec 2018 17:14:00 +0100 Subject: [PATCH 17/22] Feature: Power limitation Weller tips are rated for 40W (at least most of them). On higher input voltage, this is exceeded. This feature limits it by put a cap on the pwm, dependent on the input voltage. --- Maiskolben_TFT/Maiskolben_TFT.ino | 15 ++++++++++++--- Maiskolben_TFT/definitions.h | 2 ++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/Maiskolben_TFT/Maiskolben_TFT.ino b/Maiskolben_TFT/Maiskolben_TFT.ino index 1633dba..598b0a2 100644 --- a/Maiskolben_TFT/Maiskolben_TFT.ino +++ b/Maiskolben_TFT/Maiskolben_TFT.ino @@ -1000,10 +1000,19 @@ void compute(void) { last_measured = cur_t; heaterPID.Compute(); - if (error != NO_ERROR || off) + + // Power limitation. + // Tips are rated for 40W, do not exceed that. + // note t-hat we have inherently only 50% PWM, as we have it on 10ms and then wait with pwm off for another 10ms. + // Formula: P = 0.5 * ( U^2 / ( R )) * (pwm) + float pwm_max = 2 * PMAX / ((v*v) / 2.4); + if (pwm_max > pid_val) pwm_max = pid_val; + + if (error != NO_ERROR || off) { pwm = 0; - else - pwm = min(255,pid_val*255); + } else { + pwm = min(255, pwm_max * 255); + } analogWrite(HEATER_PWM, pwm); } diff --git a/Maiskolben_TFT/definitions.h b/Maiskolben_TFT/definitions.h index b0179a7..83a516b 100644 --- a/Maiskolben_TFT/definitions.h +++ b/Maiskolben_TFT/definitions.h @@ -13,6 +13,8 @@ #define TEMP_STBY 150 #define TEMP_COLD (adc_offset + 15) +#define PMAX (40) // max watts to pump into the tip. (note: Weller specifies the tips as 40W; the big RT-11 has 55W) + #define SHUTOFF_ACTIVE #define BOOTHEAT_ACTIVE From b186d66255e67b9533b4354408e09eeb3d4cd3b6 Mon Sep 17 00:00:00 2001 From: Tobias Frost Date: Sat, 22 Dec 2018 18:10:41 +0100 Subject: [PATCH 18/22] Tune the battery display --- Maiskolben_TFT/Maiskolben_TFT.ino | 13 ++++++++----- Maiskolben_TFT/definitions.h | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Maiskolben_TFT/Maiskolben_TFT.ino b/Maiskolben_TFT/Maiskolben_TFT.ino index 598b0a2..9e0156b 100644 --- a/Maiskolben_TFT/Maiskolben_TFT.ino +++ b/Maiskolben_TFT/Maiskolben_TFT.ino @@ -839,23 +839,26 @@ void display(void) { tft.setCursor(30,5); if (v > (v_c3+1.5)) { - if (v_c3 > NUM_CELLS*MIN_VOLTS_PER_CELL) { + if (v_c3 > 6.0) { // on wall power, with battery present. // we print a cyan symbol to indicate that we're (likely) charging, and a green one if completed. - const unsigned char *symbol = get_battery_symbol(v_c3+0.35, false, nullptr, nullptr, &percent); + const unsigned char *symbol = get_battery_symbol(v_c3+0.35, true, nullptr, nullptr, &percent); uint16_t color = tft.Color565(red, green, 0); if (percent > 98) { color = GREEN; + tft.setTextColor(GREEN,BLACK); + tft.print("DC: "); tft.print(v, 1); tft.print("V"); + tft.fillRect(77, 5, 40, 9, BLACK); } else { color = CYAN; + tft.setTextColor(CYAN,BLACK); + tft.print("BAT: "); tft.print(v_c3 + 0.25 ,2); tft.print("V"); + tft.fillRect(89, 5, 32, 9, BLACK); } tft.drawBitmap(0, 5, symbol, 24, 9 , color, BLACK); } else { tft.drawBitmap(0, 5, power_cord, 24, 9 , GREEN, BLACK); } - tft.setTextColor(WHITE,BLACK); - tft.print("DC "); tft.print(v,1); tft.print("V"); - tft.fillRect(77, 5, 45, 9, BLACK); } else { // on battery. const unsigned char *symbol = get_battery_symbol(v_c3+0.35, false, &red, &green, &percent); diff --git a/Maiskolben_TFT/definitions.h b/Maiskolben_TFT/definitions.h index 83a516b..b15a762 100644 --- a/Maiskolben_TFT/definitions.h +++ b/Maiskolben_TFT/definitions.h @@ -39,7 +39,7 @@ #define MAX_CHARGE_PER_CELL (4.2) // When charged, full at 4.2 #else // NOTE: LiFePO4 needs an own BMS! Do not use the LiIon charging circuitry that might be on your Maiskolben! Ignoring this warning can cause your cell to explode and may cause fires! -#define MIN_VOLTS_PER_CELL (2.5) // LiFePo in my case, they can go down to 2.0V, my BMS wi4,2ll lockout at 2.1. The 2.75 are margin. +#define MIN_VOLTS_PER_CELL (3.0) // LiFePo in my case, they can go down to 2.0V, my BMS wi4,2ll lockout at 2.1. The 2.75 are margin. #define MAX_VOLTS_PER_CELL (3.2) // LiFePo: nominal voltage is 3.2V #define MAX_CHARGE_PER_CELL (3.6) // When charged, full at 3.6V #endif From 1d24a754d1711f7d347b5a26f4c63d22b3281390 Mon Sep 17 00:00:00 2001 From: Tobias Frost Date: Sat, 22 Dec 2018 18:28:45 +0100 Subject: [PATCH 19/22] Ensure that the temperature is rising when it should. We observerd a strange error yielding in dead tips* we attribute to shorts between two contacts on the 3.5 mm connector** (bad cable...) and we hope this failure mode will be covered by this feature. The feature works by monitoring the temperature and making sure that in a certain time a certain temperature rising is seen. The tuning can be done by a few parameters: - WATCH_TEMP_PERIOD -- The time the temperature has to rise - WATCH_TEMP_INCREASE -- by this value - WATCH_TEMP_DEACTIVATE -- if we are that close to the target temperature, disable this protection. - WATCH_TEMP_REBOUND -- if the temperature drops below the target window (e.g by cleaning with a wet sponge), wait this time until the protection is re-armed. * heating up at full power, until red-glowing and then dying) ** it might be tip and ring1, combined with phase reversal on the OpAmp caused by exceeding the OpAmps Common Mode voltage ratings.. But this is only a theory... --- Maiskolben_TFT/Maiskolben_TFT.ino | 49 +++++++++++++++++++++++++++++++ Maiskolben_TFT/definitions.h | 12 ++++---- 2 files changed, 56 insertions(+), 5 deletions(-) diff --git a/Maiskolben_TFT/Maiskolben_TFT.ino b/Maiskolben_TFT/Maiskolben_TFT.ino index f22c917..25fdfca 100644 --- a/Maiskolben_TFT/Maiskolben_TFT.ino +++ b/Maiskolben_TFT/Maiskolben_TFT.ino @@ -638,6 +638,10 @@ void display(void) { case NO_TIP: tft.print(F("Error: No tip connected\nTip slipped out?")); break; + case FAILED_TO_HEAT: + tft.print(F("Error: Heating\nTemp not increasing.")); + break; + } tft.setTextSize(2); tft.setTextColor(YELLOW, BLACK); @@ -838,12 +842,19 @@ void display(void) { } void compute(void) { + static int16_t rising_protection_milestone_temperature = 0; + static int16_t rising_protection_timeout = WATCH_TEMP_PERIOD; + static int16_t rising_rebound_timeout = WATCH_TEMP_PERIOD; + static bool rising_protection_target_reached = false; + #ifndef USE_TFT_RESET setStandbyLayoff(!digitalRead(STBY_NO)); //do not measure while heater is active, potential is not neccessary == GND #endif cur_t = getTemperature(); if (off) { target_t = 0; + rising_protection_milestone_temperature = 0; + rising_protection_timeout = WATCH_TEMP_PERIOD; if (cur_t < adc_offset + TEMP_RISE) { threshold_counter = TEMP_UNDER_THRESHOLD; //reset counter } @@ -856,6 +867,44 @@ void compute(void) { if (cur_t-last_measured <= -30 && last_measured != 999) { setError(EXCESSIVE_FALL); //decrease of more than 30 degree is uncommon, short of ring and gnd is possible. } + + // if target_t has been lowered, make sure that we also lower that milestone temperature + if (target_t < rising_protection_milestone_temperature) { + rising_protection_milestone_temperature = target_t; + } + + // ensure that the temperature is actually rising when it should. + if(target_t - cur_t > WATCH_TEMP_DEACTIVATE ) { + // temperature is lower than setpoint by WATCH_TEMP_DEACTIVATE °C. + if (rising_protection_target_reached) { + // if previously we've been at target, e.g cleaning the tip might drop the temp significantly in a short time. + // so we need to temporarily suspend the protection and also continue it with a lower milestone. + if(rising_rebound_timeout) { rising_rebound_timeout--; } + else { + // rebound timeout expired, arm protection again. + rising_protection_milestone_temperature = cur_t + WATCH_TEMP_INCREASE; + rising_protection_target_reached = false; + } + } else { + // target was previously not reached, see if next milestone has been reached. + if (cur_t >= rising_protection_milestone_temperature + WATCH_TEMP_INCREASE) { + rising_protection_milestone_temperature = cur_t + WATCH_TEMP_INCREASE; // Yes, raise the bar. + rising_protection_timeout = WATCH_TEMP_PERIOD; // and give a new time window. + } else { + rising_protection_timeout--; // milestone not reached. + } + } + } else { + // we are near the target, time to disarm the protection.. + rising_protection_timeout = WATCH_TEMP_PERIOD; + rising_protection_target_reached = true; + } + + if(0 == rising_protection_timeout) { + // milestone not reached, E-STOP. + setError(FAILED_TO_HEAT); + } + if (cur_t < adc_offset + TEMP_RISE) { if (threshold_counter == 0) { setError(NOT_HEATING); //temperature is not reached in desired time, short of sensor and gnd too? diff --git a/Maiskolben_TFT/definitions.h b/Maiskolben_TFT/definitions.h index 58c2385..8c9020e 100644 --- a/Maiskolben_TFT/definitions.h +++ b/Maiskolben_TFT/definitions.h @@ -23,10 +23,11 @@ #define TEMP_UNDER_THRESHOLD 80 // x (TIME_COMPUTE_IN_MS + DELAY_BEFORE_MEASURE) #define THRES_MAX_DECEED 2 //max times the threshold temperature may be undercut by the current temperature -//Temperature in degree to rise at least in given time -#define TEMP_MIN_RISE 10 -//Time in that the temperature must rise by the set temperature -#define TEMP_RISE_TIME 1000 +#define WATCH_TEMP_PERIOD (1500/20) // Time allowed (in meas cycles ~20ms) to raise temperature +#define WATCH_TEMP_REBOUND (1000/20) // Time after, when target has been reached previously, the temp may drop without re-arming the protection +#define WATCH_TEMP_INCREASE 5 // by this degrees. +#define WATCH_TEMP_DEACTIVATE 50 // deacticate the watching when we are this near the target (in °C) -- to avoid that loads + //#define OLD_PWM @@ -96,7 +97,8 @@ typedef enum ERROR_TYPE { NOT_HEATING, NO_TIP, BATTERY_LOW, - USB_ONLY + USB_ONLY, + FAILED_TO_HEAT } error_type; const unsigned char power_cord [] PROGMEM = { From 3806af93c6e521ba4fca6de582f53d770f737c3a Mon Sep 17 00:00:00 2001 From: Tobias Frost Date: Wed, 19 Nov 2025 07:50:41 +0100 Subject: [PATCH 20/22] Bugfix and better documentation. The rebound timer was never re-activated and not initialized with the correct value. --- Maiskolben_TFT/Maiskolben_TFT.ino | 5 +++-- Maiskolben_TFT/definitions.h | 11 ++++++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/Maiskolben_TFT/Maiskolben_TFT.ino b/Maiskolben_TFT/Maiskolben_TFT.ino index 25fdfca..c07c22b 100644 --- a/Maiskolben_TFT/Maiskolben_TFT.ino +++ b/Maiskolben_TFT/Maiskolben_TFT.ino @@ -844,7 +844,7 @@ void display(void) { void compute(void) { static int16_t rising_protection_milestone_temperature = 0; static int16_t rising_protection_timeout = WATCH_TEMP_PERIOD; - static int16_t rising_rebound_timeout = WATCH_TEMP_PERIOD; + static int16_t rising_rebound_timeout = WATCH_TEMP_REBOUND; static bool rising_protection_target_reached = false; #ifndef USE_TFT_RESET @@ -895,8 +895,9 @@ void compute(void) { } } } else { - // we are near the target, time to disarm the protection.. + // we are near the target, time to disarm the protection and rearm the rebound timer. rising_protection_timeout = WATCH_TEMP_PERIOD; + rising_rebound_timeout = WATCH_TEMP_REBOUND; rising_protection_target_reached = true; } diff --git a/Maiskolben_TFT/definitions.h b/Maiskolben_TFT/definitions.h index 8c9020e..4fadee4 100644 --- a/Maiskolben_TFT/definitions.h +++ b/Maiskolben_TFT/definitions.h @@ -23,11 +23,12 @@ #define TEMP_UNDER_THRESHOLD 80 // x (TIME_COMPUTE_IN_MS + DELAY_BEFORE_MEASURE) #define THRES_MAX_DECEED 2 //max times the threshold temperature may be undercut by the current temperature -#define WATCH_TEMP_PERIOD (1500/20) // Time allowed (in meas cycles ~20ms) to raise temperature -#define WATCH_TEMP_REBOUND (1000/20) // Time after, when target has been reached previously, the temp may drop without re-arming the protection -#define WATCH_TEMP_INCREASE 5 // by this degrees. -#define WATCH_TEMP_DEACTIVATE 50 // deacticate the watching when we are this near the target (in °C) -- to avoid that loads - +// Protection: Make sure that the tip gets actually hotter when heated. +#define WATCH_TEMP_PERIOD (1500/20) // Time allowed (in measurement cycles) ~20ms) for temperature to raise. (x/20) gives you around x ms. +#define WATCH_TEMP_INCREASE 5 // temperature must raise by this value (°C) +// Rebound: When tip is suddenly cooled (e.g cleaning, or soldering), allow this extra time before re-actviating the protection. +#define WATCH_TEMP_REBOUND (1000/20) // Time, when target has been reached previously, where the temp may drop without re-arming the protection +#define WATCH_TEMP_DEACTIVATE 30 // disarm the protection when the current temperature is close to the target temperature by this temperature (°C) //#define OLD_PWM From c862db76f0920434728b8fcece8a66eaf58e598f Mon Sep 17 00:00:00 2001 From: Tobias Frost Date: Fri, 2 Jan 2026 18:03:25 +0100 Subject: [PATCH 21/22] Improve temperature protection. fixing some corner-cases, making it more reliable and less often to drop out due to false positivss. make the rebound time a bit longer as well. --- Maiskolben_TFT/Maiskolben_TFT.ino | 8 ++++++++ Maiskolben_TFT/definitions.h | 4 ++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Maiskolben_TFT/Maiskolben_TFT.ino b/Maiskolben_TFT/Maiskolben_TFT.ino index 44f788f..6068171 100644 --- a/Maiskolben_TFT/Maiskolben_TFT.ino +++ b/Maiskolben_TFT/Maiskolben_TFT.ino @@ -955,6 +955,13 @@ void compute(void) { rising_protection_milestone_temperature = target_t; } + // if target_t has been changed, timeouts needs to be reset. + if(old_target_t != target_t) { + rising_protection_timeout = WATCH_TEMP_PERIOD ; + rising_rebound_timeout = WATCH_TEMP_REBOUND; + old_target_t = target_t; + } + // ensure that the temperature is actually rising when it should. if(target_t - cur_t > WATCH_TEMP_DEACTIVATE ) { // temperature is lower than setpoint by WATCH_TEMP_DEACTIVATE °C. @@ -981,6 +988,7 @@ void compute(void) { rising_protection_timeout = WATCH_TEMP_PERIOD; rising_rebound_timeout = WATCH_TEMP_REBOUND; rising_protection_target_reached = true; + rising_protection_milestone_temperature = target_t - WATCH_TEMP_DEACTIVATE; // in case temperature has been lowered, follow the target. } if(0 == rising_protection_timeout) { diff --git a/Maiskolben_TFT/definitions.h b/Maiskolben_TFT/definitions.h index e2af9a7..3aa6849 100644 --- a/Maiskolben_TFT/definitions.h +++ b/Maiskolben_TFT/definitions.h @@ -29,8 +29,8 @@ #define WATCH_TEMP_PERIOD (1500/20) // Time allowed (in measurement cycles) ~20ms) for temperature to raise. (x/20) gives you around x ms. #define WATCH_TEMP_INCREASE 5 // temperature must raise by this value (°C) // Rebound: When tip is suddenly cooled (e.g cleaning, or soldering), allow this extra time before re-actviating the protection. -#define WATCH_TEMP_REBOUND (1000/20) // Time, when target has been reached previously, where the temp may drop without re-arming the protection -#define WATCH_TEMP_DEACTIVATE 30 // disarm the protection when the current temperature is close to the target temperature by this temperature (°C) +#define WATCH_TEMP_REBOUND (2000/20) // Time, when target has been reached previously, where the temp may drop without re-arming the protection +#define WATCH_TEMP_DEACTIVATE 15 // disarm the protection when the current temperature is close to the target temperature by this temperature (°C) // voltage ranges for the voltage display. #define NUM_CELLS (4) From e5ebea54a0c91da3371db12672d364b0c95112f4 Mon Sep 17 00:00:00 2001 From: Tobias Frost Date: Fri, 2 Jan 2026 18:59:06 +0100 Subject: [PATCH 22/22] Add missing commit-part. --- Maiskolben_TFT/Maiskolben_TFT.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Maiskolben_TFT/Maiskolben_TFT.ino b/Maiskolben_TFT/Maiskolben_TFT.ino index 6068171..8bef607 100644 --- a/Maiskolben_TFT/Maiskolben_TFT.ino +++ b/Maiskolben_TFT/Maiskolben_TFT.ino @@ -48,7 +48,7 @@ volatile uint8_t pwm, threshold_counter; volatile int16_t cur_t, last_measured; volatile error_type error = NO_ERROR; error_type error_old; -int16_t stored[3] = {300, 350, 450}, set_t = TEMP_MIN, set_t_old, cur_t_old, target_t; +int16_t stored[3] = { 300, 350, 450 }, set_t = TEMP_MIN, set_t_old, cur_t_old, target_t, old_target_t; double pid_val, cur_td, set_td; uint8_t store_to = 255; p_source power_source, power_source_old = NO_INIT;