Hamid Mousavi
Hamid Mousavi

Reputation: 223

Problem with interruptions in Arduino Uno

I work with interruptions in Arduino UNO. In this project, I want to when the Door is opened the LED blink 10 times, and when the door is closed again, stop blinking the LED and exit the function. But in this code the LED only turn on and off once and it does not flash again. My other problem is that, when the door is opened or closed, sometimes the opened or closed word appears several times in the Series monitor.

const byte LED_Red = 13;
const byte DOOR_SENSOR = 2; // magnetic door sensor pin

volatile int SensorState = LOW; // 0 close - 1 open wwitch

void setup()
{
Serial.begin(9600);
pinMode(LED_Red, OUTPUT);
pinMode(DOOR_SENSOR, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(DOOR_SENSOR), DoAction, CHANGE);
}

void DoAction()
{
    SensorState = digitalRead(DOOR_SENSOR);
    if (SensorState == HIGH) {
    Serial.println("Opened");
    blinkLED(10, 500);
}
    else {
    Serial.println("Closed");
        }
}

void blinkLED(int repeats, int time)
{
    for (int i = 0; i < repeats; i++) {
        if (SensorState == HIGH) {
        digitalWrite(LED_Red, HIGH);
        delay(time);
        digitalWrite(LED_Red, LOW);
        delay(time);
    }
    else
        return;
}
}

void loop()
{
}

Upvotes: 0

Views: 975

Answers (1)

Masoud Rahimi
Masoud Rahimi

Reputation: 6031

You can't simply put a delay() on an interrupt's function. You need to just set a flag when the door is opened and based on that start blinkLED inside the main loop.

I also recommend you to use millis() function for an unblocking delay inside blinkLED function (e.g when you want to stop blinking while the door is closed).

const byte LED_Red = 13;
const byte DOOR_SENSOR = 2; // magnetic door sensor pin

// flag to check door is opened
volatile bool isOpened = false;

//flag to check already blinked
volatile bool isBlinked = false;

void setup()
{
    Serial.begin(9600);
    pinMode(LED_Red, OUTPUT);
    pinMode(DOOR_SENSOR, INPUT_PULLUP);
    attachInterrupt(digitalPinToInterrupt(DOOR_SENSOR), DoAction, CHANGE);
}

void DoAction()
{
    if (digitalRead(DOOR_SENSOR) == HIGH)
    {
        //Serial.println("Opened");
        isOpened = true;
    }
    else
    {
        isOpened = false;
        isBlinked = false;
        //Serial.println("Closed");
    }
}

void blinkLED(int repeats, int time)
{
    byte LEDState = LOW;
    unsigned long delay_start = millis();
    for (int i = 0; i < 2 * repeats; i++)
    {
        //Toggle LED state
        if (LEDState == HIGH)
            LEDState = LOW;
        else
            LEDState = HIGH;
        // set value
        digitalWrite(LED_Red, LEDState);
        // some unblocking delay
        while (millis() - delay_start < time)
        {
            // return if door is closed
            if (!isOpened)
            {
                // turn off LED
                digitalWrite(LED_Red, LOW);
                return;
            }
        }
        delay_start = millis();
    }
    isBlinked = true;
}

void loop()
{
    // Check isBlinked beacue don't want to blink again until door is closed
    if (isOpened && !isBlinked)
    {
        blinkLED(10, 500);
    }
}

Upvotes: 2

Related Questions