3

I am making a simple calculator with Arduino Uno R3. It only has +, -, x and /.

I use 3 libraries:

  1. This use for LCD with I2C module. Arduino-LiquidCrystal-I2C-library
  2. This use for keypad 4x4. Chris--A/Keypad
  3. And this: jamesgregson/expression_parser

My code:

#include "expression_parser.h"
#include <Keypad.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>


LiquidCrystal_I2C lcd(0x3F, 16, 2);

const byte ROWS = 4; 
const byte COLS = 4; 

char keys[ROWS][COLS] = {
  {'1', '2', '3', '+'},
  {'4', '5', '6', '-'},
  {'7', '8', '9', '*'},
  {'.', '0', '=', '/'}
};

byte rowPins[ROWS] = {10, 9, 8, 7}; 
byte colPins[COLS] = {6, 5, 4, 3}; 

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

String s = "";  
char ex[16];

void setup() {
  Serial.begin(9600);
  lcd.init();          
  lcd.backlight();      
  lcd.setCursor(0, 0);  
}

int cur = 0;
bool enter = false;

void loop() 
{
  char key = keypad.getKey();   

  if ((key != '=') && (key != NO_KEY) ) {
    if (!enter) {               
      Serial.println(F("key"));
      if(key=='/')
        lcd.print(F("':'"));
      else 
      if (key=='*')
        lcd.print(F("'x'"));
      else
        lcd.print(F("key"));
      s = s + key;              
      cur++;                    
      lcd.setCursor(cur, 0);    
    } else {                    

      lcd.setCursor(0, 0);      
      lcd.print("");
      enter = false;
      lcd.setCursor(0, 0);
      cur = 0;
      lcd.print(F("key"));
      s = "";
      s = s + key;
      cur++;
      lcd.setCursor(cur, 0);
    }
  } else if (key == '=') {    
    enter = true;

    if ((s[0] == '=') || (s[0] == '/') || (s[0] == '*') || (s[0] == '.')) {
      lcd.setCursor(0, 1);
      lcd.print("Error");
    } else {
      lcd.setCursor(0, 1);
      lcd.print("");
      s.toCharArray(ex, 16);
      Serial.println(F("s"));
      int re = parse_expression(ex); 
      String check = String(re);
      if (check.length() > 15) {
        lcd.setCursor(0, 1);
        lcd.print("Overflow");
      } else {
        Serial.println(re);
        lcd.setCursor(0, 1);
        lcd.print("=");
        lcd.print(F("re"));                
      }
    }
  }
}

I ran it and got error:

Global variables use 3302 bytes (161%) of dynamic memory, leaving -1254 bytes for local variables. Maximum is 2048 bytes. Not enough memory; see http://www.arduino.cc/en/Guide/Troubleshooting#size for tips on reducing your footprint. Error compiling for board Arduino/Genuino Uno.

So what should I do?

3
  • 4
    the expression parser uses a lot of ram, get rid of it. You're only doing 4 basic operations, so all you need to do is a small set of IF statements and parse the numbers themselves, which arduino can do without a big lib.
    – dandavis
    Oct 13, 2018 at 15:01
  • The most efficient system you can use is called "Reverse Polish Notation", or RPN. It's a stack-based system and can run very efficiently on systems with very very little memory. You just have to get used to how to enter the equations properly...
    – Majenko
    Oct 13, 2018 at 17:08
  • which Arduino board you are using? Oct 14, 2018 at 6:33

2 Answers 2

3

Your own declared global variables do not use up much space.

Watch out for using string, this can be extended during the flow of the program thus using more.

The problem is in the libraries.

What you can do:

  • Leave out the include and related code per library to see which is using up a lot of global space.
  • When you find out which causes problems, try to follow the internals of the library to see if there is some buffered memory that you can decrease.

If not, I'm afraid the only solution is to move to an Arduino with more memory (like the Arduino Mega which has 8 KB).

With the use of PROGMEM you can save some space on

char keys[ROWS][COLS] = {
  {'1', '2', '3', '+'},
  {'4', '5', '6', '-'},
  {'7', '8', '9', '*'},
  {'.', '0', '=', '/'}
};

byte rowPins[ROWS] = {10, 9, 8, 7}; 
byte colPins[COLS] = {6, 5, 4, 3}; 

Because it will be placed in Flash instead of SRAM, but it will save you just 24 bytes.

1
  • 2
    From a cursory look at those libraries, it seems to me that the expression parser eats a lot more RAM than the two others. It contains lots of error messages and code to deal with transcendental functions: things the OP does not have use of. Oct 13, 2018 at 19:58
-1

Move up to a '1284P based board. They have 16K of SRAM and 12 more IO pins, will give you plenty of room to add and expand into more functions later.

I offer '1284P boards in several form factors at www.crossroadsfencing.com/BobuinoRev17/

It is easy to add to the IDE with MCUdude's MegaCore https://github.com/MCUdude/MegaCore

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.