Basic Arduino Clock

I'm trying to make a relatively basic Arduino clock that also measures Temp/Humidity, but I think there is something amiss with my pushbutton, which should allow me to set the time and a couple of alarms. When a pull-up resistor is used, they are nonresponsive, but when they are not they will simply power cycle the LCD in use. My code compiles fine, and several other individuals I've reached out to say my code should work as advertised which leads me to believe I'm overlooking something. Any help is appreciated.

#include <Wire.h>
#include <RTClib.h>
#include <LiquidCrystal.h>
#include <DHT.h>
#include <Bounce2.h> // Added Bounce2 library for button debouncing

#define DHTPIN 22 // Pin connected to the DHT11 sensor
#define DHTTYPE DHT11 // DHT type

DHT dht(DHTPIN, DHTTYPE);
RTC_DS3231 rtc;
LiquidCrystal lcd(12, 11, 5, 4, 3, 2); // Change the pin numbers accordingly for your setup

const int passiveBuzzerPin = 13;
const int activeBuzzerPin = 6;

const int buttonSetHour = 10;
const int buttonSetMinute = 9;
const int buttonSetAlarm1 = 8;
const int buttonSetAlarm2 = 7;

bool alarm1Set = false;
bool alarm2Set = false;

// Define Bounce objects for the buttons
Bounce buttonHour = Bounce();   // Bounce object for buttonSetHour
Bounce buttonMinute = Bounce(); // Bounce object for buttonSetMinute
Bounce buttonAlarm1 = Bounce(); // Bounce object for buttonSetAlarm1
Bounce buttonAlarm2 = Bounce(); // Bounce object for buttonSetAlarm2

void setup() {
  Serial.begin(9600);
  Wire.begin();
  rtc.begin();
  dht.begin();

  lcd.begin(16, 2);
  lcd.print(" Alarm Clock ");
  delay(2000);
  lcd.clear();

  pinMode(passiveBuzzerPin, OUTPUT);
  pinMode(activeBuzzerPin, OUTPUT);

  // Set button pins as INPUT_PULLUP
  pinMode(buttonSetHour, INPUT_PULLUP);
  pinMode(buttonSetMinute, INPUT_PULLUP);
  pinMode(buttonSetAlarm1, INPUT_PULLUP);
  pinMode(buttonSetAlarm2, INPUT_PULLUP);

  // Set debounce interval to 50ms (adjust as needed)
  buttonHour.attach(buttonSetHour, INPUT_PULLUP);
  buttonHour.interval(50);
  buttonMinute.attach(buttonSetMinute, INPUT_PULLUP);
  buttonMinute.interval(50);
  buttonAlarm1.attach(buttonSetAlarm1, INPUT_PULLUP);
  buttonAlarm1.interval(50);
  buttonAlarm2.attach(buttonSetAlarm2, INPUT_PULLUP);
  buttonAlarm2.interval(50);
}

void loop() {
  DateTime now = rtc.now();
  int hour = now.hour();
  int minute = now.minute();
  int second = now.second();
  float temperature = dht.readTemperature();
  float humidity = dht.readHumidity();

  displayTime(hour, minute, second);
  displayTemperatureAndHumidity(temperature, humidity);
  checkAlarms(hour, minute);
}

void displayTime(int hour, int minute, int second) {
  lcd.setCursor(0, 0);
  lcd.print("Time: ");
  if (hour < 10) {
    lcd.print("0");
  }
  lcd.print(hour);
  lcd.print(":");
  if (minute < 10) {
    lcd.print("0");
  }
  lcd.print(minute);
  lcd.print(":");
  if (second < 10) {
    lcd.print("0");
  }
  lcd.print(second);
}

void displayTemperatureAndHumidity(float temperature, float humidity) {
  lcd.setCursor(0, 1);
  lcd.print("Temp: ");
  lcd.print(temperature, 1);
  lcd.print(" C");

  lcd.setCursor(9, 1);
  lcd.print("Humidity: ");
  lcd.print(humidity, 1);
  lcd.print(" %");
}

const int ALARM1_HOUR = 7;
const int ALARM1_MINUTE = 30;
const int ALARM2_HOUR = 10;
const int ALARM2_MINUTE = 0;

