Arduino Uno Simple Interrupt Causes Program to Freeze

Hi, I want to use interrupt and used a very simple interrupt command to test it before proceeding for further coding. However whenever an interrupt occurs loop stops but interrupt routine does not work.

Normally during the loop I should see the date and time, changing every second.

When Interrupt happens, the screen freezes, nothing changes. If interrupt happens when servo is rotating then servo stops and again nothing happens on the screen.

Note that I'm using external power for all peripherals, so it is not a power issue.

Here is my code. I'm connecting interrupt pin to GND to start interrupt sequence.

#include <Wire.h> // Include IIC communication library
#include <LiquidCrystal_I2C.h> // Include LCD library
#include <RTClib.h> // Include RTC library
#include <Servo.h> // Include Servo library

Servo myservo; // Declare Servo name as myservo

#if defined(ARDUINO) && ARDUINO >= 100
#define printByte(args) write(args);
#else
#define printByte(args) print(args,BYTE);
#endif

uint8_t clock[8] = {0x0,0xe,0x15,0x17,0x11,0xe,0x0};

RTC_DS1307 RTC;
LiquidCrystal_I2C lcd(0x27,16,2); // Set the LCD address to 0x27 for a 16 chars and 2 line display

void setup()
{
Serial.begin(9600);
Wire.begin();
RTC.begin();
pinMode(2, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(2), setbuttonpressed, FALLING);
myservo.attach(10); // Servo is attached to pin 10
lcd.init(); // Initialize the lcd
lcd.backlight(); // Initialize LCD backlight
lcd.print("Curtain System"); // Print "Curtain System"
lcd.setCursor(0, 1); // Go to second line 1(second line) pixel zero(actually first)
lcd.print("Is Starting"); // Print "Is Starting"
delay(5000); // 2000ms delay
lcd.createChar(2, clock);

//RTC.adjust(DateTime(2019,5,9,0,30,0)); // Following line sets the RTC to the date & time this sketch was compiled,

}

void loop()
{
lcd.clear();
DateTime now = RTC.now(); // Describe now item
lcd.print(now.day(), DEC); // Print Day
lcd.print('.'); // Print .
lcd.print(now.month(), DEC); // Print Month
lcd.print('.'); // Print .
lcd.print(now.year(), DEC); // Print Year
lcd.print(' '); // Print Space

lcd.setCursor(0, 1); // Go to second line 1(second line) pixel zero(actually first)
lcd.printByte(2); // Print clock icon
lcd.print(" "); // Print Space
lcd.print(now.hour(), DEC); // Print Hour
lcd.print(':'); // Print :
lcd.print(now.minute(), DEC); // Print Minute
lcd.print(':'); // Print :
lcd.print(now.second(), DEC); // Print Second

delay(1000); // 1000ms delay and go back to beginning of loop, meaning renew screen every second

if((now.hour()>= 7) && (now.hour()<=19)) // If the hour is bigger than 7 and smaller than 19(During day)
// if((now.hour()>= 23 & now.minute() == 0 ) && (now.hour() <= 7 & now.minute() == 0 ))
{
lcd.clear();
lcd.print("Servo turns"); // Print "Servo turns"
lcd.setCursor(0,1); // Go to second line first pixel
lcd.print("counterclockwise"); // Print "counterclockwise"
myservo.attach(10); // Servo is attached to pin 10
myservo.write(45); // Turn servo counter clockwise
delay(5000); // For 2 seconds
myservo.write(90); // Stop servo
delay(1000);
myservo.detach(); // Servo is detached to stop jittering

while((now.hour()>=7) && (now.hour()<=19)) // Run an empty loop while the time is between 07:00-19:00. Exit when condition is invalid
{lcd.clear();
DateTime now = RTC.now(); // Describe now item
lcd.print(now.day(), DEC); // Print Day
lcd.print('.'); // Print .
lcd.print(now.month(), DEC); // Print Month
lcd.print('.'); // Print .
lcd.print(now.year(), DEC); // Print Year
lcd.print(' '); // Print Space
lcd.print("Curtn"); // Print "Curtn"

lcd.setCursor(0, 1); // Go to second line 1(second line) pixel zero(actually first)
lcd.printByte(2); // Print clock icon
lcd.print(" "); // Print Space
lcd.print(now.hour(), DEC); // Print Hour
lcd.print(':'); // Print :
lcd.print(now.minute(), DEC); // Print Minute
lcd.print(':'); // Print :
lcd.print(now.second(), DEC); // Print Second
lcd.print(' '); // Print Space
lcd.print("Opend"); // Print "Opend"

delay(1000); // 1000ms delay and go back to beginning of loop, meaning renew screen every second
}
}

else
{
lcd.clear();
lcd.print("Servo turns"); // Print "Servo turns"
lcd.setCursor(0, 1); // Go to second line first pixel
lcd.print("clockwise"); // Print "clockwise"
myservo.attach(10); // Servo is attached to pin 10
myservo.write(135); // Turn servo clockwise
delay(5000); // For 2 seconds
myservo.write(90); // Stop servo
delay(1000);
myservo.detach(); // Servo is detached to stop jittering

while((now.hour()>19) || (now.hour()<7)) // Run an empty loop while time is between 19:00-07:00. Exit when condition is invalid.
{
lcd.clear();
DateTime now = RTC.now(); // Describe now item
lcd.print(now.day(), DEC); // Print Day
lcd.print('.'); // Print .
lcd.print(now.month(), DEC); // Print Month
lcd.print('.'); // Print .
lcd.print(now.year(), DEC); // Print Year
lcd.print(' '); // Print Space
lcd.print("Curtn"); // Print "Curtn"

lcd.setCursor(0, 1); // Go to second line 1(second line) pixel zero(actually first)
lcd.printByte(2); // Print clock icon
lcd.print(" "); // Print Space
lcd.print(now.hour(), DEC); // Print Hour
lcd.print(':'); // Print :
lcd.print(now.minute(), DEC); // Print Minute
lcd.print(':'); // Print :
lcd.print(now.second(), DEC); // Print Second
lcd.print(' '); // Print Space
lcd.print("Closd"); // Print "Closd"

delay(1000); // 1000ms delay and go back to beginning of loop, meaning renew screen every second
}
}

}
void setbuttonpressed()
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("interrupt start");
delay(4000);
//Put date and time change menu here, include plus and minus buttons
}

