xQueueSend multiple messages on Arduino Mega 2560

Hi, I am working on a project using freeRTOS V10.0.0. on a Arduino Mega 2560 There is some issues with the xQueueReceive function… This code is inspired by the code example of “xQueueSend”. REF: https://www.freertos.org/a00117.html This is the code: ~~~

include <Arduino_FreeRTOS.h>

include <queue.h>

struct AMessage { char ucMessageID; char ucData[20]; } xMessage; unsigned long ulVar = 10UL; void vATask(void); void setup() { Serial.begin(115200); vATask(); } void loop() { // Nothing } void vATask(void) { //void pvParameters QueueHandle_t xQueue1, xQueue2; struct AMessage *pxMessage; / Create a queue capable of containing 10 unsigned long values. / xQueue1 = xQueueCreate( 10, sizeof( unsigned long ) ); / Create a queue capable of containing 10 pointers to AMessage structures. These should be passed by pointer as they contain a lot of data. / xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) ); / … */ xMessage.ucMessageID = 1; strcpy(xMessage.ucData, “Message1”); if(xQueue1 != 0) { /* Send an unsigned long. Wait for 10 ticks for space to become available if necessary. / if(xQueueSend(xQueue1, (void)&ulVar, (TickTypet)10) != pdPASS ) { /* Failed to post the message, even after 10 ticks. */ } } if(xQueue2 != 0) { /* Send a pointer to a struct AMessage object. Don’t block if the queue is already full. */ pxMessage = &xMessage; xQueueSend(xQueue2, (void*)&pxMessage, (TickTypet)0);
Serial.println("SEND 1");
Serial.print("pxMessage->ucMessageID: ");
Serial.println(pxMessage->ucMessageID, DEC);
Serial.print("pxMessage->ucData: ");
Serial.println(pxMessage->ucData);
Serial.println();

xMessage.ucMessageID = 2;
strcpy(xMessage.ucData, "Message2");
pxMessage = &xMessage;
xQueueSend(xQueue2, (void*)&pxMessage, (TickType_t)0);
Serial.println("SEND 2");
Serial.print("pxMessage->ucMessageID: ");
Serial.println(pxMessage->ucMessageID, DEC);
Serial.print("pxMessage->ucData: ");
Serial.println(pxMessage->ucData);
Serial.println();

xQueueReceive(xQueue2, (void*)&pxMessage, (TickType_t)0);
Serial.println("RECEIVE 1");
Serial.print("pxMessage->ucMessageID: ");
Serial.println(pxMessage->ucMessageID, DEC);
Serial.print("pxMessage->ucData: ");
Serial.println(pxMessage->ucData);
Serial.println();

xQueueReceive(xQueue2, (void*)&pxMessage, (TickType_t)0);
Serial.println("RECEIVE 2");
Serial.print("pxMessage->ucMessageID: ");
Serial.println(pxMessage->ucMessageID, DEC);
Serial.print("pxMessage->ucData: ");
Serial.println(pxMessage->ucData);
Serial.println();
} } ~~~ And this is the result on the arduino serial monitor: ~~~ SEND 1 pxMessage->ucMessageID: 1 pxMessage->ucData: Message1 SEND 2 pxMessage->ucMessageID: 2 pxMessage->ucData: Message2 RECEIVE 1 pxMessage->ucMessageID: 2 pxMessage->ucData: Message2 RECEIVE 2 pxMessage->ucMessageID: 2 pxMessage->ucData: Message2 ~~~ This is just a simple test code that send two messages with a ID and a char array. i want to receive this two message but I read two times the last messag sended (ID=2, message=Message2). I want this output: ~~~ SEND 1 pxMessage->ucMessageID: 1 pxMessage->ucData: Message1 SEND 2 pxMessage->ucMessageID: 2 pxMessage->ucData: Message2 RECEIVE 1 pxMessage->ucMessageID: 1 pxMessage->ucData: Message1 RECEIVE 2 pxMessage->ucMessageID: 2 pxMessage->ucData: Message2 ~~~ Thank you for your help.

xQueueSend multiple messages on Arduino Mega 2560

It looks like the example code on that page is wrong, and you have copied the error into your code. The line: xQueueSend(xQueue2, (void*)&pxMessage, (TickType_t)0); is taking the address of a pointer to an xMessage structure, whereas it should take the address of the xMessage structure directly. Can you try changing the line to: xQueueSend(xQueue2, (void*)pxMessage, (TickType_t)0); (remove the ‘&’). In the mean time I will review the example code, which I see also calls xMessage AMessage, and fix as appropriate. Let me know if this solves your problem.

xQueueSend multiple messages on Arduino Mega 2560

On second look the queue was created to hold pointers. Hang on a second or two I will try again….

xQueueSend multiple messages on Arduino Mega 2560

You are seeing the expected behavour because you are queuing a pointer to the structure. In the first send you set the structure values to 1 and Message1, and queue a pointer to the structure. In the second send you set the structure values to 2 and Message2, and queue a pointer to the structure. In the first receive you receive a pointer to the structure. When you dereference the pointer you read the values out of the structure. The actually in the structure being pointed to are still 2 and Message2, which is what is printed out.

