Кнопка выбора задержки

Моя цель — создать систему Arduino, которая сможет переключать режимы с разными задержками, нажимая кнопку. Например, если я нажму кнопку, она перейдет в режим 1 с циклом 1 с задержкой 30 секунд. Если я нажму его еще раз, он перейдет в режим 2 с циклом 2 с задержкой в 1 минуту и т. д. Важно то, что режим 1 должен прерываться при нажатии кнопки.

Приведенный ниже код решил часть проблемы. Однако светодиоды горят постоянно, они не мигают определенное время, а затем загораются или выключаются в режиме при нажатии кнопки.

int b =3;int rl= 5;int gl=6;
int yl=7; int s=0; int o=0;
 int bp =0;

void setup() {
  // поместите сюда свой код установки для однократного запуска:
pinMode(b,INPUT);
pinMode(rl,OUTPUT);
pinMode(gl,OUTPUT);
pinMode(yl,OUTPUT);

 digitalWrite(rl,LOW);
digitalWrite(gl,LOW);
digitalWrite(yl,LOW);
}

void loop() {
  // поместите сюда свой основной код для многократного запуска:

bp=digitalRead(b);
if (bp==1){
  delay(50);
  bp=digitalRead(b);
  if (bp==0){
    s=o+1;}}
    else{
      delay(100);}
      switch(s){
        case 1:
        digitalWrite(rl,HIGH);
digitalWrite(gl,LOW);
digitalWrite(yl,LOW);
o=s;
break;

case 2 :
digitalWrite(rl,LOW);
digitalWrite(gl,HIGH);
digitalWrite(yl,LOW);
o=s;
break;

case 3:

digitalWrite(rl,LOW);
digitalWrite(gl,LOW);
digitalWrite(yl,HIGH);
o=s;
break;
default:

digitalWrite(rl,LOW);
digitalWrite(gl,LOW);
digitalWrite(yl,LOW);
o=0;
break;}}

Схема подключения

S1 отвечает за постоянное включение D12 (при однократном нажатии), что приводит к включению питания UNO2, а затем миганию правого светодиода: ВКЛ (1 мин) и ВЫКЛ (4 часа), (двойное нажатие должно выключить D12 (необязательно) ). То же самое и с S2: при однократном нажатии он должен сначала отключить D12 и вместо этого активировать D11, подавая питание UNO3, мигая левым светодиодом ВКЛ (30 с), ВЫКЛ (4 часа).

Кроме того, необходимо многократное мигание on() off() (если действие не прерывается/не происходит, например: нажатие S1 или S2).

О S1 и S2. Светодиод на D12 будет мигать в течение 1 минуты, а затем погаснет на 4 часа. По истечении 4 часов светодиод на D12 снова замигает на 1 минуту, затем снова погаснет на 4 часа. снова... как бесконечный цикл. При использовании S2 светодиод на D11 будет мигать в течение 30 секунд, а затем погаснет на 4 часа. По истечении 4 часов светодиод D11 снова замигает на 30 секунд, а затем снова и снова погаснет на 4 часа в виде бесконечного цикла.

, 👍2

Обсуждение

Я устал безрезультатно>< что это вообще значит? что ты уже испробовал? Вы вообще писали **ЛЮБОЙ** код?, @Jaromanda X

конечный автомат, запускаемый прерываниями, @MichaelT


2 ответа


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

0

В ответ на ваш комментарий к ответу Матея @Ibrahim.M: «Мне хотелось бы сократить его до одного UNO, который может выполнять ту же задачу с помощью программирования». Вы можете сделать это всего с одним Uno.

Я бы начал с обнаружения нажатий кнопок и устранения их дребезга. Это легко сделать с помощью библиотеки Bounce2. Вы можете использовать кнопки для запуска таймеров, которые будут включать и выключать светодиоды.

Чтобы заставить светодиод мигать и следить за временем, вы можете использовать функцию millis(). Я начал с учебника BlinkWithoutDelay и получил следующий скетч. У него только один таймер/светодиод, но в скетче достаточно информации, чтобы понять, как сделать второй таймер/светодиод.

#include <Bounce2.h>

byte led1State = LOW;
byte timer1Active = 0;
const byte led1Pin = LED_BUILTIN;
const byte buttonPin1 = 6;
const byte buttonPin2 = 7;
unsigned int timer1Counter = 0;
const unsigned long debouncerInterval = 50;
const unsigned long oneSecond = 1000;
unsigned long previousMillis = 0;

Bounce debouncer = Bounce();
Bounce debouncer2 = Bounce();

