Waiting for an input

Hi,
I'm working on a project where I'm going to be saving some hours in the EEPROM.
The project has an RTC module, an LCD and a 4x4 keyboard. When I click on the letter A, the saving process needs to start. I have the following code that reads the current EEPROM values for bits 0 (hours) and 1 (minutes). If you know a better way to store/save/read hours and minutes, let me know, I'm pretty new.
The idea is that when you click A, you get the current saved hour and minute, then the cursor starts blinking waiting for input. I haven't worked out the full process yet, but I'm thinking of a loop to go through the 4 iterations (seconds don't apply here), so the cursor will be moving automatically and saving the input. Hence that for pointer = 0, it can only be 0, 1 or 2.
The main issue I'm facing out (and I think I can figure out the rest of the code if I can solve this) is that I can't seem to get out of the while loop that is there awaiting for a key input. It just stays there blinking without updating the time, even if I provide valid values. Any idea of what can I be doing wrong?

  if (key == 'A') {

    lcd.backlight();
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Hora inicio");
    lcd.setCursor(0, 1);
    lcd.print(EEPROM.read(0));
    lcd.setCursor(2, 1);
    lcd.print(":");
    lcd.setCursor(3, 1);
    lcd.print(EEPROM.read(1));
    lcd.setCursor(0, 1);
    char key = keypad.getKey();

    while (!key) {
      lcd.blink();
    }
    
    int pointer = 0;

    if ((!isDigit(key)) || ((pointer == 0) && (key > 2))) {
    } else {
      lcd.print(key);
    }
  }

Thank you

Fine that You used code tags. Please post the entire code, not a snippet.

It’s quite big, but ok… I’ve already added the loop in this version

#include <EEPROM.h>
#include <Keypad.h>
#include <Wire.h>
#include <RTClib.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 20, 4);

RTC_DS1307 rtc;

String daysOfTheWeek[7] = { "Domingo", "Lunes", "Martes", "Miercoles", "Jueves", "Viernes", "Sabado" };
String monthsNames[12] = { "Ene", "Feb", "Mar", "Abr", "May",  "Jun", "Jul", "Ago", "Sep", "Oct", "Nov", "Dic" };

const byte rowsCount = 4;
const byte columsCount = 4;

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

const byte rowPins[rowsCount] = { 4, 5, 6, 7 };
const byte columnPins[columsCount] = { 8, 9, 10, 11 };

Keypad keypad = Keypad(makeKeymap(keys), rowPins, columnPins, rowsCount, columsCount);

int rele = 12;
int ledrojo = 3;
int ledverde = 2;
int encendido = 0;
int activo = 1;

void setup() {
  Serial.begin(9600);
  pinMode(rele, OUTPUT);
  pinMode(ledverde, OUTPUT);
  pinMode(ledrojo, OUTPUT);

  lcd.init();                      // initialize the lcd
  //lcd.backlight();

#ifndef ESP8266
  while (!Serial); // wait for serial port to connect. Needed for native USB
#endif

  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    Serial.flush();
    abort();
  }

  if (! rtc.isrunning()) {
    Serial.println("RTC is NOT running, let's set the time!");
    // When time needs to be set on a new device, or after a power loss, the
    // following line sets the RTC to the date & time this sketch was compiled
    // rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
  }

}

