2

I'm trying to make a home automation setup but I'm having a bit of trouble.

I want to be able to send commands of varying sizes to my arduino, separated by "|" and after receiving it completely it runs code corresponding to the command.

Example:

input "RCP=10001|CMD=D|VAL=120" would result in an array like:

String cmd[][] = {{"RCP", "10001"}, {"CMD", "D"}, {"VAL", "120"}}

with the amount of 'variables' being... well, variable.

The code would continue checking if the RCP (recipient) ID corresponds with the ID of the current client and then run code based on the following variables. But I don't think that's important info for the code which separated the string.

This string would be sent through an NRF24L01+ (That code already works)

  • Is the data always going to be triplets of RCP/CMD/VAL? – Majenko Nov 23 '15 at 16:10
  • No, I'd like to be able to add like: VAL1, VAL2, or RESP=1 or something like that. Is this possible? – Nathan Prins Nov 23 '15 at 16:34
  • 1
    I've read this twice, but I can't find any question. – Gerben Nov 23 '15 at 16:44
  • My apologies Gerben, I should've been clearer. But it has already been solved. Thanks for commenting anyway. :) – Nathan Prins Nov 23 '15 at 17:10
  • Why not use a library like RF24Mesh that does all this for you. – Avamander Nov 24 '15 at 9:00
3

What you are asking is very tricky at best. Your average Arduino doesn't have enough memory to start storing arrays of Strings.

Instead you will need to "distil" the information as it comes in and store the distilled information.

If the possible keys are all known beforehand then you can assign a number to each possible key - say RCP is 1, CMD is 2, VAL is 3, etc. If the values are all numeric or can be represented by a number, then convert those to the corresponding number and store those.

Also the Arduino is not good at working with dynamic memory allocations - again because of lack of memory. If you can decide on a reasonable maximum number of messages to store then you can pre-allocate the memory for them.

For instance it may be good to define a structure which is the content of a message:

struct message {
    uint8_t key;
    uint16_t val;
};

Then make an array of that structure - one slice per possible command, say 10 of them:

struct message messageQueue[10];

That would take a total of 30 bytes in memory - each entry being 3 bytes (1 for the key, two for the value). Now you can set the keys and values to the correct data as it arrives.

Depending on how you want to deal with the messages as they come in - add them to the end of an existing queue, or always starting the queue from empty every time a new message arrives - you might want to implement a circular buffer. This is basically how the Serial port on the Arduino works - in involves having two pointers to locations in the array - one where you are writing to, and one where you are reading from. As you write to the array the writing pointer moves along - if it reaches the end it starts from the beginning again. As you read from the array the reading pointer moves along too. If the two pointers are together then the array is empty. If the writing pointer would end up where the reading pointer is, the array is full. Take a look in the Arduino source code (HardwareSerial.cpp) to see how it's implemented.

As for parsing the string as it comes in - if you have it as a single String already then it's a case of looking through it for the | characters and splitting out each portion in turn, then doing the same with each portion looking for the =. Then you can interpret what is in the key/value pairs and decide what to store in the array.

  • Thank you very much! So it boils down to the fact that Arduino's have a small amount of memory and thus aren't suitable for dynamic memory allocation like a higher level language would be? I think I'll be able to think of a reasonable max amount of commands. The reason I wanted to have it dynamic was that newer version of my "master" might want to send more commands, but I could implement a type of version check on the client so the master knows if he is capable of those commands. Again, thanks :) – Nathan Prins Nov 23 '15 at 17:14
  • The lowest (RAM) memory footprint would to act on the information as it is received, and so basically avoid storing commands at all, except for a small (provided by Arduino anyway) circular buffer between the serial port and main-loop parsing. – Chris Stratton Nov 24 '15 at 2:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.