void checkAlarms(int hour, int minute) {
  // Update the button states
  buttonHour.update();
  buttonMinute.update();
  buttonAlarm1.update();
  buttonAlarm2.update();

  // Toggle the alarm setting when buttons are pressed
  if (buttonAlarm1.fell()) {
    alarm1Set = !alarm1Set;
  }

  if (buttonAlarm2.fell()) {
    alarm2Set = !alarm2Set;
  }

  if (alarm1Set && hour == ALARM1_HOUR && minute == ALARM1_MINUTE) {
    tone(activeBuzzerPin, 2000, 1000);
  }

  if (alarm2Set && hour == ALARM2_HOUR && minute == ALARM2_MINUTE) {
    tone(activeBuzzerPin, 2000, 1000);
  }
}

Please post a wiring diagram, so we can understand the wire jungle that you have there.

Where is this advertisement? I see only a few line comments. If you explained things to "some individuals" please reproduce that information here.

Looks like you have the push buttons directly shorting power to ground when pressed, that can easily damage the Mega.

With the bounce library, you likely only need the push button connected to ground and the pin on the Mega, the internal pull-up is used.

Yes, so put a debug statement in your setup() like

Serial.println("starting program");

So you can detect if the MCU is being reset by a power cycle when a button is pushed.

Using this guidance, I can verify that it is being power cycled with a button push. I apologize for my rat nest as I've been trying to work on this for the better part of 6 hours. "Some individuals" would be several tutors I reached out to as I'm not great with C++ coding.

There is nothing wrong with a rat's nest. I have three rat's nest projects on my desk as I type. But they all have full schematics drawn in KiCad. I would never expect that anyone could learn anything from a photo of the wiring alone. We usually ask for that here, to spot glaring mistakes, not minutae.

For now, it would be sufficient if you could just convey the button wiring.

Does this suffice? All buttons are connected like this to their corresponding digital pins.

Are you using this circuit with the INPUT_PULLUP configurations in pinMode()? Because, I see no pull up or down resistor.

It would be helpful if you would move the components on to the work sheet. :slight_smile:

The button pins are connected in opposing pairs. So in the shown circuit, the two possibilities are:

  1. The power will always be shorted
  2. The power will be shorted when you push the button.

Have you looked at the push button tutorials on this site? The code ships with the IDE.

So thats actually my problem. I originally had a pull up resistor setup just like the tutorial here:

However, the push button was simply non responsive. Is there a better tutorial I am looking over?

Incomplete tutorial, because it doesn't explain the possibility to use a button without resistor, which is a lot easier. Just use pinMode(buttonPin, INPUT_PULLUP); as you already do now, and wire the button between pin and ground. There should be no 5volt going to that button breadboard.
Leo..

I tried setting up my pull-up resistors as you suggest, but I'm getting no output from them. I've used a multimeter to try and verify if the button is providing an output, which it is only doing so when set up with 5V attached like in this setup:

No.

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?
Hand drawn and photographed is perfectly acceptable.
Please include ALL hardware, power supplies, component names and pin labels.

Thanks.. Tom... :smiley: :+1: :coffee: :australia:

Your diagram shows pull-down resistors, not pull-up resistors. Pull-up resistors would go between +5V and the side of the switch connected to the Mega pin, and the other side of the switch would go to ground. The way you have the switch wired, it likely will not work, because the 10K ohm pull-down resistor in combination with the internal pull-up resistor may not pull the pin voltage low enough for the processor to see a LOW on the input.

With your code, you should only need one side of the switch connected to ground, and the other side connected to the Mega pin. No connection to +5V, no resistors.

I apologize as I'm not very savvy with CAD, but here is my attempt.

Pinout Attempt.pdf (23.9 KB)

Some of the Hardware to note:

The push buttons are generic
I have a 3 pin DHT11, so one of the diagram's pins is unused intentionally.

I also ran some troubleshooting with another set of code, which allows me to change the minutes and hours, but nothing else. This suggests to me that the hardware setup is okay after some of the fixes everyone here has suggested, but I'm missing something with the code.

This is the code that allows me to manually change hours and minutes:

#include <Wire.h>
#include <RTClib.h>
#include <LiquidCrystal.h>
#include <DHT.h>

#define DHTPIN 22       // Pin connected to the DHT11 sensor
#define DHTTYPE DHT11  // DHT type

DHT dht(DHTPIN, DHTTYPE);
RTC_DS3231 rtc;
LiquidCrystal lcd(12, 11, 5, 4, 3, 2); // Change the pin numbers accordingly for your setup

const int passiveBuzzerPin = 13;
const int activeBuzzerPin = 6;

