Digicode LCD Timer and Millis

Hi there,
I would like to run a 10 min timer on a lcd and use a Digicode with the password library. The 2 separate codes works fine oon their own but once i merge them it doesnt (lcd is blank and digicode takes ages to printLN on serial monitor). I tried using millis() but i couldnt make it work. Is there any problem having a delay while using an lcd ? what should the time interval between actual-time and millis's time be for the lcd and the digicode ?
Thanks a lot.

(PS my code is a little long so try to focus on the millis() variables, the beginning of the setup and the two if's with millis, whats inside the if's and the function at the end of the code works fine)

#include <Keypad.h>
#include <Password.h>
#include <LiquidCrystal.h>

//----------Millis()--------------
unsigned long millisDigicode;
unsigned long millisTimer;
int IntervalDigicode = 100;
int IntervalTimer = 100;


//--------Digicode---------------
int GreenPin = A4;
int RedPin = A3;
char buzzerPin = 12;
//
String newPasswordString; //hold the new password
char newPassword[6]; //charater string of newPasswordString
const byte ROWS = 4;
const byte COLS = 4;
Password password = Password( "4578" );
byte maxPasswordLength = 4;
byte currentPasswordLength = 0;
char keys[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};
//R2-8 , R3-9 ,C1-10 , C2-11
byte rowPins[ROWS] = {NULL, 8, 9, NULL};
byte colPins[COLS] = {10, 11 , NULL , NULL };
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
//-------------------------------------

//-----------TIMER------------------
const int rs = 7, en = 6, d4 = 2, d5 = 3, d6 = 4, d7 = 5;
const int resetButtonPin = A5;
int buttonState = 0;
//buzzerPin in previous digicode part
//
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
const int initial_min = 10; //xx
const int initial_sec = 0; //xx
int flag = 1;
signed short minutes, secondes;
char timeline[16];
//--------------------------




void setup() {
  millisDigicode = millis();
  millisTimer = millis();

  Serial.begin(9600);
  //  pinMode(GreenPin, OUTPUT);
  //  pinMode(RedPin, OUTPUT);

  //-----Timer--------
  pinMode(resetButtonPin, INPUT);
  lcd.begin(16, 2);
  lcd.print("Time Left :");
  minutes = initial_min;
  secondes = initial_sec;
  //-----------------

}



void loop() {
  //------DIGI-------------
  if ( (millis() - millisDigicode) > IntervalDigicode) {
    char key = keypad.getKey();
    if (key != NO_KEY) {
      delay(60);
      switch (key) {
        default: processNumberKey(key);
      }
    }
  }
  //----------------------

  //----Timer------
  if ( (millis() - millisTimer) > IntervalTimer) {
    buttonState = digitalRead(resetButtonPin);
    if (buttonState == HIGH) {
      minutes = initial_min;
      secondes = initial_sec;
      flag = 1;
    }

    lcd.setCursor(0, 1);
    sprintf(timeline, "%0.2d mins %0.2d secs", minutes, secondes);
    lcd.print(timeline);
    delay(1000);

    if (secondes == 0 && minutes != 0)
    {
      secondes = 60;
      minutes --;
    }
    if (minutes != 0 or secondes != 0) {
      secondes--;
    }
    if (secondes == 0 && minutes == 0) {
      if ( flag == 1) {
        for (int i = 0; i < 4; i++) {
          tone(buzzerPin, 600, 500);
          delay(1000);
          tone(buzzerPin, 600, 500);
          delay(1000);
          tone(buzzerPin, 600, 500);
          delay(1000);
        }
      }
      flag = 0;
    }
    //-----------------------

  }
}


//-------Functions----------\\


void processNumberKey(char key) {
  Serial.print(key);
  currentPasswordLength++;
  password.append(key);
  if (currentPasswordLength == maxPasswordLength) {
    checkPassword();
  }
}

void checkPassword() {
  if (password.evaluate()) {
    Serial.println(" OK.");
    buzzer(true);
  } else {
    Serial.println(" Wrong password!");
    buzzer(false);
  }
  resetPassword();
}

void resetPassword() {
  password.reset();
  currentPasswordLength = 0;
}

void buzzer(int x) {
  if (x == true) {
    digitalWrite(GreenPin, HIGH);
    tone(buzzerPin, 800, 1000);
    delay(2000);
    digitalWrite(GreenPin, LOW);
  }
  else {
    digitalWrite(RedPin, HIGH);
    tone(buzzerPin, 1000, 500);
    delay(1000);
    tone(buzzerPin, 1000, 500);
    digitalWrite(RedPin, LOW);
  }
}

I'd try to solve the above issue before packing on layers of code.

