Please explain what "does not work" means. What did you expect to happen, and what happened instead?
Also, post complete code that compiles and demonstrates the problem. See the "How to get the best out of the forum" post for instructions.
Please explain what "does not work" means. What did you expect to happen, and what happened instead?
Also, post complete code that compiles and demonstrates the problem. See the "How to get the best out of the forum" post for instructions.
I edited the post, if you run the code you'll see that nothing is copied into serialInCstring. It prints empty, so the strcpy function does not work at all and I don't understand what I'm doing wrong?
Please post the code in a new post. The thread becomes impossible to follow if you change previous posts.
The enum code does not compile.
I appreciate your time and your replies. Since I cannot use strings the way that I have, it appears I'm out of options and I'm going to have to reevaluate the entire project.
For anyone that stumbles upon this in a search, here is how I got the enum portion to compile and work.
This goes outside of any functions
enum Settings
{
automation = 20,
empty = 30,
full = 40,
alldays = 50,
alldaystime = 60,
sundays = 70,
sundaytime = 80,
mondays = 90,
mondaytime = 100,
tuesdays = 110,
tuesdaytime = 120,
wednesdays = 130,
wednesdaytime = 140,
thursdays = 150,
thursdaytime = 160,
fridays = 170,
fridaytime = 180,
saturdays = 190,
saturdaytime = 200,
chime = 210,
weighttarget = 220
};
This goes inside of setup or loop
Settings setting = automation;
Serial.print("setting: "); Serial.println(setting);
and it will print out the following
setting: 20
Hi Delta, I've read Robin2's posts 4 times. None of his examples involve an expandable char array, they all have hard coded array lengths and if you look at my puedo code, hard coded is not what I'm after. You'll also notice that I'm using his variable "newData" from one of his examples.
Maybe they can be easily adapted to that, however in my inexperience I do not know how to do that.
I understand that none of the seasoned forum members want to answer a question that's already been answered or is answered in a thread has been dedicated to the subject, however I have read through that thread many times and have spent hours trying to adapt those examples to my needs and have not been able to, which is why I made a post.
An "expandable" character array is hardly ever a good idea with an Arduino, especially if you are inexperienced, as you are very likely to crash it.
Experienced people make the array a fixed size, a bit larger than needed, and make sure to never write past the end of it.
Having hard coded values fly in the face of everything I've been taught with .net, so the expandable char array, the way I was trying to implement it seemed like a clever way to have a flexible solution, but I will digress to your advice.
Can I set the vhar array bucket to 50 ot 100? I believe I read that 22 or 32 was a max but I can't find that post now.
.net does not run on an Arduino.
To avoid endless trouble with programming microprocessors, change your style to face the reality of very limited memory.
char arrays can have any size that fits into available memory. 50 or 100 bytes is usually practical.
His examples declare an array that is large enough for the longest text that will be received. A String would need slightly more memory for the same text, and if there is insufficient memory for the char array the String would crash the program too.
So with that advice in mind, I cannot get your enum suggestion to work in a function. When I try to set settings action = variable (as opposed to settings action = "variable value"), the first example will not compile. Do I have to cast the variable into a constant somehow?
enum settings { monday, tuesday, wednesday, thursday, friday, saturday, sunday, everday };
void setup()
{
Serial.begin(9600);
while (!Serial)
{
; // Wait for serial to connect
}
delay(2000);
//String var = "monday";
//settings action = var; <-- does not work with a variable, I need this to be inside of a function that takes a String value to represent the day
settings action = monday; // <-- works but defeats the purpose in a function as I'd have to use an if/elseif ladder again to use the String name passed to the function
int returnValue;
switch(action)
{
case monday:
{
returnValue = 20;
break;
}
case tuesday:
{
returnValue = 30;
break;
}
// etc...
}
}
Post the code that demonstrates the problem, and explain the problem. Copy and post the full text of any error messages that appear, using code tags.
.net programs live in a computational utopia where there is near infinite memory, and nearly infinite CPU power to manipulate it. Not so, embedded systems.
Let's consider how an "expandable array" (of bytes) actually works.
You have a collection of N bytes of data somewhere in memory, and a couple of counters that say there are N bytes out of a maximum of M. If you try to add a byte that would make the size grow beyond M, the library goes off and allocates a new chunk of memory that has at least M+1 bytes, copies the old data to the new memory chunk, returns the old chunk to free memory (or arranges for it to be "garbage collected", eventually), and updates all the references and counters to reflect the location and size of the new chunk of memory.
Without even considering esoteric issues like "fragmentation", it should be obvious that this requires about 2*N memory to deal with arrays of max size N: at one point you need to have both the old and new arrays present so that the data can be copied.
So, if yiou can guess the max size of your string within a factor of 2, you'll be using less memory with a fixed size array than with an expandable array.
Also note that on a single-threaded microcontroller, there is no advantage to using less memory in the "growing" stage of the string - there are no other memory users that could be using that space instead.
I believe I read that 22 or 32 was a max
Max size of an array in avr-gcc is 32768 (limited by the size of pointers.) That is more memory than exists in any AVR chip, so you're normally just limited to the size of memory (minus whatever is in use by other things.)
The Serial input buffer can be as small as 16 bytes (on chips with less than 1k of RAM), but is normally 64 bytes. This is the maximum number of bytes that can be received by the hardwareSerial driver, before your sketch has to Serial.read() some of them in order to prevent loss of data.
Here is the code and the error messages, the problem is that the code does not compile because the enum declaration will not accept a variable name. I've placed it inside of setup() for the example. I'm not able to use a variable name, which I'd like to use this inside of a function and need to be able to pass a variable to the function and then to the enum declaration, rather than having to declare the enum with = "text here" .
The errors are:
C:\Users\acct\AppData\Local\Temp.arduinoIDE-unsaved202411-7488-1mwjm1o.6sqqk\sketch_feb1a\sketch_feb1a.ino: In function 'void setup()':
C:\Users\acct\AppData\Local\Temp.arduinoIDE-unsaved202411-7488-1mwjm1o.6sqqk\sketch_feb1a\sketch_feb1a.ino:15:23: error: 'var' was not declared in this scope
settings action = var; <-- does not work with a variable, I need this to be inside of a function that takes a String value to represent the day
^~~
C:\Users\acct\AppData\Local\Temp.arduinoIDE-unsaved202411-7488-1mwjm1o.6sqqk\sketch_feb1a\sketch_feb1a.ino:15:28: error: expected primary-expression before '<' token
settings action = var; <-- does not work with a variable, I need this to be inside of a function that takes a String value to represent the day
^
C:\Users\acct\AppData\Local\Temp.arduinoIDE-unsaved202411-7488-1mwjm1o.6sqqk\sketch_feb1a\sketch_feb1a.ino:15:32: error: 'does' was not declared in this scope
settings action = var; <-- does not work with a variable, I need this to be inside of a function that takes a String value to represent the day
^~~~
C:\Users\acct\AppData\Local\Temp.arduinoIDE-unsaved202411-7488-1mwjm1o.6sqqk\sketch_feb1a\sketch_feb1a.ino:15:32: note: suggested alternative: 'cos'
settings action = var; <-- does not work with a variable, I need this to be inside of a function that takes a String value to represent the day
^~~~
cos
C:\Users\acct\AppData\Local\Temp.arduinoIDE-unsaved202411-7488-1mwjm1o.6sqqk\sketch_feb1a\sketch_feb1a.ino:22:7: error: 'returnValue' was not declared in this scope
returnValue = 20;
^~~~~~~~~~~
C:\Users\acct\AppData\Local\Temp.arduinoIDE-unsaved202411-7488-1mwjm1o.6sqqk\sketch_feb1a\sketch_feb1a.ino:28:7: error: 'returnValue' was not declared in this scope
returnValue = 30;
^~~~~~~~~~~exit status 1
Compilation error: 'var' was not declared in this scope
enum settings { monday, tuesday, wednesday, thursday, friday, saturday, sunday, everday };
void setup()
{
Serial.begin(9600);
while (!Serial)
{
; // Wait for serial to connect
}
delay(2000);
String var = "monday";
settings action = var; <-- does not work with a variable, I need this to be inside of a function that takes a String value to represent the day
//settings action = monday; // <-- works but defeats the purpose in a function as I'd have to use an if/elseif ladder again to use the String name passed to the function
int returnValue;
switch(action)
{
case monday:
{
returnValue = 20;
break;
}
case tuesday:
{
returnValue = 30;
break;
}
// etc...
}
}
void loop() {
// put your main code here, to run repeatedly:
}
This make no sense. What is your thinking here?
Under the hood an enum is an integer. so you cannot push a String in an enum.
You can set your action variable to monday (without the "").
You need to make an array of Strings that corresponds to the enum if you want to print the enum monday as "monday".
Yes. An array of small s strings works well too.
enum state {ASLEEP = 0, WAKING, MOVING, EATING};
const char *stateTag[] = {
"I am asleep.",
"I am waking up.",
"I am getting out of bed.",
"I am breaking fast."
};
state myState;
void setup()
{
Serial.begin(115200);
Serial.print("Hello World ");
myState = MOVING;
Serial.println(stateTag[myState]);
}
void loop() {}
I only wrote the entire sketch because I routinely bungle the syntax and it takes a few cycles to get it right.
And ASLEEP would be zero even if I didn't say, I just like to remind myself because I forget. ![]()
Numbers in the logic in the code, tags when you need to present things.
And the tags array could be designed so you can strcmp() your way through it to find a match for a char array that has arrived from the real world however.
Time for coffee.
a7
Hi,
Can this
myState = MOVING;
be done this way
char *stateName = "MOVING";
myState = stateName;
or
String stateName = "MOVING";
myState = stateName;
or something similar? It was suggested to do this in this thread to get rid of a long if/elseif ladder in a function, however if I can't pass a char array or string to the function for the enum state, then I have to have an if/elseif to check the string and determine the state that way.
The way you'd like to do it is sensible, but C/C++ has no features that would allow you to code it directly in that manner.
No. Well you could use endless massive if/else chains, but I mentioned strcmp().
It could be used in a for loop to look through an array of string constants to find a match, resulting in the determination of a number which would be used in the logic in place of the matched input.
So when you print for humans, you use the number to get the tag and print that string.
When a string is arrived from whatever external source, it is transformed to its corresponding number, and that number used everywhere else subsequently.
If there is a way to arrange it, the external source could deal directly with numbers, and more compact communication of information would result.
I don't remember where your external information is coming from, so the above assumes you want or need or can't help but receive "Tuesday" and would need to turn it into 3, if that was the third enum and the third entry in the tag array.
Here's some code I googled up that shows a simple lookup table that is a bit more general in that it lets you determine an arbitrary number that is associated with any of a list of character strings by searching through a table of key-value pairs.
Read it line by line like you understand it, it may daunt but the logic is fairly simple.
const char *keys[13];
int keytoindex[13];
/* build table */
keys[0] = "A";
keys[1] = "A#";
/* etc. eleven more keys */
keytoindex[0] = 9; /* Value for 'A' */
keytoindex[1] = 10;
/* etc. eleven more associated values */
/* later */
char *userInput = ...; /* somehow get input */
int keyvalue = -1; /* I assume -1 is not in the value array, so it can be an error condition that we didn't find that key when searching in the first array */
for( int i = 0; i < 13; i++ ) {
if(strcmp(userInput,keys[i]) == 0 )) {
keyvalue = keytoindex[i];
break;
}
}
if(keyvalue == -1) exit(1); /* send an error */
/* otherwise, keep going */
The big idea is that internally, the logic can deal with and exploit numbers way easier than dealing with character arrays or worse capital S strings.
And with use of the enum feature, the code can remain quite readable by us.
a7
HTH
a7
You suggested in post #4 that I remove the if/elseif ladder and replace it with an enum and I'm trying to follow your advice. That ladder resides in a function, and I can't see how to use the function with the enum unless I can call the enum with a variable rather than a variable value inside of quotes. You have it hard coded as settings action = empty , but that will not work with my function int getEePromAddress(String settingName)