Нужна помощь: Кнопка, тайминг, реле
- Войдите на сайт для отправки комментариев
Пнд, 11/08/2014 - 10:11
Здравствуйте!
Помогите мне пожалуйста со скетчем, с апаратной я знаком.
Алгоритм такой:
Ардуинка при включении слушает кнопку на пине №X, и при нажатии, включает реле на пине №Y на 6 секунд 19 милисекунд в это время ардуинка на кнопку не реагирует (то-есть таймер на 6 секунд 19 милисекунд не перезапускает), а по истечению этого времени, не реагирует еще 10 секунд 53 милисекунды и сново уходит в ожидание команды с кнопки.
Нужно использовать функцию millis() , две константы#define RELAY_ON 6019 и #define RELAY_OFF 10053. Еще должна быть некоторая переменная offset, которая будет точкой отсчета для сравнения с millis(). также нужна переменная флаг для того чтобы нажатие на кнопку не вызывали никаких действий.
в цикле loop пишем: если кнопка нажата и флаг не установлен то установить флаг, задать точку отсчета, включить реле. Еще один оператор сравнеия - если флаг установлне и millis() - offset больше или равно константе RELAY_ON то выключить реле. Еще один оператор сравнения - если флаг установлен и millis() - offset больше или равно сумме констант RELAY_ON и RELAY_OFF то снять флаг.
Если проект расти не будет, то вполне сойдёт и delay(). Чтобы не реагировать на кнопку после запуска таймера, можно ввести переменную-флаг, состояние которой будет указывать на состояние кнопки, была нажата, или нет.
#define button 2 // кнопка #define relay 1 // реле void setup(){ pinMode(button,INPUT_PULLUP); // кнопка на вход вкл.подтягивающий резистор. pinMode(relay,OUTPUT); // реле на выход } void loop() { if (!digitalRead(button)) // нажали кнопку digitalWrite(relay,HIGH); // включили реле }Попробуйте вот так (реле на пин 13):
bool _gen1I = 0; bool _gen1O = 0; unsigned long _gen1P = 0UL; bool _kp1 = 0; bool _tim1I = 0; bool _tim1O = 0; unsigned long _tim1P = 0UL; bool _ktim1 = 0; bool _bounseInput2S = 0; bool _bounseInput2O = 0; unsigned long _bounseInput2P = 0UL; void setup() { pinMode(2, INPUT); digitalWrite(2, HIGH); pinMode(13, OUTPUT); _bounseInput2O = digitalRead(2); } void loop() { bool _bounceTmp2 = (digitalRead (2)); if (_bounseInput2S) { if (millis() >= (_bounseInput2P + 40)) { _bounseInput2O= _bounceTmp2; _bounseInput2S=0; } } else { if (_bounceTmp2 != _bounseInput2O ) { _bounseInput2S=1; _bounseInput2P = millis(); } } if((!_bounseInput2O)&& (!(_ktim1))){ _kp1 = 1; } if(_ktim1&& (!((!_bounseInput2O)))){ _kp1 = 0; } if (_kp1) { if (_tim1I) { if (_isTimer(_tim1P, 5000)) { _tim1O = 1; } } else { _tim1I =1; _tim1P = millis(); } } else { _tim1O = 0; _tim1I = 0; } if(_tim1O) { _ktim1 = 1; } else { _ktim1 = 0; } if (_kp1) { if (! _gen1I){ _gen1I = 1; _gen1O = 1; _gen1P = millis(); } } else { _gen1I = 0 ; _gen1O= 0; } if (_gen1I && _gen1O) _gen1O = !( _isTimer( _gen1P , 5000 )); if(_gen1O) { digitalWrite (13, 1); } else { digitalWrite (13, 0); } } bool _isTimer(unsigned long startTime, unsigned long period ) { unsigned long currentTime; currentTime = millis(); if (currentTime>= startTime) { return (currentTime>=(startTime + period)); } else { return (currentTime >=(4294967295-startTime+period)); } }Попробуйте вот так (реле на пин 13):
bool _gen1I = 0; bool _gen1O = 0; unsigned long _gen1P = 0UL; bool _kp1 = 0; bool _tim1I = 0; bool _tim1O = 0; unsigned long _tim1P = 0UL; bool _ktim1 = 0; bool _bounseInput2S = 0; bool _bounseInput2O = 0; unsigned long _bounseInput2P = 0UL; void setup() { pinMode(2, INPUT); digitalWrite(2, HIGH); pinMode(13, OUTPUT); _bounseInput2O = digitalRead(2); } void loop() { bool _bounceTmp2 = (digitalRead (2)); if (_bounseInput2S) { if (millis() >= (_bounseInput2P + 40)) { _bounseInput2O= _bounceTmp2; _bounseInput2S=0; } } else { if (_bounceTmp2 != _bounseInput2O ) { _bounseInput2S=1; _bounseInput2P = millis(); } } if((!_bounseInput2O)&& (!(_ktim1))){ _kp1 = 1; } if(_ktim1&& (!((!_bounseInput2O)))){ _kp1 = 0; } if (_kp1) { if (_tim1I) { if (_isTimer(_tim1P, 5000)) { _tim1O = 1; } } else { _tim1I =1; _tim1P = millis(); } } else { _tim1O = 0; _tim1I = 0; } if(_tim1O) { _ktim1 = 1; } else { _ktim1 = 0; } if (_kp1) { if (! _gen1I){ _gen1I = 1; _gen1O = 1; _gen1P = millis(); } } else { _gen1I = 0 ; _gen1O= 0; } if (_gen1I && _gen1O) _gen1O = !( _isTimer( _gen1P , 5000 )); if(_gen1O) { digitalWrite (13, 1); } else { digitalWrite (13, 0); } } bool _isTimer(unsigned long startTime, unsigned long period ) { unsigned long currentTime; currentTime = millis(); if (currentTime>= startTime) { return (currentTime>=(startTime + period)); } else { return (currentTime >=(4294967295-startTime+period)); } }Спасибо. Вроде работает.
Но почему для такой простой функции нужен такой огромный код ?
Подругому не как ?
1SANTER1, ваш случай удобно реализовать используя внешнее прерывание (вывод под кнопку не изменять). Кнопка нажата - ничего. Кнопка -отжата, и счёт 5 секунд пошёл, я правильно понял?
#define button 2 // кнопка #define relay 13 // реле volatile bool flag=0; volatile unsigned long prevmillis; void setup(){ pinMode(button,INPUT_PULLUP); // кнопка на вход вкл.подтягивающий резистор. pinMode(relay,OUTPUT); // реле на выход attachInterrupt(0, my_func, RISING); //прерывание на возрастание лог. уровня } void loop() { if (flag==1) { // если кнопку отжали digitalWrite(relay,HIGH); //включаем что-то if ( millis()-prevmillis >=5000){ //если счёт 5 секунд вышел, то digitalWrite(relay,LOW); //отключаем что-то flag=0; //сбрасываем флаг работы } } } void my_func() { //отжали flag=1; //ставим флаг что работа идёт.. prevmillis= millis(); //запомним время }1SANTER1, ваш случай удобно реализовать используя внешнее прерывание (вывод под кнопку не изменять). Кнопка нажата - ничего. Кнопка -отжата, и счёт 5 секунд пошёл, я правильно понял?
#define button 2 // кнопка #define relay 13 // реле volatile bool flag=0; volatile unsigned long prevmillis; void setup(){ pinMode(button,INPUT_PULLUP); // кнопка на вход вкл.подтягивающий резистор. pinMode(relay,OUTPUT); // реле на выход attachInterrupt(0, my_func, RISING); //прерывание на возрастание лог. уровня } void loop() { if (flag==1) { // если кнопку отжали digitalWrite(relay,HIGH); //включаем что-то if ( millis()-prevmillis >=5000){ //если счёт 5 секунд вышел, то digitalWrite(relay,LOW); //отключаем что-то flag=0; //сбрасываем флаг работы } } } void my_func() { //отжали flag=1; //ставим флаг что работа идёт.. prevmillis= millis(); //запомним время }Несовсем так. Нажимается кнопка и с ней включается реле, через 5 секунд реле должно выключится деже если кнопка остается нажатой.
Спасибо. Вроде работает.
Но почему для такой простой функции нужен такой огромный код ?
Подругому не как ?
В каком смысле большой? Если по количеству строк, ну так выкинте из него защиту от дребезга. Будет немного меньше.
1SANTER1, ну тогда по идее только слово RISING поменять на FALLING
1SANTER1, ну тогда по идее только слово RISING поменять на FALLING
Ага :) Огромное вам спасибо.
Топикстартера нет, а про решение второй части вопроса никто не написал.
а по истечению этого времени, не реагирует еще 10 секунд 53 милисекунды и сново уходит в ожидание команды с кнопки.
Так скетч из 4 сообщения вам не подходит? Поменяйте тайминги и всё. По топикстартеру:
bool _gen1I = 0; bool _gen1O = 0; unsigned long _gen1P = 0UL; bool _kp1 = 0; bool _tim1I = 0; bool _tim1O = 0; unsigned long _tim1P = 0UL; bool _ktim1 = 0; bool _bounseInput2S = 0; bool _bounseInput2O = 0; unsigned long _bounseInput2P = 0UL; void setup() { pinMode(2, INPUT); digitalWrite(2, HIGH); pinMode(13, OUTPUT); _bounseInput2O = digitalRead(2); } void loop() { bool _bounceTmp2 = (digitalRead (2)); if (_bounseInput2S) { if (millis() >= (_bounseInput2P + 40)) { _bounseInput2O = _bounceTmp2; _bounseInput2S = 0; } } else { if (_bounceTmp2 != _bounseInput2O ) { _bounseInput2S = 1; _bounseInput2P = millis(); } } if ((!_bounseInput2O) && (!(_ktim1))) { _kp1 = 1; } if (_ktim1 && (!((!_bounseInput2O)))) { _kp1 = 0; } if (_kp1) { if (_tim1I) { if (_isTimer(_tim1P, 16720)) { _tim1O = 1; } } else { _tim1I = 1; _tim1P = millis(); } } else { _tim1O = 0; _tim1I = 0; } if (_tim1O) { _ktim1 = 1; } else { _ktim1 = 0; } if (_kp1) { if (! _gen1I) { _gen1I = 1; _gen1O = 1; _gen1P = millis(); } } else { _gen1I = 0 ; _gen1O = 0; } if (_gen1I && _gen1O) _gen1O = !( _isTimer( _gen1P , 6190 )); if (_gen1O) { digitalWrite (13, 1); } else { digitalWrite (13, 0); } } bool _isTimer(unsigned long startTime, unsigned long period ) { unsigned long currentTime; currentTime = millis(); if (currentTime >= startTime) { return (currentTime >= (startTime + period)); } else { return (currentTime >= (4294967295 - startTime + period)); } }У меня получилось так
#include <Timer_P.h> #define RELAY_PIN 13 #define KEY_PIN 2 Timer_P RelayOn, RelayBlock; long Pulse_ms = 6019, Block_ms = 10063; bool RelayOnQO_Old = false; void setup(){ pinMode(KEY_PIN, INPUT_PULLUP); pinMode(RELAY_PIN, OUTPUT); } void loop(){ RelayOn.TimerV(!digitalRead(KEY_PIN) && !RelayOn.Q0(), RelayBlock.Q0(), 1, Pulse_ms); RelayBlock.TimerV(!RelayOn.Q0() && RelayOnQO_Old, 0, 1, Block_ms); digitalWrite (RELAY_PIN, RelayOn.Q0()); RelayOnQO_Old = RelayOn.Q0(); }Библиотека Timer_P.h здесь
https://github.com/X-Dron/X-Dron_lib/archive/master.zip
Это для схемы со стягивающим резистором (INPUT_PULLUP и !digitalRead(KEY_PIN)