Adafruit custom keypad / EEPROM issue

Adafruit custom keypad stops working when i save or recall eeprom ?!

Please read the forum guidelines.

Please post your properly formatted code in code tags. Use the IDE autoformat tool (ctrl-t or Tools, Auto format) before posting code in code tags.

Describe what the code actually does. "Code doesn't work" is not an adequate description. Describe how that is different from what you want.

Please post a schematic. Written descriptions are always more ambiguous than a drawing. Hand drawn, photographed and posted is fine. Include all pin names/numbers, components, their part numbers and/or values and power supplies.

1 Like

Thanks @groundFungus for your prompt guidance, actually code is a bit lenghthy and may not be upto proper standards. Its a microwave oven controller I am working on. I have used a Graphic LCD, 8X30 keypad, MAX6675 thermocouple interface, two relays and an optocoupler ... Full schematic is attached herewith

All things are working okay so far as I dont use EEPROM commands.
Complete code is here.
(I am using custom designed PCB with ATMEGA328P as in Arduino UNO.)

#include <Arduino.h>
#include <U8g2lib.h>
#include "max6675.h"
#include <EEPROM.h>

#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif

#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif

#include "Adafruit_Keypad.h"

#define door_sw 9  // oven door switch, active low
#define drive_out 10 // magnetron drive output
#define buzzer  8   // acaustic buzzer drive output

#define heater_out  2 // heater drive relay
#define setpoint 40  // pre heat setpoint
#define diff 5  // operating differential

unsigned long currentMillis, startMillis, period = 1000;
byte warm_up_time = 15; // preheat / warm up delay time, 15 seconds
byte stepp = 0;
bool door_sw_state;
byte item = 0;
int a;

int thermoDO = A3;
int thermoCS = A4;
int thermoCLK = A5;
int temperature;

MAX6675 thermocouple(thermoCLK, thermoCS, thermoDO);

const char *names[] = {
  "PIZZA",
  "SANDWICH",
  "PASTA",
  "BREAD"
};

const byte ROWS = 3; // rows
const byte COLS = 8; // columns
//define the symbols on the buttons of the keypads

char keys[ROWS][COLS] = {
  {'D', 'B', '-', ' ', '1', '4', '<', '7'},
  {'C', 'G', '.', 'F', '2', '5', '0', '8'},
  {'A', 'H', '+', 'E', '3', '6', '>', '9'}
};

byte rowPins[ROWS] = {5, 4, 3}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {7, 6, A0, A1, 1, 0, A2, A3}; //connect to the column pinouts of the keypad


//initialize an instance of class NewKeypad
Adafruit_Keypad customKeypad = Adafruit_Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS);


// item timings
signed int item_minutes[] {
  0, 0, 0, 1 
};
signed int item_seconds[] {
  15, 30, 45, 25 
};


//U8G2_ST7920_128X64_F_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* CS=*/ 10); // , /* reset=*/ 8
U8G2_ST7920_128X64_F_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* CS=*/ 12); // , /* reset=*/ 8 // 

void save_eeprom(){
  int i, j;
for(i=0; i<=3; i++){
  EEPROM.write(i, item_minutes[i]);
  delay(20);
  }
for(j=5; j<=8; j++){
  EEPROM.write(j, item_seconds[j-5]);
  delay(20);
  }
}

void recall_eeprom(){
  int i, j;
for(i=0; i<=3; i++){
  item_minutes[i] = EEPROM.read(i);
  delay(20);
  }
for(j=5; j<=8; j++){
  item_seconds[j] = EEPROM.read(j-5);
  delay(20);
  }
}
// heater drive
void heater_on() {
  digitalWrite(heater_out, HIGH);
}
void heater_off() {
  digitalWrite(heater_out, LOW);
}

// megnerton drive
void drive_on() {
  digitalWrite(drive_out, HIGH);
}
void drive_off() {
  digitalWrite(drive_out, LOW);
}

// keyboard click sound
void pip() {
  digitalWrite(buzzer, HIGH);
  delay(50);
  digitalWrite(buzzer, LOW);
}

// step1 warming up / pre-heating 
void show_warm_up() {
  u8g2.clearBuffer();
  u8g2.drawStr(80, 5, "PRE-HEAT"); // top
  u8g2.setCursor(60, 5);
  u8g2.print("[");
  u8g2.print(setpoint);
  u8g2.print(" C]");
  u8g2.setCursor(40, 15);
  u8g2.print(temperature); 
  u8g2.print(" C");
  u8g2.sendBuffer();
  delay(500);
}

