moinickcres
moinickcres

Reputation: 25

ESP32 and Freertos: how to use properly the tasks and the queues from Freertos

I have a program using the ESP32 and Freertos that reads certain values from a joystick and sends it to several task depending of the values. The problem is that the queues are giving me some errors that I can't find information about: enter image description here

This is only with one launched task, without the queue. And this other image is whith the queue:

enter image description here

And now, this is the part of the code I mean:

These are the tasked launched:

adc1_config_width(ADC_WIDTH_BIT_12);
    adc1_config_channel_atten(ADC1_CHANNEL_6,ADC_ATTEN_DB_11);
    adc1_config_channel_atten(ADC1_CHANNEL_7,ADC_ATTEN_DB_11);

xTaskCreatePinnedToCore(S, "stop", 100000, NULL, 1, NULL,0);

xTaskCreatePinnedToCore(queues, "queues", 100000, NULL, 4, NULL,0);

And these are the tasks:

    void S(void* pvParam)
    {Serial.print("se ejecuta el STOP");
      for(;;) {
        if (sS != 1){
          xQueueReceive(xQueueS, &( xMessageReceive ), (( TickType_t ) 10 ) != pdPASS );
          
            xSemaphoreTake( xMutex, 200/portTICK_PERIOD_MS  );
            {
              if (strcmp(xMessageReceive, "STOP") == 0){
                snprintf(msg_bt, sizeof msg_bt, "S");
              //SerialBT.write((uint8_t*)&msg_bt,1);
              }
            }
            xSemaphoreGive(xMutex);
            sS = 0;
        }
      }
      vTaskDelete(NULL);
    }

void queues(void* pvParam){

  for(;;) {


    valx = adc1_get_raw(ADC1_CHANNEL_6);
    valy = adc1_get_raw(ADC1_CHANNEL_7);
    

    Serial.print("The X and Y coordinates are:");
    Serial.print(valx, DEC);
    Serial.print(",");
    Serial.println(valy, DEC);
    Serial.println(" ");
    delay(100);

if (valx <= 2623 && valx >= 823 && valy <= 2500 && valy >= 923 ){
      xSemaphoreTake( xMutexSendCommand, 1000/portTICK_PERIOD_MS  );
      {
        strcpy(xMessageSend, "STOP");
        Serial.print("Se envia un sTOP");
        xQueueSend(xQueueS, & (xMessageSend), (( TickType_t ) 10 ) != pdPASS );
        sS = 1;
      }
    }
  }
}

There are other tasks and the program is bigger, but I reduced the program to this part, where I comment the Queue to see what happens.

Here is the full code, just in case in can helps:

#include <Arduino.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <PubSubClient.h>
#include <driver/dac.h>
#include <driver/adc.h>
#include <math.h>
#include <string>
#include <stdlib.h>
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "BluetoothSerial.h"

using namespace std;

const int xpin = 34, ypin = 35;

int valx, valy;

int sF = 0, sB = 0, sL = 0, sR = 0, sG = 0, sI = 0, sH = 0, sJ = 0, sS = 0;

BluetoothSerial SerialBT;

SemaphoreHandle_t xMutex, xMutexSendCommand;

QueueHandle_t xQueueSendCoordinates;

QueueHandle_t xQueueF, xQueueB, xQueueL, xQueueR, xQueueG, xQueueI, xQueueH, xQueueJ, xQueueS;

char xMessageReceive[64];
char xMessageSend[64];

char msg_bt[64];


void t_F(void* pvParam)
{
  Serial.print("Se ejecuta la tarea FORWARD");
  for(;;) {
    if (sF != 1){
      xQueueReceive(xQueueF, &( xMessageReceive ), (( TickType_t ) 10 ) != pdPASS );

      xSemaphoreTake( xMutex, 200/portTICK_PERIOD_MS  );{
        if (strcmp(xMessageReceive, "FORWARD") == 0)
        {
          snprintf(msg_bt, sizeof msg_bt, "F");
          SerialBT.write((uint8_t*)&msg_bt,1);
        }
      }
      xSemaphoreGive(xMutex);
      sF = 0;
    }
  }
  vTaskDelete(NULL);
}