xQueueSend multiple messages on Arduino Mega 2560

Thank you Richard Barry. I have try your answers and many others solution but nothing seems to work… I make another example code with 10 different messages. First, here is the code that uses a structure pointer that contains a variable and a char array: ~~~ /*Begining of Auto generated code by Atmel studio */

include <Arduino.h>

/*End of auto generated code by Atmel studio */

include <Arduino_FreeRTOS.h>

include <queue.h>

//Beginning of Auto generated function prototypes by Atmel Studio //End of Auto generated function prototypes by Atmel Studio // CHAR ARRAY POINTER ————————– struct tabData { int messsageID = 0; //char* pData; char pData[10] = {0}; }; struct tabData *pDataSend; struct tabData *pDataReceive; QueueHandle_t queue; void setup() {
pDataSend = (struct tabData*)malloc(sizeof(struct tabData));
//pDataSend->pData = (char*)malloc(sizeof(char)*10);

pDataReceive = (struct tabData*)malloc(sizeof(struct tabData));
//pDataReceive->pData = (char*)malloc(sizeof(char)*10);
Serial.begin(115200); queue = xQueueCreate( 10, sizeof(tabData) ); if(queue == NULL){ Serial.println(“Error creating the queue”); } } void loop() { if(queue == NULL)return; for(int i = 0; i<10; i++){ pDataSend->messsageID = i; switch(i) { case 0: strcpy(pDataSend->pData, “abcd”); break; case 1: strcpy(pDataSend->pData, “efgh”); break; case 2: strcpy(pDataSend->pData, “ijkl”); break; case 3: strcpy(pDataSend->pData, “mnop”); break;
case 4: strcpy(pDataSend->pData, “qrst”); break;
case 5: strcpy(pDataSend->pData, “uvwx”); break;
case 6: strcpy(pDataSend->pData, “yz12”); break;
case 7: strcpy(pDataSend->pData, “3456”); break;
case 8: strcpy(pDataSend->pData, “7890”); break; case 9: strcpy(pDataSend->pData, “Test”); break;
default: break;
} xQueueSend(queue, pDataSend, portMAX_DELAY); } for(int j = 0; j<10; j++){ xQueueReceive(queue, pDataReceive, portMAX_DELAY); Serial.print(pDataReceive->messsageID); Serial.print(” | “); Serial.print(pDataReceive->pData); Serial.println(); } Serial.println(); delay(1000); } ~~~ this version works perfectly and I have the message ID and the message on the terminal in the good order: ~~~ 0 | abcd 1 | efgh 2 | ijkl 3 | mnop 4 | qrst 5 | uvwx 6 | yz12 7 | 3456 8 | 7890 9 | Test ~~~ After that, I tried to make the same program, but using a char pointer instead of the array. ~~~ /*Begining of Auto generated code by Atmel studio */

include <Arduino.h>

/*End of auto generated code by Atmel studio */

include <Arduino_FreeRTOS.h>

include <queue.h>

//Beginning of Auto generated function prototypes by Atmel Studio //End of Auto generated function prototypes by Atmel Studio // CHAR ARRAY POINTER ————————– struct tabData { int messsageID = 0; char* pData; //char pData[10] = {0}; }; struct tabData *pDataSend; struct tabData *pDataReceive; QueueHandle_t queue; void setup() {
pDataSend = (struct tabData*)malloc(sizeof(struct tabData));
pDataSend->pData = (char*)malloc(sizeof(char)*10);

pDataReceive = (struct tabData*)malloc(sizeof(struct tabData));
pDataReceive->pData = (char*)malloc(sizeof(char)*10);
Serial.begin(115200); queue = xQueueCreate( 10, sizeof(tabData) ); if(queue == NULL){ Serial.println(“Error creating the queue”); } } void loop() { if(queue == NULL)return; for(int i = 0; i<10; i++){ pDataSend->messsageID = i; switch(i) { case 0: strcpy(pDataSend->pData, “abcd”); break; case 1: strcpy(pDataSend->pData, “efgh”); break; case 2: strcpy(pDataSend->pData, “ijkl”); break; case 3: strcpy(pDataSend->pData, “mnop”); break;
case 4: strcpy(pDataSend->pData, “qrst”); break;
case 5: strcpy(pDataSend->pData, “uvwx”); break;
case 6: strcpy(pDataSend->pData, “yz12”); break;
case 7: strcpy(pDataSend->pData, “3456”); break;
case 8: strcpy(pDataSend->pData, “7890”); break; case 9: strcpy(pDataSend->pData, “Test”); break;
default: break;
} xQueueSend(queue, pDataSend, portMAX_DELAY); } for(int j = 0; j<10; j++){ xQueueReceive(queue, pDataReceive, portMAX_DELAY); Serial.print(pDataReceive->messsageID); Serial.print(” | “); Serial.print(pDataReceive->pData); Serial.println(); } Serial.println(); delay(1000); } ~~~ And this time, the teminal show this… ~~~ 0 | Test 1 | Test 2 | Test 3 | Test 4 | Test 5 | Test 6 | Test 7 | Test 8 | Test 9 | Test ~~~ I don’t understand why there is the good ID but the message doesn’t change. Sorry I do not have much experience with pointers of structures with pointers. Thank you for your help.

