Saving an unsigned long int to internal EEPROM

Similar compiler warnings, what do I do?

GautamD:
Similar compiler warnings, what do I do?

INSTALL THE LIBRARY!!!

Sketch -> Include Library -> Manage Libraries

type EEPROM into the search and select the EEPROM library.

It shows installed.

which version of the IDE are you using?

Have you installed another library called EEPROM?

So because I also benefit from this thread, I learn new things everyday :D, so I make a simple sketch that almost simulate what you need to write values to eeprom. I hope you take your time to examine my code and understand it. It might not be the best, but explanation in my code should get you idea. You just need to apply that idea to your OWN CODE.

I don't have 4x4 keypad, so I had to use Proteus to simulate the code and 3x4 keypad. The concept is still the same regardless of what keypad I use as long the library is same. It works in Proteus, and should also work in real hardware given the wiring is correct.

A brief of how the program works:

'*' is used to save our long value to EEPROM

'#' is used to read back our EEPROM

Other value (0-9) is used to store a digit into a C-string buffer. This buffer is converted into a long value by using atol.

The rest is in my code.

#include <Keypad.h>
#include <EEPROM.h>

#define SIZEOFBUFFER   10

const byte ROWS = 4; //four rows
const byte COLS = 3; //three columns
char keys[ROWS][COLS] = {
  {'1', '2', '3'},
  {'4', '5', '6'},
  {'7', '8', '9'},
  {'*', '0', '#'}
};
byte rowPins[ROWS] = {5, 4, 3, 2}; //connect to the row pinouts of the kpd
byte colPins[COLS] = {8, 7, 6}; //connect to the column pinouts of the kpd

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

byte keyBuffer[SIZEOFBUFFER];
int keyIndex = 0;
unsigned long largeValue; //your so desired long value

void setup() {
  Serial.begin(9600);
}

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

  if (key != NO_KEY)
  {
    switch (key)
    {
      case '*':
        largeValue = atol(keyBuffer);
        Serial.println("is our long value correct?");
        Serial.println(largeValue);
        Serial.println("correct, so now lets write to eeprom");
        EEPROM.put(0, largeValue);
        Serial.println("written...");
        Serial.println("clear our long value for next use....");
        largeValue = 0; // reset our long value for our next use
        Serial.println(largeValue);
        break;

      case '#':
        Serial.println("let's read out eeprom to check if we write the correct long value");
        EEPROM.get(0, largeValue);
        Serial.println(largeValue);
        break;

      default:
        {
          Serial.write(key);
          keyBuffer[keyIndex++] = key;
          break;
        }
    }
  }
}

Ask if there's confusion, I really hope you get the idea...

EDIT: In case you need a version without using atol...use this one. The commented out part is the one that uses atol

#include <Keypad.h>
#include <EEPROM.h>

#define SIZEOFBUFFER   10

const byte ROWS = 4; //four rows
const byte COLS = 3; //three columns
char keys[ROWS][COLS] = {
  {'1', '2', '3'},
  {'4', '5', '6'},
  {'7', '8', '9'},
  {'*', '0', '#'}
};
byte rowPins[ROWS] = {5, 4, 3, 2}; //connect to the row pinouts of the kpd
byte colPins[COLS] = {8, 7, 6}; //connect to the column pinouts of the kpd

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

byte keyBuffer[SIZEOFBUFFER];
int keyIndex = 0;
unsigned long largeValue; //your so desired long value

void setup() {
  Serial.begin(9600);
}

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

  if (key != NO_KEY)
  {
    switch (key)
    {
      case '*':

        /*largeValue = atol(keyBuffer);
        Serial.println("is our long value correct?");
        Serial.println(largeValue);
        Serial.println("correct, so now lets write to eeprom");
        EEPROM.put(0, largeValue);
        Serial.println("written...");
        Serial.println("clear our long value for next use....");
        largeValue = 0; // reset our long value for our next use
        Serial.println(largeValue);*/

        Serial.println();
        Serial.println("writing to eeprom without atol conversion. we write the byte directly");
        for(int i = 0; i < keyIndex; i++)
        {
          EEPROM.put(i, keyBuffer[i]);
        }
        Serial.println("write done so clear our keyBuffer for next use");
        keyBuffer[0] = '\0';
        
        break;

      case '#':
        Serial.println("let's read our eeprom to check if we write the correct long value");

        /*EEPROM.get(0, largeValue);
        Serial.println(largeValue);*/

        for(int i = 0; i < keyIndex; i++)
        {
          Serial.write(EEPROM.get(i, keyBuffer[i]));
        }
        
        break;

      default:
          Serial.write(key);
          keyBuffer[keyIndex++] = key;
          break;
    }
  }
}