void B(void* pvParam)
{Serial.print("Se ejecuta la tarea BACKWARD");
  for(;;) {
    if (sB != 1){
      xQueueReceive(xQueueB, &( xMessageReceive ), (( TickType_t ) 10 ) != pdPASS );

      xSemaphoreTake( xMutex, 200/portTICK_PERIOD_MS  );
      {
        if (strcmp(xMessageReceive, "BACKWARD") == 0){
          snprintf(msg_bt, sizeof msg_bt, "B");
          SerialBT.write((uint8_t*)&msg_bt,1);
        }
      }
      xSemaphoreGive(xMutex);
      sB = 0;
    }
  }
  vTaskDelete(NULL);
}
void L(void* pvParam)
{
  for(;;) {
    if (sL != 1){
      xQueueReceive(xQueueL, &( xMessageReceive ), (( TickType_t ) 10 ) != pdPASS );
      

        xSemaphoreTake( xMutex, 200/portTICK_PERIOD_MS  );
        {
          if (strcmp(xMessageReceive, "LEFT") == 0){
            snprintf(msg_bt, sizeof msg_bt, "L");
          SerialBT.write((uint8_t*)&msg_bt,1);;
          }
        }
        xSemaphoreGive(xMutex);
        sL = 0;
    }
  }
  vTaskDelete(NULL);
}

void R(void* pvParam)
{
  for(;;) {
    if (sR != 1){
      xQueueReceive(xQueueR, &( xMessageReceive ), (( TickType_t ) 10 ) != pdPASS );

        xSemaphoreTake( xMutex, 200/portTICK_PERIOD_MS  );
        {
          if (strcmp(xMessageReceive, "RIGHT") == 0){
            snprintf(msg_bt, sizeof msg_bt, "R");
          SerialBT.write((uint8_t*)&msg_bt,1);
          }
        }
        xSemaphoreGive(xMutex);
        sR = 0;
    }
  }
  vTaskDelete(NULL);
}

void G(void* pvParam)
{
  for(;;) {
    if (sG != 1){
      xQueueReceive(xQueueG, &( xMessageReceive ), (( TickType_t ) 10 ) != pdPASS );
      
        xSemaphoreTake( xMutex, 200/portTICK_PERIOD_MS  );
        {
          if (strcmp(xMessageReceive, "RF") == 0){

            snprintf(msg_bt, sizeof msg_bt, "G");
          SerialBT.write((uint8_t*)&msg_bt,1);
          }
        }
        xSemaphoreGive(xMutex);
        sG = 0;
    }
  }
  vTaskDelete(NULL);
}

void I(void* pvParam)
{
  for(;;) {
    if (sI != 1){
      xQueueReceive(xQueueI, &( xMessageReceive ), (( TickType_t ) 10 ) != pdPASS );
      
        xSemaphoreTake( xMutex, 200/portTICK_PERIOD_MS  );
        {
          if (strcmp(xMessageReceive, "LF") == 0){
            snprintf(msg_bt, sizeof msg_bt, "I");
          SerialBT.write((uint8_t*)&msg_bt,1);
          }
        }
        xSemaphoreGive(xMutex);
        sI = 0;
    }
  }
  vTaskDelete(NULL);
}
void H(void* pvParam)
{
  for(;;) {
    if (sH != 1){
      xQueueReceive(xQueueH, &( xMessageReceive ), (( TickType_t ) 10 ) != pdPASS );
      
        xSemaphoreTake( xMutex, 200/portTICK_PERIOD_MS  );
        {
          if (strcmp(xMessageReceive, "RB") == 0){
            snprintf(msg_bt, sizeof msg_bt, "H");
          SerialBT.write((uint8_t*)&msg_bt,1);
          }
        }
        xSemaphoreGive(xMutex);
        sH = 0;
    }
  }
  vTaskDelete(NULL);
}

void J(void* pvParam)
{
  for(;;) {
    if (sJ != 1){
      xQueueReceive(xQueueJ, &( xMessageReceive ), (( TickType_t ) 10 ) != pdPASS );
      
        xSemaphoreTake( xMutex, 200/portTICK_PERIOD_MS  );
        {
          if (strcmp(xMessageReceive, "RL") == 0){
            snprintf(msg_bt, sizeof msg_bt, "J");
          SerialBT.write((uint8_t*)&msg_bt,1);
          }
        }
        xSemaphoreGive(xMutex);
        sJ = 0;
    }
  }
  vTaskDelete(NULL);
}

