Good afternoon everyone! I really hope you can help me out again!
I am using ESP32 and FreeRTOS. I have a task to improve the existing code to track possible pump failure, clogged pipelines, or microcontroller freezes. Let's get to the point.
Tasks 1 and 2 are located on different ESP cores and work in parallel. At startup, Task2 must check the upper liquid level and give permission to start Task1, that is, to turn on the pump, then Task2 monitors the critical liquid level in the container and, if this level is reached, will turn off the pump. After the pump is turned off, Task1 stops Task2 and they wait together for 10 seconds. After the time has elapsed, Task1 resumes Task2 and waits for it to start, this is repeated cyclically.
Using the capabilities of FreeRTOS, I would like to use a binary semaphore to track the emergency modes.
That is, when starting up, Task2 takes the semaphore, and if the level is normal, releases it for a short period of time so that Task1 can take it and start the pump, and then return the semaphore to Task2 so that it starts tracking the lower critical liquid level (distance_cm > 31.50).
Now, if Task2 does not return the semaphore for some time, then the liquid level is not normal else if (flag == true && distance_cm > 10.5), then some kind of accident has occurred and, accordingly, Task1 will report that it could not take the semaphore (since Task2 did not release it).
But the first time you run the ESP, you will see the following:
That is, Task1 starts first for some reason, without waiting for permission, which should not be the case since distance_cm = 20. However, during subsequent starts, Task2 still prevails and does not release the semaphore, preventing the Task1 pump from turning on.
How to make it so that even at the first startup, if the level is not normal, Task1 with the pump does not start, and signals if necessary "-----TASK 2 ERROR -----!!!!"?
I really hope for your help! Thank you for your time!
#include <EEPROM.h>
TaskHandle_t Task1Handle;
TaskHandle_t Task2Handle;
SemaphoreHandle_t xSemaphore = NULL;
void Task1code(void *pvParameters);
void Task2code(void *pvParameters);
float distance_cm = 20; //The distance was measured by my sensor.
//If it is < 10.5 at the first start, then the pump is allowed to switch on, if it is > 10.5,
//then you need to wait up to 10 seconds, if during this time the water has
//not reached the required level (< 10.5), then an error message from TASK1
//(‘-----TASK 2 ERROR -----!!!!’) occurs, because TASK1 could not pick up the semaphore
bool flag = true; //the flag that restores the TASK2 operation
void setup()
{
Serial.begin(9600);
xSemaphore = xSemaphoreCreateBinary(); // Set the semaphore as binary
xTaskCreatePinnedToCore(
Task1code,
"Task1",
1024,
NULL,
2,
&Task1Handle,
0);
delay(500);
xTaskCreatePinnedToCore(
Task2code,
"Task2",
1024,
NULL,
2,
&Task2Handle,
1);
delay(500);
}
void Task1code(void *pvParameters)
{
for (;;)
{
xSemaphoreGive(xSemaphore);
vTaskDelay(200 / portTICK_PERIOD_MS);
if (!flag)
{
flag = true;
vTaskResume(Task2Handle);
Serial.println(" 6) Task2->Resume");
}
if (xSemaphoreTake(xSemaphore, (10000 * portTICK_PERIOD_MS)) == pdTRUE)
{
vTaskDelay(50 / portTICK_PERIOD_MS);
xSemaphoreGive(xSemaphore);
Serial.println(" 2) PUMP ___ON___");
vTaskDelay(10000 / portTICK_PERIOD_MS);
Serial.println(" 3) PUMP !!!OFF!!!");
vTaskSuspend(Task2Handle);
Serial.println(" 4) Task2 || Suspend");
vTaskDelay(10000 / portTICK_PERIOD_MS);
}
else
{
Serial.println(" ");
Serial.println(" ");
Serial.println("-----TASK 2 ERROR -----!!!!");
Serial.println(" ");
Serial.println(" ");
vTaskSuspend(Task2Handle);
vTaskDelay(20000 / portTICK_PERIOD_MS);
}
}
}
void Task2code(void *pvParameters)
{
for (;;)
{
Serial.println("TASK 2 TAKE SEMAPHORE");
if (xSemaphoreTake(xSemaphore, (10000 * portTICK_PERIOD_MS)) == pdTRUE)
{
Serial.println("MEASUREMENT LEVEL");
vTaskDelay(350 / portTICK_PERIOD_MS);
if (flag == true && distance_cm <= 10.5)
{
Serial.println(" 1)__________________________The upper level is normal_______________________");
flag = false;
xSemaphoreGive(xSemaphore); // Release the semaphore
vTaskDelay(200 / portTICK_PERIOD_MS);
}
else if (flag == true && distance_cm > 10.5)
{
//If you are in this block, we will not return the semaphore until the level is normalised. If it does not return to normal, something bad has happened
Serial.println(" RESOLUTION FALSE");
flag = false;
vTaskDelay(5000 / portTICK_PERIOD_MS);
}
if (distance_cm > 31.50)
{
Serial.println("- - - - - - - - -Emergency shutdown of the pump- - - - - - - - - ");
Serial.println("PUMP !!!OFF!!!");
vTaskDelay(10000 / portTICK_PERIOD_MS);
}
Serial.print(" Distance cm:");
Serial.println(distance_cm);
}
else
{
Serial.println(" ");
Serial.println(" ");
Serial.println("-----TASK _1_ ERROR -----!!!!");
Serial.println(" ");
Serial.println(" ");
vTaskDelay(20000 / portTICK_PERIOD_MS);
}
}
}
void loop() {
}

