Push Button Interrupt to read and display time from DS3231 in Serial Monitor

OK, I am having all sorts of issues, and do not know how fix it. I’ve now spent a total of 18 hours trying to get this to work, and I’m ready to microwave something.

All I want to do is use the following code with an ISR to read and display the time from the DS3231 into the Serial Monitor, if a button is pressed.

#include "Wire.h"
#define DS3231_I2C_ADDRESS 0x68
const int BUTTON = 2; //pin # of the pushbutton
volatile int buttonState = 0;

// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
  return ( (val / 10 * 16) + (val % 10) );
}
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
  return ( (val / 16 * 10) + (val % 16) );
}
void setup()
{
  pinMode(BUTTON, INPUT);
  attachInterrupt(digitalPinToInterrupt(2), pin_ISR, FALLING);
  Wire.begin();
  Serial.begin(9600);
  // set the initial time here:
  // DS3231 seconds, minutes, hours, day, date, month, year
  // setDS3231time(25,55,21,3,14,11,17);
}
void setDS3231time(byte second, byte minute, byte hour, byte dayOfWeek, byte
                   dayOfMonth, byte month, byte year)
{
  // sets time and date data to DS3231
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0); // set next input to start at the seconds register
  Wire.write(decToBcd(second)); // set seconds
  Wire.write(decToBcd(minute)); // set minutes
  Wire.write(decToBcd(hour)); // set hours
  Wire.write(decToBcd(dayOfWeek)); // set day of week (1=Sunday, 7=Saturday)
  Wire.write(decToBcd(dayOfMonth)); // set date (1 to 31)
  Wire.write(decToBcd(month)); // set month
  Wire.write(decToBcd(year)); // set year (0 to 99)
  Wire.endTransmission();
}
void readDS3231time(byte *second,
                    byte *minute,
                    byte *hour,
                    byte *dayOfWeek,
                    byte *dayOfMonth,
                    byte *month,
                    byte *year)
{
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0); // set DS3231 register pointer to 00h
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
  // request seven bytes of data from DS3231 starting from register 00h
  *second = bcdToDec(Wire.read() & 0x7f);
  *minute = bcdToDec(Wire.read());
  *hour = bcdToDec(Wire.read() & 0x3f);
  *dayOfWeek = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month = bcdToDec(Wire.read());
  *year = bcdToDec(Wire.read());
}
void displayTime()
{
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  // retrieve data from DS3231
  readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month,
                 &year);
  // send it to the serial monitor
  Serial.print(hour, DEC);
  // convert the byte variable to a decimal number when displayed
  Serial.print(":");
  if (minute < 10)
  {
    Serial.print("0");
  }
  Serial.print(minute, DEC);
  Serial.print(":");
  if (second < 10)
  {
    Serial.print("0");
  }
  Serial.print(second, DEC);
  Serial.print(" ");
  Serial.print(dayOfMonth, DEC);
  Serial.print("/");
  Serial.print(month, DEC);
  Serial.print("/");
  Serial.print(year, DEC);
  Serial.print(" Day of week: ");
  switch (dayOfWeek) {
    case 1:
      Serial.println("Sunday");
      break;
    case 2:
      Serial.println("Monday");
      break;
    case 3:
      Serial.println("Tuesday");
      break;
    case 4:
      Serial.println("Wednesday");
      break;
    case 5:
      Serial.println("Thursday");
      break;
    case 6:
      Serial.println("Friday");
      break;
    case 7:
      Serial.println("Saturday");
      break;
  }
}

void pin_ISR()
{
  displayTime();
}

void loop()
{
  Serial.println("5");
  delay(5000);
  Serial.println("10");
  delay(5000);
  Serial.println("15");
  delay(5000);
  Serial.println("20");
  delay(5000);
  Serial.println("25");
  delay(5000);
  Serial.println("30");
  delay(5000);
  Serial.println("35");
  delay(5000);
  Serial.println("40");
  delay(5000);
  Serial.println("45");
  delay(5000);
  Serial.println("50");
}

Here’s what I run into. If I put ANYTHING and I mean anything into the ISR section of my code, it messes up.

void pin_ISR() 
{

}

My output on the serial monitor freezes up. I’ve tried RISING, FALLING, CHANGE and LOW

I’ve tried adding the following code and I still have the same issue

void pin_ISR()
{
buttonState = digitalRead(BUTTON);
if (buttonState == HIGH) 
{ displayTime();
}

What am I doing wrong?

Which Arduino board are you using ?

Arduino UNO.

Your ISR is way too complicated.

Try something like this (untested)

volatile byte buttonPressed;

void pin_ISR() {
  buttonPressed = true;
}

unsigned long lastPrint = -5000;
byte dispCount = 5;

void loop() {
  unsigned long topLoop = millis();
  if (topLoop - lastPrint >= 5000) {
    lastPrint = topLoop;
    Serial.println(dispCount);
    dispCount += 5;
    if (dispCount > 50) {
      dispCount = 5;
    }
  }
  if (buttonPressed) {
    displayTime();
    buttonPressed = false;
  }
}

I replaced the delay junk with a non-blocking variant and let the ISR only set a flag,
which triggers the printout in loop context.

Added: If you don't have an external pullup on the button, INPUT_PULLUP is useful.
(Since you trigger on FALLING, I assume your button closes to GND.)

Whandall:
Your ISR is way too complicated.

Try something like this (untested)

volatile byte buttonPressed;

void pin_ISR() {
  buttonPressed = true;
}

unsigned long lastPrint = -5000;
byte dispCount = 5;

void loop() {
  unsigned long topLoop = millis();
  if (topLoop - lastPrint >= 5000) {
    lastPrint = topLoop;
    Serial.println(dispCount);
    dispCount += 5;
    if (dispCount > 50) {
      dispCount = 5;
    }
  }
  if (buttonPressed) {
    displayTime();
    buttonPressed = false;
  }
}



I replaced the delay junk with a non-blocking variant and let the ISR only set a flag,
which triggers the printout in loop context.

Added: If you don't have an external pullup on the button, INPUT_PULLUP is useful.
(Since you trigger on FALLING, I assume your button closes to GND.)

Dude, I owe you a beer.

Works perfectly. Thanks 1,000,000.

Never mind. :wink:

Keep ISRs as fast as possible and loop running freely.

A good reference here: https://www.gammon.com.au/interrupts