So, I'm not sure if I'm really doing the correctly in the first place. I'm trying to take an int and replace part of a char array with it. I know I've done something similar before, but for the life of me can't remember how.
The code basically saves the state of 8 relays for power recovery. What I need to do is take what's stored (and retrieved) as a char array of 8 values (one for each relay) that are either 1 or 0 and be able to just replace one of them as the relay states are changed. The initial value that it is reading right now is "00000000"
Here's a bit of example code, that I'm sure I'm doing something wrong with. Can anyone point me in the right direction?
void SetSavedState(int Relay, int State) {
char* LastState = "";
char buffer[1];
Relay--; // to handle the fact that the relays are numbered elsewere as 1-8 while the array will actually store as 0-7
LastState = functiontogetstateofrelaysfromeeprom(); // returns a char* of "00000000" currently
itoa(State, buffer, 10); // convert into to char
LastState[Relay] = buffer[0]; // I've also tried just buffer
// code here to store the state again into eeprom
I know something is wrong, because when this function gets run it crashes and reboots. I'm just hoping someone else sees something I am too tired to see or knows the correct way to do what I want to do.
Thanks in advance!
Oh, and before anybody says it, the reason I'm not just storing integers in an array in the first place has to do with the library I'm using to store and retrieve configuration. It's not really an option right now.
because when returning raw-pointer to a stack allocated variable you may run into memory leaks.
Edit: if you have 8 relays whose state is 1 or 0 so you can do the job using only one byte of memory, (not 8 as you planned in the char array) so again, either use enum, or just use a byte. Personally in this problem I would prefer to use a byte
Change a bit (I use a random bit which is randomly set to 0 or 1).
Convert it to text.
Never ever return a pointer to an array on the stack.
#include <EEPROM.h>
void setup()
{
Serial.begin(115200);
}
void loop()
{
SetSavedState( random(0,8), random(0,2));
delay(3000);
}
// Return a byte with a random pattern.
byte functiontogetstateofrelaysfromeeprom()
{
byte result = 0;
for(int i=0; i<8; i++)
bitWrite(result, i, random(0,2));
return( result);
}
// Request the data from EEPROM and change it and send it
// Relay: 0...7
// State: 0 or 1
void SetSavedState(int Relay, int State)
{
// Get it
byte myRelaysOld = functiontogetstateofrelaysfromeeprom();
// Change it
byte myRelaysNew = myRelaysOld;
bitWrite( myRelaysNew, Relay, State);
// Conver it to text
char text[] = "00000000"; // must be 8 characters of 0
for( int i=0; i<8; i++)
{
if( bitRead( myRelaysNew, 7-i) == 1) // start with higest bit
text[i] = '1';
}
// Print everything
Serial.print("From EEPROM: ");
for( int i=7; i>=0; i--) // print zeros in front
{
if( bitRead( myRelaysOld, i) == 0)
Serial.print('0');
else
break;
}
Serial.print( myRelaysOld, BIN);
Serial.print(", Relay = ");
Serial.print(Relay);
Serial.print(", State = ");
Serial.print(State);
Serial.print(", result as text = ");
Serial.println(text);
}
If you are not familiar with using pointers you should not use them at all.
the asteriks the "star" * is changing from variable to pointer to variable
just define all variables global.
defining global means define them outside all functions on top of your source-code
an array of char needs a byte for every character you want to store
and one additional byte for the terminating zero of the array of char
so for storing your characters
12345678
00000000
instead of coding
you have to code
char buffer[9]; // 9 elements 8 chars and 1 for terminating_zero
and you have to know that the indexnumbers start at zero
Ahhh. ... but using them is how you get familiar with them. Like interrupts, it's a Catch 22 ... you shouldn't use them unless you're familiar, but you won't get familiar until you try using them and get burned a few times.
there are of course lots of languages that don't have pointers. And even those that have pointer (Pascal) maintain them thru the language, don't allow there values to be specified.
while array indices can replace the use of pointers in some applications (e.g. linked lists), C's definition of pointers make programming on hardware much more convenient. avoiding assembler routines makes the code more portable and is the reason why the Arduino IDE supports C++. but when has an OP on this forum described a program needing such features
while pointers can make the code a bit easier to read, i wonder where/if there a line where they aren't necessary (function ptrs, callback functions)?
or is the issue really the mis-application of ptrs, using them when not appropriate?
In my own code, I think "nothing" of using pointers, just a natural as I learned C (early) immediately after Fortran at uni.
But, I go out of my way to avoid pointer examples in this Forum. Pointers are just too easy to "break" when used by the novice; heck, I have even gotten myself into pointer-hades after a couple of brews and untwisting pointer logic is no fun the next day when one has a hangover. :face_vomiting:
IMO: teaching/learning to utilize pointers correctly is not well suited to brief forum exchanges.
Yes, you can cast any typed variable you have to a char array and mess with it for whatever purpose you have in mind. But type-punning through unions is illegal in C++, there are no buts and excuses. Yes, it may work. Yes, if you're not bothered by it, you may continue to use it. But per C++ standard, it is clearly illegal.
Hey everyone, sorry it's been a few days. It's been very busy and tiring with work.
That is a possibility, but the library that I'm using (if I wasn't using it I would just write my own eeprom routines) stores things as a char array that it's web interface can read for users to modify settings. And, ideally if the settings is going to be displayed, I was hoping it could be easily user readable and modifiable as the string of 8 characters.
This line is not an exact representation, but more of an arbitrary piece of code I just put for an example. As I said above, I'm using functions of a library I'm already using for other features and the function is actually defined as...
both of which work fine as they are coded, so I didn't bother to post the code within them. The second one is a void function that gets the data from eeprom and stores it in a variable. The first one calls that function, but stores it in a local variable to return to the calling code, which can sometimes be easier for coding.
To be fair on this one, buffer[1] is exactly that, a buffer for the single character as I was going crazy trying to figure out how to do this and I was thinking maybe I could have an array of 1 character, put the value into that and then copy, lets say buffer[0] to LastState[3] as I could not figure out how to directly put an integer into the char array. And, I am fully aware of arrays beginning at zero, which is why I had the line...
Relay--;
to decrement the relay number to match the array location.
gcjr, I am not awake enough yet to read that much code. lol. But I will definitely be looking at that later as it looks promising.
I will look into this as well.
As far as the pointers, I'm not going to say I'm an expert, but I do somewhat understand them. It is sometimes useful to pass the pointer to a function and then have the function access that pointer to update the info for the previous calling function as I have run into the calling function (whether loop or something else) getting random gibberish back from a return statement even though the variable being used in the return line can be printed to serial before the return statement without any problems. And, some things you just don't want a global variable for because they are only used in certain cases.
For example, part of what I am doing is a relay board that will be able to be controlled by remote...by multiple remotes (think handheld, dash mounted and maybe a tablet) that will all be able to be paired at once and configured. Now, if you're using something dash mounted in your vehicle, then you step out and use a hand remote, you don't want the global variables being used and your functions getting confused in the case of maybe someone inside he vehicle sending commands to control one thing while someone outside of the vehicle is using a remote at the same time to control another thing.
I appreciate all the advice and will be looking at some of it later today to see if it will work for my code. Any other suggestions are welcome, and I hope I don't offend anyone with any of my replies. Mostly I'm just trying to work with the library I'm using for other functions, which include OTA updates and a web configuration interface. Perhaps I could use other options later, but this library suits my needs for now and already has the eeprom functions and I don't want to accidentally store something in the wrong spot and mess up the library's configuration.
From the initial description
having a sequence of 8 characters beeing either "0" or "1"
examples
You haven't posted the complete sketch. Just a small snippet. What you have written above sounds like you try to change values stored in an EEPROM in a way that is different from the standard-way of the library-functions you are using is doing it.
But I can't really tell if this is true because you did not post the rest of your code.
additional you have not told what microcontroller you are using. OTA sounds like ESP8266 / ESP32 but I'm not sure
You should post at least this part of your code that shows
What is the standard-way of your library to store any kind of value in the EEPROM
your initial code
LastState = functiontogetstateofrelaysfromeeprom(); // returns a char* of "00000000" currently
if the comment is right you store a pointer into variable named "LastState"
You did not show what type of variable this is
next line uses a different variable named "State"
Where was which value assigned to variable "State"?
itoa(State, buffer, 10); // convert into a char
Then next line
LastState[Relay] = buffer[0];
shows that variable LastState[Relay] is an array
again you did not post what variable-type are the elements of your array LastState[]
You are assigning a single char from char-array "buffer" to an element of array LastState
It would help a lot if you would post your complete sketch. It doesn't matter if this sketch has 2000 lines of code
You initially wrote
Somewhere in your code there must be a part that does the storing
"the state of 8 relays as a char-array"
.
and somewhere there must be a part that is
"retrievieving the states of 8 relays as a char array of 8 values"
or is this exactly that part of the code you want to add????
If so somewhere in your code the relays are switched on/off. How does this code look like??
Again in summary post your complete sketch to be able to look-up what ever details is required to get an overview about how your code does what.