Global Values - taking up too much memory

Attempting to upload a Catchphrase clone to my Uno Minima R4 and the code I have grabbed from the internet is not allowing me many topics. I want to add 500+ words to this code and it only allows a few dozen, keeps erroring out with message below about Global Variables. Does anyone know how I can simplify the code to allow this many variables plus many more?? I only have a handful of variables uploaded just to validate my code I have, but I want to add hundreds more but I am maxed.

Global variables use 1985 bytes (96%) of dynamic memory, leaving 63 bytes for local variables. Maximum is 2048 bytes.

#include <LiquidCrystal.h> // include the library code:
LiquidCrystal lcd(12, 11, 5, 4, 3, 2); // initialize the library with the numbers of the interface pins

//counting vars
int newGame = 0;
int timerCounter = 0;
int timerMaxCount = 60;
int teamOneReadScore = 0;
int teamTwoReadScore = 0;
int teamOneWins = 0;
int teamTwoWins = 0;

//setting up the buzzer
const int buzzerPin = 10; // the number of the buzzer pin
int buzzerState = LOW; // buzzerState used to set the buzzer
long previousMillis = 0; // will store last time buzzer was updated
long buzzerInterval = 300; // buzzerInterval (milliseconds)

// setting up start button
int startButtonPin = 9;
int startButtonPushCounter = 0; // counter for the number of button presses
int startButtonState = 0; // current state of the button
int startButtonLastestState = 0; // previous state of the button

// setting up next button
int nextButtonPin = 8;
int nextButtonPushCounter = 0;
int nextButtonState = 0;
int nextButtonLastestState = 0;

// setting up teamOne button
int teamOneButtonPin = 7;
int teamOneButtonPushCounter = 0;
int teamOneButtonState = 0;
int teamOneButtonLastestState = 0;

// setting up teamTwo button
int teamTwoButtonPin = 6;
int teamTwoButtonPushCounter = 0;
int teamTwoButtonState = 0;
int teamTwoButtonLastestState = 0;

String words[] = {
"Alsace Lorraine","American League","April O'Neil","AquaLink","Aria","Arizona Cardinals","Arson","Assault","Atlanta Braves","Atlanta Falcons","Atlantic Ave","Avocado tree","Arizona Diamondbacks","B & E","Bake n Broil","Ballantree St","Ballast Point","Balls back","Baltimore Ravens","Baltimore Orioles","Barry's Beach Shack","Baseball Bat","Bases Loaded","Beavis and Butthead","Behind the Back","Belmont Heights","Belmont Shore","Big League Chew","Big Leagues","Bixby Knolls","Bixby Road","Bixby Village","Bakrnd Investigation","Blitz","Bloody Mary","Blooper","Blue Line","Bluff Park","Bobblehead","Bond","Boston Red Sox","Bottomless Mimosas","Bourbon","Boys in Blue","Brandy Burger","Breakers Hotel","Breathalyzer","Bud Light","Buffalo Bills","Bullpen","Bunt","Burglary","C17 Globe Master","Cactus Cooler","Cactus League","Caddyshack","California Ave","California Heights","Call Bowl","Calvin Broadus","Cambodia Town","Cameron Diaz","Carl Weathers","Carl's Jr","Carmelitos","Carolina Panthers","Catalina Express","Catalina Island","Catwalk","Caught Looking","Cedar Ave","Cerritos Ave","Change Up","Chase Utley","Cherry Ave","Chestnut Ave","Chicago Bears","Chicago Cubs","Chicago White Sox","Chief of Police","Christmas Parade","Cincinnati Bengals","Cincinnati Reds","Circa","Classic Car Show","Cleveland Guardians","Cleveland Browns","Code 3","Code 7","Colorado Rockies","Contra","Coors Light","Cops in Nihongo","Cosmopolitan","Coyote Ugly","Cup In Cup"}; // an array of words for catchphrase
int maxSize = sizeof(words)/sizeof(String);
int interval = 0;

void setup() {
lcd.begin(2,16);
shuffle();
pinMode(startButtonPin, INPUT_PULLUP); // button as input
digitalWrite(startButtonPin, HIGH); // turns on pull-up resistor after input
pinMode(nextButtonPin, INPUT_PULLUP);
digitalWrite(nextButtonPin, HIGH);
pinMode(teamOneButtonPin, INPUT_PULLUP);
digitalWrite(teamOneButtonPin, HIGH);
pinMode(teamTwoButtonPin, INPUT_PULLUP);
digitalWrite(teamTwoButtonPin, HIGH);
pinMode(buzzerPin, OUTPUT); //buzzer setup
lcd.print("Press Start!");
}