void setup(){
  Serial.begin(9600);
  debouncer.attach(buttonPin1, INPUT_PULLUP);
  debouncer.interval(debouncerInterval);
  debouncer2.attach(buttonPin2, INPUT_PULLUP);
  debouncer2.interval(debouncerInterval);
  pinMode(led1Pin, OUTPUT);
}

void loop(){

  unsigned long currentMillis = millis();

  // Таймер на 4 часа 30 секунд.
  if((currentMillis - previousMillis >= oneSecond) && (timer1Active == 1)){
    previousMillis = currentMillis;
    timer1Counter++;
    if(timer1Counter < 31){
      //if(led1State == НИЗКИЙ){
        led1State = HIGH;
      //}
      //еще{
        //led1State = НИЗКИЙ;
      //}
      digitalWrite(led1Pin, led1State);
    }
    else if(timer1Counter == 31){
      digitalWrite(led1Pin, LOW);
    }

    // 60 секунд X 60 минут X 4 часа + 30 секунд.
    if(timer1Counter > 14430){
      timer1Counter = 0;
    }
  }

  // Кнопка 1
  if(debouncer.update()){
    if(debouncer.read() == 0){
      Serial.println("Start 30 second ON, 4 hour OFF timer.");
      timer1Active = 1;
      timer1Counter = 0;
    }
  }

  // Кнопка 2
  if(debouncer2.update()){
    if(debouncer2.read() == 0){
      Serial.println("Start 1 minute ON, 4 hour OFF timer.");
      timer1Active = 0;
      digitalWrite(led1Pin, LOW);
    }
  }

}

На основе этой части вашего последнего комментария «У меня есть трюк! 'const unsigned long oneSecond = 1000;' следует отредактировать на «const unsigned long oneSecond = 10;» это приведет к тому, что светодиод будет постоянно включен. Похоже, вы хотите, чтобы светодиод оставался включенным постоянно в течение 30 или 60 секунд. Я «закомментировал» 5 строк приведенного выше скетча, чтобы это произошло.

,

Матей и VE7JRO, вы замечательные люди, большое вам спасибо., @Ibrahim.M


0

Не используйте задержку, а millis(). Пример:

#define BTN 2
#define MAX_MODE 1   //2 modes

const unsigned int times[] = {1000, 2000};

unsigned int time = times[0];

unsigned long btn_tm = 0;
unsigned long l_time = 0;

byte mode = 0;



void setup(){
  Serial.begin(9600);
  pinMode(BTN, INPUT);
}

void loop(){
  if(digitalRead(BTN) == 1 && millis() - btn_tm > 200){
    btn_tm = millis();
    mode ++
    if(mode > MAX_MODE) mode = 0;
    time = times[mode];
 } 
  if(millis() - l_time >= time){
    l_time = millis();
    if(mode == 0) Serial.println("mode 0");
    if(mode == 1) Serial.println("mode 1");
 } 
}

Прочитайте и попробуйте.

,

Спасибо, Матей. В коде есть ошибка, связанная с этой частью: ' if(mode > MAX_MODES) mode = 0; ', пожалуйста, как мне добавить светодиоды в качестве выхода для каждого режима?, @Ibrahim.M

Можно ли сделать так, чтобы код внутри ссылки выполнял каждый *случай*, упомянутый в коде моей темы? где тогда для каждого случая будет свое время [https://www.arduino.cc/en/tutorial/BlinkWithoutDelay], @Ibrahim.M

@Ibrahim.MI исправил эту ошибку, это было неправильное имя переменной. Если вы хотите использовать код по ссылке, удалите эту часть из кода `if(millis() - l_time >= time){ l_time = millis(); if(режим == 0) Serial.println("режим 0"); if(mode == 1) Serial.println("режим 1"); } ` и вместо него поместите внутрь код if(mode == 0){ }, который находится в loop() из вашей ссылки., @Matej

@Ibrahim.M И для вашего первого комментария просто поместите pinMode() в setup() выше настройки, поместите bool state = 0; и в if(mode == 0){ } put digitalWrite(светодиод, состояние); состояние = !state;, @Matej

Спасибо, Матей, я ценю это. К сожалению, моя проблема до сих пор не решена. Я предполагаю, что микросхема Uno не может делать то, что я хочу (например, желтая кнопка активирует контакт 9 на 1 минуту каждые 6 часов, тогда как синяя кнопка активирует контакт 10 на 30 секунд каждые 6 часов)., @Ibrahim.M

Я только что загрузил изображение с электрической схемой с длинным хвостом по этой ссылке: https://i.stack.imgur.com/Cg3k0.jpg. Мне бы хотелось сократить его до одной UNO, способной выполнить ту же задачу с помощью программирования., @Ibrahim.M

@Ibrahim.M Напиши 3 кода на 3 уноса и я помогу тебе эти коды объединить., @Matej