# HG changeset patch # User Michiel Broek # Date 1624393269 -7200 # Node ID 1885d0c75c48dd2b845bc2a29747c450e2c546e6 # Parent 96e30a3a39808256f09b07171ff50c59671f038a Default equipment max_watt set to 2750. Added defaults for new equipment record. Switched PWM timer to high-speed. Implemented the safety timer to prevent the MLT + HLT will draw too much power in shared mode. Removed some code ideas that were not used. The fake heater now uses the faked PWM power. diff -r 96e30a3a3980 -r 1885d0c75c48 main/config.c --- a/main/config.c Mon Jun 21 19:04:10 2021 +0200 +++ b/main/config.c Tue Jun 22 22:21:09 2021 +0200 @@ -124,7 +124,7 @@ equipment.SampleTime = 3000; equipment.Hendi = false; equipment.RampPower = 100; - equipment.Max_watt = 3000; + equipment.Max_watt = 2750; bytes = fwrite(dst, 1, sizeof(equipment), f); fclose(f); } else { diff -r 96e30a3a3980 -r 1885d0c75c48 main/setup.c --- a/main/setup.c Mon Jun 21 19:04:10 2021 +0200 +++ b/main/setup.c Tue Jun 22 22:21:09 2021 +0200 @@ -216,8 +216,10 @@ case 1: memset(&equipment, 0, sizeof(equipment)); equipment.MLT_watt = 2000; equipment.HLT_watt = 2000; + equipment.Max_watt = 2750; sprintf(equipment.Name, "new eq %d", Records + 1); equipment.BoilPower = 80; + equipment.RampPower = 100; equipment.MashPower = 100; equipment.PumpCycle = 8; equipment.PumpRest = 2; @@ -228,6 +230,7 @@ equipment.PumpMaxTemp = 80; equipment.PIDPipe = true; equipment.SSR2 = 0; + equipment.Hendi = false; equipment.TempHLT = 85.0; equipment.PID_kP = 200.0; equipment.PID_kI = 2.0; diff -r 96e30a3a3980 -r 1885d0c75c48 main/task_driver.c --- a/main/task_driver.c Mon Jun 21 19:04:10 2021 +0200 +++ b/main/task_driver.c Tue Jun 22 22:21:09 2021 +0200 @@ -64,7 +64,7 @@ /** * @brief Calculate and set PWM value. - * @param percent Then power percentage, 0..100 + * @param percent The power percentage, 0..100 */ void MLT_PWM(int percent); @@ -116,7 +116,6 @@ } -//int oldval = 200; void MLT_PWM(int percent) { int val; static int oldval = -1; @@ -133,10 +132,16 @@ val = 0; } + /* + * If the Hendi is on, the lowest setting is 500 Watt. So, if we need less then + * 10% power, turn it off, just like the manual knob. + */ + MLT((val >= 10) ? 1:0); + if (val != oldval) { ESP_LOGI(TAG, "MLT_PWM(%d) val=%d %.0f watt", percent, val, (percent / 100.0) * equipment.MLT_watt); - ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, 1024 - val); - ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0); + ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, 1024 - val); + ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0); } oldval = val; } @@ -184,6 +189,7 @@ { TickType_t wait_ticks, last_tick, now_tick; bool rc; + int SafeCount = 0; unsigned long now, RealTime, w_StartTime = 0; ESP_LOGI(TAG, "Start drivers"); @@ -200,8 +206,8 @@ // Prepare and then apply the LEDC PWM timer configuration ledc_timer_config_t ledc_timer = { - .speed_mode = LEDC_LOW_SPEED_MODE, ///< Use low speed - .timer_num = LEDC_TIMER_1, + .speed_mode = LEDC_HIGH_SPEED_MODE, ///< Use high speed timer + .timer_num = LEDC_TIMER_0, ///< Timer 0 .duty_resolution = LEDC_TIMER_10_BIT, ///< 10 bits resolution .freq_hz = 100, ///< 100 Hz .clk_cfg = LEDC_AUTO_CLK ///< Auto select PWM clock @@ -212,10 +218,10 @@ .channel = LEDC_CHANNEL_0, .duty = 1024, ///< Default 0% (inverted value) .gpio_num = PWM_MLT, ///< MLT pin - .speed_mode = LEDC_LOW_SPEED_MODE, + .speed_mode = LEDC_HIGH_SPEED_MODE, .hpoint = 0, .intr_type = LEDC_INTR_DISABLE, - .timer_sel = LEDC_TIMER_1 + .timer_sel = LEDC_TIMER_0 ///< Timer 0 }; ledc_channel_config(&pwm_channel); @@ -235,9 +241,6 @@ driver_state->hlt_and_mlt = false; driver_state->pump_gpio = SSR_PUMP; driver_state->pump_run = 0; - driver_state->pwm_gpio = PWM_MLT; - driver_state->pwm_mlt = false; - driver_state->pwm_nohlt = 10; /* Conservative safety value. */ PID(&Input, &Output, &Setpoint, 200, 2.0, 1.5, PID_DIRECT); @@ -318,33 +321,45 @@ int PWMout = (int)((Output * 100) / 255.0); if ((PID_GetMode() == PID_AUTOMATIC) && (MLT_Mode == MLT_MODE_PID)) { + /* Mash power limited */ if (PWMout > equipment.MashPower) PWMout = equipment.MashPower; } /* - * Hendi minimum power is 500 Watt, this is 14%. - * So, we turn the cooker on around 10% power. + * Do not send power values < 10%. */ if (PWMout >= 10) { // Hendi minimum power is 500 Watt, this is 10% if ((((PWMout / 100.0) * equipment.MLT_watt) + equipment.HLT_watt) > equipment.Max_watt) { if (HLT_pin) { - ESP_LOGI(TAG, "Power %f %d", ((PWMout / 100.0) * equipment.MLT_watt) + equipment.HLT_watt, equipment.Max_watt); - ESP_LOGI(TAG, "Immediate HLT panic shutdown"); + ESP_LOGI(TAG, "Current %.0f Watt above %d limit, shutdown HLT", + ((PWMout / 100.0) * equipment.MLT_watt) + equipment.HLT_watt, equipment.Max_watt); HLT_Output = 0; HLT(0); // As soon as possible before the Hendi increases power. } - } else { - AllowHLT(); // TODO: delay this one loop. + SafeCount = (int)(15000 / equipment.SampleTime) + 1; // About 15 seconds release time + } else if (rc) { + if (SafeCount > 0) { + SafeCount--; + } else { + AllowHLT(); + } } MLT_PWM(PWMout); - MLT(1); } else { MLT_PWM(0); - MLT(0); - AllowHLT(); + if (rc) { + if (SafeCount > 0) { + SafeCount--; + } else { + AllowHLT(); + } + } } } else if ((int)((Output / 255.0) * RealTime) > (now - w_StartTime)) { + /* + * Use On/Off kettles using time slices. + */ MLT(1); if ((equipment.SSR2 == SSR2_HLT_SHARE) || (equipment.SSR2 == SSR2_ON_IDLE)) { HLT(0); diff -r 96e30a3a3980 -r 1885d0c75c48 main/task_driver.h --- a/main/task_driver.h Mon Jun 21 19:04:10 2021 +0200 +++ b/main/task_driver.h Tue Jun 22 22:21:09 2021 +0200 @@ -43,9 +43,6 @@ double mlt_sp; ///< Setpoint MLT temperature double mlt_pv; ///< Current MLT temperature int mlt_power; ///< Current MLT drive power % - int pwm_gpio; ///< PWM GPIO pin - bool pwm_mlt; ///< PWM in use for MLT - int pwm_nohlt; ///< PWM power limit to shutdown HLT int hlt_gpio; ///< HLT SSR GPIO pin int hlt_mode; ///< HLT Mode: 0 = off, 1 = bang on/off, 2 = always on double hlt_sp; ///< Setpoint HLT temperature diff -r 96e30a3a3980 -r 1885d0c75c48 main/task_ds18b20.c --- a/main/task_ds18b20.c Mon Jun 21 19:04:10 2021 +0200 +++ b/main/task_ds18b20.c Tue Jun 22 22:21:09 2021 +0200 @@ -26,6 +26,7 @@ float Fake_MLT = 18.90; float Fake_HLT = 18.70; +extern double Output; #endif static const char *TAG = "task_ds18b20"; @@ -218,8 +219,12 @@ } // If plate is hotter then the water with a offset so that cooling later works. if (Plate_MLT > (Fake_MLT + 5.0)) { - if (Fake_MLT < 100.05) - Fake_MLT += SAMPLE_PERIOD * 0.000001 * (Plate_MLT - Fake_MLT); + if (Fake_MLT < 100.05) { + if (equipment.Hendi) + Fake_MLT += SAMPLE_PERIOD * 0.000001 * (Plate_MLT - Fake_MLT) * (Output / 255.0) * 2; + else + Fake_MLT += SAMPLE_PERIOD * 0.000001 * (Plate_MLT - Fake_MLT); + } } // Allways loose heat to the air if (Fake_MLT > 16.0) {