Кнопка выбора задержки
Моя цель — создать систему 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 часа в виде бесконечного цикла.
@Ibrahim.M, 👍2
Обсуждение2 ответа
Лучший ответ:
В ответ на ваш комментарий к ответу Матея @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
Не используйте задержку, а 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
- Использование millis() и micros() внутри процедуры прерывания
- Как сделать очень долгую функцию delay(), несколько часов
- Разница между «time_t» и «DateTime»
- Получение BPM из данного кода
- Как считать время в секундах?
- Создание таймера с использованием часов реального времени с указанием времени начала и остановки
- Arduino непрерывно считывает значение АЦП с помощью прерывания
- Использование TIMER0_COMPB_vect
Я устал безрезультатно><
что это вообще значит? что ты уже испробовал? Вы вообще писали **ЛЮБОЙ** код?, @Jaromanda Xконечный автомат, запускаемый прерываниями, @MichaelT