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

问题描述

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

enter image description here

这只有一个已启动的任务,没有队列。另一个图像在队列中:

enter image description here

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

这些是已启动的任务:

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

xTaskCreatePinnedToCore(queues,"queues",4,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;
      }
    }
  }
}

还有其他任务,程序更大,但我将程序缩减到这一部分,在那里我评论队列以查看会发生什么。

这是完整的代码,以防万一有帮助:

#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,(( TickType_t ) 10 ) != pdPASS );

      xSemaphoreTake( xMutex,200/portTICK_PERIOD_MS  );{
        if (strcmp(xMessageReceive,"FORWARD") == 0)
        {
          snprintf(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,200/portTICK_PERIOD_MS  );
      {
        if (strcmp(xMessageReceive,"BACKWARD") == 0){
          snprintf(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,(( TickType_t ) 10 ) != pdPASS );
      

        xSemaphoreTake( xMutex,200/portTICK_PERIOD_MS  );
        {
          if (strcmp(xMessageReceive,"LEFT") == 0){
            snprintf(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,(( TickType_t ) 10 ) != pdPASS );

        xSemaphoreTake( xMutex,"RIGHT") == 0){
            snprintf(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,(( TickType_t ) 10 ) != pdPASS );
      
        xSemaphoreTake( xMutex,"RF") == 0){

            snprintf(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,"LF") == 0){
            snprintf(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,"RB") == 0){
            snprintf(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,"RL") == 0){
            snprintf(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,"STOP") == 0){
            snprintf(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.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,"BACKWARD");
        xQueueSend(xQueueB,(( TickType_t ) 10 ) != pdPASS );
        sB = 1;
      }
    }
    if (valx == 0 && valy <= 2500 && valy >= 923 ){
      xSemaphoreTake( xMutexSendCommand,"LEFT");
        xQueueSend(xQueueL,(( TickType_t ) 10 ) != pdPASS );
        sL = 1;
      }
    }
    if (valx == 4095 && valy <= 2500 && valy >= 923 ){
      xSemaphoreTake( xMutexSendCommand,"RIGHT");
        xQueueSend(xQueueR,(( TickType_t ) 10 ) != pdPASS );
        sR = 1;
      }
    }
    if (valx <= 4095 && valx >= 2623 && valy <= 823 && valy > 0 ){
      xSemaphoreTake( xMutexSendCommand,"RF");
        xQueueSend(xQueueG,(( TickType_t ) 10 ) != pdPASS );
        sG = 1;
      }
    }
    if (valx <= 823 && valx >= 0 && valy <= 923 && valy > 0 ){
      xSemaphoreTake( xMutexSendCommand,"LF");
        xQueueSend(xQueueI,(( TickType_t ) 10 ) != pdPASS );
        sI = 1;
      }
    }
    if (valx <= 4095 && valx >= 2623 && valy < 4095 && valy >= 2500 ){
      xSemaphoreTake( xMutexSendCommand,"RB");
        xQueueSend(xQueueH,(( TickType_t ) 10 ) != pdPASS );
        sH = 1;
      }
    }
    if (valx <= 823 && valx >= 0 && valy < 4095 && valy >= 2500 ){
      xSemaphoreTake( xMutexSendCommand,"LB");
        xQueueSend(xQueueJ,(( TickType_t ) 10 ) != pdPASS );
        sJ = 1;
      }
    }
    
    if (valx <= 2623 && valx >= 823 && valy <= 2500 && valy >= 923 ){
      xSemaphoreTake( xMutexSendCommand,(( 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);


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

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

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

    xTaskCreatePinnedToCore(queues,0);
}

void loop()
{
}

解决方法

此代码中有很多问题,但最紧迫的问题是您在启动任何使用它们的任务之前必须create the mutexes(和 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,0);
...

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