Хайтек шагает по планете. Влепи геркон и реле под торпеду и в путь.
Это очень просто, ненадежно и палевно.
Таки чем? Если я вскрою торпеду, то хоть дуина, хоть геркон, хоть супер сигналка, похрен. А не зная куды класть магнит хрен чего сделаешь, а кнопочки они на дурацкие мысли наводят.
Хотя из личного опыта, самая лучшая штука это стальная шняга на педаль. Два раза пробовали и оба бросили, только ключик под ковриками поискали.
Хайтек шагает по планете. Влепи геркон и реле под торпеду и в путь.
Это очень просто, ненадежно и палевно.
Таки чем? Если я вскрою торпеду, то хоть дуина, хоть геркон, хоть супер сигналка, похрен. А не зная куды класть магнит хрен чего сделаешь, а кнопочки они на дурацкие мысли наводят.
Хотя из личного опыта, самая лучшая штука это стальная шняга на педаль. Два раза пробовали и оба бросили, только ключик под ковриками поискали.
В том то и дело что будет нестандартный подход, а кнопочки можно и в неприглядном месте спрятать.
Может кто поправить код фэйдера на базе милис?? Вместо 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; //и передаем значение переменной, что свет выключен
}
}
}
}
доброй ночи. подскажите как реализовать простой код:
дано 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);
}
}
так вот код работает неадекватно. немогу понять как его заставить работать не переключая диоды, а включая и гася их по заданному времени.
Доброго времени суток! Не стал создавать новую тему, так как мой вопрос также связан с кнопкой.
Имеется процессор Atmega328p программируемый через среду Arduino IDE, для контроля нажатия на кнопку использую библиотеку Bounce2 для установки триггера:
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.Попробую просто расписать как писать программу по вашей задаче.Где-то так #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 байт.
*/
Сенсоры висят на ногах процессора. И при срабатывании должны вызавать обработчик - фунцию в которой описано, что делать в случае срабатывания этого сенсора.
Датчик движения промышленный имеющий контакт "NC" типа мастеркит МА802(через него лучше запускать +12в и через делитель на вход ардуины(2).Фотореле я думаю нужно оставить отдельно как модуль,оно днем блокирует вход "NC"(com и 1) GSM модуля.Остается сторожевой таймер и счетчик.
Как только контакт NC датчика движения разрывается,то сразу запускается таймер и счетчик.Дело в том,что если даже стоять перед датчиком он через четыре сек вернется в NC и тутже в NO на четыре секунды,потом все повторится.
Таймер независимо не от чего отсчитыват 20сек и обнуляется.
Счетчик в течении этих 20сек отсчитал 4-ре разрыва NC датчика движения и тогда пошел сигнал(A0) LOW в виде исчезновения нуля (2сек) на входе gsm.Если счетчик не успел отсчитать 4-ре разрыва за период 20сек,то все обнуляется и опять сначала.Все конечно на milles.
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 байт.
*/
С перепадами не понял.У меня протянута витая пара и у всех датчиков NC соединены последовательно.Через NC дачиков проходит логическая единица +12в соответственно через делитель получается +5в в ардуину на вход (2)-это и получается сенсор запуска таймера и счетчика.
1При исчезновении логической единицы (+12в делитель) на входе 2 ардуины (у датчика движения alarm=NC)-запускается таймер и независимо от того есть на входе сигнал начинает считать 20сек.
Это вы написали . Раньше была единица, а позже что ?. Разумеется 0 . это перепад с 1 на 0 *\_. ПС не забудьте сделать резисторную подтяжку вывода на GND (или 0) Ардуины. Хотя если делитель . То нижний резистор это и есть подтяжка при обрыве +12B.
Теперь понял про перепад.Про подтяжку помню,заказал специально в китае по 1000шт 10кОм и 20кОм.Делаю все на 12в чтобы не путаться Ардуин сжег уже десяток.Закупил еще в китае распайку пинов с клемниками,там внизу на плату можно впаивать резисторы -очень удобно
Не так.Эти датчики движения имеют встроенную функцию:если перед ним стоять он на 4сек войдет в состояние NO потом в NC потом опять на четыре сек NO -все по кругу.Вход главного сенсора и сенсора запуска -один (2) выход с ардуины тоже один (А0) с временем работы 2сек с о в 1
Обратный таймер может иметь 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 байт.
*/
Все работает,только я не понял,запуск таймера и запуск счетчика объеденить на одном входе нельзя? OUTPUT куда вставить? там на выходе "время работы 2сек" переход из 0 в 1 на 2сек
Хайтек шагает по планете. Влепи геркон и реле под торпеду и в путь.
Хайтек шагает по планете. Влепи геркон и реле под торпеду и в путь.
Это очень просто, ненадежно и палевно.
Хайтек шагает по планете. Влепи геркон и реле под торпеду и в путь.
Это очень просто, ненадежно и палевно.
Таки чем? Если я вскрою торпеду, то хоть дуина, хоть геркон, хоть супер сигналка, похрен. А не зная куды класть магнит хрен чего сделаешь, а кнопочки они на дурацкие мысли наводят.
Хотя из личного опыта, самая лучшая штука это стальная шняга на педаль. Два раза пробовали и оба бросили, только ключик под ковриками поискали.
Хотя из личного опыта, самая лучшая штука это стальная шняга на педаль. Два раза пробовали и оба бросили, только ключик под ковриками поискали.
верно - я на угоны теперь только со своими педалями хожу. О_О
Хайтек шагает по планете. Влепи геркон и реле под торпеду и в путь.
Это очень просто, ненадежно и палевно.
Таки чем? Если я вскрою торпеду, то хоть дуина, хоть геркон, хоть супер сигналка, похрен. А не зная куды класть магнит хрен чего сделаешь, а кнопочки они на дурацкие мысли наводят.
Хотя из личного опыта, самая лучшая штука это стальная шняга на педаль. Два раза пробовали и оба бросили, только ключик под ковриками поискали.
В том то и дело что будет нестандартный подход, а кнопочки можно и в неприглядном месте спрятать.
верно - я на угоны теперь только со своими педалями хожу. О_О
А мне больше мусорный контейнер нравится, там хоть чего вешай, все равно уведут. Можно еще эвакуатор, но сильно на виду пока перемещают.))))
Спрячь за решеткой машину, выкраду вместе с решеткой https://www.youtube.com/watch?v=rkrmR0YWttw популярная песня времен "демократии".
Спасибо за помощь
Может кто поправить код фэйдера на базе милис?? Вместо
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; //и передаем значение переменной, что свет выключен } } } }http://arduino.ru/forum/programmirovanie/esli-temnovato-i-kto-podoshel-p...
Если эта ссылка мне, та чем мой дэлей в лупе, хуже, чем там. ??? То что не на 10, а на 5 ))
voidloop(void) {29if(temno() && kto_to_ryadom()) vklycharm_esli_ets_kuda();30elsegasim_esli_est_kuda();31delay(5);Она лутше тем что каждые 5 милисекунд Вы заходити в лооп и проверяете не изменилось ли условие.
А в Вашем коде 10*150 = 1500 -вот через сколько вернетесь в лооп
Если для Вас критично 5 мс то можно и их поставить на миллс - на основании кода по ссылке, потому что с фор это не пройдет
Если для Вас критично 5 мс то можно и их поставить на миллс - на основании кода по ссылке, потому что с фор это не пройдет
Так как У меня 3 потока в лупе, мне не подходит даже 1мс, ибо вся программа виснет из за этого
Добрый вечер. Можно включать одновременно и с кнопки и по блютуз светодиоды
Так Я за 2 месяца не могу сразу обучиться, вот только на чужих примерах, как то объединяю под свои нужду, кое как пока
"Вы или трусы оденьте или крестик снимите"= "или забейте про потоки или все же займитесь Си++"
доброй ночи. подскажите как реализовать простой код:
дано 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); } }так вот код работает неадекватно. немогу понять как его заставить работать не переключая диоды, а включая и гася их по заданному времени.
svjatoy.alex, Ознакомьтесь #7 и #18
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; } } }спасибо огромное
Доброго времени суток! Не стал создавать новую тему, так как мой вопрос также связан с кнопкой.
Имеется процессор 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)
Также имеется лампа:
особенности работы которой должы быть следующими:
при нахождении значения в 1 участке (от 1 до 9) лампа не горит.
при переходе на 2 участок значений (от 10 до 30) лампа должна гореть.
при нажатии на кнопку лампа загорается и горит непрерывно во всём 1 участке, а также при переходе на 2 участок.
при нажатии на кнопку и нахождении значений во 2 участке - лампа тухнет и не загорается при переходе на 1 участок.
повторное нажатие на кнопку в 1 участке погасит лампу.
повторное нажатие на кнопку во 2 участке зажжет лампу.
цикл повторяется.
При включении устройства значение NUM может быть в любом участке (будет считано последнее значение сохраненное в EEPROM)
Заранее огромное спасибо!
И распишите пожалуйста его.
Уважаемый 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(); }GKV, лучше дайте ТЗ. Я чуть попроще напишу код.
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.Необходимо видеть на нулевой строке -обратный отсчет таймера,на первой строке кол-во сигналов д.движения для точной подстройки времени и кол-ва программно.
Одна кнопка два счетчика вывод на 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; } }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 байт. */Сенсоры висят на ногах процессора. И при срабатывании должны вызавать обработчик - фунцию в которой описано, что делать в случае срабатывания этого сенсора.
/**/ 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 байт. */Немного не так.
Датчик движения промышленный имеющий контакт "NC" типа мастеркит МА802(через него лучше запускать +12в и через делитель на вход ардуины(2).Фотореле я думаю нужно оставить отдельно как модуль,оно днем блокирует вход "NC"(com и 1) GSM модуля.Остается сторожевой таймер и счетчик.
Как только контакт NC датчика движения разрывается,то сразу запускается таймер и счетчик.Дело в том,что если даже стоять перед датчиком он через четыре сек вернется в NC и тутже в NO на четыре секунды,потом все повторится.
Таймер независимо не от чего отсчитыват 20сек и обнуляется.
Счетчик в течении этих 20сек отсчитал 4-ре разрыва NC датчика движения и тогда пошел сигнал(A0) LOW в виде исчезновения нуля (2сек) на входе gsm.Если счетчик не успел отсчитать 4-ре разрыва за период 20сек,то все обнуляется и опять сначала.Все конечно на milles.
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 байт. */С перепадами не понял.У меня протянута витая пара и у всех датчиков NC соединены последовательно.Через NC дачиков проходит логическая единица +12в соответственно через делитель получается +5в в ардуину на вход (2)-это и получается сенсор запуска таймера и счетчика.
Теперь понял про перепад.Про подтяжку помню,заказал специально в китае по 1000шт 10кОм и 20кОм.Делаю все на 12в чтобы не путаться Ардуин сжег уже десяток.Закупил еще в китае распайку пинов с клемниками,там внизу на плату можно впаивать резисторы -очень удобно
разумется такой же должен быть перепад и на датчике движения. Иначе как определить это 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 байт. */Для отладки и отработки подключим 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 байт. */Не так.Эти датчики движения имеют встроенную функцию:если перед ним стоять он на 4сек войдет в состояние NO потом в NC потом опять на четыре сек NO -все по кругу.Вход главного сенсора и сенсора запуска -один (2) выход с ардуины тоже один (А0) с временем работы 2сек с о в 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() {} /*запуск подсчета*/ 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 байт. */Да в сериале start and tick.получается что 2 и 4 нужно спаралелить,ведь выход с сенсора у меня один
В строке
34 надоpinMode(pin, INPUT);В строке
34 надоpinMode(pin, INPUT);исправил
Обратный таймер может иметь 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 байт. */Сделаем обратный отчет и выведем в 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 байт. */Теперь сделаем подсчет сработок датчика движения и скетч готов. Остальное вы подключите сами. Нет у меня нужного железа. Проверить не смогу.
/**/ 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 байт. */Все работает,только я не понял,запуск таймера и запуск счетчика объеденить на одном входе нельзя? OUTPUT куда вставить? там на выходе "время работы 2сек" переход из 0 в 1 на 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"); 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 байт. */У меня кнопки китайские,забыл я к ногам припаять керамические кондеры 0.1мкф-дребезг.даже с резисторами.
OUTPUT с ардуины куда вставить
Ну можно поставить программный антидребезг
/**/ 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 байт. */С дребезгом завтра решу,подключу к щиту.Я на 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 байт. */