xQueueSend multiple messages on Arduino Mega 2560

If you think what the program is doing it is creating a single buffer with malloc to hold that data, and overwriting it with each loop of the program. The queue send copies the data in the base structure itself, but that just has a pointer to the pData buffer, so that data is reused for each structure. You need to create a seperate buffer for each chunck of data. With the array, since that is part of the structure that is copied, you get it. With the pointer to malloced data, it isn’t, so you need to malloc a new buffer for each thing you send (and then free it after using it at the receiver).

xQueueSend multiple messages on Arduino Mega 2560

I understood my mistakes thanks to you. There is a problem with dynamic allocation memory now… When I malloc memory out of the for loop there is the problem you just explained. But now I make malloc memory in the for loop and free it in another loop (both loop have the same iteration number). The for loop become endless. The variable “i” is incremented at every iteration but never break. Maybe there is a memory problem with the heap size. I actually make some rechearch for this. I put the code modified code below. ~~~ /*Begining of Auto generated code by Atmel studio */

include <Arduino.h>

/*End of auto generated code by Atmel studio */

include <Arduino_FreeRTOS.h>

include <queue.h>

include <avr/pgmspace.h>

include <stdlib.h>

//Beginning of Auto generated function prototypes by Atmel Studio //End of Auto generated function prototypes by Atmel Studio

define NUMBER_MSG 2

define SIZE_MSG 10

// CHAR ARRAY POINTER ————————– struct tabData { int messsageID = 0; char* pData; //char pData[SIZE_MSG] = {0}; }; struct tabData *pDataSend; struct tabData *pDataReceive; QueueHandle_t queue; char sendMsg[SIZEMSG]; int sendID; char receiveMsg[SIZEMSG]; int receiveID; void setup() { pDataSend = (struct tabData)malloc(sizeof(struct tabData)); pDataReceive = (struct tabData)malloc(sizeof(struct tabData)); //pDataSend->pData = (char)malloc(sizeof(char)SIZE_MSG);
Serial.begin(115200);

queue = xQueueCreate(NUMBER_MSG, sizeof(tabData) );

if(queue == NULL){
    //Serial.println("Error creating the queue");
}
} void loop() {
if(queue == NULL)return;

for(int i = 0; i<NUMBER_MSG; i++){
    Serial.print("i = ");
    Serial.println(i);
    pDataSend->pData = (char*)malloc(sizeof(char)*SIZE_MSG);
    //free(pDataSend->pData);
    pDataSend->messsageID = i;
    switch(i) {
        case 0:
        strcpy(pDataSend->pData, "abcd");
        break;
        case 1:
        strcpy(pDataSend->pData, "efgh");
        break;
        case 2:
        strcpy(pDataSend->pData, "ijkl");
        break;
        /*case 3:
        strcpy(pDataSend->pData, "mnop");
        break;
        case 4:
        strcpy(pDataSend->pData, "qrst");
        break;
        case 5:
        strcpy(pDataSend->pData, "uvwx");
        break;
        case 6:
        strcpy(pDataSend->pData, "yz12");
        break;
        case 7:
        strcpy(pDataSend->pData, "3456");
        break;
        case 8:
        strcpy(pDataSend->pData, "7890");
        break;
        case 9:
        strcpy(pDataSend->pData, "Test");
        break;*/
        default:
        break;
    }
    sendID = pDataSend->messsageID;
    strcpy(sendMsg, pDataSend->pData);
    xQueueSend(queue, pDataSend, portMAX_DELAY);
}

for(int j = 0; j<NUMBER_MSG; j++){
    xQueueReceive(queue, pDataReceive, portMAX_DELAY);
    receiveID = pDataReceive->messsageID;
    strcpy(receiveMsg, pDataReceive->pData);

    Serial.print(pDataReceive->messsageID);
    Serial.print(" | ");
    Serial.print(pDataReceive->pData);  
    Serial.println();
    free(pDataReceive->pData);
}
Serial.println();
delay(1000);
} ~~~ Thank you again

xQueueSend multiple messages on Arduino Mega 2560

First, every call to malloc should be checking for a NULL return, which indicates that you have run out of heap (what to do in this case is on reason it is generally discouraged from using malloc in embedded systems). If you do process with a NULL buffer you likely overwrite some memory, which can cause all sorts of issues.

xQueueSend multiple messages on Arduino Mega 2560

Thanks for the tip. By controlling each malloc, when the malloc is realized in the “settings” loop the memory is allocated correctly and returns a correct pointer. When memory is allocated in the main infinite loop, malloc returns a NULL pointer. I do not understand how it is possible to allocate memory in the settings loop but not in the infinite loop.