Problem with EEPROM write after converting string to int

Problem with EEPROM writing

Hi I have been trying to make this code where it simulates a bank account on an Arduino nano. I have a Atmega328P (old bootloader). My code is shown below. I am getting this error that says:

C:\Users\palla\Documents\Arduino\Cash_Register\Cash_Register.ino: In function 'void account()':
C:\Users\palla\Documents\Arduino\Cash_Register\Cash_Register.ino:58:28: error: no matching function for call to 'EEPROMClass::get(int&)'
   money = EEPROM.get(actnum);
                            ^
In file included from C:\Users\palla\Documents\Arduino\Cash_Register\Cash_Register.ino:4:0:
C:\Users\palla\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\libraries\EEPROM\src/EEPROM.h:130:31: note: candidate: template<class T> T& EEPROMClass::get(int, T&)
     template< typename T > T &get( int idx, T &t ){
                               ^~~
C:\Users\palla\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\libraries\EEPROM\src/EEPROM.h:130:31: note:   template argument deduction/substitution failed:
C:\Users\palla\Documents\Arduino\Cash_Register\Cash_Register.ino:58:28: note:   candidate expects 2 arguments, 1 provided
   money = EEPROM.get(actnum);
                            ^
C:\Users\palla\Documents\Arduino\Cash_Register\Cash_Register.ino:63:17: error: invalid operands of types 'const char [2]' and 'float' to binary 'operator+'
   lcd.print("$" + money);
             ~~~~^~~~~~~
C:\Users\palla\Documents\Arduino\Cash_Register\Cash_Register.ino: In function 'void charge(float)':
C:\Users\palla\Documents\Arduino\Cash_Register\Cash_Register.ino:77:28: error: no matching function for call to 'EEPROMClass::get(int&)'
   money = EEPROM.get(actnum);
                            ^
In file included from C:\Users\palla\Documents\Arduino\Cash_Register\Cash_Register.ino:4:0:
C:\Users\palla\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\libraries\EEPROM\src/EEPROM.h:130:31: note: candidate: template<class T> T& EEPROMClass::get(int, T&)
     template< typename T > T &get( int idx, T &t ){
                               ^~~
C:\Users\palla\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\libraries\EEPROM\src/EEPROM.h:130:31: note:   template argument deduction/substitution failed:
C:\Users\palla\Documents\Arduino\Cash_Register\Cash_Register.ino:77:28: note:   candidate expects 2 arguments, 1 provided
   money = EEPROM.get(actnum);
                            ^
C:\Users\palla\Documents\Arduino\Cash_Register\Cash_Register.ino:86:5: error: 'bob' was not declared in this scope
     bob = String(actnum) + k.getKey();
     ^~~

exit status 1

Compilation error: no matching function for call to 'EEPROMClass::get(int&)'
#include <Keypad.h>
#include <LiquidCrystal_I2C.h>
#include <Wire.h> 
#include <EEPROM.h>
LiquidCrystal_I2C lcd(0x27,16,2);

float money;

int i=0;
const char number_of_rows = 4;
const char number_of_columns = 4;

char row_pins[number_of_rows] = {2, 3, 4, 5};
char column_pins[number_of_columns] = {6, 7, 8, 9};

char key_array[number_of_rows][number_of_columns] = {  
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
  };

Keypad k = Keypad(makeKeymap(key_array),row_pins , column_pins, number_of_rows, number_of_columns);
char key_pressed;
void setup()
{
  Serial.begin(9600);
  lcd.begin(16,2);                     
  lcd.backlight();
  lcd.setBacklight(HIGH);
}

void loop()
{
  key_pressed = k.getKey();
  if(key_pressed)
  {
    if(key_pressed == "B"){
      account();
    }
    if(key_pressed == "C"){

    }
  }
}
void account(){
  int actnum;
  lcd.setCursor(0,0);
  lcd.print("Enter Account ID: ");
  lcd.setCursor(0,1);
  while(k.getKey()!='#'){
    if(k.getKey() != '#'){
    lcd.print(k.getKey());
    String bob = String(actnum) + k.getKey();
    actnum = bob.toInt();
    }
  }
  money = EEPROM.get(actnum);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Account Balance: ");
  lcd.setCursor(0, 1);
  lcd.print("$" + money);
}
void charge (float amount){
  int actnum;
  lcd.setCursor(0,0);
  lcd.print("Enter Account ID: ");
  lcd.setCursor(0,1);
  while(k.getKey()!='#'){
    if(k.getKey() != '#'){
    lcd.print(k.getKey());
     String bob = String(actnum) + k.getKey();
    actnum = bob.toInt();
    }
  }
  money = EEPROM.get(actnum);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Charge Amount: ");
  lcd.setCursor(0, 1);
  float amt;
  while(k.getKey()!='#'){
    if(k.getKey() != '#'){
    lcd.print(k.getKey());
    bob = String(actnum) + k.getKey();
    amt = bob.toInt();
    }
  }
  money = money+amt;
  EEPROM.write(actnum, money);
}

Can you please tell my how to fix this problem and what i can do to make it better?

sintaxe wrong.

Correct : EEPROM.get(actnum, money );

Wrong too: lcd.print("$" + money);
Correct: Concatenate before pint command.

There is more errors.

Change this

to this:

  lcd.print("$");
  lcd.print(money);

AVOID using Strings on an ATmega Arduino. They cause memory problems and program crashes. There are much better ways of inputting a number from the keypad, and plenty of tutorials on line that show you how.

Thanks I get no more errors while uploading, but nothing shows up on the screen (lcd)... Is there any keypad syntax I am missing? My wiring is simple, an i2c bus connected to ground, vcc, a4, and a5, and a keypad connected from pin 2 to pin 9.

For questions about code and wiring, post the code, using code tags, and a wiring diagram, with pins and connections clearly labeled. Hand drawn is fine.

I think you can find the code above in my first post but here, ill post it again:

#include <Keypad.h>
#include <LiquidCrystal_I2C.h>
#include <Wire.h> 
#include <EEPROM.h>
LiquidCrystal_I2C lcd(0x27,16,2);

float money;

int i=0;
const char number_of_rows = 4;
const char number_of_columns = 4;

char row_pins[number_of_rows] = {2, 3, 4, 5};
char column_pins[number_of_columns] = {6, 7, 8, 9};

char key_array[number_of_rows][number_of_columns] = {  
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
  };

Keypad k = Keypad(makeKeymap(key_array),row_pins , column_pins, number_of_rows, number_of_columns);
char key_pressed;
void setup()
{
  Serial.begin(9600);
  lcd.begin(16,2);                     
  lcd.backlight();
  lcd.setBacklight(HIGH);
}

void loop()
{
  key_pressed = k.getKey();
  if(key_pressed)
  {
    if(key_pressed == "B"){
      account();
    }
    if(key_pressed == "C"){

    }
  }
}
void account(){
  int actnum;
  lcd.setCursor(0,0);
  lcd.print("Enter Account ID: ");
  lcd.setCursor(0,1);
  while(k.getKey()!='#'){
    if(k.getKey() != '#'){
    lcd.print(k.getKey());
    String bob = String(actnum) + k.getKey();
    actnum = bob.toInt();
    }
  }
  EEPROM.get(actnum, money);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Account Balance: ");
  lcd.setCursor(0, 1);
  lcd.print("$ ");
  lcd.print(money);
}
void charge (float amount){
  int actnum;
  lcd.setCursor(0,0);
  lcd.print("Enter Account ID: ");
  lcd.setCursor(0,1);
  while(k.getKey()!='#'){
    if(k.getKey() != '#'){
    lcd.print(k.getKey());
     String bob = String(actnum) + k.getKey();
    actnum = bob.toInt();
    }
  }
  money = EEPROM.get(actnum, money);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Charge Amount: ");
  lcd.setCursor(0, 1);
  float amt;
  while(k.getKey()!='#'){
    if(k.getKey() != '#'){
    lcd.print(k.getKey());
    String bob = String(actnum) + k.getKey();
    amt = bob.toInt();
    }
  }
  money = money+amt;
  EEPROM.write(actnum, money);
}

Test the LCD with one of the LCD library examples, to make sure it is working.

Get rid of the Strings.

what do you mean by getting rid of the strings? is there a way to append a number to an existing integer?

Do NOT use Strings on AVR-based Arduinos. This kind of nonsense:

    String bob = String(actnum) + k.getKey();
    actnum = bob.toInt();

They cause program crashes, and are never necessary. You can find keypad example code that does not use Strings for number entry.

Run I2Cscanner e verify which LCD I2C address.
" Arduino Playground - I2cScanner

I have the correct i2c address in my code. I don't know what is wrong. Also @jremington, I have changed the code to where it has no strings. Here it is:

#include <Keypad.h>
#include <LiquidCrystal_I2C.h>
#include <Wire.h> 
#include <EEPROM.h>
LiquidCrystal_I2C lcd(0x27,16,2);

float money;

int i=0;
const char number_of_rows = 4;
const char number_of_columns = 4;

char row_pins[number_of_rows] = {2, 3, 4, 5};
char column_pins[number_of_columns] = {6, 7, 8, 9};

char key_array[number_of_rows][number_of_columns] = {  
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
  };

Keypad k = Keypad(makeKeymap(key_array),row_pins , column_pins, number_of_rows, number_of_columns);
char key_pressed;
void setup()
{
  Serial.begin(9600);
  lcd.begin(16,2);                     
  lcd.backlight();
  lcd.setBacklight(HIGH);
}

void loop()
{
  key_pressed = k.getKey();
  if(key_pressed)
  {
    if(key_pressed == "B"){
      account();
    }
    if(key_pressed == "C"){

    }
  }
}
void account(){
  int actnum;
  lcd.setCursor(0,0);
  lcd.print("Enter Account ID: ");
  lcd.setCursor(0,1);
  while(k.getKey()!='#'){
    if(k.getKey() != '#'){
    lcd.print(k.getKey());
    String bob = String(actnum) + k.getKey();
    actnum = bob.toInt();
    }
  }
  EEPROM.get(actnum, money);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Account Balance: ");
  lcd.setCursor(0, 1);
  lcd.print("$ ");
  lcd.print(money);
}
void charge (float amount){
  int actnum;
  lcd.setCursor(0,0);
  lcd.print("Enter Account ID: ");
  lcd.setCursor(0,1);
  while(k.getKey()!='#'){
    if(k.getKey() != '#'){
    lcd.print(k.getKey());
    actnum = actnum*10 + k.getKey();
    }
  }
  money = EEPROM.get(actnum, money);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Charge Amount: ");
  lcd.setCursor(0, 1);
  float amt;
  while(k.getKey()!='#'){
    if(k.getKey() != '#'){
    lcd.print(k.getKey());
    amt = amt*10+k.getKey();
    }
  }
  money = money+amt;
  EEPROM.write(actnum, money);
}

Can you please figure out what is wrong?

These are String operations, which poke holes in memory and cause program crashes.

if you run this (extracted from your code basically, removing all the other stuff)

#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);

void setup()
{
  Serial.begin(9600);
  lcd.begin(16, 2);
  lcd.backlight();
  lcd.setBacklight(HIGH);
  lcd.setCursor(0, 0);
  lcd.print("Enter Account ID: ");
}

void loop() {}

do you see something on screen.

1 Like

Yep, that works.

good so your screen is working. that's something :slight_smile:

Now, do you understand that by calling twice getKey() here, you lost the first key?

then think about what you test for

may be it was something like this you wanted to write ?

  char received = NO_KEY;
  do {
    received = k.getKey();
    if (received != '#') {
      lcd.print(k.getKey());
      String bob = String(actnum) + k.getKey();
      actnum = bob.toInt();
    }
  } while (received != '#');

(bad number input approach but you can fix that later)

ok i did a bunch of debug tests, and I found out that my code is breaking at the start during the if statements. I found out that with this code:

#include <Keypad.h>
#include <LiquidCrystal_I2C.h>
#include <Wire.h> 
#include <EEPROM.h>
LiquidCrystal_I2C lcd(0x27,16,2);

float money;

int i=0;
const char number_of_rows = 4;
const char number_of_columns = 4;

char row_pins[number_of_rows] = {2, 3, 4, 5};
char column_pins[number_of_columns] = {6, 7, 8, 9};

char key_array[number_of_rows][number_of_columns] = {  
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
  };

Keypad k = Keypad(makeKeymap(key_array),row_pins , column_pins, number_of_rows, number_of_columns);
char key_pressed;
void setup()
{
  Serial.begin(9600);
  lcd.begin(16,2);                     
  lcd.backlight();
  lcd.setBacklight(HIGH);
}

void loop()
{
  key_pressed = k.getKey();
  if(key_pressed)
  {
    if(k.getKeys() == "B"){
      Serial.print("b");
    }
    if(key_pressed == "C"){

    }
  }
}

If I run this code, it doesn't even work, however if I do the basic serial printing of the key pressed, then i get a good response. i can't figure out what is happening. can you figure it out please?

New problem with lcd:

Here is my code so far, if I press B, it calls the account function like expected, but then just displays a bunch of white lines... take a look:

#include <LiquidCrystal_I2C.h>
#include <Wire.h> 
#include <EEPROM.h>
LiquidCrystal_I2C lcd(0x27,16,2);

float money;

int i=0;
const char number_of_rows = 4;
const char number_of_columns = 4;

char row_pins[number_of_rows] = {2, 3, 4, 5};
char column_pins[number_of_columns] = {6, 7, 8, 9};

char key_array[number_of_rows][number_of_columns] = {  
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
  };

Keypad k = Keypad(makeKeymap(key_array),row_pins , column_pins, number_of_rows, number_of_columns);
char key_pressed;
void setup()
{
  Serial.begin(9600);
  lcd.begin(16,2);                     
  lcd.backlight();
  lcd.setBacklight(HIGH);
}

void loop()
{
  key_pressed = k.getKey();
  if(key_pressed != '\0'){ 
    if(key_pressed == 'B'){
      account();  
    }
    /*if(k.getKeys() == "B"){
      Serial.print("b");
    }
    if(key_pressed == "C"){

    }*/
  }
}

void account(){
  int actnum;
  lcd.setCursor(0,0);
  lcd.print("Enter Bank ID: ");
  lcd.setCursor(0,1);
    do {
    key_pressed = k.getKey();
    if (key_pressed != '#'||key_pressed != '\0') {
      lcd.print(key_pressed);
      actnum = actnum*10 + key_pressed;
    }
  } while (key_pressed != '#');
  /*
  EEPROM.get(actnum, money);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Account Balance: ");
  lcd.setCursor(0, 1);
  lcd.print("$ ");
  lcd.print(money);*/
}
void charge (float amount){
  int actnum;
  lcd.setCursor(0,0);
  lcd.print("Enter Account ID: ");
  lcd.setCursor(0,1);
  do {
    key_pressed = k.getKey();
    if (key_pressed != '#') {
      lcd.print(key_pressed);
      actnum = actnum*10 + key_pressed;
    }
  } while (key_pressed != '#');

  EEPROM.get(actnum, money);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Charge Amount: ");
  lcd.setCursor(0, 1);
  float amt;
  do {
    key_pressed = k.getKey();
    if (key_pressed != '#') {
      lcd.print(key_pressed);
      amt = amt*10 + key_pressed;
    }
  } while (key_pressed != '#');
  money = money+amt;
  EEPROM.write(actnum, money);
}

Now what is wrong? I expect the error to be in the account function itself.

Of course you should NOT call getKey multiple times

You should await for a key, memorize it and deal with it. Then read again.

That above line should be as follows; because, k.getKey() function returns a single character:
if(key_pressed == 'B'){

ok it works now, at least it is calling a function. the problem is that the lcd shows a bunch of lines after I press 'b'. Idk why that is happening. Here is the void i am calling:

void account(){
  int actnum;
  lcd.setCursor(0,0);
  lcd.print("Enter Bank ID: ");
  lcd.setCursor(0,1);
    do {
    key_pressed = k.getKey();
    if (key_pressed != '#'||key_pressed != '\0') {
      lcd.print(key_pressed);
      actnum = actnum*10 + key_pressed;
    }
  } while (key_pressed != '#');
  
  EEPROM.get(actnum, money);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Account Balance: ");
  lcd.setCursor(0, 1);
  lcd.print("$ ");
  lcd.print(money);