Post the code where the 2 are combined that does not use millis() so that the underlaying issue can be solved first?

Thanks for your reply.
Its exactly the same but without the millis (unsigned long and int), millis in setup and millis(if) in the loop.

What do you mean by underlaying issue ? the 2 separate codes works fine, only the merged code doesnt.

#include <Keypad.h>
#include <Password.h>
#include <LiquidCrystal.h>

//--------Digi---------------
int GreenPin = A4;
int RedPin = A3;
char buzzerPin = 12;
//
String newPasswordString; //hold the new password
char newPassword[6]; //charater string of newPasswordString
const byte ROWS = 4;
const byte COLS = 4;
Password password = Password( "4578" );
byte maxPasswordLength = 4;
byte currentPasswordLength = 0;
char keys[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};
//R2-8 , R3-9 ,C1-10 , C2-11
byte rowPins[ROWS] = {NULL, 8, 9, NULL};
byte colPins[COLS] = {10,11 ,NULL ,NULL };
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
//-------------------------------------

//-----------TIMER------------------
const int rs = 7, en = 6, d4 = 2, d5 = 3, d6 = 4, d7 = 5;
const int resetButtonPin = A5;
int buttonState = 0;
//buzzerPin in previous digicode part
//
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
const int initial_min = 10; //xxxxxxxxxxxxxxxxxx
const int initial_sec = 0; //xxxxxxxxxxxxxxxxxx
int flag = 1;
signed short minutes, secondes;
char timeline[16];
//--------------------------




void setup() {
  Serial.begin(9600);
//  pinMode(GreenPin, OUTPUT);
//  pinMode(RedPin, OUTPUT);

  //-----Timer--------
  pinMode(resetButtonPin, INPUT);
  lcd.begin(16, 2);
  lcd.print("Time Left :");
  minutes = initial_min;
  secondes = initial_sec;
  //-----------------
  
}



void loop() {
  //------DIGI-------------
  char key = keypad.getKey();
  if (key != NO_KEY) {
    delay(60);
    switch (key) {
      default: processNumberKey(key);
    }
  }
  //----------------------

  //----Timer------
  buttonState = digitalRead(resetButtonPin);
  if (buttonState == HIGH) {
    minutes = initial_min;
    secondes = initial_sec;
    flag = 1;
  }

  lcd.setCursor(0, 1);
  sprintf(timeline, "%0.2d mins %0.2d secs", minutes, secondes);
  lcd.print(timeline);
  delay(1000);

  if (secondes == 0 && minutes != 0)
  {
    secondes = 60;
    minutes --;
  }
  if (minutes != 0 or secondes != 0) {
    secondes--;
  }
  if (secondes == 0 && minutes == 0) {
    if ( flag == 1) {
      for (int i = 0; i < 4; i++) {
        tone(buzzerPin, 600, 500);
        delay(1000);
        tone(buzzerPin, 600, 500);
        delay(1000);
        tone(buzzerPin, 600, 500);
        delay(1000);
        } 
      }
      flag=0;
    }
  //-----------------------

}



//-------Functions----------\\


void processNumberKey(char key) {
  Serial.print(key);
  currentPasswordLength++;
  password.append(key);
  if (currentPasswordLength == maxPasswordLength) {
    checkPassword();
  }
}

void checkPassword() {
  if (password.evaluate()) {
    Serial.println(" OK.");
    buzzer(true);
  } else {
    Serial.println(" Wrong password!");
    buzzer(false);
  }
  resetPassword();
}

void resetPassword() {
  password.reset();
  currentPasswordLength = 0;
}

void buzzer(int x) {
  if (x == true) {
    digitalWrite(GreenPin, HIGH);
    tone(buzzerPin, 800, 1000);
    delay(2000);
    digitalWrite(GreenPin, LOW);
  }
  else {
    digitalWrite(RedPin, HIGH);
    tone(buzzerPin, 1000, 500);
    delay(1000);
    tone(buzzerPin, 1000, 500);
    digitalWrite(RedPin, LOW);
  }
}
1 Like

Now, while I look the code from post#3 over describe what is meant by it does not work, please.

Did the code work before millis() was used? If so then adding millis() is the issue otherwise something else is the issue?

Why use signed short minutes, secondes;?

  if (secondes == 0 && minutes != 0)
  {
    secondes = 60;
    minutes --;
  }

