Having trouble with string (char) queue

Hi all,

I am trying to create a queue that will use string (char) variables, but I am having trouble understanding how it works and therefore it doesn't work.

The queue library:

My code:

/*
        Author: Vasco Baptista
        email: vascojdb@gmail.com
        An example of using Einar Arnason's queue
        In this example we create a queue of int's
        limited by the maximum amount of items
        Usage and further info:
        https://github.com/EinarArnason/ArduinoQueue
*/

#include "Queue.h"

#define QUEUE_SIZE_ITEMS 10

// Queue creation:
ArduinoQueue<char> charQueue(QUEUE_SIZE_ITEMS);

void printQueueStats() {
  Serial.println("");
  Serial.printf("Size of each element:    %u bytes\r\n", charQueue.item_size());
  Serial.printf("Items in queue now:      %u items\r\n", charQueue.item_count());
  Serial.printf("Queue actual max items:  %u items\r\n",
                charQueue.maxQueueSize());
  Serial.printf("Queue actual max memory: %u bytes\r\n",
                charQueue.maxMemorySize());
  Serial.println("");
}

void setup() {
  Serial.begin(115200);
  Serial.println("");
  Serial.println("========== Queue example ==========");
  Serial.printf("Desired max item size:  %u items\r\n", QUEUE_SIZE_ITEMS);
  Serial.println("===================================");
}

void loop() {
  printQueueStats();

  // Add elements: (add more than the queue size for demo purposes)
  if (!charQueue.isFull()) {
    char n[] = "1";
    Serial.printf("Adding value: %i\r\n", n);
    charQueue.enqueue(n);
  }

  printQueueStats();

  if (!charQueue.isEmpty()) {
    char result[] = intQueue.dequeue();
    Serial.printf("Removed value: %i\r\n", result);
  }
  else {
    Serial.println("Queue is empty!");
  }

  printQueueStats();

  // Loop forever
  while (true) {
#ifdef ESP8266
    ESP.wdtFeed();
#endif
  }
}

Shows this error:

invalid conversion from 'char*' to 'char' [-fpermissive]

About this line:

charQueue.enqueue(n);

Any help would be awesome.

Thanks,

Zeb

invalid conversion from 'char*' to 'char' [-fpermissive]

//char n[] = "1";
char n[] = '1';

Single quotes to indicate a char.

Hi cattledog,

Thanks very much for your help! Unfortunately I have changed it to "123" instead of "1", and am I correct that it is double quotes for anything more than one character?

Updated code (still got same error)

/*
        Author: Vasco Baptista
        email: vascojdb@gmail.com
        An example of using Einar Arnason's queue
        In this example we create a queue of int's
        limited by the maximum amount of items
        Usage and further info:
        https://github.com/EinarArnason/ArduinoQueue
*/

#include "Queue.h"

#define QUEUE_SIZE_ITEMS 10

// Queue creation:
ArduinoQueue<char> charQueue(QUEUE_SIZE_ITEMS);

void printQueueStats() {
  Serial.println("");
  Serial.printf("Size of each element:    %u bytes\r\n", charQueue.item_size());
  Serial.printf("Items in queue now:      %u items\r\n", charQueue.item_count());
  Serial.printf("Queue actual max items:  %u items\r\n",
                charQueue.maxQueueSize());
  Serial.printf("Queue actual max memory: %u bytes\r\n",
                charQueue.maxMemorySize());
  Serial.println("");
}

void setup() {
  Serial.begin(115200);
  Serial.println("");
  Serial.println("========== Queue example ==========");
  Serial.printf("Desired max item size:  %u items\r\n", QUEUE_SIZE_ITEMS);
  Serial.println("===================================");
}

void loop() {
  printQueueStats();

  // Add elements: (add more than the queue size for demo purposes)
  if (!charQueue.isFull()) {
    char n[] = "123";
    Serial.printf("Adding value: %i\r\n", n);
    charQueue.enqueue(n);
  }

  printQueueStats();

  if (!charQueue.isEmpty()) {
    char result[] = intQueue.dequeue();
    Serial.printf("Removed value: %i\r\n", result);
  }
  else {
    Serial.println("Queue is empty!");
  }

  printQueueStats();

  // Loop forever
  while (true) {
#ifdef ESP8266
    ESP.wdtFeed();
#endif
  }
}

Do you know what else might be wrong?

Thanks,

Zeb

ZebH:
Thanks very much for your help! Unfortunately I have changed it to "123" instead of "1", and am I correct that it is double quotes for anything more than one character?

Correct, but then it’s no longer a char. It’s a char[].
To add this to your queue you must add them one at a time...

char n[] = "123";
char* p = n;
while (*p) charQueue.enqueue(*p++);

Thanks very much pcbbc, that line now compiles without an error!

My last probem/question (hopefully) is how to dequeue into a char[] variable?

I am trying to do it like this currently:

    char result[] = charQueue.dequeue();

