main/task_driver.c

changeset 102
96e30a3a3980
parent 101
1bc6e9263ada
child 103
1885d0c75c48
--- 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.

mercurial