void loop() {
printScore();
timerTone();

startButtonState = digitalRead(startButtonPin);
if (startButtonState != startButtonLastestState) {
if(digitalRead(startButtonPin) == LOW){
if(timerCounter == 0){
startGame();
}
else {
digitalWrite(buzzerPin, LOW);
timerCounter = 0;
}
}

}
startButtonLastestState = startButtonState;

nextButtonState = digitalRead(nextButtonPin);
if (nextButtonState != nextButtonLastestState) {
if(digitalRead(nextButtonPin) == LOW){
printWord();
}

}
nextButtonLastestState = nextButtonState;

teamOneButtonState = digitalRead(teamOneButtonPin);
if (teamOneButtonState != teamOneButtonLastestState) {
if(digitalRead(teamOneButtonPin) == LOW){
teamOneScore();
}

}
teamOneButtonLastestState = teamOneButtonState;

teamTwoButtonState = digitalRead(teamTwoButtonPin);
if (teamTwoButtonState != teamTwoButtonLastestState) {
if(digitalRead(teamTwoButtonPin) == LOW){
teamTwoScore();
}

}
teamTwoButtonLastestState = teamTwoButtonState;

}

// shuffle the list of words
void shuffle(){
for (int a=0; a<maxSize; a++){
int r = random(a+1);
String temp = words[a];
words[a] = words[r];
words[r] = temp;
}
}

//start the game
void startGame() {
lcd.clear();
lcd.print(words[interval]);
interval++;
newGame++;
timerCounter ++;
if (interval == maxSize) {
interval = 0;
shuffle();
}
}

//print the word
void printWord() {
if (timerCounter !=0) {
lcd.clear();
lcd.print(words[interval]);
interval++;
if (interval == maxSize) {
interval = 0;
shuffle();
}
}
}

//timer with buzzer
void timerTone() {
unsigned long currentMillis = millis();
if (timerCounter > 0) {
if (timerCounter < timerMaxCount) {
if(currentMillis - previousMillis > buzzerInterval) {
previousMillis = currentMillis;
if (buzzerState == LOW){
buzzerState = HIGH;
}
else{
buzzerState = LOW;
}
digitalWrite(buzzerPin, buzzerState);
timerCounter++;
}
}
}
if (timerCounter == timerMaxCount) {
digitalWrite(buzzerPin, LOW);
timerCounter = 0;
}
}

//teamOne score
void teamOneScore() {
if (newGame != 0) {
teamOneReadScore++;
lcd.setCursor(0, 1); // bottom left
lcd.print("One: ");
lcd.print(teamOneReadScore);
if (teamOneReadScore > 10) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Team One wins!");
newGame = 0;
teamOneReadScore = 0;
teamTwoReadScore = 0;
teamOneWins = 1;
timerCounter = 0;
digitalWrite(buzzerPin, LOW);
}
}
}

//teamTwo score
void teamTwoScore() {
if (newGame != 0) {
teamTwoReadScore++;
lcd.setCursor(9, 1); // bottom right
lcd.print("Two: ");
lcd.print(teamTwoReadScore);
if (teamTwoReadScore > 10) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Team Two wins!");
newGame = 0;
teamOneReadScore = 0;
teamTwoReadScore = 0;
teamTwoWins = 1;
timerCounter = 0;
digitalWrite(buzzerPin, LOW);
}
}
}

//print score
void printScore() {
if (newGame > 0) {
lcd.setCursor(0, 1); // bottom left
lcd.print("One: ");
lcd.print(teamOneReadScore);
lcd.setCursor(9, 1); // bottom right
lcd.print("Two: ");
lcd.print(teamTwoReadScore);
}
}

Welcome to the forum

Please follow the advice given in the link below when posting code, in particular the section entitled 'Posting code and common code problems'


Use code tags (the < CODE/ > icon above the compose window) to make it easier to read and copy for examination

https://forum.arduino.cc/t/how-to-get-the-best-out-of-this-forum

Please post your sketch, using code tags when you do
Posting your code using code tags prevents parts of it being interpreted as HTML coding and makes it easier to copy for examination

In my experience the easiest way to tidy up the code and add the code tags is as follows
Start by tidying up your code by using Tools/Auto Format in the IDE to make it easier to read. Then use Edit/Copy for Forum and paste what was copied in a new reply. Code tags will have been added to the code to make it easy to read in the forum thus making it easier to provide help.

There seems to be something wrong with the IDE board-selection