But I am getting this error:

initializer fails to determine size of 'result'

Updated code:

/*
        Author: Vasco Baptista
        email: vascojdb@gmail.com
        An example of using Einar Arnason's queue
        In this example we create a queue of int's
        limited by the maximum amount of items
        Usage and further info:
        https://github.com/EinarArnason/ArduinoQueue
*/

#include "Queue.h"

#define QUEUE_SIZE_ITEMS 10

// Queue creation:
ArduinoQueue<char> charQueue(QUEUE_SIZE_ITEMS);

void printQueueStats() {
  Serial.println("");
  Serial.printf("Size of each element:    %u bytes\r\n", charQueue.item_size());
  Serial.printf("Items in queue now:      %u items\r\n", charQueue.item_count());
  Serial.printf("Queue actual max items:  %u items\r\n",
                charQueue.maxQueueSize());
  Serial.printf("Queue actual max memory: %u bytes\r\n",
                charQueue.maxMemorySize());
  Serial.println("");
}

void setup() {
  Serial.begin(115200);
  Serial.println("");
  Serial.println("========== Queue example ==========");
  Serial.printf("Desired max item size:  %u items\r\n", QUEUE_SIZE_ITEMS);
  Serial.println("===================================");
}

void loop() {
  printQueueStats();

  // Add elements: (add more than the queue size for demo purposes)
  if (!charQueue.isFull()) {
    char n[] = "123";
    char* p = n;
    while (*p) charQueue.enqueue(*p++);
    Serial.printf("Added value: %i\r\n", n);
  }

  printQueueStats();

  if (!charQueue.isEmpty()) {
    char result[] = charQueue.dequeue();
    Serial.printf("Removed value: %i\r\n", result);
  }
  else {
    Serial.println("Queue is empty!");
  }

  printQueueStats();

  // Loop forever
  while (true) {
#ifdef ESP8266
    ESP.wdtFeed();
#endif
  }
}

Thanks again,

Zeb

What data types are you trying to hold in your queue?

If you are trying to hold character arrays like "123" instead of the individual chars 1,2,3 you may need to switch your approach to queue something like the structs mentioned in the library read me.

Are you are trying to hold the individual chars in each slot of the queue, but then write them in and out in groups of three?

Hi cattledog,

I am trying to store a date and time and I want each entry to be one complete string so it would be something like 2020-08-10N14:23Z.

Would it be easier if I used a String variable instead of char[]?

Thanks,

Zeb

Would it be easier if I stored it in a String variable?

I am not familiar with the data types handled by the queue library and if you can use

ArduinoQueue<String> StringQueue(QUEUE_SIZE_ITEMS);

I have my doubts, although the read me talks about queuing pointers

You will probably need to use char arrays, but I'm not clear on how to present them to the library.

Why do you wish to use a queue and the dynamic memory management of the library.

What are the requirements of your program?

Thanks for your help cattledog.

The program "posts" the time of sensor readings over the internet but it needs to store the time of sensor reading when there is no internet connection and then "post" those times when internet connection is back, that is what I need the queue for.

Thanks,

Zeb

I'm not very familiar with the ESP environment, and whether or not you can get into the same memory issues as with the smaller avr's when using dynamic memory.

The program "posts" the time of sensor readings over the internet but it needs to store the time of sensor reading when there is no internet connection and then "post" those times when internet connection is back

How long do you think the off line time can be, and the max number of timestamps that need to be stored? I believe that the queue library needs to know the size of the queue although it appears to dynamically fill and empty the slots.

The timestamps can certainly be a known length, and given the memory available in the ESP you may just be able to declare a 2d character array in ram or perhaps the file system or eeprom to cover the max off line time.

If the off line time can be very long and indeterminate, perhaps an SD card or other external memory could be used.

I'm not certain that the Queue library is really an solution to your issue.

OK, thanks for all your help cattledog!

If possible I would like to stay away from the SD card solution, and I may well want to add sensor value readings into the queue which would mean the length of the variable being entered into the queue would change from entry to entry. So I think that those solutions won't work for me?

I am hoping to store about 180 readings. Is it possible to make that work?

Thanks again,

Zeb

I have changed to using String instead of char[], and it works fine.

Code:

/*
        /*
        Author: Vasco Baptista
        email: vascojdb@gmail.com
        An example of using Einar Arnason's queue
        In this example we create a queue of int's
        limited by the maximum amount of items
        Usage and further info:
        https://github.com/EinarArnason/ArduinoQueue
*/

#include "Queue.h"

#define QUEUE_SIZE_ITEMS 2000

// Queue creation:
ArduinoQueue<String> charQueue(QUEUE_SIZE_ITEMS);

void printQueueStats() {
  Serial.println("");
  Serial.printf("Size of each element:    %u bytes\r\n", charQueue.item_size());
  Serial.printf("Items in queue now:      %u items\r\n", charQueue.item_count());
  Serial.printf("Queue actual max items:  %u items\r\n",
                charQueue.maxQueueSize());
  Serial.printf("Queue actual max memory: %u bytes\r\n",
                charQueue.maxMemorySize());
  Serial.println("");
}