const int buttonSetHour = 10;
const int buttonSetMinute = 9;
const int buttonSetAlarm1 = 8;
const int buttonSetAlarm2 = 7;

bool alarm1Set = false;
bool alarm2Set = false;

int setHour = 0;
int setMinute = 0;
int setAlarm1Hour = 0;
int setAlarm1Minute = 0;
int setAlarm2Hour = 0;
int setAlarm2Minute = 0;

void setup() {
  Serial.begin(9600);
  Wire.begin();
  rtc.begin();
  dht.begin();

  lcd.begin(16, 2);
  lcd.println("Starting program");
  lcd.print("   Alarm Clock   ");
  delay(2000);
  lcd.clear();

  pinMode(passiveBuzzerPin, OUTPUT);
  pinMode(activeBuzzerPin, OUTPUT);
  pinMode(buttonSetHour, INPUT_PULLUP);
  pinMode(buttonSetMinute, INPUT_PULLUP);
  pinMode(buttonSetAlarm1, INPUT_PULLUP);
  pinMode(buttonSetAlarm2, INPUT_PULLUP);
  lcd.println("Starting program");
}

void loop() {
  DateTime now = rtc.now();
  int hour = now.hour();
  int minute = now.minute();
  int second = now.second();

  float temperature = dht.readTemperature();
  float humidity = dht.readHumidity();

  displayTime(hour, minute, second);
  displayTemperatureAndHumidity(temperature, humidity);
  checkAlarms(hour, minute);
  setDateTime();
  setAlarms();
}

void displayTime(int hour, int minute, int second) {
  lcd.setCursor(0, 0);
  lcd.print("Time: ");
  lcd.print(hour);
  lcd.print(":");
  if (minute < 10) {
    lcd.print("0");
  }
  lcd.print(minute);
  lcd.print(":");
  if (second < 10) {
    lcd.print("0");
  }
  lcd.print(second);
}

void displayTemperatureAndHumidity(float temperature, float humidity) {
  lcd.setCursor(0, 1);
  lcd.print("Temp: ");
  lcd.print(temperature, 1);
  lcd.print(" C");
  lcd.setCursor(9, 1);
  lcd.print("Humidity: ");
  lcd.print(humidity, 1);
  lcd.print(" %");
}

void checkAlarms(int hour, int minute) {
  if (digitalRead(buttonSetAlarm1) == LOW) {
    delay(200);
    alarm1Set = !alarm1Set;
  }

  if (digitalRead(buttonSetAlarm2) == LOW) {
    delay(200);
    alarm2Set = !alarm2Set;
  }

  if (alarm1Set && hour == setAlarm1Hour && minute == setAlarm1Minute) {
    tone(activeBuzzerPin, 2000, 1000);
  }

  if (alarm2Set && hour == setAlarm2Hour && minute == setAlarm2Minute) {
    tone(activeBuzzerPin, 2000, 1000);
  }
}

void setDateTime() {
  if (digitalRead(buttonSetHour) == LOW) {
    delay(200);
    setHour++;
    if (setHour > 23) {
      setHour = 0;
    }
  }

  if (digitalRead(buttonSetMinute) == LOW) {
    delay(200);
    setMinute++;
    if (setMinute > 59) {
      setMinute = 0;
    }
  }

  rtc.adjust(DateTime(2022, 1, 1, setHour, setMinute, 0));
}

void setAlarms() {
  if (digitalRead(buttonSetAlarm1) == LOW) {
    delay(200);
    setAlarm1Hour++;
    if (setAlarm1Hour > 23) {
      setAlarm1Hour = 0;
    }
  }

  if (digitalRead(buttonSetAlarm2) == LOW) {
    delay(200);
    setAlarm2Hour++;
    if (setAlarm2Hour > 23) {
      setAlarm2Hour = 0;
    }
  }
}

OP's diagram:

I didn't realize the crop cut the right side off. I can resubmit if need be, the things that were cut off were the DHT11, which is connected to digital pin 33, ground, and 5V. I also had the DS3231 there, which is connected to SDA, SCL, ground, and 3.3 V

Please don't bother. It's not useful. Please use a pen and paper and make a proper diagram. Don't forget to label all components, pins and connections.

Hopefully, this is better understood. The buttons are at the bottom

Hi,
Thanks for the diagram.

Do you have 4K7 pullup on the DHT11 signal output?

Do you have a DMM? Digital MultiMeter.

Thanks.. Tom... :smiley: :+1: :coffee: :australia: