Работа с кнопками. В помощь новичку.

bwn
Offline
Зарегистрирован: 25.08.2014

Хайтек шагает по планете. Влепи геркон и реле под торпеду и в путь.

Mercury
Offline
Зарегистрирован: 01.11.2017

bwn пишет:

Хайтек шагает по планете. Влепи геркон и реле под торпеду и в путь.

Это очень просто, ненадежно и палевно.

bwn
Offline
Зарегистрирован: 25.08.2014

Mercury пишет:

bwn пишет:

Хайтек шагает по планете. Влепи геркон и реле под торпеду и в путь.

Это очень просто, ненадежно и палевно.

Таки чем? Если я вскрою торпеду, то хоть дуина, хоть геркон, хоть супер сигналка, похрен. А не зная куды класть магнит хрен чего сделаешь, а кнопочки они на дурацкие мысли наводят.
Хотя из личного опыта, самая лучшая штука это стальная шняга на педаль. Два раза пробовали и оба бросили, только ключик под ковриками поискали.

Клапауций 112
Клапауций 112 аватар
Offline
Зарегистрирован: 01.03.2017

bwn пишет:

Хотя из личного опыта, самая лучшая штука это стальная шняга на педаль. Два раза пробовали и оба бросили, только ключик под ковриками поискали.

верно - я на угоны теперь только со своими педалями хожу. О_О

Mercury
Offline
Зарегистрирован: 01.11.2017

bwn пишет:

Mercury пишет:

bwn пишет:

Хайтек шагает по планете. Влепи геркон и реле под торпеду и в путь.

Это очень просто, ненадежно и палевно.

Таки чем? Если я вскрою торпеду, то хоть дуина, хоть геркон, хоть супер сигналка, похрен. А не зная куды класть магнит хрен чего сделаешь, а кнопочки они на дурацкие мысли наводят.
Хотя из личного опыта, самая лучшая штука это стальная шняга на педаль. Два раза пробовали и оба бросили, только ключик под ковриками поискали.

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

bwn
Offline
Зарегистрирован: 25.08.2014

Клапауций 112 пишет:

верно - я на угоны теперь только со своими педалями хожу. О_О

А мне больше мусорный контейнер нравится, там хоть чего вешай, все равно уведут. Можно еще эвакуатор, но сильно на виду пока перемещают.))))

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Спрячь за решеткой машину, выкраду вместе с решеткой https://www.youtube.com/watch?v=rkrmR0YWttw  популярная песня времен "демократии".

Mercury
Offline
Зарегистрирован: 01.11.2017

Спасибо за помощь

АлексейЭтоЯ
Offline
Зарегистрирован: 31.10.2017

Может кто поправить код фэйдера на базе милис?? Вместо  delay(10)  Похожего  что то Я не нашёл.  Спасибо.

void pir_() { 
if(digitalRead(pirPin) == HIGH )  //если сигнал с датчика высокого уровня
   {
     // Записываем время когда началось дижение
     timeent=millis();
     {
     if(light == 0)   //и если свет не был включен
      {
       for(int i=0; i<=150; i++)  //то плавно включаем свет
        {
         analogWrite(outpirPin, i);
         delay(10);   //каждые 10мс увелияение на 1
          }
          light = 1; //и передаем значение переменной, что свет включен
       }
     } 
   }
   else  //иначе
   {
    //Если время без движение превышает паузу => движение окончено
    if(millis()- timeent > pause)
    { 
     if(light == 1) //если свет включен
     {
      for(int i=150; i>=0; i--)//плавно гасим его
       {
        analogWrite(outpirPin, i);
        delay(10);
         }
         light = 0; //и передаем значение переменной, что свет выключен
       }
     }
   }
}

 

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014
АлексейЭтоЯ
Offline
Зарегистрирован: 31.10.2017

Если эта ссылка мне, та чем мой дэлей  в лупе, хуже, чем   там. ???  То что не на 10,  а на 5 ))

void loop(void) {
29    if (temno() && kto_to_ryadom()) vklycharm_esli_ets_kuda();
30    else gasim_esli_est_kuda();
31    delay(5);

 

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

Она лутше тем что каждые 5 милисекунд Вы заходити в лооп и проверяете не изменилось ли условие.

А в Вашем коде 10*150 = 1500 -вот через сколько вернетесь в лооп

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

Если для Вас критично 5 мс то можно и их поставить на миллс - на основании кода по ссылке, потому что с фор это не пройдет

АлексейЭтоЯ
Offline
Зарегистрирован: 31.10.2017

vosara пишет:

Если для Вас критично 5 мс то можно и их поставить на миллс - на основании кода по ссылке, потому что с фор это не пройдет

 

Так как  У меня 3 потока в лупе, мне не подходит даже 1мс, ибо вся программа виснет из за этого

Sliva
Offline
Зарегистрирован: 18.01.2017

Добрый вечер. Можно включать одновременно и с кнопки и по блютуз светодиоды

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

АлексейЭтоЯ пишет:
Так как  У меня 3 потока в лупе, мне не подходит даже 1мс, ибо вся программа виснет из за этого
Вот я поэтому не могу вас понять, почему вы до сих пор не пытаетесь перейти на Си++. Там проще будет.

АлексейЭтоЯ
Offline
Зарегистрирован: 31.10.2017

Так Я за 2 месяца не могу сразу обучиться, вот только на чужих примерах, как то объединяю под свои нужду, кое как пока 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

"Вы или трусы оденьте или крестик снимите"= "или забейте про потоки или все же займитесь Си++"

svjatoy.alex
Offline
Зарегистрирован: 06.12.2015

доброй ночи. подскажите как реализовать простой код:

дано 2 светодиодаи 1 кнопка.

надо:

нажимаем кнопку загораеться 1 диод и через 1 сек тухнет(непринципиально время настрою), нажимаем ещё раз  загораеться 2 диод и через  1 сек тухнет. и так по кругу. нажатие кнопки может быть и через сутки(пытаюсь сделать центральный замок авто от датчика обьёма.)

пробовал через

int regim=1; 
 int flag=0; 

 void setup()   
 { 
    pinMode(10,OUTPUT);    
 pinMode(9,OUTPUT);    
       
 } 

 void loop() 

 { 
       
     if(digitalRead(14)==HIGH&&flag==0)
 
     { 
       regim++;   
       flag=1; 
         
       
        if(regim>2)
        { 
          regim=1;
        } 
       
     } 
       
      if(digitalRead(14)==LOW&&flag==1)//если кнопка НЕ нажата 
     //и переменная flag равна - 1 ,то ... 
     { 
          
        flag=0;//обнуляем переменную "knopka" 
     } 
      
    } 
    if(regim==1)//второй режим 
    { 
      digitalWrite(10,HIGH);
      digitalWrite(9,LOW); 
        
   
    } 
      
    if(regim==2)//третий режим 
    { 
        
      digitalWrite(9,HIGH);
      digitalWrite(10,LOW); 

    } 
      
   
  
      
 } 
 

