Есть ли лучший способ объединить оператор if с ISR?

В моем скетче при срабатывании прерывания переменная состояния переключается с высокого на низкий уровень и наоборот. В зависимости от состояния переменной у меня есть оператор if в основном цикле, который вызовет функцию alarm_On, если состояние высокое, а часть else условного оператора вызовет функцию alarm_Off, если прерывание сработает во второй раз. Таким образом, я хочу, чтобы это условие if запускалось только при срабатывании прерывания. Во всех других случаях я хочу запустить другой код, но если он касается тех же компонентов, например, светодиодов, другой код не выполняется. Если это не общий компонент, то он работает нормально. Как решить эту проблему с "общим компонентом"?

 // Аналоговые устройства ввода
# define humiditySensor A5

// Тревожный вход
# define alarmButton 2 // Кнопка

// Устройства вывода
# define redLed 10
# define yellowLed 11
# define greenLed 12
# define waterPump 9 // светодиод на реле
# define spk 5

// Переменные
volatile byte alarm = LOW;

void setup() {
  pinMode (alarmButton, INPUT);
  pinMode (redLed, OUTPUT);
  pinMode (yellowLed, OUTPUT);
  pinMode (greenLed, OUTPUT);
  pinMode (waterPump, OUTPUT);
  attachInterrupt(digitalPinToInterrupt(alarmButton), ISR_Alarm, RISING);
  Serial.begin(9600);
}

void loop() {
  if (alarm == 1) {
    alarm_On();
  } else if (alarm == 0) {
    alarm_Off();
  }
  int humVal = analogRead(humiditySensor);
  Serial.println(humVal);
  if (humVal >= 500) {
    digitalWrite(redLed, HIGH);
  } else {
    digitalWrite(redLed, LOW);
  }
} // пустой цикл

void ISR_Alarm () {
  alarm = !alarm;  // переключение функции будильника при нажатии более одного раза
}

void alarm_On() {
  tone (spk, 100);
  digitalWrite(waterPump, HIGH);
  static byte ledState = LOW;
  static unsigned long oldTime = 0;
  if (millis() - oldTime >= 250) { // цикл для мигания светодиодов в аварийной ситуации
    oldTime = millis();
    if (ledState == LOW) {
      digitalWrite(redLed, HIGH);
      digitalWrite(yellowLed, HIGH);
      digitalWrite(greenLed, HIGH);
      ledState = HIGH;
    } else {
      digitalWrite(redLed, LOW);
      digitalWrite(yellowLed, LOW);
      digitalWrite(greenLed, LOW);
      ledState = LOW;
    }
  }
} // конец сигнала тревоги в функции

void alarm_Off () {
  noTone (spk);
  digitalWrite(redLed, LOW);
  digitalWrite(yellowLed, LOW);
  digitalWrite(greenLed, LOW);
  digitalWrite(waterPump, LOW);
} // конец функции отключения будильника

void high_Humidity() {
  digitalWrite(waterPump, HIGH);
}

void low_Humidity() {
  digitalWrite(waterPump, LOW);
}

, 👍0

Обсуждение

первый оператор if-else неправильно сформулирован, @jsotola

насколько я могу судить, ваш код не блокируется .... вы сможете без проблем добавлять дополнительные функции в loop(), @jsotola

код alarm_On() не нуждается в кодовом блоке if (ledState) ...... используйте ledState = ((ledState == LOW) ? HIGH : LOW); следует с помощью digitalWrite(redLed, ledState); и т. д., @jsotola

Он блокирует код, если я хочу что-то сделать с компонентами/датчиками, упомянутыми в функциях arlam_on и alarm_Off. Единственный случай, когда это не мешает, - это когда код не включает эти компоненты., @Zaffresky

@jsotola вы также упоминаете, что первое выражение if-else сформулировано неправильно. Подскажите, пожалуйста, как правильно сформулировать?, @Zaffresky

операторы else не должны иметь с ними условия., @Delta_G

@Zaffresky, погуглите c++ if-else, @jsotola

Это даже компилируется? } еще (тревога == 0) {, @Thomas Weller

@ThomasWeller, нет, код не компилируется ... компилятор возвращает «ожидаемый»; перед ошибкой '{' token` .... OP небрежно представил нерабочий код, @jsotola

Извините, что плохо, но я убрал ошибки и повторно вставил код., @Zaffresky


1 ответ


Лучший ответ:

0

Ваш код не заблокирован, но каждый цикл вызывается ON или OFF, поэтому ваши изменения в «общих» компонентах перезаписываются довольно быстро.

Не отслеживать состояние внутри IRQ. Вы можете сделать что-то вроде:

volatile byte alarm = 1;
byte alarm_state = 1;

void ISR_Alarm () {
    alarm = 1;  
}

void loop() {
    if (alarm){
        alarm = 0;

        if (alarm_state) {
            alarm_state = 0;
            alarm_Off();
        } else {
            alarm_state = 1;
            alarm_On();
        }
    }

    // другой код
}
,

Я использовал «блокировку» в другом контексте, но код действительно не блокируется. Было легче понять с вашим примером кода. Спасибо, @Zaffresky