main/task_driver.c

changeset 103
1885d0c75c48
parent 102
96e30a3a3980
child 108
9bfd85878edc
equal deleted inserted replaced
102:96e30a3a3980 103:1885d0c75c48
62 */ 62 */
63 void Pump(int onoff); 63 void Pump(int onoff);
64 64
65 /** 65 /**
66 * @brief Calculate and set PWM value. 66 * @brief Calculate and set PWM value.
67 * @param percent Then power percentage, 0..100 67 * @param percent The power percentage, 0..100
68 */ 68 */
69 void MLT_PWM(int percent); 69 void MLT_PWM(int percent);
70 70
71 71
72 72
114 Pump_pin = 0; 114 Pump_pin = 0;
115 } 115 }
116 } 116 }
117 117
118 118
119 //int oldval = 200;
120 void MLT_PWM(int percent) { 119 void MLT_PWM(int percent) {
121 int val; 120 int val;
122 static int oldval = -1; 121 static int oldval = -1;
123 122
124 if (outEnable) { 123 if (outEnable) {
131 } 130 }
132 } else { 131 } else {
133 val = 0; 132 val = 0;
134 } 133 }
135 134
135 /*
136 * If the Hendi is on, the lowest setting is 500 Watt. So, if we need less then
137 * 10% power, turn it off, just like the manual knob.
138 */
139 MLT((val >= 10) ? 1:0);
140
136 if (val != oldval) { 141 if (val != oldval) {
137 ESP_LOGI(TAG, "MLT_PWM(%d) val=%d %.0f watt", percent, val, (percent / 100.0) * equipment.MLT_watt); 142 ESP_LOGI(TAG, "MLT_PWM(%d) val=%d %.0f watt", percent, val, (percent / 100.0) * equipment.MLT_watt);
138 ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, 1024 - val); 143 ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, 1024 - val);
139 ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0); 144 ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0);
140 } 145 }
141 oldval = val; 146 oldval = val;
142 } 147 }
143 148
144 149
182 187
183 void task_driver(void *pvParameter) 188 void task_driver(void *pvParameter)
184 { 189 {
185 TickType_t wait_ticks, last_tick, now_tick; 190 TickType_t wait_ticks, last_tick, now_tick;
186 bool rc; 191 bool rc;
192 int SafeCount = 0;
187 unsigned long now, RealTime, w_StartTime = 0; 193 unsigned long now, RealTime, w_StartTime = 0;
188 194
189 ESP_LOGI(TAG, "Start drivers"); 195 ESP_LOGI(TAG, "Start drivers");
190 196
191 /* 197 /*
198 gpio_pad_select_gpio(SSR_PUMP); 204 gpio_pad_select_gpio(SSR_PUMP);
199 gpio_set_direction(SSR_PUMP, GPIO_MODE_OUTPUT); 205 gpio_set_direction(SSR_PUMP, GPIO_MODE_OUTPUT);
200 206
201 // Prepare and then apply the LEDC PWM timer configuration 207 // Prepare and then apply the LEDC PWM timer configuration
202 ledc_timer_config_t ledc_timer = { 208 ledc_timer_config_t ledc_timer = {
203 .speed_mode = LEDC_LOW_SPEED_MODE, ///< Use low speed 209 .speed_mode = LEDC_HIGH_SPEED_MODE, ///< Use high speed timer
204 .timer_num = LEDC_TIMER_1, 210 .timer_num = LEDC_TIMER_0, ///< Timer 0
205 .duty_resolution = LEDC_TIMER_10_BIT, ///< 10 bits resolution 211 .duty_resolution = LEDC_TIMER_10_BIT, ///< 10 bits resolution
206 .freq_hz = 100, ///< 100 Hz 212 .freq_hz = 100, ///< 100 Hz
207 .clk_cfg = LEDC_AUTO_CLK ///< Auto select PWM clock 213 .clk_cfg = LEDC_AUTO_CLK ///< Auto select PWM clock
208 }; 214 };
209 ledc_timer_config(&ledc_timer); 215 ledc_timer_config(&ledc_timer);
210 216
211 ledc_channel_config_t pwm_channel = { 217 ledc_channel_config_t pwm_channel = {
212 .channel = LEDC_CHANNEL_0, 218 .channel = LEDC_CHANNEL_0,
213 .duty = 1024, ///< Default 0% (inverted value) 219 .duty = 1024, ///< Default 0% (inverted value)
214 .gpio_num = PWM_MLT, ///< MLT pin 220 .gpio_num = PWM_MLT, ///< MLT pin
215 .speed_mode = LEDC_LOW_SPEED_MODE, 221 .speed_mode = LEDC_HIGH_SPEED_MODE,
216 .hpoint = 0, 222 .hpoint = 0,
217 .intr_type = LEDC_INTR_DISABLE, 223 .intr_type = LEDC_INTR_DISABLE,
218 .timer_sel = LEDC_TIMER_1 224 .timer_sel = LEDC_TIMER_0 ///< Timer 0
219 }; 225 };
220 ledc_channel_config(&pwm_channel); 226 ledc_channel_config(&pwm_channel);
221 227
222 /* 228 /*
223 * Initialize state 229 * Initialize state
233 driver_state->hlt_sp = driver_state->hlt_pv = 0.0; 239 driver_state->hlt_sp = driver_state->hlt_pv = 0.0;
234 driver_state->hlt_power = 0; 240 driver_state->hlt_power = 0;
235 driver_state->hlt_and_mlt = false; 241 driver_state->hlt_and_mlt = false;
236 driver_state->pump_gpio = SSR_PUMP; 242 driver_state->pump_gpio = SSR_PUMP;
237 driver_state->pump_run = 0; 243 driver_state->pump_run = 0;
238 driver_state->pwm_gpio = PWM_MLT;
239 driver_state->pwm_mlt = false;
240 driver_state->pwm_nohlt = 10; /* Conservative safety value. */
241 244
242 PID(&Input, &Output, &Setpoint, 200, 2.0, 1.5, PID_DIRECT); 245 PID(&Input, &Output, &Setpoint, 200, 2.0, 1.5, PID_DIRECT);
243 246
244 /* 247 /*
245 * One loop must complete in 20 mSecs, that is one mains 248 * One loop must complete in 20 mSecs, that is one mains
316 if (equipment.Hendi) { 319 if (equipment.Hendi) {
317 320
318 int PWMout = (int)((Output * 100) / 255.0); 321 int PWMout = (int)((Output * 100) / 255.0);
319 322
320 if ((PID_GetMode() == PID_AUTOMATIC) && (MLT_Mode == MLT_MODE_PID)) { 323 if ((PID_GetMode() == PID_AUTOMATIC) && (MLT_Mode == MLT_MODE_PID)) {
324 /* Mash power limited */
321 if (PWMout > equipment.MashPower) 325 if (PWMout > equipment.MashPower)
322 PWMout = equipment.MashPower; 326 PWMout = equipment.MashPower;
323 } 327 }
324 328
325 /* 329 /*
326 * Hendi minimum power is 500 Watt, this is 14%. 330 * Do not send power values < 10%.
327 * So, we turn the cooker on around 10% power.
328 */ 331 */
329 if (PWMout >= 10) { // Hendi minimum power is 500 Watt, this is 10% 332 if (PWMout >= 10) { // Hendi minimum power is 500 Watt, this is 10%
330 if ((((PWMout / 100.0) * equipment.MLT_watt) + equipment.HLT_watt) > equipment.Max_watt) { 333 if ((((PWMout / 100.0) * equipment.MLT_watt) + equipment.HLT_watt) > equipment.Max_watt) {
331 if (HLT_pin) { 334 if (HLT_pin) {
332 ESP_LOGI(TAG, "Power %f %d", ((PWMout / 100.0) * equipment.MLT_watt) + equipment.HLT_watt, equipment.Max_watt); 335 ESP_LOGI(TAG, "Current %.0f Watt above %d limit, shutdown HLT",
333 ESP_LOGI(TAG, "Immediate HLT panic shutdown"); 336 ((PWMout / 100.0) * equipment.MLT_watt) + equipment.HLT_watt, equipment.Max_watt);
334 HLT_Output = 0; 337 HLT_Output = 0;
335 HLT(0); // As soon as possible before the Hendi increases power. 338 HLT(0); // As soon as possible before the Hendi increases power.
336 } 339 }
337 } else { 340 SafeCount = (int)(15000 / equipment.SampleTime) + 1; // About 15 seconds release time
338 AllowHLT(); // TODO: delay this one loop. 341 } else if (rc) {
342 if (SafeCount > 0) {
343 SafeCount--;
344 } else {
345 AllowHLT();
346 }
339 } 347 }
340 MLT_PWM(PWMout); 348 MLT_PWM(PWMout);
341 MLT(1);
342 } else { 349 } else {
343 MLT_PWM(0); 350 MLT_PWM(0);
344 MLT(0); 351 if (rc) {
345 AllowHLT(); 352 if (SafeCount > 0) {
353 SafeCount--;
354 } else {
355 AllowHLT();
356 }
357 }
346 } 358 }
347 } else if ((int)((Output / 255.0) * RealTime) > (now - w_StartTime)) { 359 } else if ((int)((Output / 255.0) * RealTime) > (now - w_StartTime)) {
360 /*
361 * Use On/Off kettles using time slices.
362 */
348 MLT(1); 363 MLT(1);
349 if ((equipment.SSR2 == SSR2_HLT_SHARE) || (equipment.SSR2 == SSR2_ON_IDLE)) { 364 if ((equipment.SSR2 == SSR2_HLT_SHARE) || (equipment.SSR2 == SSR2_ON_IDLE)) {
350 HLT(0); 365 HLT(0);
351 HLT_Output = 0; 366 HLT_Output = 0;
352 } 367 }

mercurial