void setup() {
  Serial.begin(115200);
  Serial.println("");
  Serial.println("========== Queue example ==========");
  Serial.printf("Desired max item size:  %u items\r\n", QUEUE_SIZE_ITEMS);
  Serial.println("===================================");
}

void loop() {
  printQueueStats();

  // Add elements: (add more than the queue size for demo purposes)
  if (!charQueue.isFull()) {
    String n = "2020-08-10N14:23:12Z";
    charQueue.enqueue(n);
    Serial.println("Added value (n):");
    Serial.println(n);

    n = "2020-08-10N14:23:13Z";
    charQueue.enqueue(n);
    Serial.println("Added value (n):");
    Serial.println(n);

    n = "2020-08-10N14:23:14Z";
    charQueue.enqueue(n);
    Serial.println("Added value (n):");
    Serial.println(n);
  }

  printQueueStats();

  while (!charQueue.isEmpty()) {
    String result = charQueue.dequeue();
    Serial.println("Removed value:");
    Serial.println(result);
  }
  Serial.println("Queue is empty!");

  printQueueStats();

  delay(2000);
}

In the Serial Monitor it says:

Size of each element:    16 bytes
Items in queue now:      0 items
Queue actual max items:  2000 items
Queue actual max memory: 4294967295 bytes

It looks to me that it will have no trouble at all doing what I want. Am I correct?

Thanks,

Zeb

It looks to me that it will have no trouble at all doing what I want. Am I correct?

You've certainly got the library to work with the String objects. However, it is queuing pointers, not the actual characters. Your time stamps are 20 characters plus a null terminator, but the size of each element is reported as 16 bytes.

You can see that if you change the data type from String to char*, the program functions as before, but the reported size of each element is reduced to 8 bytes.

/*
        /*
        Author: Vasco Baptista
        email: vascojdb@gmail.com
        An example of using Einar Arnason's queue
        In this example we create a queue of int's
        limited by the maximum amount of items
        Usage and further info:
        https://github.com/EinarArnason/ArduinoQueue
*/

#include "ArduinoQueue.h" //Queue.h

#define QUEUE_SIZE_ITEMS 2000

// Queue creation:
ArduinoQueue<char*> charQueue(QUEUE_SIZE_ITEMS);

void printQueueStats() {
  Serial.println("");
  Serial.printf("Size of each element:    %u bytes\r\n", charQueue.item_size());
  Serial.printf("Items in queue now:      %u items\r\n", charQueue.item_count());
  Serial.printf("Queue actual max items:  %u items\r\n",
                charQueue.maxQueueSize());
  Serial.printf("Queue actual max memory: %u bytes\r\n",
                charQueue.maxMemorySize());
  Serial.println("");
}

void setup() {
  Serial.begin(115200);
  Serial.println("");
  Serial.println("========== Queue example ==========");
  Serial.printf("Desired max item size:  %u items\r\n", QUEUE_SIZE_ITEMS);
  Serial.println("===================================");
}

void loop() {
  printQueueStats();

  // Add elements: (add more than the queue size for demo purposes)
  if (!charQueue.isFull()) {
    char* n = "2020-08-10N14:23:12Z";
    charQueue.enqueue(n);
    Serial.println("Added value (n):");
    Serial.println(n);

    n = "2020-08-10N14:23:13Z";
    charQueue.enqueue(n);
    Serial.println("Added value (n):");
    Serial.println(n);

    n = "2020-08-10N14:23:14Z";
    charQueue.enqueue(n);
    Serial.println("Added value (n):");
    Serial.println(n);
  }

  printQueueStats();

  while (!charQueue.isEmpty()) {
    char* result = charQueue.dequeue();
    Serial.println("Removed value:");
    Serial.println(result);
  }
  Serial.println("Queue is empty!");

  printQueueStats();

  delay(2000);
}

The library read me says this about queuing pointers

Memory safety
The memory for the queue nodes are dynamically allocated. Note that while the Queue class cleans up the nodes in memory after destructor or dequeue is called, it keeps a copy of the item being queued. So for example if you are queuing pointers, you will need to keep track of the memory behind them.

I do not have enough experience with dynamic memory allocation and deallocation to give any advice. You may need to figure out the clean up of the underlying memory and time will tell if the program runs reliably over the long haul.

I may well want to add sensor value readings into the queue which would mean the length of the variable being entered into the queue would change from entry to entry. So I think that those solutions won't work for me?

I am hoping to store about 180 readings. Is it possible to make that work?

As I said, my approach, based on lack of experience with dynamic memory allocation, would be to not use the queue library, but instead declare 180 character arrays of max length and manage the indexes for the add and delete.

OK, thank you very much for your help cattledog!

Thanks again,

Zeb