First thing I would try is to eliminate "Happy Birthday " in the print statements and replace with a variable that was set to "Happy Birthday ". I may be wrong, but each one of those in the print are considered separate temp variables that added together to your total.
Photo Bud (aka John)
The Old Curmudgeon!
No expert but the issue must be related to the error message "Global variables use 2065 bytes (100%) of dynamic memory, leaving -17 bytes for local variables. Maximum is 2048 bytes.data section exceeds available space in board".
Maybe delete all your code except the "include" lines and compile and see how much memory the libraries are using. Then add back one by one your variables then compiling watching how you memory is being used up.
The above code goes on checking just like above. The total number of lines is about 655.
The first thing I thought was, that can't be right, as many examples of such a projects have been provided and built successfully, including by myself.
So, I pasted your code from the top, and only included the setup code to check the compile size for myself.
The first thing I found when I hit the compile button, was that you have an error on the first line of your code following the Serial.begin(9600); statement, that is: lcd.init(); which error's out as private in context.
What you were probably looking for was: lcd.begin(16, 2);
I also think there are to few arguments provided to your lcd object declaration, but I haven't looked at the constructors of the library to be 100% sure on that.
Aside from that, the global memory size is not even close to being full at this stage, so I suspect the issue might be in the code we haven't seen - You could post it as an attachment, but remove any sensitive strings/dates etc... before doing so, if you wish.
Having said that, it's a good practice to compile your code frequently upon any new sections of code, that way you nail down any problems early, and eliminate compound errors, making things much harder to troubleshoot later... it's something I have trained myself to do, as have many other programmers.
So in summary, minimize your code to get the lcd working, then the sensor and so on. The other comments are also quite valid things to check for.
Well, here is my suggestion to "Reduce" the lines of codes -
- Use a pretty small function
void printToLCD(char *Msg, char *Name) { lcd.setCursor(0,2); lcd.print(Msg); lcd.setCursor(0,3); lcd.print(Name); } /* and call it to replace these instances*/ lcd.setCursor(0,2); lcd.print("Happy Birthday "); /*Other Messages as well*/ lcd.setCursor(0,3); lcd.print("Chris H. "); /*As an example*/
printToLCD("Happy Birthday", "Chris H");
As you can see, you replace each 4 lines of codes with just one line. Using a function will definitely help you keep your code smaller and easy to maintain.
And I would agree with @photo-bud to use the variables instead
Life is exploring and learning
Thanks all. Using F, worked. I know the code is a bit sloppy. I'm new. I'd like to use an array but first have to look up a few examples to get me started.
Folks,
I'm working on a clock that is programmed with mostly birthdays, but also some anniversaries, and a few RIPs for some special people that have passed. I have about 100 people so far but I'm new to programming so I used 100 if statements. I have yet to learn about arrays so I thought this would be a good opportunity for me to learn - hopefully I didn't pick a task too hard for someone of my skill level. My initial thought was to use a the following format.
Name, Month of Birth, Day of Birth, 1-3 (1 = Bday, 2 = Anniversary, 3 = RIP)
Below is my attempt at the code but it did not compile. Your thoughts about my approach or the error I'm getting below would be appreciated.
char birthdays[15,4] = { { "Amanda",1,2,1}, // Name, Month, Day, 1=Bday 2=Anniversary 3=RIP
{ "Amy",1,4,1 },
{ "Bill",1,5,1 },
{ "Bob",1,13,1 },
{ "Carl",1,21,1 },
{ "Dan",2,2,1 },
{ "Diane",2,7,1 },
{ "Edna",3,15,1 },
{ "Frank & Lisa",5,20,2 },
{ "George",6,18,3 },
{ "Hank",7,2,1 },
{ "Joan",8,13,1 },
{ "Kim & Dan",9,13,2 },
{ "Larry",10,13,1 },
{ "Mary",11,17,1 } };
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
Serial.print(birthdays[0][0]); // I want to print "Amanda"
}
void loop() {
// put your main code here, to run repeatedly:
}
Array:2:18: error: expected ']' before ',' token
char birthdays[15,4] = { { "Amanda",1,2,1}, // Name, Month, Day, 1=Bday 2=Anniversary 3=RIP
^
Array:2:19: error: expected unqualified-id before numeric constant
char birthdays[15,4] = { { "Amanda",1,2,1}, // Name, Month, Day, 1=Bday 2=Anniversary 3=RIP
^
/Users/tonyperry/Documents/Arduino/Array/Array.ino: In function 'void setup()':
Array:22:14: error: 'birthdays' was not declared in this scope
Serial.print(birthdays[0][0]);
^~~~~~~~~
exit status 1
expected ']' before ',' token
I have yet to learn about arrays so I thought this would be a good opportunity for me to learn - hopefully I didn't pick a task too hard for someone of my skill level. My initial thought was to use a the following format.
Name, Month of Birth, Day of Birth, 1-3 (1 = Bday, 2 = Anniversary, 3 = RIP)
Below is my attempt at the code but it did not compile. Your thoughts about my approach or the error I'm getting below would be appreciated.
char birthdays[15,4] = { { "Amanda",1,2,1}, // Name, Month, Day, 1=Bday 2=Anniversary 3=RIP
{ "Amy",1,4,1 },
[snip]
OK, the first problem with the code above is that you are using 'char' which can only store a single character, and not a string literal, so you'll need to change that to:
const char* birthdays[15, 4]
The second problem is how you're initializing the array - You cannot mix strings and integers in this way, so they much all be string literals, such as:
const char* birthdays[15, 4] = {{ "Amanda", "1", "2", "1"}, etc...
Although the above will work, it's also much better to allow the compiler to determine the number of groups of strings for you, so something like this is even better:
#define MAX_ELEMENTS 4
const char* birthdays[][MAX_ELEMENTS] =
{
{"Amanda", "1", "2", "1"},
{"Amy","1","4","1"},
{"Larry","10","13","1"},
{"Mary","11","17","1"}
// ...
};
All you needed to do was supply the number of elements in each group.
In summary:
1) const char* handles string literals and their length automatically
2) Empty brackets [] handle the number of group items you add automatically
3) All elements of the array must be of the same data type
As you know, I normally advocate using the 'String' data type unless you have a reason to do otherwise... running low on memory is a good reason, but such a decision also depends on the full design of your code.
Cheers.
@frogandtoad Thank you for taking the time to reply. I've got some learning to do, and some work to do. Hopefully it will work out. The first version of the sketch with 100 if statements was over 700 lines long. And in that long sketch I seem to have some gremlins in the LCD display because odd things are happening - like printing PM twice for some reason. I'd like to use an array to reduce the size of the program and make it easier to debug. And with an array, easier to add new folks.
Best,
Tony
I have about 100 people so far but I'm new to programming so I used 100 if statements.
Nothing wrong about using the if statements, and also nothing about being sloppy code. I am sure, most of us were more sloppy as we started out. Programming takes a while to learn, but once you get the hang of it, things come in quick, right? (Why only programming, I think it happens with almost everything we learn and become proficient in our years).
Another suggestion now that you are getting to use Arrays, consider using something known as the switch ...case statement set. This will cut down those "else" that you will have to continue using if you are using the if, which again will be beneficial.
Here is the link on the switch...case statement in arduino - https://www.arduino.cc/reference/en/language/structure/control-structure/switchcase/.
Life is exploring and learning
@frogandtoad Thank you for taking the time to reply. I've got some learning to do, and some work to do. Hopefully it will work out. The first version of the sketch with 100 if statements was over 700 lines long. And in that long sketch I seem to have some gremlins in the LCD display because odd things are happening - like printing PM twice for some reason. I'd like to use an array to reduce the size of the program and make it easier to debug. And with an array, easier to add new folks.
Best,
Tony
No problem, do let us know how you go with your new version.
#define MAX_ELEMENTS 4
const char* birthdays[][MAX_ELEMENTS] =
{
{"Amanda", "1", "2", "1"},
{"Amy","1","4","1"},
{"Larry","10","13","1"},
{"Mary","11","17","1"}
// ...
};
Nothing about the code though. It has always been considered as a Good Practice.
But there always has been a doubt or something that I fail to understand why we use the #define in such a case. It confuses me because of this-
Arrays are handled differently in C, C++ (and so I assume in Arduino as well)- What I imply is, if I change MAX_ELEMENTS to any other legal value, it would also (always) require me to update every Array element(row) to match the number of elements to that value. For instance, if I do this -
#define MAX_ELEMENTS 3 - I would have to remove one element from every row (or member arrays) and similarly, if I #define MAX_ELEMENTS 6, I would have to add 2 more elements to every member array.
If you get me until this point, why is the necessity to #define it instead of Hard Coding it right in the array declaration itself - so say something like - const char* birthdays[][4] or const char* birthdays[][6].
I have always been told that it is a convention (to use #define), it is easier to maintain but I still dont see it beneficial, instead, I have run into issues with this at times - I forgot changing the value to 4 or 6 or even updated its value and forgot about the array.
If anyone could help me on this, it would help me clear a pain that has been with me since past 20 years or more.
Life is exploring and learning
#define MAX_ELEMENTS 4
const char* birthdays[][MAX_ELEMENTS] =
{
{"Amanda", "1", "2", "1"},
{"Amy","1","4","1"},
{"Larry","10","13","1"},
{"Mary","11","17","1"}
// ...
};Nothing about the code though. It has always been considered as a Good Practice.
But there always has been a doubt or something that I fail to understand why we use the #define in such a case. It confuses me because of this-
Arrays are handled differently in C, C++ (and so I assume in Arduino as well)
OK, firstly, no... arrays in C and C++ are handled exactly the same way - Arduino uses a C++ compiler (g++), which can also compile C code.
What I imply is, if I change MAX_ELEMENTS to any other legal value, it would also (always) require me to update every Array element(row) to match the number of elements to that value. For instance, if I do this -
#define MAX_ELEMENTS 3 - I would have to remove one element from every row (or member arrays) and similarly, if I #define MAX_ELEMENTS 6, I would have to add 2 more elements to every member array.
Not quite.
You're right that if you make the number smaller, you would have to remove the elements to suit, but if the number is larger, you can have less elements, but not more than what you specified.
If you get me until this point, why is the necessity to #define it instead of Hard Coding it right in the array declaration itself - so say something like - const char* birthdays[][4] or const char* birthdays[][6].
I used #define (known as a preprocessor macro) in this case for 2 main reasons:
1) Because he was having memory issues, macros do not use up any extra memory space
2) Making the size global allows for easier program modifications, as this size is usually required elsewhere in your code, for example in a for loop to iterate over the whole array to print out the full array attributes - So just a good coding practice in general.
If anyone could help me on this, it would help me clear a pain that has been with me since past 20 years or more.
I'm very tired and need to get some sleep!
I hope my explanation has alleviated your pain 🙂