The tech specs of an

https://docs.arduino.cc/hardware/uno-r4-minima/#tech-specs
says

Your compile-log says

To me it seems that you have adjusted the IDE to the classical Arduino Uno but not to the

You should adjust the compile-log to most verbose output like shown in this tutorial

Do some research on the use of PROGMEM (and/or const) to put the text into program memory

See https://docs.arduino.cc/language-reference/en/variables/utilities/PROGMEM

The usual advice would be to store the extensive text data in flash RAM (PROGMEM) but I have no experience with the Minima's processor to know if this is possible.

From the page that I linked to

PROGMEM is useful only wwhen working with AVR boards (UNO R3, Leonardo etc.). Newer boards (Due, MKR WiFi 1010, GIGA R1 WiFi etc.) automatically use the program space when a variable is declared as a const However, for retro compatibility PROGMEM can still be used with newer boards. This implementation currently lives here

I forgot to mention I am a newb and have no programming background. My apologies. Any input here to help my caveman like programming skills will be so ever helpful. I am not the best at this.

Thanks @UKHeliBob. Looks like we were posting at the same time.

So the OP needs to declare the text data as const and the compiler will take care of the rest?

const String words[] = {
"Alsace Lorraine","American League","April O'Neil","AquaLink","Aria",

I would also probably think about using C-strings (character arrays) rather that Strings as they take up less space.

It sounds like it but there seem to be other factors at play. See post #3 above

His code compiles for a Uno R4 Minima with the following result even without declaring the String array as const, which is not possible in any case

Sketch uses 54628 bytes (20%) of program storage space. Maximum is 262144 bytes.
Global variables use 5372 bytes (16%) of dynamic memory, leaving 27396 bytes for local variables. Maximum is 32768 bytes.

I agree about the use of C strings

The shuffle goes in the wrong direction

For one thing, the first "swap" is always zero for zero. And you might as well use auto for the temp variable in a swap: it makes the function more general

void shuffle() {
  auto start = millis();
  for (int a = maxSize - 1; a > 0; a--) {
    int r = random(a + 1);
    if (a == r) continue;
    auto temp = words[a];
    words[a] = words[r];
    words[r] = temp;
    Serial.print(a); Serial.print('\t'); Serial.print(r); Serial.print('\t'); Serial.println(millis() - start);
  }
}

Wow, random is really slow on R4. Each swap takes about 90ms, totaling eight-and-a-half seconds (!) to shuffle the 96 "words". Replacing it with a simple shift like (a + 3) % maxSize, each swap takes about a half-milli. On ESP32, each random swap takes about a tenth-milli.

Still time to learn how to use the forum and fix your ill formatted post. It looks ugly and will attract negative attention to your ask.

Please correct your post and add code tags around your code.

There is a small pencil image below your existing posts.

  • click on this pencil ➜ that will let you edit your post.
  • Select the part of the text that corresponds to the code
  • Click on the <code/> icon in the toolbar to indicate that it is code
  • click image Save Edit

(Also make sure to properly indent the code in the IDE before copying and pasting it here. This can be done by pressing ctrlT on a PC or cmdT on a Mac)

The array has to be stored in ram if you are going to shuffle it around like this.
Actually swapping the words is going to slow things down, would be faster to have an array of indexes into the words array, and fill that with random indexes (although this adds the complication of checking that there are no duplicate numbers).

Put Serial.flush() at the end of your list of print() statements, otherwise your timing will be wrong once the serial buffer is full.

Does it ?
Fill the index array with numbers in sequence and swap pairs of them a few thousand times (I am exaggerating) then use the values one by one as the index to the array of words

I think the pertinent reply here is the one by @StefanL38

Wrong Board Selected!

still no code tags. I'm bailing out.

Solved, I had the wrong board and I feel stupid. Thank you everyone who helped me here, you guys are the greatest.

+1 !

He had it out of the gate.

-jim lee

As a thank you please format your post with the code as code-section like described in this 3 minute tutorial

I could make suggestions but they would involve knowing the code you posted very well which is something I'd rather not have to do in order to give you every detail through Q and A posts.

But long story short, the match words and all related const data should be stored in and accessed from PROGMEM (flash, data along with the program) instead of RAM. And that would mean not using C++ String objects but C char array strings.

But hey! There should be forum members ready, able and willing to walk you through the whole process!

And just BTW, you always need to leave enough RAM for your code to run. Every loop, every function call with parameters, every local variable needs RAM. You can write code that minimizes that but most people's code don't including what can be grabbed from the net.