Выключение светодиода

Я пытаюсь сделать 2 сигнала тревоги для 2 разных времен, используя 2 светодиода, которые должны включаться, когда время соответствует установленному времени, а затем, если нажать кнопку, светодиод должен выключиться. Для первого сигнала тревоги первый светодиод может быть выключен с помощью кнопки, вместо этого для второго сигнала тревоги включается второй светодиод, но если кнопка нажата, то он не выключится, даже если это тот же код. Что я могу сделать, чтобы выключить второй светодиод?

#include <RTClib.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2); 
int nowHr, nowMin, nowSec;
RTC_DS3231 rtc;


int h1 = 15;
int m1 = 51;
int h2 = 15;
int m2 = 52 ;
int pin_buton1 = 8;
int stop_buton =9;
int state_stop_buton = 0;

int led1_pin = 6;
int state_led = LOW;
int pushpressed = 0;

int led2_pin = 7;
int state_led2 = LOW;


void setup()
{

  Wire.begin();
  //rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));           
  rtc.adjust(DateTime(2021, 03, 27, 15, 50, 50));                
 

  lcd.backlight();
  lcd.begin(16, 2);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Welcome To Our");                                     
  lcd.setCursor(0, 1);
  lcd.print("device");



  pinMode(pin_buton1, INPUT);
  pinMode(stop_buton, INPUT);
  pinMode(led1_pin, OUTPUT);
  pinMode(led2_pin, OUTPUT);
  delay(2000);
  Serial.begin(9600);
}




void loop() {
  timeScreen();
  first_alarm();
  stopPins();
  second_alarm();
  stopPins2();

  state_stop_buton = digitalRead(stop_buton);

}



void timeScreen() {              

  DateTime now = rtc.now();             
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Time:");
  lcd.setCursor(6, 0);
  lcd.print(nowHr = now.hour(), DEC);
  lcd.print(":");
  lcd.print(nowMin = now.minute(), DEC);
  lcd.print(":");
  lcd.print(nowSec = now.second(), DEC);
  lcd.setCursor(0, 1);
  lcd.print("Date: ");
  lcd.print(now.day(), DEC);
  lcd.print("/");
  lcd.print(now.month(), DEC);
  lcd.print("/");
  lcd.print(now.year(), DEC);
  delay(500);

}



void stopPins() {                   
  if (state_stop_buton == 1) {

    pushpressed =1;
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("first message ");
    lcd.setCursor(0, 1);
    lcd.print("was read");
    delay(1200);
    lcd.clear();
  }
}

void startBuzz() {                    

  
  if (pushpressed == 0) {
   
    if (state_led == LOW) {                 
      state_led = HIGH;
      digitalWrite(led1_pin, state_led);
     
    }
  }
  else if (pushpressed == 1) {

   
    state_led = LOW;
    digitalWrite(led1_pin, state_led);
  }
}



void first_alarm() {
  DateTime t = rtc.now();
  if (int(t.hour()) == h1 && int(t.minute()) == m1) {

    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("first ");
    lcd.setCursor(0, 1);
    lcd.print("text");
    startBuzz();
    delay(5000);

  }
}



//

void stopPins2() {                   
  if (state_stop_buton == 1) {

    pushpressed = 1;
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("second message ");
    lcd.setCursor(0, 1);
    lcd.print("was read ");
    delay(1200);
    lcd.clear();
  }
}

void startBuzz2() {                   

  
  if (pushpressed == 1) {
   
 
    if (state_led2 == LOW) {                 
      state_led2 = HIGH;
      digitalWrite(led2_pin, state_led2);
  
    }
  }
  else  if (pushpressed == 0 ) {
    state_led2 = LOW;
   digitalWrite(led2_pin, state_led2);
 }
}



void second_alarm() {
  DateTime t = rtc.now();
  if (int(t.hour()) == h2 && int(t.minute()) == m2   ) {

    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("second");
    lcd.setCursor(0, 1);
    lcd.print("text");
    startBuzz2();
    delay(5000);

  }
}

, 👍4


1 ответ


3

1. pushpressed устанавливается, но никогда не сбрасывается.

Он устанавливается в stopPins() и stopPins2 (), если вход HIGH. Поскольку он никогда не сбрасывается обратно в ноль, как только он установлен, логика в startBuzz и startBuzz2 будет следовать за одним проходом. Вы создали защелкнутый переключатель.


Общие вещи


2. Непоследовательное именование: затрудняет чтение кода

Выберите snake_case или camelCase или smashitalltogether (не рекомендуется) и придерживайтесь его :) То же самое относится и к "типам" переменных: некоторые вещи называются xxx pin xxx, некоторые-xxx state xxx, некоторые-нет. Это яснее, когда одно и то же-вещи называются-одно и то же.

3. Дублирование: затрудняет понимание кода

Наряду с именованием (по существу) дублированный код затрудняет отслеживание проблем, как вы заметили, пытаясь отладить эту проблему. Существует масса способов уменьшить код, чтобы сделать его понятным. Ореховая скорлупа состоит в том, чтобы определить различия в подобном коде и сделать меньше сразу.

