Проблема с прерываниями в Arduino Uno - PullRequest
0 голосов
/ 25 мая 2019

Я работаю с перебоями в Arduino UNO. В этом проекте я хочу, чтобы при открытии двери светодиод мигал 10 раз, а когда дверь снова закрылась, перестал мигать светодиод и вышел из функции. Но в этом коде светодиод включается и выключается только один раз, и он не мигает снова. Моя другая проблема заключается в том, что когда дверь открывается или закрывается, иногда на мониторе серии появляется несколько раз открытое или закрытое слово.

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()
{
}

1 Ответ

2 голосов
/ 26 мая 2019

Вы не можете просто поставить delay() на функцию прерывания.Вам нужно просто установить флаг, когда дверь открыта, и исходя из этого запуска blinkLED внутри основного цикла.

Я также рекомендую использовать функцию millis() для задержки разблокировки внутри функции blinkLED(например, когда вы хотите прекратить мигать, когда дверь закрыта).

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);
    }
}
...