Button stops everything else from working

Hi, I'm working on a puzzle box and one of these items is a button to initiate a timer sequence on a TM1637 display. There are also other parts such as a keypad to input a password into a LCD. The LCD and keypad work perfectly on their own but the second the TM1637 display turns on, it stops working. The same happens for the entire box really. Nothing seems to work when the timer starts.

That code is below

#include <Key.h>
#include <Keypad.h>
#include <LiquidCrystal_I2C.h>
#include <TM1637Display.h>

//button
const int button3 = 30;
int button3State = 0;
int lastState = HIGH;
int currentState;

//TM1637
#define clk1 15
#define dio1 14
#define clk2 16
#define dio2 17

#define numberOfSeconds(_time_)  ((_time_ / 1000) & 60)
#define numberOfMinutes(_time_)  (((_time_ / 1000) / 60) & 60)

const uint8_t OFF[] = {0, 0, 0, 0};
const uint8_t PLAY[] = {B01110011, B01011111, B01101110};

TM1637Display display(clk1, dio1);
TM1637Display display2(clk2, dio2);

unsigned long timeLimit = 3600000;

//LCD
LiquidCrystal_I2C lcd(0x27, 16, 2);

//Keypad
    const int ROW_NUM = 4; //four rows
  const int COLUMN_NUM = 3; //three columns

  char keys[ROW_NUM][COLUMN_NUM] = {
    {'1','2','3'},
    {'4','5','6'},
    {'7','8','9'},
    {'*','0','#'}
  };
  byte pin_rows[ROW_NUM] = {5, 6, 7, 8}; 
  byte pin_column[COLUMN_NUM] = {2, 3, 4}; 
  Keypad keypad = Keypad( makeKeymap(keys), pin_rows, pin_column, ROW_NUM, COLUMN_NUM );


  //Passwords
  const int Password_Length = 5;
  String Data;
  String Master = "1970#";
  char customKey;
  byte data_count = 0;
  int lockOutput = 7;

void setup(){

  pinMode(button3, INPUT_PULLUP);

  lcd.init();
  lcd.backlight();

  display.setBrightness(0x0c);
  display.setSegments(OFF);
  display2.setBrightness(0x0c);
  display2.setSegments(OFF);

}

void countdown(){


  unsigned long timeRemaining = timeLimit - millis();


  while(timeRemaining > 0) {
      int seconds = numberOfSeconds(timeRemaining);
      int minutes = numberOfMinutes(timeRemaining);


      display.showNumberDecEx(seconds, 0, true, 2, 2);
      display.showNumberDecEx(minutes, 0x80>>3, true, 2, 0);


      timeRemaining = timeLimit - millis();


  }
}

void Timer() {
  currentState = digitalRead(button3);


  if(lastState == LOW && currentState == HIGH){
   countdown();
   delay(100);
  }

  // save the last state
  lastState = currentState;
}

void LCD() {

  // Initialize LCD and print
  lcd.setCursor(0, 0);
  lcd.print("Enter Password:");

  // Look for keypress
  customKey = keypad.getKey();
  if (customKey) {
    // Enter keypress into array and increment counter
    Data += customKey;
    lcd.setCursor(data_count, 1);
    lcd.print(Data[data_count]);
    data_count++;
  }

  // See if we have reached the password length
  if (data_count == Password_Length) {
    lcd.clear();

    if (Data == Master) {
      // Correct Password
      delay(300);
      lcd.print("Correct:");
      delay(300);
      lcd.setCursor(0,1);
      lcd.print("D2");
      delay(10000);

    }
    else {
      // Incorrect Password
      lcd.print("Incorrect");
      delay(1000);
    }

    // Clear data and LCD display
    lcd.clear();
  
  }
}

void loop(){

  Timer();
  LCD();

}

Sounds like something is wired wrong.

Can you post a schematic of what you have and some good quality photos as well.

First thing. Are you aware the fact the "coundown()" function completely stops Arduino from doing anything except showing the time remaining?

void countdown(){
  unsigned long timeRemaining = timeLimit - millis();
  while(timeRemaining > 0) {
      int seconds = numberOfSeconds(timeRemaining);
      int minutes = numberOfMinutes(timeRemaining);

      display.showNumberDecEx(seconds, 0, true, 2, 2);
      display.showNumberDecEx(minutes, 0x80>>3, true, 2, 0);

      timeRemaining = timeLimit - millis();
 }
}

And without a "delay(1000)" the "while()" is executed thousands of times per second?
And this is not the way to start a timer? If "timeLimit" is the target millis() value but it's statically defined as 3600000 (3600 seconds), the timer always ends 1 hour after you power on Arduino, and not from the moment you start the timer (I suppose after you type the correct password)?

All this maybe it's not the cause of your issue or a consequence, anyway I think you should first make some changes to the code.

1 Like

Unfortunately, there is quite a lot going on and it looks like a rat's nest of wires. Not the best at cable management yet LOL.

Why does the "countdown()" function stop the Arduino? I have a much larger program running. This is just a small piece and the other functions used don't stop the Arduino. How would you recommend changing the code? I'm still pretty new at this and could use as many pointers as possible.

So one out of two is no. What about the other thing I asked?

Or do I just leave it an put you down as someone who will not cooperate and leave it there?

it doesn't stop the arduino, but it does consume all of the arduinos attention due to your while() loop. Nothing else can happen while your countdown is displaying (e.g. reading buttons, etc). You need to break that function into tiny increments and call it repeatedly inside loop() to other functionality can continue to work. several things at the same time

Something like this will only update when the seconds change, else do nothing. Call it often from loop();

void countdown(){
  static int lastSeconds;
  static int lastMinutes;
  unsigned long timeRemaining = timeLimit - millis();
      int seconds = numberOfSeconds(timeRemaining);
      int minutes = numberOfMinutes(timeRemaining);

    if ( lastSeconds != seconds ) {
      lastSeconds = seconds;
      lastMinutes = minutes;
      display.showNumberDecEx(seconds, 0, true, 2, 2);
      display.showNumberDecEx(minutes, 0x80>>3, true, 2, 0);
    }
}

Also, you are tracking time incorrectly. duration = millis() - startTime is the correct way to deal with unsigned math.

Thank you so much! That makes so much more sense! It seems to work perfectly now with those changes. I really appreciate it.

I haven't said that, I said "...stops Arduino from doing anything except showing the time remaining". You're using a while loop waiting for the end of the time, thus during this time you can't do anything with Arduino. You can just sit and wait.

Something like the @blh64 code already suggested you.

He is using proper end - start = elapsed math only rearranged to target - now = difference which also works but we both know that the target should set (in unsigned math) the target as end = elapsed + start and let the rollover get it right , clock math 10 + 4 = 2 when plus is CW and minus is CCW.

The common term here is "blocking".
I think there is nothing in this you don't know but Nick arranges his materia;s very very clearly and well, Nick's tutorial on using timed events on Arduino.

Link to all subjects tutorials, great full explains.

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