// step3 menu
void show_menu() {
  u8g2.clearBuffer();
  u8g2.setCursor(117, 0);
  u8g2.print(names[0]);
  u8g2.setCursor(81, 0);
  u8g2.print(names[1]);
  u8g2.setCursor(45, 0);
  u8g2.print(names[2]);
  u8g2.setCursor(9, 0);
  u8g2.print(names[3]);
  u8g2.sendBuffer();
  customKeypad.tick();
  while (customKeypad.available()) {
    keypadEvent e = customKeypad.read();
    if (customKeypad.isPressed('A')) {
      pip();
      item = 0;
      stepp = 4;
    }
    if (customKeypad.isPressed('B')) {
      pip();
      item = 1;
      stepp = 4;
    }
    if (customKeypad.isPressed('C')) {
      pip();
      item = 2;
      stepp = 4;
    }
    if (customKeypad.isPressed('D')) {
      pip();
      item = 3;
      stepp = 4;
    }
  }
}


// step4 syatem ready 
void show_ready() {
  u8g2.clearBuffer();
  u8g2.drawStr(117, 0, "EDIT");
  u8g2.drawStr(81, 0, "BACK");
  u8g2.setCursor(50, 5);
  u8g2.print(names[item]);
  u8g2.setCursor(32, 25);
  u8g2.print(item_minutes[item]);
  u8g2.print(':');
  u8g2.print(item_seconds[item]);
  u8g2.print(a);
  u8g2.drawStr(4, 30, "START"); 
  u8g2.sendBuffer();
  customKeypad.tick();
  while (customKeypad.available()) {
    keypadEvent e = customKeypad.read();
    if (customKeypad.isPressed('A')) {
      pip();
      stepp = 6;
    }
    if (customKeypad.isPressed('B')) {
      pip();
      stepp = 3;
    }
    if (customKeypad.isPressed('E')) {
      pip();
      drive_on();
      stepp = 5;
    }
  }
}


// step 5 show actual cooking process
void show_cooking() {
  u8g2.clearBuffer();
  u8g2.drawStr(100, 5, "COOKING");
  u8g2.setCursor(80, 5);
  u8g2.print(names[item]);
  u8g2.setCursor(40, 25);
  u8g2.print(item_minutes[item]);
  u8g2.print(':');
  u8g2.print(item_seconds[item]);
  u8g2.sendBuffer();
}


// step 6 show time editing mode
void edit_mode() {

  // recall timings from eeprom
//  recall_eeprom();
      
  u8g2.clearBuffer();
  u8g2.drawStr(100, 5, "EDIT");
  u8g2.setCursor(80, 5);
  u8g2.print(names[item]);
  u8g2.drawStr(40, 0, ">>");
  u8g2.setCursor(40, 25);
  u8g2.print(item_minutes[item]);
  u8g2.print(':');
  u8g2.print(item_seconds[item]);
  u8g2.sendBuffer();

  
  customKeypad.tick();
  while (customKeypad.available()) {
    keypadEvent e = customKeypad.read();
    if (customKeypad.isPressed('+')) {
      pip();
      item_seconds[item]++;
      if (item_seconds[item] > 59) {
        item_seconds[item] = 0;
        item_minutes[item]++;
        if (item_minutes[item] > 9)
          item_minutes[item] = 9;
      }

    }
    if (customKeypad.isPressed('-')) {
      pip();
      item_seconds[item]--;
      if (item_seconds[item] < 0) {
        item_seconds[item] = 59;
        if (item_minutes[item] > 0)
          item_minutes[item]--;
        else {
          item_minutes[item] = 0;
          item_seconds[item] = 0;
        }
      }
    }
    if (customKeypad.isPressed('>')) {
      pip();
      
      // update eeprom
//      save_eeprom();
      
      u8g2.drawStr(5, 0, "SAVED ...");
      u8g2.sendBuffer();
      pip();
      delay(2000);
      stepp = 4;
    }
    if (customKeypad.isPressed('<')) {
      pip();
      stepp = 3;
    }
  }
}
// door open warning
void warning() {
  u8g2.clearBuffer();
  digitalWrite(buzzer, HIGH);
  u8g2.drawStr(96, 5, "WARNING!");
  u8g2.drawStr(64, 5, "THE DOOR");
  u8g2.drawStr(32, 5, "IS OPEN");
  u8g2.sendBuffer();
  delay(500);
  digitalWrite(buzzer, LOW);
  u8g2.clearBuffer();
  u8g2.sendBuffer();
  delay(500);
}

//  warm_up procedure ... only performed on first start

void warm_up() {
  temperature = thermocouple.readCelsius();
  if(temperature < setpoint-diff){
    heater_on();
    show_warm_up();
  }
    else {
    heater_off();
    pip();
    stepp = 3;
    }
    delay(500);    
}

// waiting the door to be opened
void beep() {
  digitalWrite(buzzer, HIGH);
  delay(100);
  digitalWrite(buzzer, LOW);
  delay(100);
  digitalWrite(buzzer, HIGH);
  delay(100);
  digitalWrite(buzzer, LOW);
  delay(4000);
}

