Pages: [1]   Go Down
Author Topic: array questions (append char variables)  (Read 1471 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Full Member
***
Karma: 0
Posts: 111
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello!

I've a little problem implementing arrays.
Im my code I obtain a variable of type char containing a message like "node:1;value1:10;value2:20";
I would like to create an array that will contain all these messages. The end result should:

array: { "node:1;value1:10;value2:20", "node:2;value1:15;value2:25", node:3;value1:17;value2:27", ... }

The array should be created empty at the beginning and the populated with these messages. In case the array contains an element that begins with "node:1..." then the element should be replaced with the new one. If the string is not present in the array, the message should be added as new element at the end of the array.
Could someone help me? I'm blocked at the beginning on creating an array and appending a simple char variable. smiley-sad

Thank's

Simon
Logged

Brisbane, Australia
Offline Offline
Edison Member
*
Karma: 29
Posts: 1071
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Simon

There are a few ways to attack this, depending on a few factors.

Is the total length of the data you will be operating on once received known, or easily estimated?  If so, you could predefine a buffer array to do all your working in, however memory isn't a plentiful resource on Arduino so that isn't often the best way.

For longer data streams you might consider using the onboard EEPROM as your working storage.  If that's not large enough there are other ways to consider also.  conversely, for short data streams, the inbuilt String data type can be very handy too.

Perhaps if you could describe the goal of your project we will have an understanding of these factors.

Cheers!
Geoff
Logged

"There is no problem so bad you can't make it worse"
- retired astronaut Chris Hadfield

UK
Offline Offline
Shannon Member
****
Karma: 184
Posts: 11159
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Im my code I obtain a variable of type char containing a message like "node:1;value1:10;value2:20";
I would like to create an array that will contain all these messages. The end result should:

array: { "node:1;value1:10;value2:20", "node:2;value1:15;value2:25", node:3;value1:17;value2:27", ... }

The array should be created empty at the beginning and the populated with these messages.


How many messages will be in the array?

Are you constrained to hold these messages as strings? (And if so, why?) It would be far easier to manipulate, and take up much less space, if you parsed each message to extract the numbers, and store them instead of storing the strings.

If the nodes are numbered consecutively you could just define an array of ints indexed by node number to hold value1, and another similar array to hold value2. I would be quite surprised if you can't think of a more meaningful name for those, by the way.

If the nodes are not numbered consecutively it may not be feasible to use the node number as an array index. In that case I would define a struct to hold the values associated with a node (node number, value1 and value2) and define an array of those structs. Since we know there won't be a huge number of them I don't see any need to do any indexing - I'd just walk the array looking for the relevant node.
Logged

I only provide help via the forum - please do not contact me for private consultancy.

0
Offline Offline
Full Member
***
Karma: 0
Posts: 111
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


Well, I'm expecting to have not more than 10 nodes. I'm collecting values (temperature) from a central node and then print it out on ehternet requests.

I've thought this could be the best solution, but always available for better ones.
The nodes are not consecutively. I'm receiving these messages from nodes trought radio device. The nodes could be not all on and, btw, they are not consecutively.

I've tried someting like this:

Code:
(...)
char radioMessage[30];
String sensorValues;
char *sensorArray[max_active_nodes];
(...)

  // populate the array.
  for ( int n=0 ; n<max_active_nodes; n++) {
    sensorArray[n] = "-empty--";
  }



in the code I use sensorValues to concat different values and then I converti it to char into radioMessage to send it out and receive it back. Until here all works well
When I receive the radioMessage as a char, I've thought to save it into an array so that I can collect it from different nodes. Add if new, update if present.

Code:

    String toSearch;
    boolean stringFound = false;
    String findMe = String("ode:");
    findMe += header.from_node;
    findMe += ";";
    Serial.print("Searching =======> ");
    Serial.println(findMe);                                             // this results in "ode:0;" or "ode:2" ...

    for ( int n=0 ; n<max_active_nodes; n++) {
      toSearch = String(sensorArray[n]);
      printf_P(PSTR("Array in position %d: %s \n\r"),n, sensorArray[n]);
      if ( toSearch.indexOf(findMe) > 0) {
        printf_P(PSTR("   Found, I rewrite it with new one\n\r"));
        sensorArray[n] = radioMessage;
        stringFound = true;
        break;
      }
      else {
        printf_P(PSTR("   Not found\n\r"));
      }
    }
   
    if (!stringFound) {
      printf_P(PSTR("   Not found, I put the record in the first empty element\n\r"));
      for ( int o=0 ; o<max_active_nodes; o++) {
        toSearch = String(sensorArray[o]);
        if ( toSearch.indexOf("empty") > 0) {
          sensorArray[o] = radioMessage;
          break;
        }
      }
    }


What happens now? Well, seems the array contains every time the incoming radioMessage without holding the old values. are these pointers? I'm a beginner, so maybe I'm missing some important concepts smiley-sad

This the debug:

Code:

radioMessage value node:5;H1:7300;T1:1900; from 05   
Searching  =======> ode:5;
Array in position 0: -empty--
   Not found
Array in position 1: -empty--
   Not found
Array in position 2: -empty--
   Not found
Array in position 3: -empty--
   Not found
Array in position 4: -empty--
   Not found
Array in position 5: -empty--
   Not found
Array in position 6: -empty--
   Not found
Array in position 7: -empty--
   Not found
Array in position 8: -empty--
   Not found
Array in position 9: -empty--
   Not found
   Not found, I put the record in the first empty element

radioMessage value node:0;H1:6800;T1:1900; from 00   
Searching  =======> ode:0;
Array in position 0: node:0;H1:6800;T1:1900;          ////////////// why here is node:0 if before it was written with node:5??                               
   Found, I rewrite it with new one

radioMessage value node:5;H1:7300;T1:1900; from 05   
Searching =======> ode:5;
Array in position 0: node:5;H1:7300;T1:1900;
   Found, I rewrite it with new one      ////////////// wasn't it node:0?                         

Maybe there is a better solution to do that.

My prupose is to hold these informations into an array because on an ehternet request I should print all values from all nodes... smiley

Thank's for the help!

Simon
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 548
Posts: 46029
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
char *sensorArray[max_active_nodes];
Where do these pointers point? Nowhere, right now.

You need to make these point somewhere before you can copy data to where they point.

Code:
    String toSearch;
Lose the String class. It is a gun, aimed at your foot, waiting for you to pull the trigger.

Nothing that the String class does can not be done using strings.
Logged

California
Offline Offline
Faraday Member
**
Karma: 82
Posts: 3123
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The String object is all fine and dandy to work with when you are on a machine with plenty of memory available, but not on these little chips. You're better off ditching trying to store them as Strings (or strings for that matter) and simply extract the values from each request.

strtok() can be used to iterate through each part of the transmission separated by a ';'.

strncmp() can be used to check each deliminated section to determine if it's telling you a a node or a value.

atoi() can be used to convert the the string number int an int.

And when you're ready to send the data back out as a string...

sprintf() can be used to construct a formatted string containing the data.

Although if you're hell bent on not storing them as ints, you can simply have an array of strings (note the lowercase S) and use strncmp() to determine which node the new transmission should replace.
« Last Edit: October 14, 2012, 10:37:00 am by Arrch » Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 548
Posts: 46029
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
The String object is all fine and dandy to work with when you are on a machine with plenty of memory available,
And a bug-free version of malloc and free. Neither of which gcc (the Arduino compiler) has.
Logged

UK
Offline Offline
Shannon Member
****
Karma: 184
Posts: 11159
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Since the incoming string format looks a lot like JSON, it's conceivable that you could even find some libraries/code fragments/examples that would do the bulk of the parsing work for you.
Logged

I only provide help via the forum - please do not contact me for private consultancy.

0
Offline Offline
Full Member
***
Karma: 0
Posts: 111
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote from: PaulS
Where do these pointers point? Nowhere, right now.

You need to make these point somewhere before you can copy data to where they point.

Well, this is exactly what I'm missing to know how to manage smiley-sad AFAIK I cannot declare it without "*" 'cause it returns me an error...
What should I correct exactly in example?

Quote from: Arrch
The String object is all fine and dandy to work with when you are on a machine with plenty of memory available, but not on these little chips. You're better off ditching trying to store them as Strings (or strings for that matter) and simply extract the values from each request.

Also you suggest to rewrite the code without using the String object? (also I mean "String toSearch;" and "String findMe")?
They have nice features to search for a part of string. How should I do it instead in my case? Your suggestions doesn't include how to make a in string search.

Quote from: PeterH
Since the incoming string format looks a lot like JSON, it's conceivable that you could even find some libraries/code fragments/examples that would do the bulk of the parsing work for you.

Yess, maybe at the end I'll return a json or xml output.


If before I was in trouble with my little piece of code, now I'm really confused smiley

Do you think it's not the right choise to store all the vaues into an array? Reassuming, having many arduinos around, the central node receive status of the sensors from the other nodes without to ask about it. So, during the void loop in the first part I collect the informations -if available- and in the second part, if a ethernet request is coming I would print the whole array without to ask one by one the nodes, because I would have the status allready saved into an array.

Now, I'm confused if this would the right way to manage this scenario.

Thank's a lot for all the help!

Simon
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 548
Posts: 46029
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
What should I correct exactly in example?
The code that stores data at the location pointed to by sensorArray[0], for instance, expects that sensorArray[0] points somewhere where there is space to write to.

You can make that so using malloc() to allocate the space, dynamically. Doing so on a memory-constrained device like the Arduino is not really a good idea. Especially when you are also using the String class.

Alternatively, get rid of the pointer, and use a static array.

This is not an Arduino-specific issue. Any tutorial or book on C will tell you more than you ever wanted to know about pointers.

Quote
Also you suggest to rewrite the code without using the String object?
Yes. A String is simply a wrapper around a NULL terminated char array, also known as a string.

Quote
They have nice features to search for a part of string.
If you look at the code for those methods, you'll see that the methods use native C string functions to do the work. You can too, without the overhead and problems of the String class.

Quote
Your suggestions doesn't include how to make a in string search.
Because I assume that by the time you are writing a sketch this large, you know something about programming, including how to crack open a book and look stuff up. If not, try google.

Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 168
Posts: 12430
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


You can reduce the amount of memory needed by a large amount by only storing the three values per node in the array.

array: { "node:1;value1:10;value2:20", "node:2;value1:15;value2:25", node:3;value1:17;value2:27", ... }

would become

array: { 1,10,20,2,15,25,3,17,27...}

and if the node numbers are always consecutive one could even only store the 2 values

array: {10,20,15,25,17,27...}

in code you would something like
Code:
#define MAXSIZE 10

int values[MAXSIZE][2];
int index = 0;

void setup()
....

void loop()
....


addArray(int value1, int value2)
{
  if (index < MAXSIZE)
  {
    values[index][0] = value1;
    values[index][1] = value2;
    index++;
  }
}

getValue1(int idx)
{
  return values[idx][0];
}
 
getValue2(int idx)
{
  return values[idx][1];
}

etc

When you get the values from the array you can recreate the needed string and output it.




Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

0
Offline Offline
Full Member
***
Karma: 0
Posts: 111
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote from: PaulS
If you look at the code for those methods, you'll see that the methods use native C string functions to do the work. You can too, without the overhead and problems of the String class.
Because I assume that by the time you are writing a sketch this large, you know something about programming, including how to crack open a book and look stuff up. If not, try google.
I loved Arduino from the first use for the easy way everyone can approach some electronic concepts. This is a great benefit of Arduino. At the same time the desire to realize a project pushes persons (at least me smiley-razz) to implement code in the fastest way, to see realized what our imagination is suggesting. So, some important concepts are set aside and this isn't correct at all.
Paul, of course you are right. I've to take my time to read more in deep what those methods does and maybe read some base concepts are a good exercise too! smiley
I really appreciate the suggestions from all you!

Quote from: robtillaart
You can reduce the amount of memory needed by a large amount by only storing the three values per node in the array. (...snip...)
Thank you robtillaart for the example code. Maybe I could implement a multi-dimentional array of only integer values. I think this could the solution to reduce memory usage and the same time remove the use of the 'String' class. Iìll try this approach as well.

Thank's to all and... unfortunately for you, in case of truoble I cannot resolve, you'll read about me again smiley

Simon
Logged

0
Offline Offline
Full Member
***
Karma: 0
Posts: 111
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


Hello again!
Folowing your suggestions I've converted the message I receive from the nodes. Now all works!! smiley smiley Maybe could it be written better?

Originally they were:
Code:
node:0;value1:10;value2:20
node:2;value1:20;value2:30

Now they are:
Code:
0;10;20
2;20;30

Where first number is the sender_id, then two vaules (temperature and humidity from DHT11).
So, on base node I save the values into an integer array that I've initialized so:

Code:
int sensorArray[max_active_nodes][3];
(...)
 for ( int i=0 ; i<max_active_nodes; i++) {
   sensorArray[i][0] = 999;
 }
// this because by default the vaules are 0 and a node address is 0 as well, matching all entries...

Then, to search and add or update a record:

Code:
    // here I search the received message trought the array and add/update it
    char *var, *save;
    int intVar, n;
    char *p = radioMessage;
    int i=0;
    boolean newRecord = true;
    for (var = strtok_r(p, ";", &save); var; var = strtok_r(NULL, ";", &save)) {
      intVar = atoi(var);
      printf_P(PSTR("sender id %d from %o   <--------\n\r"),intVar,header.from_node);
      if (i == 0) {
        printf_P(PSTR("First argument to analyze, the sender_id\n\r"));
        for ( n=0 ; n<max_active_nodes; n++) {
          printf_P(PSTR("Array in position %d: %d  "),n, sensorArray[n][0]);
          if (intVar == sensorArray[n][0]) {
            printf_P(PSTR("sender_id found at position %d:0 - I'll update this entries\n\r"),n);
            newRecord = false;
            break;
          } else {
            printf_P(PSTR("sender_id not found\n\r"));
          }
        }
      }
      if ((newRecord) && (i == 0)) {
        printf_P(PSTR("I've to search a new position \n\r"),n, sensorArray[n][0]);
        for ( n=0 ; n<max_active_nodes; n++) {
          printf_P(PSTR("Array in position %d: %d \n\r"),n, sensorArray[n][0]);
          if (sensorArray[n][0] == 999) {
            printf_P(PSTR("Free position found at %d:0 \n\r"),n);
            break;
          }
        }
      }
      sensorArray[n][i] = intVar;
      printf_P(PSTR("++++ Added value '%d' in position %d:%d\n\r"), sensorArray[n][i],n,i);
      i++;
    }

The result, assuming i've 3 nodes, node0, node2 and node5 and max_active_nodes = 10, the serial debug is:

Code:

radioMessage value 0;6500;1900; from 00   <--------
=============================================
sender id 0 from 0   <--------
First argument to analyze, the sender_id
Array in position 0: 999  sender_id not found
Array in position 1: 999  sender_id not found
Array in position 2: 999  sender_id not found
Array in position 3: 999  sender_id not found
Array in position 4: 999  sender_id not found
Array in position 5: 999  sender_id not found
Array in position 6: 999  sender_id not found
Array in position 7: 999  sender_id not found
Array in position 8: 999  sender_id not found
Array in position 9: 999  sender_id not found
I've to search a new position
Array in position 0: 999
Free position found at 0:0
++++ Added value '0' in position 0:0
sender id 6500 from 0   <--------
++++ Added value '6500' in position 0:1
sender id 1900 from 0   <--------
++++ Added value '1900' in position 0:2

radioMessage value 2;6800;1900; from 02   <--------
=============================================
sender id 2 from 2   <--------
First argument to analyze, the sender_id
Array in position 0: 0  sender_id not found
Array in position 1: 999  sender_id not found
Array in position 2: 999  sender_id not found
Array in position 3: 999  sender_id not found
Array in position 4: 999  sender_id not found
Array in position 5: 999  sender_id not found
Array in position 6: 999  sender_id not found
Array in position 7: 999  sender_id not found
Array in position 8: 999  sender_id not found
Array in position 9: 999  sender_id not found
I've to search a new position
Array in position 0: 0
Array in position 1: 999
Free position found at 1:0
++++ Added value '2' in position 1:0
sender id 6800 from 2   <--------
++++ Added value '6800' in position 1:1
sender id 1900 from 2   <--------
++++ Added value '1900' in position 1:2

radioMessage value 5;6800;1900; from 05   <--------
=============================================
sender id 5 from 5   <--------
First argument to analyze, the sender_id
Array in position 0: 0  sender_id not found
Array in position 1: 2  sender_id not found
Array in position 2: 999  sender_id not found
Array in position 3: 999  sender_id not found
Array in position 4: 999  sender_id not found
Array in position 5: 999  sender_id not found
Array in position 6: 999  sender_id not found
Array in position 7: 999  sender_id not found
Array in position 8: 999  sender_id not found
Array in position 9: 999  sender_id not found
I've to search a new position
Array in position 0: 0
Array in position 1: 2
Array in position 2: 999
Free position found at 2:0
++++ Added value '5' in position 2:0
sender id 6800 from 5   <--------
++++ Added value '6800' in position 2:1
sender id 1900 from 5   <--------
++++ Added value '1900' in position 2:2

radioMessage value 2;6800;1900; from 02   <--------
=============================================
sender id 2 from 2   <--------
First argument to analyze, the sender_id
Array in position 0: 0  sender_id not found
Array in position 1: 2  sender_id found at position 1:0 - I'll update this entries
++++ Added value '2' in position 1:0
sender id 6800 from 2   <--------
++++ Added value '6800' in position 1:1
sender id 1900 from 2   <--------
++++ Added value '1900' in position 1:2

radioMessage value 5;6800;1900; from 05   <--------
=============================================
sender id 5 from 5   <--------
First argument to analyze, the sender_id
Array in position 0: 0  sender_id not found
Array in position 1: 2  sender_id not found
Array in position 2: 5  sender_id found at position 2:0 - I'll update this entries
++++ Added value '5' in position 2:0
sender id 6800 from 5   <--------
++++ Added value '6800' in position 2:1
sender id 1900 from 5   <--------
++++ Added value '1900' in position 2:2

radioMessage value 2;6700;1900; from 02   <--------
=============================================
sender id 2 from 2   <--------
First argument to analyze, the sender_id
Array in position 0: 0  sender_id not found
Array in position 1: 2  sender_id found at position 1:0 - I'll update this entries
++++ Added value '2' in position 1:0
sender id 6700 from 2   <--------
++++ Added value '6700' in position 1:1
sender id 1900 from 2   <--------
++++ Added value '1900' in position 1:2

radioMessage value 0;6500;1900; from 00   <--------
=============================================
sender id 0 from 0   <--------
First argument to analyze, the sender_id
Array in position 0: 0  sender_id found at position 0:0 - I'll update this entries
++++ Added value '0' in position 0:0
sender id 6500 from 0   <--------
++++ Added value '6500' in position 0:1
sender id 1900 from 0   <--------
++++ Added value '1900' in position 0:2


Does it look better as before?

Thanks for the support!

Simon
Logged

Pages: [1]   Go Up
Jump to: