Go Down

Topic: Variable modify (Read 718 times) previous topic - next topic

anthonyhill86

Is it possible to modify part of a variable so you can run code with a part of that variable subject to change, for example with the code below, I would like the string to print depending on what number string i put in the number variable.



String string1 = "my string1";
String string2 = "my string2";
String string3 = "my string3";
String string4 = "my string4";

String number;

void setup() {
  // put your setup code here, to run once:
number = "1";

 Serial.println(string(number));
}

PaulRB

Yes, you should use an array.

And on small Arduino like Uno, it is not a good idea to use "String", and normally not necessary anyway.

anthonyhill86

Ok, Is there a way to save array's to an eeprom?

pert


Whandall

#4
Jan 15, 2019, 08:27 am Last Edit: Jan 15, 2019, 11:25 am by Whandall
Yes. You can do that using EEPROM.put():
https://www.arduino.cc/en/Reference/EEPROMPut
And to read it back, use EEPROM.get():
https://www.arduino.cc/en/Reference/EEPROMGet
But that will not work for Strings, arrays of Strings or objects that contain Strings (or any RAM pointers).
Ah, this is obviously some strange usage of the word 'safe' that I wasn't previously aware of. (D.Adams)

pert

I certainly don't claim to (or want to) be an expert on String, but this appears to work fine:
Code: [Select]
#include <EEPROM.h>

void setup() {
  Serial.begin(9600);
  while (!Serial) {}
  String foo[] = {"qwer", "asdf", "zxcv"};
  EEPROM.put(1, foo);
  String bar[3];
  EEPROM.get(1, bar);
  for (byte elementCounter = 0; elementCounter < (sizeof(bar) / sizeof(bar[0])); elementCounter++) {
    Serial.println(bar[elementCounter]);
  }
}

void loop() {}

Is it doing something horrible to the memory?

I do note that the official support thread says:
https://forum.arduino.cc/index.php?topic=312645.msg2166705#msg2166705
Quote
Whats next?

...

  • Modification allowing .get() and .put() to accept arrays, not just objects.

Sadly, pYro_65 went MIA without submitting the PR for the new version of the EEPROM library.

Whandall

#6
Jan 15, 2019, 09:52 am Last Edit: Jan 15, 2019, 10:13 am by Whandall
You will be storing pointers to RAM into the EEPROM,
for Strings only the descriptor is saved, not the buffer that contains the data.

While it may seem to work directly after storing it, it will fail after a restart,
because the RAM content probably changes.

Code: [Select]
#include <EEPROM.h>

String value = "I was saved to EEPROM";
String readBack;

void setup() {
  Serial.begin(250000);
  EEPROM.put(0, value);
  EEPROM.get(0, readBack);
  Serial.println(readBack);
  value = "*crap crap crap crap*";
  Serial.println(readBack);
}
void loop() {}

Code: [Select]
I was saved to EEPROM
*crap crap crap crap*

Is it doing something horrible to the memory?
When deleting such cloned buffers you could run into problems with the heap,
because buffers will be freed twice.
Ah, this is obviously some strange usage of the word 'safe' that I wasn't previously aware of. (D.Adams)

GoForSmoke

Is it doing something horrible to the memory?

Just wastes bytes doing so little. Do String manipulation to add shotgun the heap to that.

Worst thing it does is teach a coder to use convenient do-it-for-you String objects while buying boards with more RAM to contain the mess that would happily run on less RAM with C char array strings.

What are BAD HABITS worth?
1) http://gammon.com.au/blink  <-- tasking Arduino 1-2-3
2) http://gammon.com.au/serial <-- techniques howto
3) http://gammon.com.au/interrupts
Your sketch can sense ongoing process events in time.
Your sketch can make events to control it over time.

anthonyhill86

I am using strings as a display for a 24h time as the input in blynk does not except an integer.  So my workaround was to convert the string to a float, "0600" to 600.0, then divide it by 10 so I will have a value small enough to store in the eeprom. Eeeprom locations are allocated so I can pull and overwrite the data in the program ui. I then convert it back when it needs to be displayed.

below is the code to pull the float and convert it back to a string

void dataCalc(int loc, String &valve)
  {
  float f;
  EEPROM.get(loc,f);
  f = f * 10;
  int a = int(f);
  valve = String(a);
  if (valve.length() < 4)
    {
      valve = "0" + valve;
    }
  }

jremington

Quote
Is it doing something horrible to the memory?
Yes and that is well documented.


GoForSmoke

Global warming is a hoax, cigarettes are actually good for people and Mexico will pay for the wall.

And if you can believe that then use freaking Strings in your project as long as you understand that asking for help will get you told to take the damn things out for your own sake!
 
1) http://gammon.com.au/blink  <-- tasking Arduino 1-2-3
2) http://gammon.com.au/serial <-- techniques howto
3) http://gammon.com.au/interrupts
Your sketch can sense ongoing process events in time.
Your sketch can make events to control it over time.

pert

You will be storing pointers to RAM into the EEPROM,
for Strings only the descriptor is saved, not the buffer that contains the data.

While it may seem to work directly after storing it, it will fail after a restart,
because the RAM content probably changes.
Thanks so much for taking time to explain that so well to me. I have stored arrays of strings successfully using EEPROM.put() and it has always magically worked for anything I threw at it before so I didn't see why it wouldn't do so with String as well. Now I understand.

Do String manipulation to add shotgun the heap to that.
I meant "Is it doing something more horrible than usual to the memory?".


Just wastes bytes doing so little. Do String manipulation to add shotgun the heap to that.

Worst thing it does is teach a coder to use convenient do-it-for-you String objects while buying boards with more RAM to contain the mess that would happily run on less RAM with C char array strings.

What are BAD HABITS worth?
Yes and that is well documented.


Global warming is a hoax, cigarettes are actually good for people and Mexico will pay for the wall.

And if you can believe that then use freaking Strings in your project as long as you understand that asking for help will get you told to take the damn things out for your own sake!
I never intended to imply that I recommend ever using String in an embedded system. I would never do that and I'm sure you've seen me do just the opposite in the past. I assumed we had already gotten past that in #1. Looking back, I can see how the point of using strings instead of String might not have been as clear as it could be at that point. In my #3, I actually was not even thinking of arrays of Strings. #4 was the first time I considered that and my response was merely a matter of wanting to learn, rather than an argument in favor of using String, even if it did happen to work with EEPROM.put().

GoForSmoke

#12
Jan 17, 2019, 03:53 am Last Edit: Jan 17, 2019, 04:01 am by GoForSmoke
Quote
I meant "Is it doing something more horrible than usual to the memory?".
Yes. Usually in small environments dynamic allocation is something to be avoided so usually you don't get a shotgunned heap.

What actual "horrible" "usual" do you refer to?

1) http://gammon.com.au/blink  <-- tasking Arduino 1-2-3
2) http://gammon.com.au/serial <-- techniques howto
3) http://gammon.com.au/interrupts
Your sketch can sense ongoing process events in time.
Your sketch can make events to control it over time.

pert

Usual horrible is the "shotgunned heap" you warn of. I'm well aware that the dynamic memory allocation of String can cause memory fragmentation. That is one of the reasons I always tell people not to use String. You don't need to convince me of this (though perhaps you do need to convince anthonyhill86).

Perhaps what Whandall wrote at the end of #6 would be the "more horrible than usual" I feared.
Quote
When deleting such cloned buffers you could run into problems with the heap,
because buffers will be freed twice.

GoForSmoke

#14
Jan 17, 2019, 05:57 am Last Edit: Jan 17, 2019, 05:58 am by GoForSmoke
Not just String, C++ has many dynamic allocation using classes.

You don't need C++ to alloc and malloc and still it's a bad idea.

But you can define a buffer space and access into that with pointers, use and reuse space in controlled ways. Consider circular buffers and FIFOs.
1) http://gammon.com.au/blink  <-- tasking Arduino 1-2-3
2) http://gammon.com.au/serial <-- techniques howto
3) http://gammon.com.au/interrupts
Your sketch can sense ongoing process events in time.
Your sketch can make events to control it over time.

Go Up