Нужна помощь: Кнопка, тайминг, реле

SC-LERA
Offline
Зарегистрирован: 11.08.2014

Здравствуйте!

Помогите мне пожалуйста со скетчем, с апаратной я знаком.

Алгоритм такой:

Ардуинка при включении слушает кнопку на пине №X, и при нажатии, включает реле на пине №Y на 6 секунд 19 милисекунд в это время ардуинка на кнопку не реагирует (то-есть таймер на 6 секунд 19 милисекунд не перезапускает), а по истечению этого времени, не реагирует еще 10 секунд 53 милисекунды и сново уходит в ожидание команды с кнопки.

NeiroN
NeiroN аватар
Offline
Зарегистрирован: 15.06.2013

Нужно использовать функцию millis() , две константы#define RELAY_ON 6019 и #define RELAY_OFF 10053. Еще должна быть некоторая переменная offset, которая будет точкой отсчета для сравнения с millis(). также нужна переменная флаг для того чтобы нажатие на кнопку не вызывали никаких действий.

в цикле loop пишем: если кнопка нажата и флаг не установлен то установить флаг, задать точку отсчета, включить реле. Еще один оператор сравнеия - если флаг установлне и millis() - offset больше или равно константе RELAY_ON то выключить реле. Еще один оператор сравнения - если флаг установлен и millis() - offset больше или равно сумме констант RELAY_ON и RELAY_OFF то снять флаг.

bool isWork; //флаг
long offset; //точка отсчета

isWork = True; //Установим флаг
offset = millis(); //зададим точку отсчета

 

Leshiy
Offline
Зарегистрирован: 19.07.2014

Если проект расти не будет, то вполне сойдёт и delay(). Чтобы не реагировать на кнопку после запуска таймера, можно ввести переменную-флаг, состояние которой будет указывать на состояние кнопки, была нажата, или нет. 

1SANTER1
1SANTER1 аватар
Offline
Зарегистрирован: 07.03.2015


Подскажите пожалуйста как решить задачу: Нажимаем кнопку и держим неизвестно сколько, (это будет не кнопка, а датчик,но пока кнопка)
Как только кнопка нажата, включается реле и работает 5 секунд, потом выключается и больше не включается до следующего нажатия на кнопку. Перерыл весь интернет нечего не нашёл, delay не подходит. Как решить незнаю :(  
#define button 2    // кнопка
#define relay  1    // реле
void setup(){
    pinMode(button,INPUT_PULLUP);    // кнопка на вход  вкл.подтягивающий резистор. 
    pinMode(relay,OUTPUT);           // реле на выход
}
void loop() 
{
  if (!digitalRead(button))           // нажали кнопку
    digitalWrite(relay,HIGH);         // включили реле
  
}

 

Kolchugin
Offline
Зарегистрирован: 15.12.2013

Попробуйте вот так (реле на пин 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
1SANTER1 аватар
Offline
Зарегистрирован: 07.03.2015

Kolchugin пишет:

Попробуйте вот так (реле на пин 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));
  }
}

 

Спасибо. Вроде работает.

Но почему для такой простой функции нужен такой огромный код ?

Подругому не как ?

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

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
1SANTER1 аватар
Offline
Зарегистрирован: 07.03.2015

dimax пишет:

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 секунд реле должно выключится деже если кнопка остается нажатой.

Kolchugin
Offline
Зарегистрирован: 15.12.2013

1SANTER1 пишет:

Спасибо. Вроде работает.

Но почему для такой простой функции нужен такой огромный код ?

Подругому не как ?

В каком смысле большой? Если по количеству строк, ну так выкинте из него защиту от дребезга. Будет немного меньше.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

1SANTER1, ну тогда по идее только слово RISING поменять на FALLING

1SANTER1
1SANTER1 аватар
Offline
Зарегистрирован: 07.03.2015

dimax пишет:

1SANTER1, ну тогда по идее только слово RISING поменять на FALLING

Ага :) Огромное вам спасибо.

X-Dron
Offline
Зарегистрирован: 24.01.2015

Топикстартера нет, а про решение второй части вопроса никто не написал.

SC-LERA пишет:

а по истечению этого времени, не реагирует еще 10 секунд 53 милисекунды и сново уходит в ожидание команды с кнопки.

Kolchugin
Offline
Зарегистрирован: 15.12.2013

X-Dron пишет:
Топикстартера нет, а про решение второй части вопроса никто не написал.
SC-LERA пишет:
а по истечению этого времени, не реагирует еще 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));
  }
}

 

X-Dron
Offline
Зарегистрирован: 24.01.2015

У меня получилось так

#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)