void S(void* pvParam)
{Serial.print("se ejecuta el STOP");
  for(;;) {
    if (sS != 1){
      xQueueReceive(xQueueS, &( xMessageReceive ), (( TickType_t ) 10 ) != pdPASS );
      
        xSemaphoreTake( xMutex, 200/portTICK_PERIOD_MS  );
        {
          if (strcmp(xMessageReceive, "STOP") == 0){
            snprintf(msg_bt, sizeof msg_bt, "S");
          //SerialBT.write((uint8_t*)&msg_bt,1);
          }
        }
        xSemaphoreGive(xMutex);
        sS = 0;
    }
  }
  vTaskDelete(NULL);
}
 

void queues(void* pvParam){

  for(;;) {


    valx = adc1_get_raw(ADC1_CHANNEL_6);
    valy = adc1_get_raw(ADC1_CHANNEL_7);
    

    Serial.print("The X and Y coordinates are:");
    Serial.print(valx, DEC);
    Serial.print(",");
    Serial.println(valy, DEC);
    Serial.println(" ");
    delay(100);


    if (valx <= 2623 && valx >= 823 && valy == 0 ){
      xSemaphoreTake( xMutexSendCommand, 200/portTICK_PERIOD_MS  );
      {
        strcpy(xMessageSend, "FORWARD");
        xQueueSend(xQueueF, (void *) &(xMessageSend), (( TickType_t ) 10 ) != pdPASS );
        sF = 1;
      }
    }
    if (valx <= 2623 && valx >= 823 && valy == 4095 ){
      xSemaphoreTake( xMutexSendCommand, 200/portTICK_PERIOD_MS  );
      {
        strcpy(xMessageSend,"BACKWARD");
        xQueueSend(xQueueB, (void *) &(xMessageSend), (( TickType_t ) 10 ) != pdPASS );
        sB = 1;
      }
    }
    if (valx == 0 && valy <= 2500 && valy >= 923 ){
      xSemaphoreTake( xMutexSendCommand, 200/portTICK_PERIOD_MS  );
      {
        strcpy(xMessageSend, "LEFT");
        xQueueSend(xQueueL, (void *) &(xMessageSend), (( TickType_t ) 10 ) != pdPASS );
        sL = 1;
      }
    }
    if (valx == 4095 && valy <= 2500 && valy >= 923 ){
      xSemaphoreTake( xMutexSendCommand, 200/portTICK_PERIOD_MS  );
      {
        strcpy(xMessageSend, "RIGHT");
        xQueueSend(xQueueR, (void *) &(xMessageSend), (( TickType_t ) 10 ) != pdPASS );
        sR = 1;
      }
    }
    if (valx <= 4095 && valx >= 2623 && valy <= 823 && valy > 0 ){
      xSemaphoreTake( xMutexSendCommand, 200/portTICK_PERIOD_MS  );
      {
        strcpy(xMessageSend, "RF");
        xQueueSend(xQueueG, (void *) &(xMessageSend), (( TickType_t ) 10 ) != pdPASS );
        sG = 1;
      }
    }
    if (valx <= 823 && valx >= 0 && valy <= 923 && valy > 0 ){
      xSemaphoreTake( xMutexSendCommand, 200/portTICK_PERIOD_MS  );
      {
        strcpy(xMessageSend, "LF");
        xQueueSend(xQueueI, (void *) &(xMessageSend), (( TickType_t ) 10 ) != pdPASS );
        sI = 1;
      }
    }
    if (valx <= 4095 && valx >= 2623 && valy < 4095 && valy >= 2500 ){
      xSemaphoreTake( xMutexSendCommand, 200/portTICK_PERIOD_MS  );
      {
        strcpy(xMessageSend, "RB");
        xQueueSend(xQueueH, (void *) &(xMessageSend), (( TickType_t ) 10 ) != pdPASS );
        sH = 1;
      }
    }
    if (valx <= 823 && valx >= 0 && valy < 4095 && valy >= 2500 ){
      xSemaphoreTake( xMutexSendCommand, 200/portTICK_PERIOD_MS  );
      {
        strcpy(xMessageSend, "LB");
        xQueueSend(xQueueJ, & (xMessageSend), (( TickType_t ) 10 ) != pdPASS );
        sJ = 1;
      }
    }
    
    if (valx <= 2623 && valx >= 823 && valy <= 2500 && valy >= 923 ){
      xSemaphoreTake( xMutexSendCommand, 1000/portTICK_PERIOD_MS  );
      {
        strcpy(xMessageSend, "STOP");
        Serial.print("Se envia un sTOP");
        xQueueSend(xQueueS, & (xMessageSend), (( TickType_t ) 10 ) != pdPASS );
        sS = 1;
      }
    }
  }
}



