diff -r 1bc6e9263ada -r 96e30a3a3980 main/task_driver.c --- a/main/task_driver.c Sat Jun 19 20:46:42 2021 +0200 +++ b/main/task_driver.c Mon Jun 21 19:04:10 2021 +0200 @@ -37,7 +37,6 @@ int HLT_Mode = HLT_MODE_NONE; ///< HLT mode flag TickType_t MLT_time, HLT_time; - static const char *MLTTypes[] = { "None", "Bang", "PID", "Off", "Ext" }; static const char *HLTTypes[] = { "None", "Bang", "Off", "On" }; @@ -63,6 +62,12 @@ */ void Pump(int onoff); +/** + * @brief Calculate and set PWM value. + * @param percent Then power percentage, 0..100 + */ +void MLT_PWM(int percent); + void MLT(int onoff) { @@ -111,6 +116,32 @@ } +//int oldval = 200; +void MLT_PWM(int percent) { + int val; + static int oldval = -1; + + if (outEnable) { + if (percent < 0) { + val = 0; + } else if (percent > 100) { + val = 1024; + } else { + val = (percent * 1024) / 100; + } + } else { + val = 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); + } + oldval = val; +} + + /** * @brief Load PID settings from equipment record. @@ -129,6 +160,26 @@ +void AllowHLT(void) { + if (equipment.SSR2 == SSR2_HLT_SHARE) { + if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { + HLT_Output = 0; + if (driver_state->hlt_mode == HLT_MODE_BANG) { + HLT_Output = (HLT_Input < HLT_Setpoint) ? 1:0; + } else if (driver_state->hlt_mode == HLT_MODE_ON) { + HLT_Output = 1; + } + xSemaphoreGive(xSemaphoreDriver); + } + HLT(HLT_Output); + } else if (equipment.SSR2 == SSR2_ON_IDLE) { + HLT_Output = 1; + HLT(1); + } +} + + + void task_driver(void *pvParameter) { TickType_t wait_ticks, last_tick, now_tick; @@ -147,6 +198,27 @@ gpio_pad_select_gpio(SSR_PUMP); gpio_set_direction(SSR_PUMP, GPIO_MODE_OUTPUT); + // 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, + .duty_resolution = LEDC_TIMER_10_BIT, ///< 10 bits resolution + .freq_hz = 100, ///< 100 Hz + .clk_cfg = LEDC_AUTO_CLK ///< Auto select PWM clock + }; + ledc_timer_config(&ledc_timer); + + ledc_channel_config_t pwm_channel = { + .channel = LEDC_CHANNEL_0, + .duty = 1024, ///< Default 0% (inverted value) + .gpio_num = PWM_MLT, ///< MLT pin + .speed_mode = LEDC_LOW_SPEED_MODE, + .hpoint = 0, + .intr_type = LEDC_INTR_DISABLE, + .timer_sel = LEDC_TIMER_1 + }; + ledc_channel_config(&pwm_channel); + /* * Initialize state */ @@ -168,7 +240,7 @@ driver_state->pwm_nohlt = 10; /* Conservative safety value. */ PID(&Input, &Output, &Setpoint, 200, 2.0, 1.5, PID_DIRECT); - + /* * One loop must complete in 20 mSecs, that is one mains * frequency period cycle in 50 Hz countries. @@ -241,7 +313,38 @@ w_StartTime = now; } - if ((int)((Output / 255.0) * RealTime) > (now - w_StartTime)) { + if (equipment.Hendi) { + + int PWMout = (int)((Output * 100) / 255.0); + + if ((PID_GetMode() == PID_AUTOMATIC) && (MLT_Mode == MLT_MODE_PID)) { + 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. + */ + 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"); + HLT_Output = 0; + HLT(0); // As soon as possible before the Hendi increases power. + } + } else { + AllowHLT(); // TODO: delay this one loop. + } + MLT_PWM(PWMout); + MLT(1); + } else { + MLT_PWM(0); + MLT(0); + AllowHLT(); + } + } else if ((int)((Output / 255.0) * RealTime) > (now - w_StartTime)) { MLT(1); if ((equipment.SSR2 == SSR2_HLT_SHARE) || (equipment.SSR2 == SSR2_ON_IDLE)) { HLT(0); @@ -249,21 +352,7 @@ } } else { MLT(0); - if (equipment.SSR2 == SSR2_HLT_SHARE) { - if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { - HLT_Output = 0; - if (driver_state->hlt_mode == HLT_MODE_BANG) { - HLT_Output = (HLT_Input < HLT_Setpoint) ? 1:0; - } else if (driver_state->hlt_mode == HLT_MODE_ON) { - HLT_Output = 1; - } - xSemaphoreGive(xSemaphoreDriver); - } - HLT(HLT_Output); - } else if (equipment.SSR2 == SSR2_ON_IDLE) { - HLT_Output = 1; - HLT(1); - } + AllowHLT(); } /* @@ -309,8 +398,7 @@ } #endif - // Not reliable, so do it manually. - //vTaskDelayUntil(&last_wake_time, (1000 / 50) / portTICK_PERIOD_MS); + // Do not use vTaskDelayUntil(), it is not reliable here. now_tick = xTaskGetTickCount(); if ((now_tick - last_tick) > (1000 / 50)) { // This happens one or two times during a brew.