Arduino Forum

Using Arduino => Storage => Topic started by: Ukulele_Sauce on Nov 05, 2019, 07:40 pm

Title: Out of dynamic memory; what to do?
Post by: Ukulele_Sauce on Nov 05, 2019, 07:40 pm
Hi, i've been into Arduino for a couple years but i'm not that programmer genie yet.
I'm making this simple project, that consists of three buttons, a display and an Arduino Nano.
The program contains a main switch function, that chooses between 3 arguments based on which button i'm pressing.
So, for example, if i press the first button, the switch will follow the "case 1".
This case contains a variable that is set to a random number between 1 and 50.
After that there's another switch, with 50 cases, based on the random number i've talked about.
Every case is an lcd.print() function, that prints a sentence.

TL;DR
Three buttons; when you press one of them, a switch selects the argument you've choosen, and another switch inside of it selects a random sentence to print.

Here's the code:

Code: [Select]

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address
 // Custom char



#define ButtonA 2
#define ButtonB 3
#define ButtonC 4

void setup() {
  lcd.begin(20,4);                  // lcd initialize
  lcd.setCursor(0,0);               

       pinMode(ButtonA,INPUT_PULLUP);
       pinMode(ButtonB,INPUT_PULLUP);
       pinMode(ButtonC,INPUT_PULLUP);

randomSeed(analogRead(0));         

}

int choose = 0;

void loop() {
    int randomNumber;
int AFacts = 50;
int BFacts = 0;                // Number of facts per argument (A, B or C)
int CFacts = 0;
 
 
 if(digitalRead(ButtonA) == LOW){choose = 1; lcd.clear(); lcd.setCursor(0,0);}
 if(digitalRead(ButtonB) == LOW){choose = 2; lcd.clear(); lcd.setCursor(0,0);}
 if(digitalRead(ButtonC) == LOW){choose = 3; lcd.clear(); lcd.setCursor(0,0);}

 
  switch(choose)
  {
    case 1:
        randomNumber = random(1,AFacts);

        switch(randomNumber)
        {
          case 1: lcd.print("Pringles once had a lawsuit trying to prove that they weren't really potato chips"); break;
          case 2: lcd.print("An average ear of corn has an even number of rows, usually 16."); break;
          case 3: lcd.print("Most wasabi consumed is not real wasabi, but colored horseradish"); break;
          case 4: lcd.print("Apples belong to the rose family, as do pears and plums"); break;
          case 5: lcd.print("About 70% of olive oil being sold is not actually pure olive oil"); break;
          case 6: lcd.print("Store bought 100% 'real' orange juice is 100% artificially flavored"); break;
          case 7: lcd.print("Chocolate was once used as currency"); break;
          case 8: lcd.print("Humans are born craving sugar"); break;
          case 9: lcd.print("Coconut water can be used as blood plasma"); break;
          case 10: lcd.print("McDonald's sells 75 hamburgers every second of every day"); break;
          case 11: lcd.print("One fast food hamburger may contain meat from 100 different cows"); break;
          case 12: lcd.print("Ketchup was used as a medicine in the 1800s to treat diarrhea"); break;
          case 13: lcd.print("Fruit-flavored snacks are made with the same wax used on cars"); break;
          case 14: lcd.print("Peanuts aren't nuts, they're legumes"); break;
          case 15: lcd.print("Eating bananas can help fight depression"); break;
          case 16: lcd.print("Honey is made from nectar and bee vomit"); break;
          case 17: lcd.print("The twists in pretzels are meant to look like arms crossed in prayer"); break;
          case 18: lcd.print("Apples float in water, because 25% of their volume is made of air"); break;
          case 19: lcd.print("The most popular carrots used to be purple"); break;
          case 20: lcd.print("One of the most hydrating foods to eat is the cucumber, which is 96% water"); break;
          case 21: lcd.print("One of the most hydrating foods to eat is the cucumber, which is 96% water."); break;
          case 22: lcd.print("Russia Only Classed Beer As Alcohol In 2011"); break;
          case 24: lcd.print("The Most Stolen Food In The World Is Cheese"); break;
          case 25: lcd.print("Bananas Are Berries, But Strawberries Aren't"); break;
          case 26: lcd.print("Lobsters & Oysters Used To Be Working Class Food"); break;
          case 27: lcd.print("Fruit Stickers Are Edible"); break;
          case 28: lcd.print("Healthy Foods Cost Up To 10x As Much As Junk Foods"); break;
          case 29: lcd.print("You Can't Overcook Mushrooms"); break;
          case 30: lcd.print("A Quarter Of The World's Hazelnuts Are Used For Nutella"); break;
          case 31: lcd.print("A Corned Beef Sandwich Made The Voyage To Space In 1965"); break;
          case 32: lcd.print("Loud Music Makes You Drink More, And Faster"); break;
          case 33: lcd.print("Without Flies, There Would No Chocolate"); break;
          case 34: lcd.print("Mcdonald's Burgers Don't Actually Rot"); break;
          case 35: lcd.print("You Can Make Diamonds From Peanut Butter"); break;
          case 36: lcd.print("Mcnuggets Always Come In Four Different Shapes"); break;
          case 37: lcd.print("Ortharexia Nervosa is an eating disorder about being obsessed with healthy food"); break;
          case 38: lcd.print("Dry swallowing one teaspoon of sugar can commonly cure hic-ups"); break;
          case 39: lcd.print("The fear of cooking is known as Mageirocophobia and is a recognized phobia"); break;
          case 40: lcd.print("The tea bag was introduced in 1908 by Thomas Sullivan of New York");
          case 41: lcd.print("Pearls melt in vinegar");
          case 42: lcd.print("The fear of vegetables is called Lachanophobia");
          case 43: lcd.print("Almonds are a member of the peach family");
          case 44: lcd.print("Onion is Latin for 'large pearl'");
          case 45: lcd.print("Peanuts can be used to make dynamite");
          case 46: lcd.print("We are eating 900% more broccoli than we did 20 years ago");
          case 47: lcd.print("Some yoghurt contain beef or pork gelatin");
          case 48: lcd.print("Baked beans are low in fat and have a lot of fiber and protein");
          case 49: lcd.print("An average person will consume 12 pubic hairs in their fast food every year");
          case 50: lcd.print("The average amount of meat eaten per person, per year is 78.5kg");         
        }
    break;

    case 2:
        randomNumber = random(1,BFacts);

        switch(randomNumber)
        {
          // B facts here
        }
    break;

    case 3:
        randomNumber = random(1,CFacts);

        switch(randomNumber)
        {
          // C Filo here
        }
    break;
   

    if(choose != 0)
    {
      delay(10000);
      choose = 0;
    }

}
}



