ESP32 和 Freertos:如何正确使用 Freertos 的任务和队列

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

我有一个使用 ESP32 和 Freertos 的程序,它从操纵杆读取某些值并根据这些值将其发送到多个任务。问题是队列给我一些错误,我找不到以下信息:

这只是一个启动任务,没有队列。另一张图片在队列中:

现在,这是代码的一部分,我的意思是:

这些是已启动的任务:

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);

这些是任务:

    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;
      }
    }
  }
}

还有其他任务,程序更大,但我将程序缩减到这部分,我在此处注释 Queue 以查看会发生什么。

这是完整的代码,以备不时之需:

#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()
{
}

这段代码中有很多问题,但在启动任何使用它们的任务之前,您实际上必须 create the mutexes (and create the queues) 解决最紧迫的问题。

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);
...

我建议阅读 Mastering the FreeRTOS Real Time Kernel - a Hands On Tutorial Guide 中的相关章节(它很好地解释了主题,而没有涉及不必要的细节)。