The delay function uses interrupts to count milliseconds. Inside of an interrupt service routine, interrupts are disabled. See the problem? Also the print method uses interrupts so print does not work well in an ISR. Just set a flag in the ISR and do the printing and delay in loop if the flag is set (then clear the flag).

The blink without delay example and the beginner's millis() tutorial show how to do timing in a non blocking fashion,

Thanks for the reply. I've read millis() tutorial but I think it is too complicated for me now as I'm still beginner.

Can you write a sample for me to use a flag? How should I declare the flag? I've seen some examples but they look complicated for me.

I understand that inside the interrupt routine I should change the status of flag. However where should I write a condition attached to flag? Inside my main loop?

where should I write a condition attached to flag? Inside my main loop?

Yes, you put code to examine and react to the value of your flag variable in loop() but you must not have any blocking code in loop() or any functions called from it

Ok I've seen a basic example for interrupt, check below. In this code "state" is declared low in the beginning, in main loop there is a digitalwrite function that is connected to the status of state and interrupt routine changes "state" from low to high in the first interrupt, and then high to low in the next and so on.

So in my loop I can do that, however I've a big loop including if and while functions means there are loops inside the main loop.

If lets say I include a digitalwrite(ledpin, state) function inside my main loop that is connected to interrupt, then I should put this several times inside all the loops. And still I'll have some delay until I see the result of interrupt becuase my loops are generally turning beginning in 1second or more. Isnt there any other simple way to start it directly without any delay? If yes I would really appreciate if you can change the code below to give a simple example, as my code is too long.

const byte ledPin = 13;
const byte interruptPin = 2;
volatile byte state = LOW;

void setup() {
pinMode(ledPin, OUTPUT);
pinMode(interruptPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(interruptPin), blink, CHANGE);
}

void loop() {
digitalWrite(ledPin, state);
}

void blink() {
state = !state;
}

So in my loop I can do that, however I've a big loop including if and while functions means there are loops inside the main loop.

That is exactly what I warned you about

If lets say I include a digitalwrite(ledpin, state) function inside my main loop that is connected to interrupt,

I don't know what you mean by this. Do you mean that you would repeat the code to check the state of the flag variable and react to it at various places in the code ?

Isnt there any other simple way to start it directly without any delay?

Yes there is but you need to refactor your program. Read Using millis() for timing. A beginners guide, Several things at the same time and look at the BlinkWithoutDelay example in the IDE.

By doing timing using millis() you can keep loop() repeating thousands of time per second and make response to inputs seem instantaneous but, of curse, if you used that technique you would not need to use an interrupt in the first place.

Isn't there any other simple way to start it directly without any delay?

Define "simple".