BulldogLowell:
which version of the IDE are you using?

IDE version 1.8.3

BulldogLowell:
Have you installed another library called EEPROM?

Is there?
Mine is built in, by christopher andrews version 2.0

I'm getting similar compiler warnings with built-in EEPROM examples as well. How do I get rid of it?

I'm getting similar compiler warnings with built-in EEPROM examples as well. How do I get rid of it?

Similar to what? Is it so difficult for you to understand that we can NOT see your computer?

I got rid of the compiler warnings. Code now compiles without warnings or errors. Could I get some more help with my code?

Could I get some more help with my code?

Come on. You KNOW the drill. Post the code you currently have. Explain what it actually does. Explain how that differs from what you want.

Or quit posting. Your choice.

#include <EEPROM.h>
#include <Wire.h>
#include <hd44780.h>                       // main hd44780 header
#include <hd44780ioClass/hd44780_I2Cexp.h> // i2c expander i/o class header

hd44780_I2Cexp lcd; // declare lcd object: auto locate & config exapander chip

// LCD geometry
const int LCD_COLS = 16;
const int LCD_ROWS = 2;

#include <Keypad.h>

const byte ROWS = 4; //four rows
const byte COLS = 4; //three columns
char keys[ROWS][COLS] = 
{
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {6, 7, 8, 9}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {5, 4, 12, 11}; //connect to the column pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
bool a = true;
unsigned long count;

void setup()
{
  Serial.begin(115200);
  lcd.begin(LCD_COLS, LCD_ROWS);
  lcd.setCursor(3, 0);
  lcd.print("  PRIYA");
  lcd.setCursor(3, 1);
  lcd.print("ELECTRONICS");
  delay(100);
  for (int positionCounter = 0; positionCounter < 40; positionCounter++)
  {
    lcd.scrollDisplayLeft();
    delay(120);
  }
  delay(800);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Set Count:");
  lcd.setCursor(11, 0);
  lcd.print(EEPROM.get(0, count)); // <<<<<<<<< read from EEPROM here
}

void loop()
{
  const byte entryMaxSize = 5;
  static char digits[entryMaxSize + 1];
  static byte x; // index

  char key = keypad.getKey();

  if (key != NO_KEY) // Check for a valid key.
  {
    switch (key)
    {
      case 'A':
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Set Count:");
        lcd.setCursor(11, 0);
  lcd.print(EEPROM.get(0, count)); // <<<<<<<<< read from EEPROM here
        x = 0; // reset the counter
        a = true;
        break;

      case 'D':
        if (a) 
        {
          if (x == 0)
          {
            invalidCount();
          }
          else 
          {
            lcd.clear();
            lcd.print("Count Set:");
            for (byte i = 0; i < x; i++) 
            {
              lcd.print(digits[i]);
              a = false;
            }
             count = atol(digits);
             EEPROM.put(0, count); // <<<<<<<<< save to EEPROM here
             Serial.print(count);
          }
        }
        break;

      default:
        if (a)
        {
          // if not 5 characters yet
          if (x < entryMaxSize)
          {
            // add key to userinput array and increment counter
            if ( key >= '0' && key <= '9' ) // key is of type char and has a value between 0 and 9 so do something with it.
            {
              digits[x++] = key;
              digits[x] = '\0';
              lcd.print( key ) ;  // new print statement <<<<<<<<<<<<<<<<
            }
          }
          else 
          {
            countWarning();
          }
        }
        break;
    }
  }
}



void invalidCount()
{
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Invalid Count!!");
  lcd.setCursor(0, 1);
  lcd.print("Press A"); // suggesting the user to enter the count again
  a = false;
}

void countWarning()
{
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("5 Digits Only!!"); // warning for the user if more than permitted digits are entered
  lcd.setCursor(0, 1);
  lcd.print("Press A"); // suggesting the user to enter the count again
  a = false;
}

On power on, set count shows the number that was saved last time. On pressing 'A' to set a new count it shows Set Count: whatever number was stored at the latest. If a three digit number was stored it shows Set Count: xxx and if I try to enter a new number, instead of replacing those digits it lets me print in the remaining places. For example if the new number to be entered is 666, then Set Count: xxx66. Only on pressing the enter key 'D' I am able to view the set count.

digits[x] = '\0';
lcd.print( key ) ; // new print statement <<<<<<<<<<<<<<<<

Where will the LCD cursor be before you print key for the first time ? Will it by any chance be at the end of the stored number printed previously ?

UKHeliBob:
Where will the LCD cursor be before you print key for the first time ? Will it by any chance be at the end of the stored number printed previously ?

Yes Bob, the new key that I enter starts to print from the end of the previously stored count.

If you do not press a key, loop() does nothing. It does NOT display the stored value of count anywhere.

It does that only if you press the 'A' key.

       x = 0; // reset the counter

It would not be necessary to have a comment if you used a meaningful name for the variable. One letter names are rarely meaningful, except in short for loops.

       a = true;

I can't even guess at what a means. This variable DEFINITELY needs a new name.

             lcd.print( key ) ;  // new print statement <<<<<<<<<<<<<<<<

But, where have you told the LCD to print this character? By default, it will print right after the last character printed. Since the last thing you printed was "Set Count: nnn", the character will go after the n.

I suspect that you need a "clear" key, to clear the displayed value, put the cursor after the space after the colon, print 5 spaces, put the cursor back after the space after the colon, AND set x (with it's new, better name) to 0.

Yes Bob, the new key that I enter starts to print from the end of the previously stored count.

You know how to position the cursor to print it where you want. Note that there is a trap here for the unwary. Can you see what it is ?

UKHeliBob:
You know how to position the cursor to print it where you want. Note that there is a trap here for the unwary. Can you see what it is ?

I'm not getting it. Will the new key I'm trying to enter overlap some of the digits in the previously set count value instead of replacing them?

#include <EEPROM.h>
#include <Wire.h>
#include <hd44780.h>                       // main hd44780 header
#include <hd44780ioClass/hd44780_I2Cexp.h> // i2c expander i/o class header

hd44780_I2Cexp lcd; // declare lcd object: auto locate & config exapander chip

// LCD geometry
const int LCD_COLS = 16;
const int LCD_ROWS = 2;

#include <Keypad.h>

const byte ROWS = 4; //four rows
const byte COLS = 4; //three columns
char keys[ROWS][COLS] = 
{
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {6, 7, 8, 9}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {5, 4, 12, 11}; //connect to the column pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
bool a = true;
unsigned long count;

void setup()
{
  Serial.begin(115200);
  lcd.begin(LCD_COLS, LCD_ROWS);
  lcd.setCursor(3, 0);
  lcd.print("  PRIYA");
  lcd.setCursor(3, 1);
  lcd.print("ELECTRONICS");
  delay(100);
  for (int positionCounter = 0; positionCounter < 40; positionCounter++)
  {
    lcd.scrollDisplayLeft();
    delay(120);
  }
  delay(800);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Set Count:");
  lcd.setCursor(11, 0);
  lcd.print(EEPROM.get(0, count)); // <<<<<<<<< read from EEPROM here
}

void loop()
{
  const byte entryMaxSize = 5;
  static char digits[entryMaxSize + 1];
  static byte index;

  char key = keypad.getKey();

  if (key != NO_KEY) // Check for a valid key.
  {
    switch (key)
    {
      case 'A':
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Set Count:");
        lcd.setCursor(11, 0);
  lcd.print(EEPROM.get(0, count)); // <<<<<<<<< read from EEPROM here
        index = 0;
        a = true;
        break;

      case 'D':
        if (a) 
        {
          if (index == 0)
          {
            invalidCount();
          }
          else 
          {
            lcd.clear();
            lcd.print("Count Set:");
            for (byte i = 0; i < index; i++) 
            {
              lcd.print(digits[i]);
              a = false;
            }
             count = atol(digits);
             EEPROM.put(0, count); // <<<<<<<<< save to EEPROM here
             Serial.print(count);
          }
        }
        break;

      default:
        if (a)
        {
          // if not 5 characters yet
          if (index < entryMaxSize)
          {
            // add key to userinput array and increment counter
            if ( key >= '0' && key <= '9' ) // key is of type char and has a value between 0 and 9 so do something with it.
            {
              digits[index++] = key;
              digits[index] = '\0';
              lcd.setCursor(11,0);
              lcd.print( key ) ;  // new print statement <<<<<<<<<<<<<<<<
            }
          }
          else 
          {
            countWarning();
          }
        }
        break;
    }
  }
}



void invalidCount()
{
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Invalid Count!!");
  lcd.setCursor(0, 1);
  lcd.print("Press A"); // suggesting the user to enter the count again
  a = false;
}

void countWarning()
{
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("5 Digits Only!!"); // warning for the user if more than permitted digits are entered
  lcd.setCursor(0, 1);
  lcd.print("Press A"); // suggesting the user to enter the count again
  a = false;
}

When I try this only the first digit from the previously set count is replaced while entering the new keys and the new count is only printed after I press the enter key.

Will the new key I'm trying to enter overlap some of the digits in the previously set count value instead of replacing them?

I did say that there was a trap for the unwary and you just fell into it.

Do you have any code saying "I am about to print the number entered by the user so it would be a good idea to clear the previous number from the screen" ?

Answer : no.

Print spaces over the stored number displayed on the LCD before you start printing the new number.

#include <EEPROM.h>
#include <Wire.h>
#include <hd44780.h>                       // main hd44780 header
#include <hd44780ioClass/hd44780_I2Cexp.h> // i2c expander i/o class header

hd44780_I2Cexp lcd; // declare lcd object: auto locate & config exapander chip

// LCD geometry
const int LCD_COLS = 16;
const int LCD_ROWS = 2;

#include <Keypad.h>

const byte ROWS = 4; //four rows
const byte COLS = 4; //three columns
char keys[ROWS][COLS] =
{
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {6, 7, 8, 9}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {5, 4, 12, 11}; //connect to the column pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
bool a = true;
unsigned long count;

void setup()
{
  Serial.begin(115200);
  lcd.begin(LCD_COLS, LCD_ROWS);
  lcd.setCursor(3, 0);
  lcd.print("  PRIYA");
  lcd.setCursor(3, 1);
  lcd.print("ELECTRONICS");
  delay(100);
  for (int positionCounter = 0; positionCounter < 40; positionCounter++)
  {
    lcd.scrollDisplayLeft();
    delay(120);
  }
  delay(800);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Set Count:");
  lcd.setCursor(11, 0);
  lcd.print(EEPROM.get(0, count)); // <<<<<<<<< read from EEPROM here
}

void loop()
{
  const byte entryMaxSize = 5;
  static char digits[entryMaxSize + 1];
  static byte index;

  char key = keypad.getKey();

  if (key != NO_KEY) // Check for a valid key.
  {
    switch (key)
    {
      case 'A':
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Set Count:");
        lcd.setCursor(11, 0);
        lcd.print(EEPROM.get(0, count)); // <<<<<<<<< read from EEPROM here
        //lcd.clear();
        index = 0;
        a = true;
        break;

      case 'D':
        if (a)
        {
          if (index == 0)
          {
            invalidCount();
          }
          else
          {
            lcd.clear();
            lcd.print("Count Set:");
            for (byte i = 0; i < index; i++)
            {
              lcd.print(digits[i]);
              a = false;
            }
            count = atol(digits);
            EEPROM.put(0, count); // <<<<<<<<< save to EEPROM here
            Serial.print(count);
          }
        }
        break;

      default:
        if (a)
        {
          // if not 5 characters yet
          if (index < entryMaxSize)
          {
            // add key to userinput array and increment counter
            if ( key >= '0' && key <= '9' ) // key is of type char and has a value between 0 and 9 so do something with it.
            {
              digits[index++] = key;
              digits[index] = '\0';
              static char lastKey = -1;
              if (key != lastKey)
              {
                lcd.clear();
                char displayText[18] = "";
                snprintf(displayText, sizeof(displayText), "Set Count:%5d", key - '0');
                lcd.setCursor(0, 0);
                lcd.print(displayText);
              }
              //lcd.print( key ) ;  // new print statement <<<<<<<<<<<<<<<<
            }
          }
          else
          {
            countWarning();
          }
        }
        break;
    }
  }
}



void invalidCount()
{
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Invalid Count!!");
  lcd.setCursor(0, 1);
  lcd.print("Press A"); // suggesting the user to enter the count again
  a = false;
}

void countWarning()
{
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("5 Digits Only!!"); // warning for the user if more than permitted digits are entered
  lcd.setCursor(0, 1);
  lcd.print("Press A"); // suggesting the user to enter the count again
  a = false;
}

While setting the count, instead of the digits printing from right to left as I enter them, they change at one position only i.e. the second last position on the lcd display i.e. the 15th column.

instead of the digits printing from right to left as I enter them, they change at one position

                lcd.clear();
                char displayText[18] = "";
                snprintf(displayText, sizeof(displayText), "Set Count:%5d", key - '0');
                lcd.setCursor(0, 0);
                lcd.print(displayText);

No wonder that you only get one character, because you have cleared the LCD. Don't clear the LCD, just remove the number previously displayed by positioning the cursor and printing " " over it, then reposition the cursor and print the digits string that you just added a digit to

Would you help me with the corrections to the code? I'm trying but I'm not able to get the keys to print it the way I want.