void loop() {

  if (activo == 1) {
    lcd.setCursor(15, 0);
    lcd.print("*");
    if (encendido == 1) {
      digitalWrite(ledrojo, HIGH);
      digitalWrite(ledverde, LOW);
      digitalWrite(rele, HIGH);
    } else {
      digitalWrite(ledrojo, LOW);
      digitalWrite(ledverde, HIGH);
      digitalWrite(rele, LOW);
    }
  } else {
    digitalWrite(ledrojo, LOW);
    digitalWrite(ledverde, HIGH);
    lcd.setCursor(15, 0);
    lcd.print(" ");
  }

  DateTime now = rtc.now();

  char buf1[] = "DD/MM/YYYY";
  char buf2[] = "hh";
  char buf3[] = "mm";
  char buf4[] = "ss";

  lcd.setCursor(0, 0);
  lcd.print(now.toString(buf1));
  lcd.setCursor(0, 1);
  lcd.print(now.toString(buf2));
  lcd.setCursor(2, 1);
  lcd.print(":");
  lcd.setCursor(3, 1);
  lcd.print(now.toString(buf3));
  lcd.setCursor(5, 1);
  lcd.print(":");
  lcd.setCursor(6, 1);
  lcd.print(now.toString(buf4));

  char key = keypad.getKey();

  //   if (key) {
  //      Serial.println(key);
  //   }

  if (key == '*') {
    lcd.backlight();
    if (activo == 1) {
      activo = 0;
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("PROGRAMA");
      lcd.setCursor(0, 1);
      lcd.print("DESACTIVADO");
      delay(5000);
      lcd.clear();
    } else {
      activo = 1;
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("PROGRAMA");
      lcd.setCursor(0, 1);
      lcd.print("ACTIVADO");
      delay(5000);
      lcd.clear();
    }
    lcd.noBacklight();
  }

  if (key == 'A') {

    lcd.backlight();
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Hora inicio");
    lcd.setCursor(0, 1);
    lcd.print(EEPROM.read(0));
    lcd.setCursor(2, 1);
    lcd.print(":");
    lcd.setCursor(3, 1);
    lcd.print(EEPROM.read(1));
    lcd.setCursor(0, 1);
    char key = keypad.getKey();

    for (int pointer = 0; pointer <= 3; pointer++) {
      while (!key) {
        lcd.blink();
      }
      if ((!isDigit(key)) || ((pointer == 0) && (key > 2))) {
      } else {
        lcd.print(key);
      }
    }


  }
}

Assamita:
I can't seem to get out of the while loop that is there awaiting for a key input.

In general if you need to get out of a WHILE loop you should not be using WHILE. Use IF and allow loop() to do the repetition.

...R

Hello,

You can't get out of the while loop because nothing in the while loop changes your variable key. If key never changes the condition the while loop looks for never changes.

This is a common beginner mistake, expecting to exit a while loop without doing anything that would change the condition.

Ideally you should not be using a while loop like that because it stops anything else happening, but I think that's a lesson for another day.

I tried capturing the input of the key inside the while to force it to get out, but didn't work either:

while (!key) {
  lcd.blink();
  char key = keypad.getKey();
}

BTW, not very useful feedback, Perry, just coming to say "you're doing it wrong", but not providing a solution, but thank you anyway.

Assamita:
BTW, not very useful feedback, Perry, just coming to say "you're doing it wrong", but not providing a solution, but thank you anyway.

I disagree, I deliberately didn't provide a solution because I wanted you to think about it, not hand you answers on a plate. Clearly it worked because you posted something you tried. You are on the right track, but you are making another beginner mistake, you are not changing the value of your original variable key, you are defining a new variable key then throwing away the result. Again, I am going to let you think about that.

At this point I think you need to learn how to break out of the while loop, when you understand that you might be ready for the next part.

Every teacher and every student has their own preferred style, maybe my style does not work for you; that's OK, there are others here with different styles who might be able to help you in a way you prefer.

I do like to think of the solution myself, and the first try I did it before you're message. I try to research as much as I can before asking, but sometimes I get stuck as my code is now. If you see my first message, I didn't ask for the solution explicitly, but what was I doing wrong.

Sorry if I sounded harsh, but at first I didn't read your message much helpful. I'm trying other things I wish I could execute step by step like in an excel macro to see where it fails, but I don't think you can with arduino, can you? I still think a while loop is the best option, instead of making the loop function take care of it, but I may be wrong again.

Assamita:
I wish I could execute step by step like in

One way I used all my time as programmer is like:

Use Serial monitor and Serial.print(ln) at strategic places in You code! You might need to move the S.p, change the variable it prints...
That way of working was my rescue during many years, facing large, unknown systems.
Recently I made a special version that Serial.print-out when I send a command from the Pc, via Serilal.

Doing some more research, I've noticed that I don't need to use neither the loop or the while at all. There is a function in the Keypad library that does that for you:

key = keypad.waitForKey();

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