Notice how minutes is automatically subtracted at this point? Initially minutes is set to 0. On the first pass minutes gets set to -1. The -1 does not satisfy any of the conditionals such as if (secondes == 0 && minutes == 0) {. The next pass of the loop makes minutes go to a -2, then a -3, then a -4 and so on and so forth till the short integer overflows.

But what if

byte minutes=60, secondes=0;

Just my initial unfocused observations.

I'm sorry I might've been unclear in my first post. I have 1 code of a 10min timer and another using a digicode for a password input. I'm putting both of these bellow. These two on their own work fine but if i put them together, as in post#3, the timer does not display the timer and neither does the digicode print in the serial monitor. Hence me trying using millis as in post#1.
About the signed short minutes and secondes, everything works as intended ; the second condition ensure that minutes will never be negative. I see though that it is sloppy not to use byte, it is not my original code so I did not want to mess around too much.

Timer Code :

#include <LiquidCrystal.h>

//------PINS-----------
//const int rs = 7, en = 6, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
const int rs = 2, en = 3, d4 = 4, d5 = 5, d6 = 6, d7 = 7;
const int resetButtonPin = A5;
int buttonState = 0;
char buzzerPin = A4;

LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

//----variables-------
const int initial_min = 10;
const int initial_sec = 0;
int flag = 1;
signed short minutes, secondes;
char timeline[16];



void setup() {
  pinMode(resetButtonPin, INPUT);
  lcd.begin(16, 2);
  lcd.print("Time Left :");
  minutes = initial_min;
  secondes = initial_sec;
}



void loop() {
  buttonState = digitalRead(resetButtonPin);
  if (buttonState == HIGH) {
    minutes = initial_min;
    secondes = initial_sec;
    flag = 1;
  }

  lcd.setCursor(0, 1);
  sprintf(timeline, "%0.2d mins %0.2d secs", minutes, secondes);
  lcd.print(timeline);
  delay(1000);

  if (secondes == 0 && minutes != 0)
  {
    secondes = 60;
    minutes --;
  }
  if (minutes != 0 or secondes != 0) {
    secondes--;
  }
  if (secondes == 0 && minutes == 0) {
    if ( flag == 1) {
      for (int i = 0; i < 4; i++) {
        tone(buzzerPin, 600, 500);
        delay(1000);
        tone(buzzerPin, 600, 500);
        delay(1000);
        tone(buzzerPin, 600, 500);
        delay(1000);
        } 
      }
      flag=0;
    }

  }

Digicode Code :

#include <Keypad.h>
#include <Password.h>

String newPasswordString; //hold the new password
char newPassword[6]; //charater string of newPasswordString
const byte ROWS = 4;
const byte COLS = 4;
int GreenPin = A4;
int RedPin = A3;
char buzzerPin = 12;

//you can use password.set(newPassword) to overwrite it
Password password = Password( "4444" );

byte maxPasswordLength = 4;
byte currentPasswordLength = 0;

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


//R2-8 , R3-9 ,C1-10 , C2-11
byte rowPins[ROWS] = {NULL, 8, 9, NULL};   //CONNECTIONS: blue-8 red-13, others in order in between
byte colPins[COLS] = {10,11 ,NULL ,NULL };

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

void setup() {
  Serial.begin(9600);
  pinMode(GreenPin, OUTPUT);
  pinMode(RedPin, OUTPUT);
}



void loop() {
  char key = keypad.getKey();
  if (key != NO_KEY) {
    delay(60);
    switch (key) {
      default: processNumberKey(key);
    }
  }
}



//-------Functions----------\\


void processNumberKey(char key) {
  Serial.print(key);
  currentPasswordLength++;
  password.append(key);
  if (currentPasswordLength == maxPasswordLength) {
    checkPassword();
  }
}

void checkPassword() {
  if (password.evaluate()) {
    Serial.println(" OK.");
    buzzer(true);
  } else {
    Serial.println(" Wrong password!");
    buzzer(false);
  }
  resetPassword();
}

void resetPassword() {
  password.reset();
  currentPasswordLength = 0;
}

void buzzer(int x) {
  if (x == true) {
    digitalWrite(GreenPin, HIGH);
    tone(buzzerPin, 800, 1000);
    delay(2000);
    digitalWrite(GreenPin, LOW);
  }
  else {
    digitalWrite(RedPin, HIGH);
    tone(buzzerPin, 1000, 500);
    delay(1000);
    tone(buzzerPin, 1000, 500);
    digitalWrite(RedPin, LOW);
  }
}

This is unusual. I'm not sure byte can hold NULL as such. I think it will probably be interpreted as 0.

What are these NULL values indicating? If your keypad is 2x2 keys, why are you setting ROWS, COLS to 4?

Hi,

thanks for your reply. These are just here to save pins on my arduino uno, it does not affect the code any other way. So instead of being able to use the full 4x4 grid, you woul only be able to use a 2x2 grid. The digicode part of the code works perfectly alone, so does the LCD part, but together something does not.

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