DS3231 + кнопка для включения подсветки

пожалуйста, кто-нибудь может помочь мне с кодом, я хочу иметь автоматический запуск в определенный час, также я хочу иметь переключатель кнопок, если это необходимо, в моем коде я могу нажать кнопку для запуска светового реле, но мой конкретный триггер времени просто мигает во время запуска и ничего не делает, вот код:

#include <LiquidCrystal_I2C.h> 
#include <DS3231.h>
LiquidCrystal_I2C lcd(0x27, 2, 1,0,4,5,6,7,3, POSITIVE);
DS3231  rtc(SDA, SCL);
Time t;

const int OnSec = 30;
const int OffSec = 5;
int relay_3 = 5 ;

void setup() { 
 lcd.begin(20,4); 
 rtc.begin();

 pinMode(relay_3,OUTPUT);                 
 pinMode(8, INPUT_PULLUP);
}

void loop() {
  int button_4 = digitalRead(8);
  t = rtc.getTime();
  lcd.setCursor(0,1);
  lcd.print(rtc.getTimeStr());


  if(t.sec == OnSec)                                  // if равно hh.mm.30 - только для 1 секунды срабатывания реле
  {
  digitalWrite(5,HIGH);
  }
    else if(t.sec == OffSec)                         //если равно hh.mm.05 - реле отключения
  {
  digitalWrite(5,LOW);
  }   
      else if (button_4 == HIGH)                     //если кнопка нажата - срабатывает реле
  {
  digitalWrite(5,HIGH);
  } 
        else
  {
  digitalWrite(5,LOW);
  }

  lcd.clear();
}

я был бы благодарен за любой совет :)

, 👍1

Обсуждение

отступ кода в поле если ... блок else действительно испорчен, @jsotola

последняя команда "еще" является виновником ... очень тщательно подумайте обо всем "если"... блок "остальное", @jsotola


1 ответ


1

Случай else выполняется каждый раз, когда другие условия if и else if не выполняются. Это означает, что если прошло не 5 секунд и не 30 секунд и ни одна кнопка не нажата, реле выключается.

Добиться того, чего вы хотите, не так-то просто, потому что вам нужно синхронизировать нажатие и отпускание кнопок с действиями таймера. Сначала вы должны указать, что именно вы хотите сделать. например, что произойдет, если вы уже нажали кнопку и отпустите ее в промежутке времени между 30 и 5. Отпускание кнопки выключит индикатор, но должен ли он оставаться включенным, потому что вы находитесь в пределах времени включения? Это всего лишь пример того, о чем нужно подумать.

Я написал небольшой код для развлечения, делая все так, как я бы это сделал:

#include <LiquidCrystal_I2C.h> 
#include <DS3231.h>
LiquidCrystal_I2C lcd(0x27, 2, 1,0,4,5,6,7,3, POSITIVE);
DS3231  rtc( SDA, SCL );
Time t;

const int OnSec = 30;
const int OffSec = 5;
int relay_3 = 5;

int timerPhase = -1;
int relayState = LOW;

void setup() 
{ 
 lcd.begin( 20, 4 ); 
 rtc.begin();

 pinMode( relay_3, OUTPUT );                 
 pinMode( 8, INPUT_PULLUP );
}

void loop() 
{
  t = rtc.getTime( );

  int button_4 = digitalRead( 8 );

  lcd.setCursor( 0, 1 );
  lcd.print( rtc.getTimeStr( ) );

  // это работает только в том случае, если время выключения 
  // меньше, чем в срок. (OffSec < ONsec)
  timerPhase = ( (t.sec > OffSec) && ( t.sec < OnSec ) ) ? 0 : 1;

  if ( button_4 == HIGH )
  {
    // кнопка переопределяет фазу
    relayState = HIGH;   
  }
  else
  {
    if ( timerPhase == 0 )
    {
      relayState = LOW;
    } 
    else
    {
      relayState = HIGH;
    } 
  }

  digitalWrite( relay_3, relayState );

  lcd.clear();
}

Я не мог попробовать код, потому что я не знаю, какие библиотеки вы использовали, и поэтому получил ошибки компилятора. Так что в моем коде могут быть синтаксические ошибки, но я надеюсь, что написал правильный код. Было бы неплохо, если бы вы сообщали об ошибках здесь, если вы найдете один / несколько ;-).

Линия

timerPhase = ( (t.sec > OffSec) && ( t.sec < OnSec ) ) ? 0 : 1;

использует троичный оператор. Это означает, что если условие ( (t.sec > OffSec) && (t.sec < ONsec ) ) истинно, возьмите первую альтернативу 0 и присвоите ее переменной timerPhase, если оно равно false, выберите вторую альтернативу '1'.

,