так вот код работает неадекватно. немогу понять как его заставить работать не переключая диоды, а включая и гася их по заданному времени.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

svjatoy.alex, Ознакомьтесь #7  и #18

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

 svjatoy.alex - Можно и так попробовать


#define led1 10
#define led2 9
#define kn1 14
bool regim;
bool flag;
bool f_regim;
uint32_t taime;

void setup()
{
  pinMode(kn1,INPUT);
  pinMode(led1,OUTPUT);
  pinMode(led2,OUTPUT);
}

void loop()
{
  if(digitalRead(kn1)&&!flag)
  {
    regim = !regim;
    flag =1;
    f_regim = 1;
    taime = millis();
    if(regim)digitalWrite(led1,HIGH);
    else digitalWrite(led2,HIGH);
  }
  else if (!digitalRead(kn1)) flag = 0;
    
  if(regim && f_regim){
    if(millis()-taime > 1000)
    {
      digitalWrite(led1,LOW);
      f_regim=0;
    }
  }
  if(!regim && f_regim){
    if(millis()-taime > 1000)
    {
      digitalWrite(led2,LOW);
      f_regim=0;
    }
  }
}

 

svjatoy.alex
Offline
Зарегистрирован: 06.12.2015

спасибо огромное

AccessD
Offline
Зарегистрирован: 19.12.2017

Доброго времени суток! Не стал создавать новую тему, так как мой вопрос также связан с кнопкой.

Имеется процессор Atmega328p программируемый через среду Arduino IDE, для контроля нажатия на кнопку использую библиотеку Bounce2 для установки триггера:

#include <Bounce2.h>

#define BTN_A A1

Bounce btnA

void updateLAMP();
void updateNUM();

volatile int_fast32_t NUM = 1;
bool switch_press = false;
bool lamp = false;

void setup()
{
pinMode(BTN_A, INPUT_PULLUP);
digitalWrite(BTN_A, HIGH);
btnA.attach(BTN_A);
btnA.interval(50);
}
void loop()
{
  btnA.update();

if (btnA.fell()) 
 {
 switch_press = true;
 }

updateLAMP();
updateNUM();
}

void updateLAMP()
{
}

void updateNUM()
{
}

 

Имеется ряд натуральных целых чисел от 1 до 30. Этот ряд делится на 2 участка от 1 до 9 включительно и от 10 до 30 включительно.

управление значениями осуществляется энкодером, при этом функция возвращает текущее значение NUM в виде целого числа (от 1 до 30)

Также имеется лампа:

bool lamp = false;

особенности работы которой должы быть следующими:

при нахождении значения в 1 участке (от 1 до 9) лампа не горит.

при переходе на 2 участок значений (от 10 до 30) лампа должна гореть.

при нажатии на кнопку лампа загорается и горит непрерывно во всём 1 участке, а также при переходе на 2 участок.

при нажатии на кнопку и нахождении значений во 2 участке - лампа тухнет и не загорается при переходе на 1 участок.

повторное нажатие на кнопку в 1 участке погасит лампу.

повторное нажатие на кнопку во 2 участке зажжет лампу.

цикл повторяется.

При включении устройства значение NUM может быть в любом участке (будет считано последнее значение сохраненное в EEPROM)

Заранее огромное спасибо!

mag155
Offline
Зарегистрирован: 21.12.2017

И распишите пожалуйста его.

GKV
Offline
Зарегистрирован: 01.10.2013
Уважаемый qwone,пожалуйста помогите с выводом обратного отсчета на lcd 1602

#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2); 
#include <Wire.h>
class Cl_Sys;
uint32_t mill;
//--------------------class Cl_Led------------------------

class Cl_Led {
    byte pin;
    bool led = 0;
  public:
    Cl_Led *pnt = NULL;
    Cl_Led(byte _pin): pin(_pin) {};
    uint32_t past = 0 ;
    uint32_t time = 0 ;
    setup() {
      if (this->pnt != NULL) this->pnt->setup();
      pinMode (pin, OUTPUT);
      digitalWrite(pin, LOW);
    };
    void ON() {
      digitalWrite(pin, HIGH);
    };
    void ON(uint32_t _time) {
      time = _time;
      past = mill;
      digitalWrite(pin, led = 1);
    };
    void OFF() {
      digitalWrite(pin, led = 0);
      
    };
    loop() {
      if (this->pnt != NULL) this->pnt->loop();
      if (led && millis() - past >= time) {
        digitalWrite(pin, led = 0);
        
      }
    }
};
//----------------class Cl_Btn----------------------------

class Cl_Btn {
    byte pin ; 
    void (* Do1)(), (* Do2)();
    bool btn, btn_old;
    bool bounce_btn = 0; 
    uint32_t past = 0 ;
//------------------------ Cl_back_timer ----------------------------------
class Cl_back_timer {
    uint32_t mill;
    bool stat;
    void (* Do1)(), (* Do2)();
    uint32_t time ;
    void convert_time() {
      sec = time / 1000;
    }
    const uint32_t interval = 1000;
    uint32_t past = 0;
    uint32_t past_end;
        
  public:
   
