-1

Good morning everyone,

I am currently working on a data acquisition project, where I have to read sensors (at around 10 kHz) and transmit the data via Wi-Fi and the MQTT-protocol. I am using an ESP32 for both of these tasks.

One core is doing the sensor reading and the other core does the transmitting stuff. I also use the FreeRTOS for this.

Now, I want to pass the data as efficient as possible between the task. Currently I'm using the xQueue function built in the FreeRtos. I pass pointers in the Queue which point to an array, where one datapackage is stored.

Task one:

*sensor reading*

for(xx)
{
   data_array[x] = sensor_data;
}

if {packageSize == 120}
{ 
    xQueueSend(Queue1, &data_pointer, 0);
}

________________________

Task two:

if( uxQueueMessagesWaiting(Queue1) >= 1)
{
    xQueueReceive(Queue1, &received_pointer, 0);

    memcpy(data_send, received_pointer, packageSize);

    * MQTT-Client sending data_send *
}

You see, my problem isn't the creation of the array with different pointers. The sensor reading task needs to create an array for every package, without overwritting the previous one.

My initial idea was to use the new and delete combination but it gave me strange results.

Is there any way I can change the location of the array on the memory at every loop of task one?

EDIT:


/* general variables*/

const int len = 150;
uint8_t data_received[len];
uint8_t data_send[len];
uint8_t *queue_pointer = 0;
uint8_t *received_pointer = 0;
uint8_t *to_delete_pointer = 0;
uint8_t dummy_data = 0;
int v = 0;

/* multithreading variables */

TaskHandle_t SPI_COM;
TaskHandle_t WIFI;
QueueHandle_t buffer_daten;


/* --------------------- Fake-SPI-Kommunikation auf Core 1 -------------------- */

void SPI_COM_code(void *pvParameters)
{

  for (;;)
  {

    while (v <= 10000)
    {
        //queue_pointer = new int[len];  // creates a new array

        queue_pointer = data_received;

        queue_pointer[dummy_data] = dummy_data;

        dummy_data++;

        delayMicroseconds(100);  // Dummy-Interrupt

      if (dummy_data == len - 1)
      {

        dummy_data = 0;

        xQueueSend(buffer_daten, &queue_pointer, 0);

        v++;
      }
    }
  }
}

/* --------------------- WiFi-Übertragung auf Core 0 --------------------- */

void WIFI_code(void *pvParameters)
{
  for (;;)
  {
    //MQTT_connect();

    if (uxQueueMessagesWaiting(buffer_daten) > 0)
    {
      xQueueReceive(buffer_daten, &received_pointer, 0);

      to_delete_pointer = received_pointer;

      memcpy(data_send, received_pointer, len);      

      // Data gets published by MQTT-Client
      
      delayMicroseconds(12);

      //delete[] to_delete_pointer; // deletes array, which was send
    }

  }
}

/* ----------------------------------- Setup ---------------------------------- */

void setup()
{
  disableCore0WDT(); // <----- MÖGLICHE PROBLEMQUELLE

  Serial.begin(115200);

  buffer_daten = xQueueCreate(1000, sizeof(int));

  xTaskCreatePinnedToCore(
      SPI_COM_code, /* Task function. */
      "SPI_COM",    /* name of task. */
      10000,        /* Stack size of task */
      NULL,         /* parameter of the task */
      1,            /* priority of the task */
      &SPI_COM,     /* Task handle to keep track of created task */
      1);           /* pin task to core 0 */
  delay(500);

  xTaskCreatePinnedToCore(
      WIFI_code, /* Task function. */
      "WIFI",    /* name of task. */
      10000,     /* Stack size of task */
      NULL,      /* parameter of the task */
      2,         /* priority of the task */
      &WIFI,     /* Task handle to keep track of created task */
      0);        /* pin task to core 1 */

  delay(500);

  
}


void loop()
{
}

Legriano
  • 1
  • 2
  • please show a [mre], what is `data_array`, `data_pointer`, `data_send`, `received_pointer` – Alan Birtles Jul 17 '20 at 06:57
  • Also include what hardware FreeRTOS is running on. With embedded systems, it is best to avoid dynamic memory allocation given the limited resources available.(that may be the ESP32, but it is not clear) – David C. Rankin Jul 17 '20 at 07:07
  • May be you should consider using a preallocated circular buffer with sufficient extra size for cases when the sending thread is not fast enough. This will allow you to avoid memory allocations generally not desired in real-time cases. Access to the circular buffer can be guarded by simple mutexes - this will eliminate data races. – Vasilij Jul 17 '20 at 07:16
  • @Vasilij in my understanding the xQueue function of the FreeRtos is such a circular buffer. But i assume, that the amount of data will be to big. – Legriano Jul 17 '20 at 07:23
  • 1
    @AlanBirtles the minimal example is added. – Legriano Jul 17 '20 at 07:24
  • 1
    With `queue_pointer = data_received;` you lose the allocated array. – IlCapitano Jul 17 '20 at 07:32
  • I see now, thanks for the example. So, you pass not the data itself, but the pointer to the data in the queue. But anyway you allocate memory. The amount of used RAM will be the same. Why not pass the data directly with xQueue, it was designed for this. May be you have some limitations I am not aware of. – Vasilij Jul 17 '20 at 07:41
  • @IlCapitano the allocation of memory is not implemented in the example because it didnt worked. – Legriano Jul 17 '20 at 07:48
  • @Vasilij i will try your suggestion! maybe its simpler than i expected :) – Legriano Jul 17 '20 at 07:49

1 Answers1

0

I would suggest you use a RTOS Message Buffers for this task

With this functions you could copy your array into the buffer and the second task could get it, when the data is available.

In both cases the consumer task should use the timeout '0' to request the data.

If the MQTT task is faster than the data acquisition (and it should be or your buffers will overflow sooner or later) this will lead to invalid pointers:

xQueueReceive(buffer_daten, &received_pointer, 0);

If the is no data available the function will return immediately giving you an invalid received_pointer.

You should either check the return value of xQueueReceive or set the timeout to portMAX_DELAY.

theSealion
  • 1,082
  • 7
  • 13
  • thank you for your suggestion. i am a bit concerned, that the amount of data will get to big to handle. thats why i chose the pointer approach. There will be 66 arrays with 600 bytes per second. Do you think the message buffer can handel this? – Legriano Jul 17 '20 at 07:39
  • I don't think the message buffer would be a problem. The first think you have to be sure about is, if you MQTT Client could send the data fast enough. The average transmitting time must be faster than your data collection. – theSealion Jul 17 '20 at 08:11