Now, when i compile this stuff, the result is an error: The global variables use too much dynamic memory.


All i thought to get out of this situation was to use an eeprom, but how? And most importantly: is there a better way?


P.E.
I'm using an I2C module to communicate with the display, a 20 x 4 one.



Title: Re: Out of dynamic memory; what to do?
Post by: marco_c on Nov 05, 2019, 09:40 pm
All that text.

Use the F() macro to put the text into PROGMEM. From this
Code: [Select]
lcd.print("something");
to
Code: [Select]
lcd.print(F("something"));
Title: Re: Out of dynamic memory; what to do?
Post by: DrAzzy on Nov 10, 2019, 03:50 am
A constant variable (including string literals) take up space in RAM unless you explicitly tell them to be stored in PROGMEM (and use special methods to access it, since ram and flash are in different address space*). For the very common situation of string literals being passed to printables, there's the F() macro which conveniently does this for you.


* Note that this is not the case on the new MegaAVR parts (for example, Uno WiFi Rev. 2, and the megaTiny parts) - the address spaces are unified, and anything declared const will not be copied to RAM, and F() is a no-op. This is of course fabulously convenient :-)
Title: Re: Out of dynamic memory; what to do?
Post by: gilshultz on Nov 11, 2019, 05:52 am
There are several options, the simplest is to switch to a Mega. You can add external memory, Give FRAM (Ferroresonant Random Access Memory) They have a lot of memory that retains data when power is removed and unlimited read/write cycles. You can disable the write function and it will keep for years and years. You can also store the strings in program memory and recall when you need them.  There is a lot on this web site telling how to do this.
Good Luck & Have Fun!
Gil
Title: Re: Out of dynamic memory; what to do?
Post by: Athanassios on Nov 30, 2019, 06:16 pm
All that text.

Use the F() macro to put the text into PROGMEM. From this
Code: [Select]
lcd.print("something");
to
Code: [Select]
lcd.print(F("something"));
I would say thank you sir. Was looking for an answer and I ended up here. This F PROGMEM way saved my project. I freed a lot of memory and now I can move on finishing it on UNO !!!