Memory management during char array parsing from Serial.

Hello,
I do hope that this is the right place to put this post.

I have a several question related to a project involving controlling of several components from a Arduino.

Let me first start by sharing the prototype code that im working on:

#include <MemoryFree.h>

char _received[5];
int _buffer_count = 0;
int _step = 0;

typedef struct uri {
  char id[4];
  char cmd[18];
  char data[12];
} Object;

Object uri;

const int STEP_READ_COMPONENT = 0;
const int STEP_READ_DATA = 1;

void setup() {
   // init Serial
   Serial.begin(115200);
}

void loop() {
   while ( Serial.available() ) {
      char _char = Serial.read();
      parseDataPerChar( _char );
   }
}

void parseDataPerChar ( const char _char ) {
   // Line completed. Execute received method and clear properties
   if (_char == '\n' || _char == '\r' ) {
      receivedData();

      // Reset values
      uri = Object();
      _step = STEP_READ_COMPONENT;
      _buffer_count = 0;
      memset(_received, 0, sizeof(_received));
      return;
   }

   // Set state to reading data
   if ( _char == '=' ) {
      _step = STEP_READ_DATA;
      _buffer_count = 0;
   }

   // Set state to reading next component
   else if ( _char == '&' ) {
      _step = STEP_READ_COMPONENT;

      // reset tracing properties
      _buffer_count = 0;
      memset(_received, 0, sizeof(_received));
   }

   // Fill data per component
   else if ( _step == STEP_READ_DATA ) {

      if ( strcmp(_received, "id") == 0 ) {
         uri.id[_buffer_count] = _char;
      } else if ( strcmp(_received, "cmd") == 0 ) {
         uri.cmd[_buffer_count] = _char;
      } else if ( strcmp(_received, "data") == 0 ) {
         uri.data[_buffer_count] = _char;
      }

      _buffer_count ++;
   }

   // Fill component name
   else if ( _step == STEP_READ_COMPONENT ) {
      _received[_buffer_count] = _char;
      _buffer_count ++;
   }
}

void receivedData() {
   Serial.print("id: ");
   Serial.println(uri.id);

   Serial.print("cmd: ");
   Serial.println(uri.cmd);

   Serial.print("data: ");
   Serial.println(uri.data);

   Serial.print("freeMemory()=");
   Serial.println(freeMemory());
}

The goal of the code is to parse incoming string “char array” so can read all of the parameters and perform different action like:

  • if receive: id=L1&cmd=on, to turn first LED on
  • if receive: id=M1&cmd=turn.left&data=3, to turn first stepper motor to the left with 3 steps

And others, and making them at least little bit humanly readable.

Now the prototype code that i shown above does exactly that, parsing the content incoming from the Serial (which is used only for the development of this logic) and assign the values to the defined type “Object”.

Here i have several question for which i couldn’t found definite answer.

  1. I’m not big fan of nested if’s, or chained “else if”, even that i used them in the code.
    Which is one of the reasons i use “typedef struct”, hoping that there is a way to call each part link in other programing languages i’m used to, eg. in JavaScript, or PHP uri[‘cmd’], in this case uri[_received] and avoid the nested if “// Fill data per component”.

Is there a way with this definition, or any other to do exactly this?

  1. Another reason to use “typedef struct”, so when the command line is read i can free the all parts by writing “uri = Object();”. This will avoid thing like: If the first command is cmd = ‘turn.left’ and the second command is cmd = “on”, the result won’t be cmd = “onrn.left”;
  • But will this free the used bytes in the memory or relocate new bytes for it?

What exactly i mean here, is it this will happen:
[see the attachment]

  • Is this the case, or it will reuse the same bytes?
  1. Since in the final code i want to add and reading and writing in the eeprom, to save the previous state, so when is turned off and then turns on, it will continue from where it stopped.
    and for eeprom i have similar concerns for the memory “RAM usage”.

Is there a tool / program with which i can monitor (hopefully some graphical UI ) the usage of the RAM in real time?
At the end of my code, it can be seen that i used a method from “MemoryFree” library, but this only shows how much free memory i have, but not how it’s dispersed and if started to fragmented with the execution of the code.

Currently i’m writing the code for Arduino Nano (ATmega328), but if such tool exist and will work only with, let’s say Arduino Due (why i suspect such thing - because of the programing and native USB ports), it’s still an option.
If the code allocates the large amount of RAM on the DUE, it will done the same with the smaller amount on the Nano - hopefully.

