问题描述
我有一个使用 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,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 中的相关章节(它很好地解释了主题,而不会涉及不必要的细节)。