void setup()
{
    Serial.begin(115200);
    SerialBT.begin("bt_esp32"); //Bluetooth device name
    SerialBT.setPin("1234");
    Serial.println("The device started, now you can pair it with bluetooth!");

    /*pinMode(34, ANALOG);
    pinMode(35, ANALOG);
    */

    adc1_config_width(ADC_WIDTH_BIT_12);
    adc1_config_channel_atten(ADC1_CHANNEL_6,ADC_ATTEN_DB_11);
    adc1_config_channel_atten(ADC1_CHANNEL_7,ADC_ATTEN_DB_11);


    //Lanzamiento de tareas para enviar información
    
    xTaskCreatePinnedToCore(t_F, "forward", 4000, NULL, 4, NULL,0);
    xTaskCreatePinnedToCore(B, "backward", 4000, NULL, 3, NULL,0);
    xTaskCreatePinnedToCore(L, "left", 4000, NULL, 3, NULL,0);
    xTaskCreatePinnedToCore(R, "right", 4000, NULL, 3, NULL,0);
    xTaskCreatePinnedToCore(G, "right-forward", 4000, NULL, 2, NULL,0);
    xTaskCreatePinnedToCore(I, "left-forward", 4000, NULL, 2, NULL,0);
    xTaskCreatePinnedToCore(H, "right-backward", 4000, NULL, 2, NULL,0);
    xTaskCreatePinnedToCore(J, "left-backward", 4000, NULL, 2, NULL,0);
    
    xTaskCreatePinnedToCore(S, "stop", 100000, NULL, 1, NULL,0);
    
/*
    pinMode(xpin, INPUT_PULLUP);
    pinMode(ypin, INPUT_PULLUP);

    attachInterrupt(digitalPinToInterrupt(xpin), blink, CHANGE);
    attachInterrupt(digitalPinToInterrupt(ypin), blink, CHANGE);
    */

    //Lanzamiento de la tarea que envía la info del joystick a las otras tareas a través de una cola

    xTaskCreatePinnedToCore(queues, "queues", 100000, NULL, 4, NULL,0);
}

void loop()
{
}

Upvotes: 1

Views: 1453

Answers (1)

Tarmo
Tarmo

Reputation: 4770

There's a bunch of issues in this code, but the most pressing one that you have to actually create the mutexes (and create the queues) before launching any tasks that use them.

const size_t QUEUE_F_LEN = 10;
const size_t QUEUE_B_LEN = 10;
void setup()
{
...
    // Create the mutexes
    xMutex = xSemaphoreCreateMutex();
    assert(xMutex);
    xMutexSendCommand = xSemaphoreCreateMutex();
    assert(xMutexSendCommand);

    // Create the queues
    xQueueF = xQueueCreate(QUEUE_F_LEN, sizeof(xMessageReceive));
    assert(xQueueF);
    xQueueB = xQueueCreate(QUEUE_B_LEN, sizeof(xMessageReceive));
    assert(xQueueB);
    // ... etc

    // Create tasks that use mutexes and queues
    xTaskCreatePinnedToCore(t_F, "forward", 4000, NULL, 4, NULL,0);
...

I would recommend going over the relevant chapters in Mastering the FreeRTOS Real Time Kernel - a Hands On Tutorial Guide (it explains the topic well without going into unnecessary details).

Upvotes: 1

Related Questions