Нужна помощь: Кнопка, тайминг, реле
- Войдите на сайт для отправки комментариев
Пнд, 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 то снять флаг.
1
bool
isWork;
//флаг
2
long
offset;
//точка отсчета
3
4
isWork = True;
//Установим флаг
5
offset = millis();
//зададим точку отсчета
Если проект расти не будет, то вполне сойдёт и delay(). Чтобы не реагировать на кнопку после запуска таймера, можно ввести переменную-флаг, состояние которой будет указывать на состояние кнопки, была нажата, или нет.
1
01
#define button 2 // кнопка
02
#define relay 1 // реле
03
void
setup
(){
04
pinMode(button,INPUT_PULLUP);
// кнопка на вход вкл.подтягивающий резистор.
05
pinMode(relay,OUTPUT);
// реле на выход
06
}
07
void
loop
()
08
{
09
if
(!digitalRead(button))
// нажали кнопку
10
digitalWrite(relay,HIGH);
// включили реле
11
12
}
Попробуйте вот так (реле на пин 13):
001
bool
_gen1I = 0;
002
bool
_gen1O = 0;
003
unsigned
long
_gen1P = 0UL;
004
bool
_kp1 = 0;
005
bool
_tim1I = 0;
006
bool
_tim1O = 0;
007
unsigned
long
_tim1P = 0UL;
008
bool
_ktim1 = 0;
009
bool
_bounseInput2S = 0;
010
bool
_bounseInput2O = 0;
011
unsigned
long
_bounseInput2P = 0UL;
012
void
setup
()
013
{
014
pinMode(2, INPUT);
015
digitalWrite(2, HIGH);
016
pinMode(13, OUTPUT);
017
018
_bounseInput2O = digitalRead(2);
019
}
020
void
loop
()
021
{
022
bool
_bounceTmp2 = (digitalRead (2));
023
024
if
(_bounseInput2S)
025
{
026
if
(millis() >= (_bounseInput2P + 40))
027
{
028
_bounseInput2O= _bounceTmp2;
029
_bounseInput2S=0;
030
}
031
}
032
else
033
{
034
if
(_bounceTmp2 != _bounseInput2O )
035
{
036
_bounseInput2S=1;
037
_bounseInput2P = millis();
038
}
039
}
040
041
if
((!_bounseInput2O)&& (!(_ktim1))){
042
_kp1 = 1;
043
}
044
if
(_ktim1&& (!((!_bounseInput2O)))){
045
_kp1 = 0;
046
}
047
if
(_kp1)
048
{
049
if
(_tim1I) {
050
if
(_isTimer(_tim1P, 5000)) {
051
_tim1O = 1;
052
}
053
}
054
else
{
055
_tim1I =1;
056
_tim1P = millis();
057
}
058
}
059
else
{
060
_tim1O = 0;
061
_tim1I = 0;
062
}
063
if
(_tim1O)
064
{
065
_ktim1 = 1;
066
}
067
else
068
{
069
_ktim1 = 0;
070
}
071
if
(_kp1) {
072
if
(! _gen1I){
073
_gen1I = 1;
074
_gen1O = 1;
075
_gen1P = millis();
076
}
077
}
078
else
{
079
_gen1I = 0 ;
080
_gen1O= 0;
081
}
082
if
(_gen1I && _gen1O) _gen1O = !( _isTimer( _gen1P , 5000 ));
083
if
(_gen1O)
084
{
085
digitalWrite (13, 1);
086
}
087
else
088
{
089
digitalWrite (13, 0);
090
}
091
}
092
bool
_isTimer(unsigned
long
startTime, unsigned
long
period )
093
{
094
unsigned
long
currentTime;
095
currentTime = millis();
096
if
(currentTime>= startTime) {
097
return
(currentTime>=(startTime + period));
098
}
099
else
{
100
return
(currentTime >=(4294967295-startTime+period));
101
}
102
}
Попробуйте вот так (реле на пин 13):
001
bool
_gen1I = 0;
002
bool
_gen1O = 0;
003
unsigned
long
_gen1P = 0UL;
004
bool
_kp1 = 0;
005
bool
_tim1I = 0;
006
bool
_tim1O = 0;
007
unsigned
long
_tim1P = 0UL;
008
bool
_ktim1 = 0;
009
bool
_bounseInput2S = 0;
010
bool
_bounseInput2O = 0;
011
unsigned
long
_bounseInput2P = 0UL;
012
void
setup
()
013
{
014
pinMode(2, INPUT);
015
digitalWrite(2, HIGH);
016
pinMode(13, OUTPUT);
017
018
_bounseInput2O = digitalRead(2);
019
}
020
void
loop
()
021
{
022
bool
_bounceTmp2 = (digitalRead (2));
023
024
if
(_bounseInput2S)
025
{
026
if
(millis() >= (_bounseInput2P + 40))
027
{
028
_bounseInput2O= _bounceTmp2;
029
_bounseInput2S=0;
030
}
031
}
032
else
033
{
034
if
(_bounceTmp2 != _bounseInput2O )
035
{
036
_bounseInput2S=1;
037
_bounseInput2P = millis();
038
}
039
}
040
041
if
((!_bounseInput2O)&& (!(_ktim1))){
042
_kp1 = 1;
043
}
044
if
(_ktim1&& (!((!_bounseInput2O)))){
045
_kp1 = 0;
046
}
047
if
(_kp1)
048
{
049
if
(_tim1I) {
050
if
(_isTimer(_tim1P, 5000)) {
051
_tim1O = 1;
052
}
053
}
054
else
{
055
_tim1I =1;
056
_tim1P = millis();
057
}
058
}
059
else
{
060
_tim1O = 0;
061
_tim1I = 0;
062
}
063
if
(_tim1O)
064
{
065
_ktim1 = 1;
066
}
067
else
068
{
069
_ktim1 = 0;
070
}
071
if
(_kp1) {
072
if
(! _gen1I){
073
_gen1I = 1;
074
_gen1O = 1;
075
_gen1P = millis();
076
}
077
}
078
else
{
079
_gen1I = 0 ;
080
_gen1O= 0;
081
}
082
if
(_gen1I && _gen1O) _gen1O = !( _isTimer( _gen1P , 5000 ));
083
if
(_gen1O)
084
{
085
digitalWrite (13, 1);
086
}
087
else
088
{
089
digitalWrite (13, 0);
090
}
091
}
092
bool
_isTimer(unsigned
long
startTime, unsigned
long
period )
093
{
094
unsigned
long
currentTime;
095
currentTime = millis();
096
if
(currentTime>= startTime) {
097
return
(currentTime>=(startTime + period));
098
}
099
else
{
100
return
(currentTime >=(4294967295-startTime+period));
101
}
102
}
Спасибо. Вроде работает.
Но почему для такой простой функции нужен такой огромный код ?
Подругому не как ?
1SANTER1, ваш случай удобно реализовать используя внешнее прерывание (вывод под кнопку не изменять). Кнопка нажата - ничего. Кнопка -отжата, и счёт 5 секунд пошёл, я правильно понял?
01
#define button 2 // кнопка
02
#define relay 13 // реле
03
volatile
bool
flag=0;
04
volatile unsigned
long
prevmillis;
05
06
void
setup
(){
07
pinMode(button,INPUT_PULLUP);
// кнопка на вход вкл.подтягивающий резистор.
08
pinMode(relay,OUTPUT);
// реле на выход
09
attachInterrupt(0, my_func, RISING);
//прерывание на возрастание лог. уровня
10
}
11
12
void
loop
() {
13
14
if
(flag==1) {
// если кнопку отжали
15
digitalWrite(relay,HIGH);
//включаем что-то
16
if
( millis()-prevmillis >=5000){
//если счёт 5 секунд вышел, то
17
digitalWrite(relay,LOW);
//отключаем что-то
18
flag=0;
//сбрасываем флаг работы
19
}
20
}
21
}
22
23
void
my_func() {
//отжали
24
flag=1;
//ставим флаг что работа идёт..
25
prevmillis= millis();
//запомним время
26
}
1SANTER1, ваш случай удобно реализовать используя внешнее прерывание (вывод под кнопку не изменять). Кнопка нажата - ничего. Кнопка -отжата, и счёт 5 секунд пошёл, я правильно понял?
01
#define button 2 // кнопка
02
#define relay 13 // реле
03
volatile
bool
flag=0;
04
volatile unsigned
long
prevmillis;
05
06
void
setup
(){
07
pinMode(button,INPUT_PULLUP);
// кнопка на вход вкл.подтягивающий резистор.
08
pinMode(relay,OUTPUT);
// реле на выход
09
attachInterrupt(0, my_func, RISING);
//прерывание на возрастание лог. уровня
10
}
11
12
void
loop
() {
13
14
if
(flag==1) {
// если кнопку отжали
15
digitalWrite(relay,HIGH);
//включаем что-то
16
if
( millis()-prevmillis >=5000){
//если счёт 5 секунд вышел, то
17
digitalWrite(relay,LOW);
//отключаем что-то
18
flag=0;
//сбрасываем флаг работы
19
}
20
}
21
}
22
23
void
my_func() {
//отжали
24
flag=1;
//ставим флаг что работа идёт..
25
prevmillis= millis();
//запомним время
26
}
Несовсем так. Нажимается кнопка и с ней включается реле, через 5 секунд реле должно выключится деже если кнопка остается нажатой.
Спасибо. Вроде работает.
Но почему для такой простой функции нужен такой огромный код ?
Подругому не как ?
В каком смысле большой? Если по количеству строк, ну так выкинте из него защиту от дребезга. Будет немного меньше.
1SANTER1, ну тогда по идее только слово RISING поменять на FALLING
1SANTER1, ну тогда по идее только слово RISING поменять на FALLING
Ага :) Огромное вам спасибо.
Топикстартера нет, а про решение второй части вопроса никто не написал.
а по истечению этого времени, не реагирует еще 10 секунд 53 милисекунды и сново уходит в ожидание команды с кнопки.
Так скетч из 4 сообщения вам не подходит? Поменяйте тайминги и всё. По топикстартеру:
01
bool
_gen1I = 0;
02
bool
_gen1O = 0;
03
unsigned
long
_gen1P = 0UL;
04
bool
_kp1 = 0;
05
bool
_tim1I = 0;
06
bool
_tim1O = 0;
07
unsigned
long
_tim1P = 0UL;
08
bool
_ktim1 = 0;
09
bool
_bounseInput2S = 0;
10
bool
_bounseInput2O = 0;
11
unsigned
long
_bounseInput2P = 0UL;
12
void
setup
()
13
{
14
pinMode(2, INPUT);
15
digitalWrite(2, HIGH);
16
pinMode(13, OUTPUT);
17
18
_bounseInput2O = digitalRead(2);
19
}
20
void
loop
()
21
{
22
bool
_bounceTmp2 = (digitalRead (2));
23
24
if
(_bounseInput2S)
25
{
26
if
(millis() >= (_bounseInput2P + 40))
27
{
28
_bounseInput2O = _bounceTmp2;
29
_bounseInput2S = 0;
30
}
31
}
32
else
33
{
34
if
(_bounceTmp2 != _bounseInput2O )
35
{
36
_bounseInput2S = 1;
37
_bounseInput2P = millis();
38
}
39
}
40
if
((!_bounseInput2O) && (!(_ktim1))) {
41
_kp1 = 1;
42
}
43
if
(_ktim1 && (!((!_bounseInput2O)))) {
44
_kp1 = 0;
45
}
46
if
(_kp1)
47
{
48
if
(_tim1I) {
49
if
(_isTimer(_tim1P, 16720)) {
50
_tim1O = 1;
51
}
52
}
else
{
53
_tim1I = 1;
54
_tim1P = millis();
55
}
56
}
else
{
57
_tim1O = 0;
58
_tim1I = 0;
59
}
60
if
(_tim1O)
61
{
62
_ktim1 = 1;
63
}
64
else
65
{
66
_ktim1 = 0;
67
}
68
if
(_kp1) {
69
if
(! _gen1I) {
70
_gen1I = 1;
71
_gen1O = 1;
72
_gen1P = millis();
73
}
74
}
else
{
75
_gen1I = 0 ;
76
_gen1O = 0;
77
}
if
(_gen1I && _gen1O) _gen1O = !( _isTimer( _gen1P , 6190 ));
78
if
(_gen1O)
79
{ digitalWrite (13, 1);
80
}
81
else
82
{ digitalWrite (13, 0);
83
}
84
}
85
bool
_isTimer(unsigned
long
startTime, unsigned
long
period )
86
{
87
unsigned
long
currentTime;
88
currentTime = millis();
89
if
(currentTime >= startTime) {
90
return
(currentTime >= (startTime + period));
91
}
else
{
92
return
(currentTime >= (4294967295 - startTime + period));
93
}
94
}
У меня получилось так
01
#include <Timer_P.h>
02
#define RELAY_PIN 13
03
#define KEY_PIN 2
04
05
Timer_P RelayOn, RelayBlock;
06
long
Pulse_ms = 6019, Block_ms = 10063;
07
bool
RelayOnQO_Old =
false
;
08
09
void
setup
(){
10
pinMode(KEY_PIN, INPUT_PULLUP);
11
pinMode(RELAY_PIN, OUTPUT);
12
}
13
14
void
loop
(){
15
RelayOn.TimerV(!digitalRead(KEY_PIN) && !RelayOn.Q0(), RelayBlock.Q0(), 1, Pulse_ms);
16
RelayBlock.TimerV(!RelayOn.Q0() && RelayOnQO_Old, 0, 1, Block_ms);
17
digitalWrite (RELAY_PIN, RelayOn.Q0());
18
RelayOnQO_Old = RelayOn.Q0();
19
}
Библиотека Timer_P.h здесь
https://github.com/X-Dron/X-Dron_lib/archive/master.zip
Это для схемы со стягивающим резистором (INPUT_PULLUP и !digitalRead(KEY_PIN)