With the help of the suggestions received below, I got a version of the program in which I used millis () instead of delay (), and I did button debounce, as much as I knew how. You can see the code below, I will continue to try to improve it.
Hello everyone!
Following on from a post I opened yesterday; I have 'arranged' a program, which should display the time (on Display No. 1) and the date (on Display No. 2), these will be adjusted by buttons.
In the Program_1 sketch I used delay (), so the program works slower; button commands are a bit difficult; the two dots on the display blink at approx. 1s.
In Program_2 I tried to give up the delay () and solve the commands by buttons, but it turned out to be a mess when the buttons were pressed, it works worse than Program_1.
How it should work: Display 1 shows the time with the blink midpoints at 0.5s; Display 2 shows DDMM date for 1s, short pause, then it shows YYYY year for 1s. I also have 3 buttons; two for increase / decrease hour, minutes and so on; the third one to be able to enter the menu, ie through each pair of digits on the display.
I use Arduino as a hobby, you can see that the program is written simply, but the use of millis () and button debounce led to something that does not lead me to solve.
What suggestions do you offer?
sketch_oct10a.ino (5.4 KB)
Program_2.ino (6.7 KB)
Debouncing
Delay using millis
#include <Wire.h>
#include <RTClib.h>
RTC_DS1307 RTC;
#include <TM1637Display.h>
#define CLK1 2
#define DIO1 3
TM1637Display Display1(CLK1, DIO1); // display no 1 for time
#define CLK2 5
#define DIO2 6
TM1637Display Display2(CLK2, DIO2); // display no 2 for date
int P1 = 8; // Button SET MENU
int P2 = 9; // Button +
int P3 = 10; // Button -
int myHour;
int myMinute;
int myYear;
int myMonth;
int myDay;
int menu = 0;
uint8_t segto;
unsigned long previousMillis = 0;
uint8_t blink_status = 0x40;
void setup()
{
Display1.setBrightness(2);
Display1.clear();
Display2.setBrightness(5);
Display2.clear();
pinMode(P1, INPUT);
pinMode(P2, INPUT);
pinMode(P3, INPUT);
Serial.begin(9600);
Wire.begin();
RTC.begin();
if (! RTC.isrunning()) {
Serial.println("RTC is NOT running!");
// Set the date and time at compile time
RTC.adjust(DateTime(__DATE__, __TIME__));
}
RTC.adjust(DateTime(__DATE__, __TIME__)); //removing "//" to adjust the time
// The default display shows the date and time
Display1.showNumberDecEx(myHour * 100 + myMinute, 0x00, true, 4, 0);
}
void loop()
{
#define buttonPressed LOW // When the button is pressed the input will be low, this is to remove the confusion this migth cause.
uint32_t currentMillis = millis(); // Millis times uses to debounce the button
static uint32_t lastMillis; // Start of the debounce timeout
const uint32_t BOUNCETIMEOUT = 20; // Debounce time in milliseconds
bool currentButtonState = digitalRead(P1); // Reads the current state of the button and saves the result in a bool
static bool lastButtonState;
if (lastButtonState != currentButtonState) { // Checks to see if the button has been pressed or released, at this point the button has not been debounced
if (currentMillis - lastMillis >= BOUNCETIMEOUT) { // Checks to see if the state of the button has been stable for at least bounceTimeout duration
lastButtonState = currentButtonState;
// check if you press the SET button and increase the menu index
if (currentButtonState == buttonPressed)
{
menu = menu + 1;
}
}
} else {
lastMillis = currentMillis; // Saves the current value of millis in last millis so the debounce timer starts from current millis
}
// ******************** select subroutine
if (menu == 0)
{
DisplayDateTime();
}
if (menu == 1)
{
DisplaySetHour();
}
if (menu == 2)
{
DisplaySetMinute();
}
if (menu == 3)
{
DisplaySetYear();
}
if (menu == 4)
{
DisplaySetMonth();
}
if (menu == 5)
{
DisplaySetDay();
}
if (menu == 6)
{
//SaveSettings();
//delay(500); // using millis() instead of this delay
if (millis() >= 500) {
SaveSettings();
menu = 0;
}
}
}
void DisplayDateTime()
{
unsigned long currentMillis = millis();
DateTime now = RTC.now();
myMinute = now.minute();
myHour = now.hour();
myYear = now.year();
myDay = now.day();
myMonth = now.month();
// make the midpoints blink - method 2
if ((currentMillis - previousMillis) > 500) {
previousMillis = millis();
if (blink_status == 0) {
blink_status = 0x40;
} else {
blink_status = 0;
//previousMillis = 0;
}
Display1.showNumberDecEx(myHour * 100 + myMinute, blink_status, true, 4, 0);
}
int mySecond = now.second();
if ((mySecond % 3) < 2) {
// show the day and month for 2 seconds out of every 3 seconds
Display2.showNumberDec((myDay / 10) % 10, false, 1, 0);
Display2.showNumberDec(myDay % 10, false, 1, 1);
Display2.showNumberDec((myMonth / 10) % 10, false, 1, 2);
Display2.showNumberDec(myMonth % 10, false, 1, 3);
}
else {
// show the year for 1 second out of every 3 seconds
Display2.showNumberDec(myYear);
}
}
void DisplaySetHour()
{
Display1.clear(); // refresh the display
#define buttonPressed LOW // When the button is pressed the input will be low, this is to remove the confusion this migth cause.
uint32_t currentMillis = millis(); // Millis times uses to debounce the button
static uint32_t lastMillis; // Start of the debounce timeout
const uint32_t BOUNCETIMEOUT = 20; // Debounce time in milliseconds
bool currentButtonState = digitalRead(P2); // Reads the current state of the button and saves the result in a bool
static bool lastButtonState; // Holds the previous debounced state of the button
if (lastButtonState != currentButtonState) { // Checks to see if the button has been pressed or released, at this point the button has not been debounced
if (currentMillis - lastMillis >= BOUNCETIMEOUT) { // Checks to see if the state of the button has been stable for at least bounceTimeout duration
lastButtonState = currentButtonState; // At this point the button has been debounced, so save the last state
if (currentButtonState == buttonPressed) {
if (currentButtonState == LOW)
{
if (myHour == 23)
{
myHour = 0;
}
else
{
myHour = myHour + 1;
}
}
}
}
} else {
lastMillis = currentMillis; // Saves the current value of millis in last millis so the debounce timer starts from current millis
}
// ***********************************************************
#define buttonPressed1 LOW // When the button is pressed the input will be low, this is to remove the confusion this migth cause.
bool currentButtonState1 = digitalRead(P3); // Reads the current state of the button and saves the result in a bool
static bool lastButtonState1; // Holds the previous debounced state of the button
if (lastButtonState1 != currentButtonState1) { // Checks to see if the button has been pressed or released, at this point the button has not been debounced
if (currentMillis - lastMillis >= BOUNCETIMEOUT) { // Checks to see if the state of the button has been stable for at least bounceTimeout duration
lastButtonState1 = currentButtonState1; // At this point the button has been debounced, so save the last state
if (currentButtonState1 == buttonPressed1) {
if (currentButtonState1 == LOW)
{
if (myHour == 0)
{
myHour = 23;
}
else
{
myHour = myHour - 1;
}
}
}
}
} else {
lastMillis = currentMillis; // Saves the current value of millis in last millis so the debounce timer starts from current millis
}
Display1.showNumberDec((myHour / 10) % 10, false, 1, 0);
Display1.showNumberDec(myHour % 10, false, 1, 1);
}
void DisplaySetMinute()
{
Display1.clear(); // refresh the display
#define buttonPressed LOW // When the button is pressed the input will be low, this is to remove the confusion this migth cause.
uint32_t currentMillis = millis(); // Millis times uses to debounce the button
static uint32_t lastMillis; // Start of the debounce timeout
const uint32_t BOUNCETIMEOUT = 20; // Debounce time in milliseconds
bool currentButtonState = digitalRead(P2); // Reads the current state of the button and saves the result in a bool
static bool lastButtonState; // Holds the previous debounced state of the button
if (lastButtonState != currentButtonState) { // Checks to see if the button has been pressed or released, at this point the button has not been debounced
if (currentMillis - lastMillis >= BOUNCETIMEOUT) { // Checks to see if the state of the button has been stable for at least bounceTimeout duration
lastButtonState = currentButtonState; // At this point the button has been debounced, so save the last state
if (currentButtonState == buttonPressed) {
if (currentButtonState == LOW)
{
if (myMinute == 59)
{
myMinute = 0;
}
else
{
myMinute = myMinute + 1;
}
}
}
}
} else {
lastMillis = currentMillis; // Saves the current value of millis in last millis so the debounce timer starts from current millis
}
//***********************************************************8
#define buttonPressed1 LOW // When the button is pressed the input will be low, this is to remove the confusion this migth cause.
bool currentButtonState1 = digitalRead(P3); // Reads the current state of the button and saves the result in a bool
static bool lastButtonState1; // Holds the previous debounced state of the button
if (lastButtonState1 != currentButtonState1) { // Checks to see if the button has been pressed or released, at this point the button has not been debounced
if (currentMillis - lastMillis >= BOUNCETIMEOUT) { // Checks to see if the state of the button has been stable for at least bounceTimeout duration
lastButtonState1 = currentButtonState1; // At this point the button has been debounced, so save the last state
if (currentButtonState1 == buttonPressed1) {
if (currentButtonState1 == LOW)
{
if (myMinute == 0)
{
myMinute = 59;
}
else
{
myMinute = myMinute - 1;
}
}
}
}
} else {
lastMillis = currentMillis; // Saves the current value of millis in last millis so the debounce timer starts from current millis
}
Display1.showNumberDec((myMinute / 10) % 10, false, 1, 2);
Display1.showNumberDec(myMinute % 10, false, 1, 3);
}
void DisplaySetYear()
{
Display2.clear(); // refresh the display
#define buttonPressed LOW // When the button is pressed the input will be low, this is to remove the confusion this migth cause.
uint32_t currentMillis = millis(); // Millis times uses to debounce the button
static uint32_t lastMillis; // Start of the debounce timeout
const uint32_t BOUNCETIMEOUT = 20; // Debounce time in milliseconds
bool currentButtonState = digitalRead(P2); // Reads the current state of the button and saves the result in a bool
static bool lastButtonState; // Holds the previous debounced state of the button
if (lastButtonState != currentButtonState) { // Checks to see if the button has been pressed or released, at this point the button has not been debounced
if (currentMillis - lastMillis >= BOUNCETIMEOUT) { // Checks to see if the state of the button has been stable for at least bounceTimeout duration
lastButtonState = currentButtonState; // At this point the button has been debounced, so save the last state
if (currentButtonState == buttonPressed) {
if (currentButtonState == LOW)
{
myYear = myYear + 1;
}
}
}
} else {
lastMillis = currentMillis; // Saves the current value of millis in last millis so the debounce timer starts from current millis
}
//***********************************************************8
#define buttonPressed1 LOW // When the button is pressed the input will be low, this is to remove the confusion this migth cause.
bool currentButtonState1 = digitalRead(P3); // Reads the current state of the button and saves the result in a bool
static bool lastButtonState1; // Holds the previous debounced state of the button
if (lastButtonState1 != currentButtonState1) { // Checks to see if the button has been pressed or released, at this point the button has not been debounced
if (currentMillis - lastMillis >= BOUNCETIMEOUT) { // Checks to see if the state of the button has been stable for at least bounceTimeout duration
lastButtonState1 = currentButtonState1; // At this point the button has been debounced, so save the last state
if (currentButtonState1 == buttonPressed1) {
if (currentButtonState1 == LOW)
{
myYear = myYear - 1;
}
}
}
} else {
lastMillis = currentMillis; // Saves the current value of millis in last millis so the debounce timer starts from current millis
}
Display2.showNumberDec(myYear);
}
void DisplaySetMonth()
{
Display2.clear(); // refresh the display
#define buttonPressed LOW // When the button is pressed the input will be low, this is to remove the confusion this migth cause.
uint32_t currentMillis = millis(); // Millis times uses to debounce the button
static uint32_t lastMillis; // Start of the debounce timeout
const uint32_t BOUNCETIMEOUT = 20; // Debounce time in milliseconds
bool currentButtonState = digitalRead(P2); // Reads the current state of the button and saves the result in a bool
static bool lastButtonState; // Holds the previous debounced state of the button
if (lastButtonState != currentButtonState) { // Checks to see if the button has been pressed or released, at this point the button has not been debounced
if (currentMillis - lastMillis >= BOUNCETIMEOUT) { // Checks to see if the state of the button has been stable for at least bounceTimeout duration
lastButtonState = currentButtonState; // At this point the button has been debounced, so save the last state
if (currentButtonState == buttonPressed) {
if (currentButtonState == LOW)
{
if (myMonth == 12)
{
myMonth = 1;
}
else
{
myMonth = myMonth + 1;
}
}
}
}
} else {
lastMillis = currentMillis; // Saves the current value of millis in last millis so the debounce timer starts from current millis
}
//***********************************************************8
#define buttonPressed1 LOW // When the button is pressed the input will be low, this is to remove the confusion this migth cause.
bool currentButtonState1 = digitalRead(P3); // Reads the current state of the button and saves the result in a bool
static bool lastButtonState1; // Holds the previous debounced state of the button
if (lastButtonState1 != currentButtonState1) { // Checks to see if the button has been pressed or released, at this point the button has not been debounced
if (currentMillis - lastMillis >= BOUNCETIMEOUT) { // Checks to see if the state of the button has been stable for at least bounceTimeout duration
lastButtonState1 = currentButtonState1; // At this point the button has been debounced, so save the last state
if (currentButtonState1 == buttonPressed1) {
if (currentButtonState1 == LOW)
{
if (myMonth == 1)
{
myMonth = 12;
}
else
{
myMonth = myMonth - 1;
}
}
}
}
} else {
lastMillis = currentMillis; // Saves the current value of millis in last millis so the debounce timer starts from current millis
}
Display2.showNumberDec((myMonth / 10) % 10, false, 1, 2);
Display2.showNumberDec(myMonth % 10, false, 1, 3);
}
void DisplaySetDay()
{
Display2.clear(); // refresh the display
#define buttonPressed LOW // When the button is pressed the input will be low, this is to remove the confusion this migth cause.
uint32_t currentMillis = millis(); // Millis times uses to debounce the button
static uint32_t lastMillis; // Start of the debounce timeout
const uint32_t BOUNCETIMEOUT = 20; // Debounce time in milliseconds
bool currentButtonState = digitalRead(P2); // Reads the current state of the button and saves the result in a bool
static bool lastButtonState; // Holds the previous debounced state of the button
if (lastButtonState != currentButtonState) { // Checks to see if the button has been pressed or released, at this point the button has not been debounced
if (currentMillis - lastMillis >= BOUNCETIMEOUT) { // Checks to see if the state of the button has been stable for at least bounceTimeout duration
lastButtonState = currentButtonState; // At this point the button has been debounced, so save the last state
if (currentButtonState == buttonPressed) {
if (currentButtonState == LOW)
{
if (myDay == 31)
{
myDay = 1;
}
else
{
myDay = myDay + 1;
}
}
}
}
} else {
lastMillis = currentMillis; // Saves the current value of millis in last millis so the debounce timer starts from current millis
}
//***********************************************************8
#define buttonPressed1 LOW // When the button is pressed the input will be low, this is to remove the confusion this migth cause.
bool currentButtonState1 = digitalRead(P3); // Reads the current state of the button and saves the result in a bool
static bool lastButtonState1; // Holds the previous debounced state of the button
if (lastButtonState1 != currentButtonState1) { // Checks to see if the button has been pressed or released, at this point the button has not been debounced
if (currentMillis - lastMillis >= BOUNCETIMEOUT) { // Checks to see if the state of the button has been stable for at least bounceTimeout duration
lastButtonState1 = currentButtonState1; // At this point the button has been debounced, so save the last state
if (currentButtonState1 == buttonPressed1) {
if (currentButtonState1 == LOW)
{
if (myDay == 1)
{
myDay = 31;
}
else
{
myDay = myDay - 1;
}
}
}
}
} else {
lastMillis = currentMillis; // Saves the current value of millis in last millis so the debounce timer starts from current millis
}
Display2.showNumberDec((myDay / 10) % 10, false, 1, 0);
Display2.showNumberDec(myDay % 10, false, 1, 1);
}
void SaveSettings()
{
if (millis() >= 200) {
Display1.clear();
Display2.clear();
Display1.showNumberDec(0123);
Display2.showNumberDec(0123);
RTC.adjust(DateTime(myYear, myMonth, myDay, myHour, myMinute, 0));
//delay(200); // using millis() instead of this delay
}
}