Тhanks to everybody who will take time to answer and help me, and everybody that read this thread, to understand the process in microcontrollers better, but please when answering any of the questions, start with simple “Yes, this is correct”, or “No, you are in huge mistake”, because English is not my native and sometimes is kinda confused when reading it - this will help a lot.

Again thanks.

Serial.print("freeMemory()=");

Irony. In reporting how much free RAM you've got, you've wasted fourteen bytes of it.

Serial.print(F("freeMemory()="));
      // Reset values
      uri = Object();

Directly calling the constructor is not a good idea. One normally uses new to call the constructor, which then returns a pointer.

Using a class, with members explicitly defined (like the constructor), is a better idea.

Having a reset() method is a much better idea than abandoning instances of the struct all over the place.

PaulS:       // Reset values       uri = Object();

Directly calling the constructor is not a good idea.

Yes, it's odd to use the default constructor followed by assignment to reset an object. It doesn't abandon anything, it's just weird-looking. Even though it does what you intend, like PaulS, I would suggest defining an init function in your "class":

class Object
{
public:
  char id[4];
  char cmd[18];
  char data[12];

  Object() { init(); }

  void init() { id[0] = cmd[0] = data[0] = '\0'; }
};

Object uri; // an instance of "Object"
  .
  .
  .

  // Reset values
  uri.init();

Now it's obvious what you mean. (In this context, structs are equivalent to classes, except class members are private by default. Hence the public keyword.)

PaulS: One normally uses new to call the constructor, which then returns a pointer.

With all due respect, I must heartily disagree. Herein lies the path to Perdition. Do not use "new" in this environment: limited RAM, long running times and unpredictable input will inevitably lead to memory fragmentation. Using new/free/malloc/delete (i.e., "dynamic memory") adds 600 bytes of program space that is just a waste. Many hobbyists use dynamic memory and have completely functional sketches. But once they approach the RAM and flash limits, or leave it running for weeks on end, they find it hangs or behaves inexplicably.

NB: There have been many discussions here and elsewhere on the innertubes about how it is possible to use dynamic memory in an embedded environment. However, it's so easy to step outside the lines that no serious embedded developer would consider it an appropriate tool.

It is much better in this embedded environment to determine beforehand how many instances really need to exist. If necessary, declare a pool of them that can be used. I would guess that a "stack" of them would work for you, if you're doing a recursive-descent parse. Just keep track of the next available index, and increment it as Objects are used.

But will this free the used bytes in the memory

The definition of Object does not "allocate" any memory. Declaring an instance of Object "uses" some memory, but only for the scope of the instance. If uri is declared at the outer level ("file scope"), it occupies memory for the entire duration of the program. It other Objects were declared inside a function, they only use memory (on the stack) for the duration of the function. When it returns, the Objects are destroyed, and their memory is "popped" off the stack. (Well, the stack pointer is just decremented).

This is just like:

int  two_bytes;

void setup()
{
  int two_more_bytes;
}

The first int always uses 2 bytes. The second only uses 2 bytes during setup. The same is true for Object, except that it uses 34 bytes. You can find out how big it is by printing sizeof(Object), just like sizeof(int).

If you take this deterministic approach, instead of dynamic memory, the only tool you need is to look at the "next available Object" index. Is it close to the end of the array?

For recursive descent parsing, you can also look at the call depth or how close the stack pointer is getting to the end of the stack area. I think something like this would tell you how much stack space is left:

int free_stack()
{
  int free_memory;
  return ((int)&free_memory) - ((int)__brkval);
}

Regarding parsing and program structure, you might take a look at NeoGPS. It does parsing in NMEAGPS.cpp and NMEAGPS.h. It decodes one character at a time, saving the state between characters. The entire NMEA message does not get saved; only the parsed values are saved, in a gps_fix member (defined here, used here in class NMEAGPS).

Cheers, /dev

With all due respect, I must heartily disagree.

I wasn't (intentionally) advocating using new. I was simply observing that typically only new actually invokes the constructor directly. The constructor is also invoked when an object is defined.

Object uri; // implicitly calls the constructor
Object *pUri = new Object(); // new calls the constructor explicitly

Using new on the limited memory Arduino can lead to all kinds of problems, unless you are rigorous in determining that new actually allocated memory.