Arduino Uno的中断问题

Arduino Uno的中断问题,arduino,interrupt,Arduino,Interrupt,我在Arduino UNO工作时会被打断。在这个项目中,我想在门打开时LED闪烁10次,当门再次关闭时,停止闪烁LED并退出该功能。但在此代码中,LED只打开和关闭一次,不会再次闪烁。 我的另一个问题是,当门打开或关闭时,有时“打开”或“关闭”字会在串行监视器中出现几次 const byte LED_Red = 13; const byte DOOR_SENSOR = 2; // magnetic door sensor pin volatile int SensorState = LOW;

我在Arduino UNO工作时会被打断。在这个项目中,我想在门打开时LED闪烁10次,当门再次关闭时,停止闪烁LED并退出该功能。但在此代码中,LED只打开和关闭一次,不会再次闪烁。 我的另一个问题是,当门打开或关闭时,有时“打开”或“关闭”字会在串行监视器中出现几次

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()
{
}
const byte LED_Red=13;
常数字节门_传感器=2;//磁性车门传感器引脚
易失性int传感器状态=低;//0关闭-1打开wwitch
无效设置()
{
Serial.begin(9600);
引脚模式(LED_红色,输出);
pinMode(车门传感器,输入上拉);
连接中断(数字插针中断(门传感器)、动作、改变);
}
无效DoAction()
{
SensorState=数字读取(车门传感器);
如果(传感器状态==高){
序列号。打印号(“打开”);
闪烁(10500);
}
否则{
序列号。打印号(“已关闭”);
}
}
无效闪烁(整数重复,整数时间)
{
for(int i=0;i
您不能简单地在中断函数上设置一个
延迟()。您只需在门打开时设置一个标志,并基于主环路内的开始
闪烁

我还建议您使用
millis()
功能在
blinkLED
功能内解除阻塞延迟(例如,当您想在车门关闭时停止闪烁时)

const byte LED_Red=13;
常数字节门_传感器=2;//磁性车门传感器引脚
//检查门是否打开的标志
易失性bool-isOpened=false;
//要检查的标志已闪烁
volatile bool isBlinked=false;
无效设置()
{
Serial.begin(9600);
引脚模式(LED_红色,输出);
pinMode(车门传感器,输入上拉);
连接中断(数字插针中断(门传感器)、动作、改变);
}
无效DoAction()
{
if(数字读取(车门传感器)=高)
{
//序列号。打印号(“打开”);
等间距=真;
}
其他的
{
等间距=假;
isBlinked=false;
//序列号。打印号(“已关闭”);
}
}
无效闪烁(整数重复,整数时间)
{
字节LEDState=低;
无符号长延迟_开始=毫秒();
对于(int i=0;i<2*重复;i++)
{
//切换LED状态
如果(LEDState==高)
LEDState=低;
其他的
LEDState=高;
//设定值
数字写入(LED_红色,LED状态);
//一些解锁延迟
while(毫秒()-延迟启动<时间)
{
//门关上时返回
如果(!等间距)
{
//关闭LED
数字写入(LED_红色,低电平);
返回;
}
}
延迟启动=毫秒();
}
isBlinked=true;
}
void循环()
{
//选中isBlinked beacue在门关闭之前不想再次闪烁
如果(等色显示和等色显示)
{
闪烁(10500);
}
}

您不能简单地在中断函数上设置一个
延迟()。您只需在门打开时设置一个标志,并基于主环路内的开始
闪烁

我还建议您使用
millis()
功能在
blinkLED
功能内解除阻塞延迟(例如,当您想在车门关闭时停止闪烁时)

const byte LED_Red=13;
常数字节门_传感器=2;//磁性车门传感器引脚
//检查门是否打开的标志
易失性bool-isOpened=false;
//要检查的标志已闪烁
volatile bool isBlinked=false;
无效设置()
{
Serial.begin(9600);
引脚模式(LED_红色,输出);
pinMode(车门传感器,输入上拉);
连接中断(数字插针中断(门传感器)、动作、改变);
}
无效DoAction()
{
if(数字读取(车门传感器)=高)
{
//序列号。打印号(“打开”);
等间距=真;
}
其他的
{
等间距=假;
isBlinked=false;
//序列号。打印号(“已关闭”);
}
}
无效闪烁(整数重复,整数时间)
{
字节LEDState=低;
无符号长延迟_开始=毫秒();
对于(int i=0;i<2*重复;i++)
{
//切换LED状态
如果(LEDState==高)
LEDState=低;
其他的
LEDState=高;
//设定值
数字写入(LED_红色,LED状态);
//一些解锁延迟
while(毫秒()-延迟启动<时间)
{
//门关上时返回
如果(!等间距)
{
//关闭LED
数字写入(LED_红色,低电平);
返回;
}
}
延迟启动=毫秒();
}
isBlinked=true;
}
void循环()
{
//选中isBlinked beacue在门关闭之前不想再次闪烁
如果(等色显示和等色显示)
{
闪烁(10500);
}
}

我进一步建议不要在您的ISR中添加打印报表。从Arduino文档中可以看出:“一般来说,ISR应该尽可能短和快”。打印报表在时间上通常非常“昂贵”。您可以在此处阅读更多内容:@GMc谢谢我编辑了代码并注释掉了这些行。谢谢您的帮助回答代码运行良好,我通过添加一个新的中断来扩展程序。现在我想知道是否有可能去掉循环函数。我认为我们不断地检查循环中的变量来判断值是否发生了变化不是一个好主意。编写程序不是更好吗,这样只有当程序中断时,才检查这些变量的值?这个问题有什么解决办法吗?@hamidmousavi是的,你可以在中断例程中调用
blinkLED
,但问题是
millis()
不会导致
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);
    }
}