(И если вы хотите довести его до логического завершения, то упаковка каждого сигнала тревоги в класс устранит все дублирование и большинство параметров функции :)


Досадное отвлечение объяснений


Давайте посмотрим на startBuzz и startBuzz2.

void startBuzz() {
  if (pushpressed == 0) {
    if (state_led == LOW) {
      state_led = HIGH;
      digitalWrite(led1_pin, state_led);
    }
  } else if (pushpressed == 1) {
    state_led = LOW;
    digitalWrite(led1_pin, state_led);
  }
}

void startBuzz2() {
  if (pushpressed == 1) {
    if (state_led2 == LOW) {
      state_led2 = HIGH;
      digitalWrite(led2_pin, state_led2);
    }
  } else if (pushpressed == 0) {
    state_led2 = LOW;
    digitalWrite(led2_pin, state_led2);
  }
}

Единственное, что здесь отличается, - это вывод светодиода и состояние светодиода. Давайте нормализуем наше именование, чтобы все стало ясно, используя startBuzz в качестве примера. Мы также предположим, что pushPressed может быть только 0 или 1 (ВЫСОКИЙ или НИЗКИЙ):

void startBuzz() {
  if (pushPressed == LOW) {
    if (led1State == LOW) {
      led1State = HIGH;
      digitalWrite(led1Pin, led1State);
    }
  } else {
    led1State = LOW;
    digitalWrite(led1Pin, led1State);
  }
}

Мы можем сделать эту работу для любого из светодиодов, выполнив две вещи: принимая pin и текущее состояние и возвращая новое состояние. Зачем возвращать новое состояние вместо того, чтобы установить его здесь? Это упрощает основной код (и позволяет избежать передачи ссылки).

void startBuzz(int ledPin, int ledState) {
  int newLedState = ledState;
  
  if (pushPressed == LOW) {
    if (ledState == LOW) {
      newLedState = HIGH;
      digitalWrite(ledPin, newLedState);
    }
  } else {
    newLedState = LOW;
    digitalWrite(ledPin, newLedState);
  }
  
  return newLedState;
}

Затем, когда мы вызываем startBuzz или startBuzz2, мы заменяем текущий код следующим:

led1State = startBuzz(led1Pin, led1State);

Мы еще не закончили.

Поскольку мы сохраняем исходное состояние ledState, мы можем удалить дублированные вызовы digitalWrite; в худшем случае у нас будет лишняя запись при нажатии pushPressed != LOW && ledState != HIGH.

Поскольку все условия, кроме одного, приводят к НИЗКОМУ значению, нам даже не нужно сохранять исходное состояние. И так как это два условия, чтобы перевернуть его HIGH, мы можем объединить их. И если мы вытащим цифровую запись, то на самом деле просто рассчитаем следующее состояние-оно не зависит от светодиодного штифта.

void getNextLedState(int ledState) {
  return (pushPressed == LOW && ledState == LOW) ? HIGH : LOW;
}

А сайты вызовов выглядят примерно так:

led1State = getNextLedState(led1State);
digitalWrite(led1Pin, led1State);

Аналогично для сигналов тревоги: создайте функцию checkAlarm, которая принимает часы и минуты и возвращает логическое значение. В цикле вызовите checkAlarm(h1, m1) и, если true, вызовите runAlarm1(). (Даже это можно было бы уменьшить еще больше, но вы поняли идею.) стопПинс отличается только строками, записанными на жидкокристаллический дисплей. И так далее.

,

Что ж, это обернулось множеством слов. Вот что происходит, когда я нахожусь в середине написания книги., @Dave Newton

большое вам спасибо за ваш ответ, я думаю, что мне придется несколько раз прочитать ваши инструкции, а затем применить их. Удачи вам с книгой!, @Biancaaa

@biancaaa Я сделаю аналогичную схему и опубликую свой код где-нибудь и опубликую ссылку. Недостаточно скоро, чтобы помочь тебе, бит эй :), @Dave Newton

извините , если я вас беспокою, но я последовал вашему совету о сбросе кнопки "Стоп", но я не могу с этим справиться. Перед окончанием void startBuzz я написал "pushpressed = 0;", но он все еще не работает @Dave Newton, @Biancaaa

@Biancaaa, возможно, опубликует ваш текущий код в gist или здесь; Я могу взглянуть через час или два., @Dave Newton

пустота startBuzz() { если (нажато == 0) { если (состояние светодиода == НИЗКОЕ) { Состояние светодиода = ВЫСОКОЕ; } Цифровая запись(ledPin, ledState); } иначе, если (нажато == 1) { Состояние светодиода = НИЗКОЕ; Цифровая запись(ledPin, ledState); } нажато = 0; } ', @Biancaaa

итак, это правка, которую я внес в код. Я новичок в этой области (arduino), но я обращу внимание на советы, которые вы объяснили выше о функциях. Если в функции startBuzz я установил значение нажата на 0, индикатор первого сигнала тревоги не будет окончательно выключен при нажатии кнопки, вместо этого второй индикатор второго сигнала тревоги может быть выключен при нажатии той же кнопки., @Biancaaa