    Cl_back_timer(Cl_Sys *Sys, void (* _Do1)(), void (* _Do2)());
    Cl_Btn *pnt = NULL;
    Cl_Btn(byte _pin, void (* _Do1)(), void (* _Do2)())
      : pin(_pin), Do1(_Do1), Do2(_Do2) {};
    void setup() {
      if (this->pnt != NULL) this->pnt->setup();
      pinMode(pin, INPUT);
      btn = digitalRead(pin);
    }
    void loop() {
      if (this->pnt != NULL) this->pnt->loop();
      if (! bounce_btn && btn != digitalRead(pin)) { 
        bounce_btn = 1;                                 
        past = mill;
      }
      else if ( bounce_btn && millis() - past >= 5 ) { 
        bounce_btn = 0;      
        btn_old = btn ;
        btn = digitalRead(pin) ; 
        if (!btn_old && btn)  (* Do1)();
        if (btn_old && !btn)  (* Do2)();
      }
    };
};
//-----------------class Cl_sys---------------------------
class Cl_sys {
    Cl_back_timer    *Start_back_timer  = NULL;
    Cl_Led * StartLed = NULL;
    Cl_Btn * StartBtn = NULL;
  public:
    Cl_sys() {};
    void setup() {
      Start_back_timer  ->setup();
      StartLed->setup();
      StartBtn->setup();
    };
    void loop() {
      Start_back_timer  ->loop();
      StartLed->loop();
      StartBtn->loop();
    };
    void Plug(Cl_Led * Led) {
      Led->pnt = StartLed;
      StartLed = Led;
    };
    void Plug(Cl_Btn * Btn) {
      Btn->pnt = StartBtn;
      StartBtn = Btn;
    };
};
//--------------------------------------------
Cl_Led Led1(A0);
Cl_back_timer  ::Cl_back_timer  (Cl_Sys *Sys, void (* _Do1)(), void (* _Do2)()): Do1(_Do1), Do2(_Do2), pnt(NULL) {}

const uint32_t time_2s = 2000 ;
const uint32_t time_5s = 5000 ;

void Do1_Back_timer();
Cl_back_timer *Back_timer = new Cl_back_timer(&Sys,/*обработчик*/ Do1_Back_timer, /*обработчик*/ Do2_Back_timer );
void Do1_Back_timer() { 
  lcd.setCursor(6, 0);
  if (Back_timer->sec < 5)lcd.print("0");
  lcd.print(Back_timer->sec);

}
void Do1_Btn1() {  
  Led1.ON(time_5s);
  Back_timer->time_start = time_10sec;
   lcd.setCursor(0, 0);
  lcd.print("5sec");
}
void Do2_Btn1() { 
  Led1.OFF();
 Back_timer->time_start = time_20min;
 lcd.setCursor(0, 0);
 lcd.print("OFF");
}
Cl_Btn Btn1(2 , Do1_Btn1, Do2_Btn1);

Cl_sys Sys;

void setup() {
  Sys.Plug(&Led1);
  Sys.Plug(&Btn1);
  lcd.begin();
  
  Sys.setup();
}
void loop() {
  mill = millis();
  Sys.loop();
}

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

GKV, лучше дайте ТЗ. Я чуть попроще напишу код.

GKV
Offline
Зарегистрирован: 01.10.2013

GSM-alarm.Лет пять назал сделал логический  модуль для снижения ложных срабатываний датчиков движения улицы на даче.Примерно снижает на 90%-проверено опытным путем.Модуль состоит из трех плат:таймер,счетчик,фотореле и занимает много места в щите.За эти годы в результате модернизаций щиты стали -пучком проводов.Сейчас собираюсь перебирать щиты и немного упростить,добавить новое.Задача модуля такова:

1При исчезновении логической единицы (+12в делитель) на входе 2 ардуины (у датчика движения alarm=NC)-запускается таймер и независимо от того есть на входе сигнал начинает считать 20сек.

2.на этом же входе (2) одновременно запускается счетчик и начинает считать количество срабатываний д.движения.

3.Если во время работы таймера 20сек счетчик отсчитал 4 прохода вблизи д/движения, то на выходе А0 исчезает 0в и "этот сигнал (длительность 2сек) уходит на GSM".

4.Если таймер отсчитал свои 20сек,а счетчик меньше 4 проходов,то все обнуляется и по новой ждет срабатывания д.движения.

5.Поскольку все это работает только с сумерек до рассвета (контроль периметра),то фотреле на световой день блокирует сигнал в GSM -модуль(настроен на пропадение 0).Постоянно охрану территории осуществляют датчики ИК-барьеры расположенные в каждом углу на столбе забора.

6.LCD.Необходимо видеть на нулевой строке -обратный отсчет таймера,на первой строке кол-во сигналов д.движения для точной подстройки времени и кол-ва программно.

GKV
Offline
Зарегистрирован: 01.10.2013

Одна кнопка два счетчика вывод на LCD 1602 

#include <LiquidCrystal_I2C.h>
#include <Wire.h>
const int SensorPin = 2;
const int SensorPinv = 3;
const int Pin=A0;
const int Pin1=A2;
const int Pinv=A1;
int signal = 0;
int signalv = 0;
int Counter = 0;
int Counterv = 0;
int lastSignal = 0;
int lastSignalv = 0;
int n;
int k;
LiquidCrystal_I2C lcd(0x27,16,2); 
void setup() {
lcd.clear();
delay(100);
lcd.begin();
lcd.setCursor(1, 0);
lcd.print("Salt(10)::>");
lcd.setCursor(1, 1);
lcd.print("Xlor(12)::>");
lcd.setCursor(12, 1);
pinMode(SensorPin, INPUT_PULLUP);
pinMode(SensorPinv, INPUT);
pinMode(Pin, OUTPUT);
pinMode(Pinv,  OUTPUT);
pinMode(Pin1,  OUTPUT);
}
void loop()
{
n=Counter;
k=Counterv;

if(digitalRead(2)==HIGH)
digitalWrite(Pin1,HIGH);
delay(500);
digitalWrite(Pin1,LOW);
if (abs(n)>=10)
{
digitalWrite(Pin, HIGH); // зажигаем светодиод
delay(25000);
digitalWrite(Pin, LOW);
if (Counter==10){Counter=0;}
lcd.setCursor(12, 0);
lcd.print("  "); 
lcd.setCursor(12, 0);
}
signal = digitalRead(SensorPin);
if (signal != lastSignal)
{
if (signal == HIGH)
{
Counter++;
lcd.setCursor(12,0);
lcd.print(Counter);
lcd.setCursor(12,0);
delay(1);
}
lastSignal = signal;
}
if (abs(k)>=12)
{digitalWrite(Pinv, HIGH); // зажигаем светодиод
delay(25000);
digitalWrite(Pinv, LOW);
if (Counterv==12){Counterv=0;}
lcd.setCursor(12, 1);
lcd.print("  "); 
lcd.setCursor(12, 1);
}
signalv = digitalRead(SensorPin);
if (signalv != lastSignalv)
{
if (signalv == HIGH)
{
Counterv++;
lcd.setCursor(12,1);
lcd.print(Counterv);
lcd.setCursor(12,1);
delay(1);
}
lastSignalv = signalv;
 }
}

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

GKV.Попробую просто расписать как писать программу по вашей задаче.Где-то так #25.Итак у вас есть три активных устройства, сторожевой таймер, сенсор запускающий счет, и сенсор датчика движения. Вск они должны быть проинициализированы и регулярно не блокирующее обсуживаться процессором.

/**/
unsigned long mill; // переменная под millis()
//--------------------------------
// класс обратный таймер
class Cl_timeBack {
  protected:
  public:
    /*конструктор*/
    /*инициализация*/
    void init() {}
    /*работа*/
    void run() {}
};
//-------------------------
// класс сенсор
class Cl_sens {
  protected:
  public:
    /*конструктор*/
    /*инициализация*/
    void init() {}
    /*работа*/
    void run() {}
};
//---Компоновка-----------------------------
Cl_timeBack timeBack;
Cl_sens sensMain;
Cl_sens sens;
//---main-----------------------------
void setup() {
  timeBack.init();
  sensMain.init();
  sens.init();
}
void loop() {
  mill = millis();
  timeBack.run();
  sensMain.run();
  sens.run();
}
/*Скетч использует 482 байт (1%) памяти устройства. Всего доступно 30720 байт.
  Глобальные переменные используют 13 байт (0%) динамической памяти, оставляя 2035 байт для локальных переменных. Максимум: 2048 байт.
*/

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Сенсоры висят на ногах процессора. И при срабатывании должны вызавать обработчик - фунцию в которой описано, что делать в случае срабатывания этого сенсора.

/**/
unsigned long mill; // переменная под millis()
typedef (*pDo)();// тип обработчик
//--------------------------------
// класс обратный таймер
class Cl_timeBack {
  protected:
  public:
    /*конструктор*/
    /*инициализация*/
    void init() {}
    /*работа*/
    void run() {}
};
//-------------------------
// класс сенсор
class Cl_sens {
  protected:
    byte pin;
    pDo Do;
  public:
    /*конструктор*/
    Cl_sens(byte p, pDo Do_): pin(p), Do(Do_) {};
    /*инициализация*/
    void init() {}
    /*работа*/
    void run() {}
};
//---Компоновка-----------------------------
Cl_timeBack timeBack;
void DoSensMain() {
}
Cl_sens sensMain(/*пин*/2,/*обработчик*/&DoSensMain);
void DoSens() {
}
Cl_sens sens(/*пин*/4,/*обработчик*/&DoSens);
//---main-----------------------------
void setup() {
  timeBack.init();
  sensMain.init();
  sens.init();
}
void loop() {
  mill = millis();
  timeBack.run();
  sensMain.run();
  sens.run();
}
/*Скетч использует 556 байт (1%) памяти устройства. Всего доступно 30720 байт.
  Глобальные переменные используют 19 байт (0%) динамической памяти, оставляя 2029 байт для локальных переменных. Максимум: 2048 байт.
*/

 

GKV
Offline
Зарегистрирован: 01.10.2013

Немного не так.

Датчик движения промышленный имеющий контакт "NC" типа мастеркит МА802(через него лучше запускать +12в и через делитель на вход ардуины(2).Фотореле я думаю нужно оставить отдельно как модуль,оно днем блокирует вход "NC"(com и 1) GSM модуля.Остается сторожевой таймер и счетчик.

Как только контакт NC датчика движения разрывается,то сразу запускается таймер и счетчик.Дело в том,что если даже стоять перед датчиком он через четыре сек вернется в NC и тутже в NO на четыре секунды,потом все повторится.

Таймер независимо не от чего отсчитыват 20сек и обнуляется.

Счетчик в течении этих 20сек отсчитал 4-ре разрыва NC датчика движения и тогда пошел сигнал(A0) LOW в виде исчезновения нуля (2сек) на входе gsm.Если счетчик не успел отсчитать 4-ре разрыва за период 20сек,то все обнуляется и опять сначала.Все конечно на milles.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

GKV, все эти потроха находятся с наружи. И ардуина не знает или не обязана знать как снаружи все устроено. Ардуина  может  реагировать на 0 ,на 1 и на перепады _/*  и  *\_  Лучше конечно на перепады. Осталось решить какой перепад будет создавать сенсор запуска , а какой сенсор движения.

Вы как заказчик должны иметь возмоность менять интервал и так же обратный таймер должен иметь обработчик, по которому он отправляет сигнал. Ну где-то так.

/**/
unsigned long mill; // переменная под millis()
typedef (*pDo)();// тип обработчик
//--------------------------------
// класс обратный таймер
class Cl_timeBack {
  protected:
    unsigned long interval;
    pDo Do;
  public:
    /*конструктор*/
    Cl_timeBack(unsigned long i, pDo Do_): interval(i), Do(Do_) {}
    /*инициализация*/
    void init() {}
    /*работа*/
    void run() {}
};
//-------------------------
// класс сенсор
class Cl_sens {
  protected:
    byte pin;
    pDo Do;
  public:
    /*конструктор*/
    Cl_sens(byte p, pDo Do_): pin(p), Do(Do_) {};
    /*инициализация*/
    void init() {}
    /*работа*/
    void run() {}
};
//---Компоновка-----------------------------
const unsigned long time_20s = 20000; //интервал 20 сек
void DoTimeBack() {
  /*здесь отправляем сообщение про проникновение*/
}
Cl_timeBack timeBack(/*интервал*/time_20s,/*обработчик*/&DoTimeBack);
void DoSensMain() {
}
Cl_sens sensMain(/*пин*/2,/*обработчик*/&DoSensMain);
void DoSens() {
}
Cl_sens sens(/*пин*/4,/*обработчик*/&DoSens);
//---main-----------------------------
void setup() {
  timeBack.init();
  sensMain.init();
  sens.init();
}
void loop() {
  mill = millis();
  timeBack.run();
  sensMain.run();
  sens.run();
}
/*Скетч использует 586 байт (1%) памяти устройства. Всего доступно 30720 байт.
  Глобальные переменные используют 25 байт (1%) динамической памяти, оставляя 2023 байт для локальных переменных. Максимум: 2048 байт.
*/

 

GKV
Offline
Зарегистрирован: 01.10.2013

С перепадами не понял.У меня протянута витая пара и у всех датчиков NC соединены последовательно.Через NC дачиков проходит логическая единица +12в соответственно через делитель получается +5в в ардуину на вход (2)-это и получается сенсор запуска таймера и счетчика.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

GKV пишет:
1При исчезновении логической единицы (+12в делитель) на входе 2 ардуины (у датчика движения alarm=NC)-запускается таймер и независимо от того есть на входе сигнал начинает считать 20сек.
  Это вы написали . Раньше была единица, а позже что ?. Разумеется 0 .  это перепад с  1 на 0     *\_. ПС не забудьте сделать резисторную подтяжку вывода на GND (или 0) Ардуины. Хотя если делитель . То нижний резистор это и есть подтяжка при обрыве +12B.

GKV
Offline
Зарегистрирован: 01.10.2013

Теперь понял про перепад.Про подтяжку помню,заказал специально в китае по 1000шт 10кОм и 20кОм.Делаю все на 12в чтобы не путаться  Ардуин сжег уже десяток.Закупил еще в китае распайку пинов с клемниками,там внизу на плату можно впаивать резисторы -очень удобно

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

разумется такой же должен быть перепад и на датчике движения. Иначе как определить это 4 отдельный или 1 но сплошной на 20 сек. 

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

/**/
unsigned long mill; // переменная под millis()
typedef (*pDo)();// тип обработчик
//--------------------------------
// класс обратный таймер
class Cl_timeBack {
  protected:
    unsigned long interval;
    pDo Do;
  public:
    /*конструктор*/
    Cl_timeBack(unsigned long i, pDo Do_): interval(i), Do(Do_) {}
    /*инициализация*/
    void init() {}
    /*работа*/
    void run() {}
    /*запуск подсчета*/
    void start() {}
    /*сработал датчик движения*/
    void tick() {}
};
//-------------------------
// класс сенсор
class Cl_sens {
  protected:
    byte pin;
    pDo Do;
  public:
    /*конструктор*/
    Cl_sens(byte p, pDo Do_): pin(p), Do(Do_) {};
    /*инициализация*/
    void init() {}
    /*работа*/
    void run() {}
};
//---Компоновка-----------------------------
const unsigned long time_20s = 20000; //интервал 20 сек
void DoTimeBack() {
  /*здесь отправляем сообщение про проникновение*/
}
Cl_timeBack timeBack(/*интервал*/time_20s,/*обработчик*/&DoTimeBack);
void DoSensMain() {
  timeBack.start();
}
Cl_sens sensMain(/*пин*/2,/*обработчик*/&DoSensMain);
void DoSens() {
  timeBack.tick();
}
Cl_sens sens(/*пин*/4,/*обработчик*/&DoSens);
//---main-----------------------------
void setup() {
  timeBack.init();
  sensMain.init();
  sens.init();
}
void loop() {
  mill = millis();
  timeBack.run();
  sensMain.run();
  sens.run();
}
/*Скетч использует 586 байт (1%) памяти устройства. Всего доступно 30720 байт.
  Глобальные переменные используют 25 байт (1%) динамической памяти, оставляя 2023 байт для локальных переменных. Максимум: 2048 байт.
*/

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Для отладки и отработки подключим Serial. Позже Serial Можно заменить на вывод LCD

/**/
unsigned long mill; // переменная под millis()
typedef (*pDo)();// тип обработчик
//--------------------------------
// класс обратный таймер
class Cl_timeBack {
  protected:
    unsigned long interval;
    pDo Do;
  public:
    /*конструктор*/
    Cl_timeBack(unsigned long i, pDo Do_): interval(i), Do(Do_) {}
    /*инициализация*/
    void init() {}
    /*работа*/
    void run() {}
    /*запуск подсчета*/
    void start() {}
    /*сработал датчик движения*/
    void tick() {}
};
//-------------------------
// класс сенсор
class Cl_sens {
  protected:
    byte pin;
    pDo Do;
  public:
    /*конструктор*/
    Cl_sens(byte p, pDo Do_): pin(p), Do(Do_) {};
    /*инициализация*/
    void init() {}
    /*работа*/
    void run() {}
};
//---Компоновка-----------------------------
const unsigned long time_20s = 20000; //интервал 20 сек
void DoTimeBack() {
  /*здесь отправляем сообщение про проникновение*/
  Serial.println("Alien in the house");
}
Cl_timeBack timeBack(/*интервал*/time_20s,/*обработчик*/&DoTimeBack);
void DoSensMain() {
  Serial.println("start");
  timeBack.start();
}
Cl_sens sensMain(/*пин*/2,/*обработчик*/&DoSensMain);
void DoSens() {
  Serial.println("tick");
  timeBack.tick();
}
Cl_sens sens(/*пин*/4,/*обработчик*/&DoSens);
//---main-----------------------------
void setup() {
  Serial.begin(9600);
  timeBack.init();
  sensMain.init();
  sens.init();
}
void loop() {
  mill = millis();
  timeBack.run();
  sensMain.run();
  sens.run();
}
/*Скетч использует 1614 байт (5%) памяти устройства. Всего доступно 30720 байт.
  Глобальные переменные используют 232 байт (11%) динамической памяти, оставляя 1816 байт для локальных переменных. Максимум: 2048 байт.
*/

 

GKV
Offline
Зарегистрирован: 01.10.2013

Не так.Эти датчики движения имеют встроенную функцию:если перед ним стоять он на 4сек войдет в состояние NO потом в NC потом опять на четыре сек NO -все по кругу.Вход главного сенсора и сенсора запуска -один (2) выход с ардуины тоже один (А0) с временем работы 2сек с о в 1

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

ну вот попробуй сейчас. Я написал код сенсора. Если сенсоры работают. То в сериал идет сообщение.

/**/
unsigned long mill; // переменная под millis()
typedef (*pDo)();// тип обработчик
//--------------------------------
// класс обратный таймер
class Cl_timeBack {
  protected:
    unsigned long interval;
    pDo Do;
  public:
    /*конструктор*/
    Cl_timeBack(unsigned long i, pDo Do_): interval(i), Do(Do_) {}
    /*инициализация*/
    void init() {}
    /*работа*/
    void run() {}
    /*запуск подсчета*/
    void start() {}
    /*сработал датчик движения*/
    void tick() {}
};
//-------------------------
// класс сенсор
class Cl_sens {
  protected:
    byte pin;
    pDo Do;
    bool btn, oldBtn;
  public:
    /*конструктор*/
    Cl_sens(byte p, pDo Do_): pin(p), Do(Do_) {};
    /*инициализация*/
    void init() {
      pinMode(pin, INPUT);
      btn = digitalRead(pin);
    }
    /*работа*/
    void run() {
      oldBtn = btn;
      btn = digitalRead(pin);
      /*если раньше 1, а сейчас 0 то вызовем обработчик*/
      if (oldBtn && !btn) Do();
    }
};
//---Компоновка-----------------------------
const unsigned long time_20s = 20000; //интервал 20 сек
void DoTimeBack() {
  /*здесь отправляем сообщение про проникновение*/
  Serial.println("Alien in the house");
}
Cl_timeBack timeBack(/*интервал*/time_20s,/*обработчик*/&DoTimeBack);
void DoSensMain() {
  Serial.println("start");
  timeBack.start();
}
Cl_sens sensMain(/*пин*/2,/*обработчик*/&DoSensMain);
void DoSens() {
  Serial.println("tick");
  timeBack.tick();
}
Cl_sens sens(/*пин*/4,/*обработчик*/&DoSens);
//---main-----------------------------
void setup() {
  Serial.begin(9600);
  timeBack.init();
  sensMain.init();
  sens.init();
}
void loop() {
  mill = millis();
  timeBack.run();
  sensMain.run();
  sens.run();
}
/*Скетч использует 2024 байт (6%) памяти устройства. Всего доступно 30720 байт.
  Глобальные переменные используют 236 байт (11%) динамической памяти, оставляя 1812 байт для локальных переменных. Максимум: 2048 байт.
*/

 

GKV
Offline
Зарегистрирован: 01.10.2013

Да в сериале start and tick.получается что 2 и 4 нужно спаралелить,ведь выход с сенсора у меня один

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

 В строке  34  надо     pinMode(pin, INPUT);

GKV
Offline
Зарегистрирован: 01.10.2013

qwone пишет:

 В строке  34  надо     pinMode(pin, INPUT);

исправил

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Обратный таймер может иметь 2 состояния - считать или ждать. Добавим это в класс и посмотрим что получилось . Да можно запускать. Но первая запускает и ждет 20 сек до повторного запуска.

/**/
unsigned long mill; // переменная под millis()
typedef (*pDo)();// тип обработчик
//--------------------------------
// класс обратный таймер
class Cl_timeBack {
  protected:
    unsigned long interval;
    pDo Do;
    unsigned long past;
    byte state; /* 0 ждем / 1 подсчет обратно*/
    /*установить в состояние*/
    void stand(byte s) {
      state = s;
      past = mill;
      switch (state) {
        case 0:
          Serial.println("timeBack stop");
          break;
        case 1:
          Serial.println("timeBack start");
          break;
      }
    }
  public:
    /*конструктор*/
    Cl_timeBack(unsigned long i, pDo Do_): interval(i), Do(Do_) {}
    /*инициализация*/
    void init() {
      stand(0);
    }
    /*работа*/
    void run() {
      if (state == 1 && mill - past >= interval) stand(0);
    }
    /*запуск подсчета*/
    void start() {
      if (state == 0) stand(1);
    }
    /*сработал датчик движения*/
    void tick() {}
};
//-------------------------
// класс сенсор
class Cl_sens {
  protected:
    byte pin;
    pDo Do;
    bool btn, oldBtn;
  public:
    /*конструктор*/
    Cl_sens(byte p, pDo Do_): pin(p), Do(Do_) {};
    /*инициализация*/
    void init() {
      pinMode(pin, INPUT);
      btn = digitalRead(pin);
    }
    /*работа*/
    void run() {
      oldBtn = btn;
      btn = digitalRead(pin);
      /*если раньше 1, а сейчас 0 то вызовем обработчик*/
      if (oldBtn && !btn) Do();
    }
};
//---Компоновка-----------------------------
const unsigned long time_20s = 20000; //интервал 20 сек
void DoTimeBack() {
  /*здесь отправляем сообщение про проникновение*/
  Serial.println("Alien in the house");
}
Cl_timeBack timeBack(/*интервал*/time_20s,/*обработчик*/&DoTimeBack);
void DoSensMain() {
  Serial.println("start");
  timeBack.start();
}
Cl_sens sensMain(/*пин*/2,/*обработчик*/&DoSensMain);
void DoSens() {
  Serial.println("tick");
  timeBack.tick();
}
Cl_sens sens(/*пин*/4,/*обработчик*/&DoSens);
//---main-----------------------------
void setup() {
  Serial.begin(9600);
  timeBack.init();
  sensMain.init();
  sens.init();
}
void loop() {
  mill = millis();
  timeBack.run();
  sensMain.run();
  sens.run();
}
/*Скетч использует 2252 байт (7%) памяти устройства. Всего доступно 30720 байт.
  Глобальные переменные используют 263 байт (12%) динамической памяти, оставляя 1785 байт для локальных переменных. Максимум: 2048 байт.
*/

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Сделаем обратный отчет и выведем в Serial

/**/
unsigned long mill; // переменная под millis()
typedef (*pDo)();// тип обработчик
//--------------------------------
// класс обратный таймер
class Cl_timeBack {
  protected:
    unsigned long interval;
    pDo Do;
    unsigned long past, past1;
    byte state; /* 0 ждем / 1 подсчет обратно*/
    /*установить в состояние*/
    void stand(byte s) {
      state = s;
      past = mill;
      switch (state) {
        case 0:
          Serial.println("timeBack stop");
          break;
        case 1:
          Serial.println("timeBack start");
          past1 = mill;
          break;
      }
    }
  public:
    /*конструктор*/
    Cl_timeBack(unsigned long i, pDo Do_): interval(i), Do(Do_) {}
    /*инициализация*/
    void init() {
      stand(0);
    }
    /*работа*/
    void run() {
      if (state == 1 && mill - past1 >= 1000) {
        past1 = mill;
        Serial.println((past - past1 + interval) / 1000);
      }
      if (state == 1 && mill - past >= interval) stand(0);
    }
    /*запуск подсчета*/
    void start() {
      if (state == 0) stand(1);
    }
    /*сработал датчик движения*/
    void tick() {}
};
//-------------------------
// класс сенсор
class Cl_sens {
  protected:
    byte pin;
    pDo Do;
    bool btn, oldBtn;
  public:
    /*конструктор*/
    Cl_sens(byte p, pDo Do_): pin(p), Do(Do_) {};
    /*инициализация*/
    void init() {
      pinMode(pin, INPUT);
      btn = digitalRead(pin);
    }
    /*работа*/
    void run() {
      oldBtn = btn;
      btn = digitalRead(pin);
      /*если раньше 1, а сейчас 0 то вызовем обработчик*/
      if (oldBtn && !btn) Do();
    }
};
//---Компоновка-----------------------------
const unsigned long time_20s = 20000; //интервал 20 сек
void DoTimeBack() {
  /*здесь отправляем сообщение про проникновение*/
  Serial.println("Alien in the house");
}
Cl_timeBack timeBack(/*интервал*/time_20s,/*обработчик*/&DoTimeBack);
void DoSensMain() {
  Serial.println("start");
  timeBack.start();
}
Cl_sens sensMain(/*пин*/2,/*обработчик*/&DoSensMain);
void DoSens() {
  Serial.println("tick");
  timeBack.tick();
}
Cl_sens sens(/*пин*/4,/*обработчик*/&DoSens);
//---main-----------------------------
void setup() {
  Serial.begin(9600);
  timeBack.init();
  sensMain.init();
  sens.init();
}
void loop() {
  mill = millis();
  timeBack.run();
  sensMain.run();
  sens.run();
}
/*Скетч использует 2588 байт (8%) памяти устройства. Всего доступно 30720 байт.
  Глобальные переменные используют 267 байт (13%) динамической памяти, оставляя 1781 байт для локальных переменных. Максимум: 2048 байт.
*/

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

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

/**/
unsigned long mill; // переменная под millis()
typedef (*pDo)();// тип обработчик
//--------------------------------
// класс обратный таймер
class Cl_timeBack {
  protected:
    unsigned long interval;
    pDo Do;
    unsigned long past, past1;
    byte counter;
    byte state; /* 0 ждем / 1 подсчет обратно*/
    /*установить в состояние*/
    void stand(byte s) {
      state = s;
      past = mill;
      switch (state) {
        case 0:
          Serial.println("timeBack stop");
          break;
        case 1:
          Serial.println("timeBack start");
          past1 = mill;
          counter = 5;
          break;
      }
    }
  public:
    /*конструктор*/
    Cl_timeBack(unsigned long i, pDo Do_): interval(i), Do(Do_) {}
    /*инициализация*/
    void init() {
      stand(0);
    }
    /*работа*/
    void run() {
      if (state == 1 && mill - past1 >= 1000) {
        past1 = mill;
        Serial.println((past - past1 + interval) / 1000);
      }
      if (state == 1 && mill - past >= interval) stand(0);
    }
    /*запуск подсчета*/
    void start() {
      if (state == 0) stand(1);
    }
    /*сработал датчик движения*/
    void tick() {
      if (state == 0) return;
      counter--;
      if (counter <= 0) { // если счетчик обнулился
        stand(0);
        Do();// то вызов аварии
      }
    }
};
//-------------------------
// класс сенсор
class Cl_sens {
  protected:
    byte pin;
    pDo Do;
    bool btn, oldBtn;
  public:
    /*конструктор*/
    Cl_sens(byte p, pDo Do_): pin(p), Do(Do_) {};
    /*инициализация*/
    void init() {
      pinMode(pin, INPUT);
      btn = digitalRead(pin);
    }
    /*работа*/
    void run() {
      oldBtn = btn;
      btn = digitalRead(pin);
      /*если раньше 1, а сейчас 0 то вызовем обработчик*/
      if (oldBtn && !btn) Do();
    }
};
//---Компоновка-----------------------------
const unsigned long time_20s = 20000; //интервал 20 сек
void DoTimeBack() {
  /*здесь отправляем сообщение про проникновение*/
  Serial.println("Alien in the house");
}
Cl_timeBack timeBack(/*интервал*/time_20s,/*обработчик*/&DoTimeBack);
void DoSensMain() {
  Serial.println("start");
  timeBack.start();
}
Cl_sens sensMain(/*пин*/2,/*обработчик*/&DoSensMain);
void DoSens() {
  Serial.println("tick");
  timeBack.tick();
}
Cl_sens sens(/*пин*/4,/*обработчик*/&DoSens);
//---main-----------------------------
void setup() {
  Serial.begin(9600);
  timeBack.init();
  sensMain.init();
  sens.init();
}
void loop() {
  mill = millis();
  timeBack.run();
  sensMain.run();
  sens.run();
}
/*Скетч использует 2672 байт (8%) памяти устройства. Всего доступно 30720 байт.
  Глобальные переменные используют 268 байт (13%) динамической памяти, оставляя 1780 байт для локальных переменных. Максимум: 2048 байт.
*/

 

GKV
Offline
Зарегистрирован: 01.10.2013

Все работает,только я не понял,запуск таймера и запуск счетчика объеденить на одном входе нельзя?  OUTPUT куда вставить? там на выходе "время работы 2сек" переход из 0 в 1 на 2сек

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Не вижу смысла. Можете тупо слить но. Надежность надо на практике определять. Может будет работать хорошо. А может сбоить.

/**/
unsigned long mill; // переменная под millis()
typedef (*pDo)();// тип обработчик
//--------------------------------
// класс обратный таймер
class Cl_timeBack {
  protected:
    unsigned long interval;
    pDo Do;
    unsigned long past, past1;
    byte counter;
    byte state; /* 0 ждем / 1 подсчет обратно*/
    /*установить в состояние*/
    void stand(byte s) {
      state = s;
      past = mill;
      switch (state) {
        case 0:
          Serial.println("timeBack stop");
          break;
        case 1:
          Serial.println("timeBack start");
          past1 = mill;
          counter = 5;
          break;
      }
    }
  public:
    /*конструктор*/
    Cl_timeBack(unsigned long i, pDo Do_): interval(i), Do(Do_) {}
    /*инициализация*/
    void init() {
      stand(0);
    }
    /*работа*/
    void run() {
      if (state == 1 && mill - past1 >= 1000) {
        past1 = mill;
        Serial.println((past - past1 + interval) / 1000);
      }
      if (state == 1 && mill - past >= interval) stand(0);
    }
    /*запуск подсчета*/
    void start() {
      if (state == 0) stand(1);
    }
    /*сработал датчик движения*/
    void tick() {
      if (state == 0) return;
      counter--;
      if (counter <= 0) { // если счетчик обнулился
        stand(0);
        Do();// то вызов аварии
      }
    }
};
//-------------------------
// класс сенсор
class Cl_sens {
  protected:
    byte pin;
    pDo Do;
    bool btn, oldBtn;
  public:
    /*конструктор*/
    Cl_sens(byte p, pDo Do_): pin(p), Do(Do_) {};
    /*инициализация*/
    void init() {
      pinMode(pin, INPUT);
      btn = digitalRead(pin);
    }
    /*работа*/
    void run() {
      oldBtn = btn;
      btn = digitalRead(pin);
      /*если раньше 1, а сейчас 0 то вызовем обработчик*/
      if (oldBtn && !btn) Do();
    }
};
//---Компоновка-----------------------------
const unsigned long time_20s = 20000; //интервал 20 сек
void DoTimeBack() {
  /*здесь отправляем сообщение про проникновение*/
  Serial.println("Alien in the house");
}
Cl_timeBack timeBack(/*интервал*/time_20s,/*обработчик*/&DoTimeBack);
void DoSens() {
  Serial.println("start-tick");
  timeBack.start();
  timeBack.tick();
}
Cl_sens sens(/*пин*/2,/*обработчик*/&DoSens);
//---main-----------------------------
void setup() {
  Serial.begin(9600);
  timeBack.init();
  sens.init();
}
void loop() {
  mill = millis();
  timeBack.run();
  sens.run();
}
/*Скетч использует 2608 байт (8%) памяти устройства. Всего доступно 30720 байт.
  Глобальные переменные используют 269 байт (13%) динамической памяти, оставляя 1779 байт для локальных переменных. Максимум: 2048 байт.
*/

 

GKV
Offline
Зарегистрирован: 01.10.2013

У меня кнопки китайские,забыл я к ногам припаять керамические кондеры 0.1мкф-дребезг.даже с резисторами.

OUTPUT с ардуины куда вставить

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Ну можно поставить программный антидребезг 

/**/
unsigned long mill; // переменная под millis()
typedef (*pDo)();// тип обработчик
//--------------------------------
// класс обратный таймер
class Cl_timeBack {
  protected:
    unsigned long interval;
    pDo Do;
    unsigned long past, past1;
    byte counter;
    byte state; /* 0 ждем / 1 подсчет обратно*/
    /*установить в состояние*/
    void stand(byte s) {
      state = s;
      past = mill;
      switch (state) {
        case 0:
          Serial.println("timeBack stop");
          break;
        case 1:
          Serial.println("timeBack start");
          past1 = mill;
          counter = 5;
          break;
      }
    }
  public:
    /*конструктор*/
    Cl_timeBack(unsigned long i, pDo Do_): interval(i), Do(Do_) {}
    /*инициализация*/
    void init() {
      stand(0);
    }
    /*работа*/
    void run() {
      if (state == 1 && mill - past1 >= 1000) {
        past1 = mill;
        Serial.println((past - past1 + interval) / 1000);
      }
      if (state == 1 && mill - past >= interval) stand(0);
    }
    /*запуск подсчета*/
    void start() {
      if (state == 0) stand(1);
    }
    /*сработал датчик движения*/
    void tick() {
      if (state == 0) return;
      counter--;
      if (counter <= 0) { // если счетчик обнулился
        stand(0);
        Do();// то вызов аварии
      }
    }
};
//-------------------------
// класс сенсор
class Cl_sens {
  protected:
    byte pin;
    pDo Do;
    bool bounce = 0;
    bool btn, oldBtn = 0;
    unsigned long past;
  public:
    /*конструктор*/
    Cl_sens(byte p, pDo Do_): pin(p), Do(Do_) {};
    /*инициализация*/
    void init() {
      pinMode(pin, INPUT);
      btn = digitalRead(pin);
    }
    /*работа*/
    void run() {
      bool newBtn = digitalRead(pin);
      if (!bounce && newBtn != btn) {
        bounce = 1;
        past = mill;
      }
      if (bounce && mill - past >= 10) {
        bounce = 0 ;
        oldBtn = btn;
        btn = newBtn;
        /*если раньше 1, а сейчас 0 то вызовем обработчик*/
        if (btn && !oldBtn) Do();
      }
    }
};
//---Компоновка-----------------------------
const unsigned long time_20s = 20000; //интервал 20 сек
void DoTimeBack() {
  /*здесь отправляем сообщение про проникновение*/
  Serial.println("Alien in the house");
}
Cl_timeBack timeBack(/*интервал*/time_20s,/*обработчик*/&DoTimeBack);
void DoSens() {
  Serial.println("start-tick");
  timeBack.start();
  timeBack.tick();
}
Cl_sens sens(/*пин*/2,/*обработчик*/&DoSens);
//---main-----------------------------
void setup() {
  Serial.begin(9600);
  timeBack.init();
  sens.init();
}
void loop() {
  mill = millis();
  timeBack.run();
  sens.run();
}
/*Скетч использует 2724 байт (8%) памяти устройства. Всего доступно 30720 байт.
  Глобальные переменные используют 274 байт (13%) динамической памяти, оставляя 1774 байт для локальных переменных. Максимум: 2048 байт.
*/

 

GKV
Offline
Зарегистрирован: 01.10.2013

С дребезгом завтра решу,подключу к щиту.Я на lcd не могу вывести количесво срабатываний счетчика 1,2,3,4 и ноль не могу убрать в обратном отсчете 10>9

/**/
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
LiquidCrystal_I2C lcd(0x27,16,2); 
unsigned long mill; // переменная под millis()
typedef (*pDo)();// тип обработчик
//--------------------------------
// класс обратный таймер
class Cl_timeBack {
  protected:
    unsigned long interval;
    pDo Do;
    unsigned long past, past1;
    byte counter;
    byte state; /* 0 ждем / 1 подсчет обратно*/
    /*установить в состояние*/
    void stand(byte s) {
      state = s;
      past = mill;
      switch (state) {
        case 0:
          Serial.println("timeBack stop");
          lcd.setCursor(8,0);
          lcd.print("stop");
          break;
        case 1:
          Serial.println("timeBack start");
          lcd.setCursor(8,0);
          lcd.print("start");
          past1 = mill;
          counter = 5;
          break;
      }
    }
  public:
    /*конструктор*/
    Cl_timeBack(unsigned long i, pDo Do_): interval(i), Do(Do_) {}
    /*инициализация*/
    void init() {
      stand(0);
    }
    /*работа*/
    void run() {
      if (state == 1 && mill - past1 >= 1000) {
        past1 = mill;
        Serial.println((past - past1 + interval) / 1000);
        lcd.setCursor(8,0);
         lcd.print("     ");
        lcd.print((past - past1 + interval) / 1000);
      }
      if (state == 1 && mill - past >= interval) stand(0);
    }
    /*запуск подсчета*/
    void start() {
      if (state == 0) stand(1);
    }
    /*сработал датчик движения*/
    void tick() {
      if (state == 0) return;
      counter--;
      if (counter <= 0) { // если счетчик обнулился
        stand(0);
        Do();// то вызов аварии
      }
    }
};
//-------------------------
// класс сенсор
class Cl_sens {
  protected:
    byte pin;
    pDo Do;
    bool btn, oldBtn;
  public:
    /*конструктор*/
    Cl_sens(byte p, pDo Do_): pin(p), Do(Do_) {};
    /*инициализация*/
    void init() {
      pinMode(pin, INPUT);
      btn = digitalRead(pin);
    }
    /*работа*/
    void run() {
      oldBtn = btn;
      btn = digitalRead(pin);
      /*если раньше 1, а сейчас 0 то вызовем обработчик*/
      if (oldBtn && !btn) Do();
    }
};
//---Компоновка-----------------------------
const unsigned long time_20s = 20000; //интервал 20 сек
void DoTimeBack() {
  /*здесь отправляем сообщение про проникновение*/
  Serial.println("Alien in the house");
}
Cl_timeBack timeBack(/*интервал*/time_20s,/*обработчик*/&DoTimeBack);
void DoSens() {
  Serial.println("start-tick");
  timeBack.start();
  timeBack.tick();
}
Cl_sens sens(/*пин*/2,/*обработчик*/&DoSens);
//---main-----------------------------
void setup() {
  lcd.clear();
  delay(1);
  lcd.begin();
  lcd.setCursor(0, 0);
lcd.print("Time::>");
lcd.setCursor(0, 1);
lcd.print("Tick::>");
  Serial.begin(9600);
  timeBack.init();
  sens.init();
}
void loop() {
  mill = millis();
  timeBack.run();
  sens.run();
}
/*Скетч использует 2608 байт (8%) памяти устройства. Всего доступно 30720 байт.
  Глобальные переменные используют 269 байт (13%) динамической памяти, оставляя 1779 байт для локальных переменных. Максимум: 2048 байт.
*/