void test_screen(){
  u8g2.clearBuffer();
  u8g2.setCursor(5,5);
  u8g2.println(EEPROM.read(0));
  u8g2.setCursor(20,5);
  u8g2.println(EEPROM.read(1));
  u8g2.setCursor(35,5);
  u8g2.println(EEPROM.read(2));
  u8g2.setCursor(50,5);
  u8g2.println(EEPROM.read(3));
  u8g2.setCursor(65,5);
  u8g2.println(EEPROM.read(5));
  u8g2.setCursor(80,5);
  u8g2.println(EEPROM.read(6));
  u8g2.setCursor(95,5);
  u8g2.println(EEPROM.read(7));
  u8g2.setCursor(110,5);
  u8g2.println(EEPROM.read(8));
  u8g2.sendBuffer();
  delay(2000);
  stepp = 3;
  }

  
void setup(void) {
  u8g2.begin();
  u8g2.setContrast(64);
  pinMode(door_sw, INPUT_PULLUP);   // door switch input
  
  pinMode(heater_out, OUTPUT); // heater output
  pinMode(drive_out, OUTPUT); // magnetron drive output
  pinMode(buzzer, OUTPUT);  // alarm buzzer output
  
  digitalWrite(heater_out, LOW); // heater relay initially off
  digitalWrite(drive_out, LOW); // magnetron drive relay initially off
  digitalWrite(buzzer, LOW);  // alarm buzzer initially off

  u8g2.clearBuffer();
//  u8g2.setFont(u8g2_font_lastapprenticebold_te);
  u8g2.setFont(u8g2_font_6x10_tf);
  u8g2.setFontPosCenter();
  u8g2.setFontDirection(1);
  
  customKeypad.begin();
  pip();
  
  save_eeprom();
  recall_eeprom();

//  stepp = 1;
test_screen();
}

void loop(void) {

  
  a=a+1;
  door_sw_state = !digitalRead(door_sw);

  if (door_sw_state) {
//    if (stepp == 2) test_screen();
    if (stepp == 1) warm_up();
    if (stepp == 3) show_menu();
    if (stepp == 4) show_ready();
    if (stepp == 6) edit_mode();


    // cooking screen
    if (stepp == 5) {
      show_cooking();

      currentMillis = millis();
      if (currentMillis - startMillis >= period)  //test whether the period 1000ms) has elapsed
      {
        item_seconds[item]--;
        startMillis = currentMillis; 
      }
      if (item_seconds[item] < 0) {
        item_seconds[item] = 59;
        item_minutes[item]--;
        if (item_minutes[item] < 0) {
          item_minutes[item] = 0;
          item_seconds[item] = 0;
          drive_off();
          u8g2.drawStr(9, 18, "DONE !");
          u8g2.sendBuffer();
          beep();
        }
      }
    }
  }
  else {
    warning();
    if (door_sw_state == LOW) {
      drive_off();
      
//      recall_eeprom();

//      item_minutes[0] = 0;
//      item_minutes[1] = 0;
//      item_minutes[2] = 0;
//      item_minutes[3] = 1;
//
//      item_seconds[0] = 15;
//      item_seconds[1] = 30;
//      item_seconds[2] = 45;
//      item_seconds[3] = 25;

      stepp = 3;
    }
  }
}

So what happens when you include the EEPROM library? "Quits working" conveys no useful information.

What are the amounts of memory reported as used when you compile the code?

1 Like

EEPROM library is already included. System hangs on, no keys working ...
The following warning is shown on compiling, but I ignored it because I am adding nothing further to RAM

"Sketch uses 14144 bytes (43%) of program storage space. Maximum is 32256 bytes.
Global variables use 1850 bytes (90%) of dynamic memory, leaving 198 bytes for local variables. Maximum is 2048 bytes.
Low memory available, stability problems may occur."

Perhaps that's unwise. How much memory do you think is being used by local (stack) variables at a given time? Do any of the libraries use dynamical allocation?

1 Like

That memory reported at compile time is only the global variables. It does not (and can not) measure how much memory is used by local variables.

you may want to check to see how much memory is being used at run time. See this Adafruit page.

1 Like

I think most of the memory is being used by <U8g2lib.h>, although I am using only text on the display.
I know nothing about "dynamical allocation" ...
I have come to a conclusion so far (may be wrong !) that when I write to or read from EEPROM, it keeps on running in a loop. Please look the problem this way ...

Very few local variables, I think.

When you start having stack / heap collisions and other memory issues, the only way to look at the problem is that it's Undefined Behavior. There is no logical way to analyze or solve the problem. The only thing you can do is reduce memory use or move to a platform with more memory.

1 Like

Your problem is almost certainly a lack of RAM. Use the Adafruit function @groundFungus suggested to find out for sure. The EEPROM stuff is just a symptom I suspect.

1 Like

Thanks for this ... I will let you know after going through this page.

Thanks a lot !
I will come back after going through all this.

You may want to look into the U8x8 library that is included with the U8g2 library. The U8x8 library uses less memory, but the font size is limited.

U8x8

Text output only (character) device.
Only fonts allowed with fit into a 8x8 pixel grid.
Writes directly to the display. No buffer in the microcontroller required.

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.