задержка с рестартом
- Войдите на сайт для отправки комментариев
Чт, 19/10/2017 - 22:32
Надо чтоб по факту срабатывания датчика активировалось реле, если датчик повторно срабатывает в течении времени когда реле активовано, отсчет задежки должен начинатся сначала.
По найденым примерам пытался написать что то. Работает, после срабатывания датчика реле включаестя и отрабатэавет весь период, повторные срабатывания датчика в этот период не регистрируются, рестарта нет. Что я сделал неправильно?
/* ARDUINI NANO
* PIR Sensor[PIN GND] -> Arduino Nano[PIN GND]
* PIR Sensor[PIN 5V] -> Arduino Nano[PIN 5V]
* PIR Sensor[PIN OUT] -> Arduino Nano[PIN A0]
* Relay Module[PIN IN] -> Arduino Nano[PIN 13]
*/
const int relout = 13;//relout - пин(выходной сигнал) для модуля реле
//prevMillis - переменная для хранения времени предидущего цикла сканирования программы
unsigned long prevMillis = 0;//interval - временной интервал для отсчета секунд до выключения реле
int interval = 1000;
int DelayValue = 10;//DelayValue - период в течение которого реле удерживается во включенном состоянии
int initSecond = 10; //initSecond - Переменная итерации цикла инициализации
static int countDelayOff = 0; //countDelayOff - счетчик временных интервалов
static bool trigger = false;//trigger - флаг срабатывания датчика движения
#define baud 9600
void setup()
{
Serial.begin(9600); //инициализация вывода в терминал
pinMode(relout, OUTPUT); //процедура инициализации порта на который подключено реле
digitalWrite(relout, LOW); //первоначальное состояние порта на который подключено реле
for(int i = 0; i < initSecond; i ++) // ждем когда закончатся X циклов(переменная initSecond) продолжительностью в 1 секунду, за это время датчик "самоинициализируется"
{
delay(100);
}
}
void loop()
{
if(analogRead(A0) > 500) //Считать значение с аналогового порта А0, Если значение выше 500
{
trigger = true; //устаналиваем флаг trigger=1
}
else
{
trigger = false; //В противном случае устаналиваем флаг trigger=0
}
Serial.println(trigger); //вывод состояния флага в терминал
while(trigger) //Пока флаг срабатывания датчика движения =1
{
unsigned long currMillis = millis(); //Сохранить в переменной currMillis значение миллисекунд прошедших с момента начала выполнения программы
if(currMillis - prevMillis > interval) //Сравниваем с предидущим значением миллисекунд, если разница больше заданного интервала, то:
{
prevMillis = currMillis; //Сохранить текущее значение миллисекунд в переменную prevMillis
if(countDelayOff >= DelayValue) //Проверяем счетчик задержки сравнивая его со значением периода в течение которого реле должно удерживаться во включенном состоянии
{
trigger = false; //Если значение сравнялось, то сбросить флаг срабатывания датчика движения
countDelayOff = 0; //Обнулить счетчик задержки
digitalWrite(relout, LOW); //Выключить реле
break; //Прервать цикл
}
else //Если значение всё еще меньше, то инкрементировать счетчик задержки на единицу
{
countDelayOff ++;
digitalWrite(relout, HIGH);//Удерживать реле во включенном состоянии
}
}
}
}
Надо чтоб по факту срабатывания датчика активировалось реле, если датчик повторно срабатывает в течении времени когда реле активовано, отсчет задежки должен начинатся сначала.
Вот так, навскидку:
#define RELAY_WORK_TIME 10000 // сколько миллисекунд на работу реле при срабатывания датчика unsigned long relayTimer = 0; // таймер времени начала работы реле bool isRelayOn = false; // флаг того, что реле включено void relayOn() { if(isRelayOn) return; // тут включаем реле isRelayOn = true; } void relayOff() { if(!isRelayOn) return; // тут выключаем реле isRelayOn = false; } void loop() { if(analogRead(A0) > 500) // сработал датчик { relayTimer = millis(); // сбрасываем таймер начала работы relayOn(); // включаем реле } // если реле включено и прошло нужное время - вырубаем его if(isRelayOn && millis() - relayTimer > RELAY_WORK_TIME) { relayOff(); // выключаем реле } }Логика проста: при любом срабатывании датчика сбрасываем таймер начала работы реле. Если датчик не срабатывал долгое время - реле выключится после истечения нужного интервала.
/**/ const byte sensPin =/*пин реле*/A0; bool old=0; const byte relPin =/*пин реле*/ 13; bool rel = 0; unsigned long past; const int time = 1000; //---------------------------------------------------------- void setup() { pinMode(relPin, OUTPUT); digitalWrite(relPin, rel = 0); } void loop() { if (!old && analogRead(sensPin) > 500) { old = 1; digitalWrite(relPin, rel = 1); past = millis(); } if (old && analogRead(sensPin) <= 500) { old = 0; } if (rel && millis() - past > time) { digitalWrite(relPin, rel = 0); } } /**//**/ const byte sensPin =/*пин реле*/A0; bool old=0; const byte relPin =/*пин реле*/ 13; bool rel = 0; unsigned long past; const int time = 1000; //---------------------------------------------------------- void setup() { pinMode(relPin, OUTPUT); digitalWrite(relPin, rel = 0); } void loop() { if (!old && analogRead(sensPin) > 500) { old = 1; digitalWrite(relPin, rel = 1); past = millis(); } if (old && analogRead(sensPin) <= 500) { old = 0; } if (rel && millis() - past > time) { digitalWrite(relPin, rel = 0); } } /**/Если А0 остается с высоким уровнем, рестарта нет, отрабатывается только один интервал.
Надо чтоб по факту срабатывания датчика активировалось реле, если датчик повторно срабатывает в течении времени когда реле активовано, отсчет задежки должен начинатся сначала.
Вот так, навскидку:
#define RELAY_WORK_TIME 10000 // сколько миллисекунд на работу реле при срабатывания датчика unsigned long relayTimer = 0; // таймер времени начала работы реле bool isRelayOn = false; // флаг того, что реле включено void relayOn() { if(isRelayOn) return; // тут включаем реле isRelayOn = true; } void relayOff() { if(!isRelayOn) return; // тут выключаем реле isRelayOn = false; } void loop() { if(analogRead(A0) > 500) // сработал датчик { relayTimer = millis(); // сбрасываем таймер начала работы relayOn(); // включаем реле } // если реле включено и прошло нужное время - вырубаем его if(isRelayOn && millis() - relayTimer > RELAY_WORK_TIME) { relayOff(); // выключаем реле } }Логика проста: при любом срабатывании датчика сбрасываем таймер начала работы реле. Если датчик не срабатывал долгое время - реле выключится после истечения нужного интервала.
Спасибо! Попробую это завтра.
Если А0 остается с высоким уровнем, рестарта нет, отрабатывается только один интервал.
/**/ const byte sensPin =/*пин сенсора*/A0; const byte relPin =/*пин реле*/ 13; bool old, rel; unsigned long past; const int time = 1000; //---------------------------------------------------------- void setup() { pinMode(relPin, OUTPUT); digitalWrite(relPin, rel = 0); old = 0; } void loop() { // сработка если уровень снизится ниже 500 if (!old && analogRead(sensPin) < 500) { old = 1; digitalWrite(relPin, rel = 1); past = millis(); } if (old && analogRead(sensPin) >= 500) { old = 0; } if (rel && millis() - past > time) { digitalWrite(relPin, rel = 0); } } /*Скетч использует 1496 байт (0%) памяти устройства. Всего доступно 253952 байт. Глобальные переменные используют 15 байт (0%) динамической памяти, оставляя 8177 байт для локальных переменных. Максимум: 8192 байт. */Если А0 остается с высоким уровнем, рестарта нет, отрабатывается только один интервал.
/**/ const byte sensPin =/*пин сенсора*/A0; const byte relPin =/*пин реле*/ 13; bool old, rel; unsigned long past; const int time = 1000; //---------------------------------------------------------- void setup() { pinMode(relPin, OUTPUT); digitalWrite(relPin, rel = 0); old = 0; } void loop() { // сработка если уровень снизится ниже 500 if (!old && analogRead(sensPin) < 500) { old = 1; digitalWrite(relPin, rel = 1); past = millis(); } if (old && analogRead(sensPin) >= 500) { old = 0; } if (rel && millis() - past > time) { digitalWrite(relPin, rel = 0); } } /*Скетч использует 1496 байт (0%) памяти устройства. Всего доступно 253952 байт. Глобальные переменные используют 15 байт (0%) динамической памяти, оставляя 8177 байт для локальных переменных. Максимум: 8192 байт. */Спасибо, почти то что надо если дергать А0 вверх вниз, есть рестарт но если сохраняется высокий уровень рестарта нет. Видимо я плохо описал задачу. Ситуация, человек зашел в комнату, датчик сработал, период включения допустим 20 минут, человек ходит по комнате, датчик может подавать все время высокий уровень на А0 но может и дергатся если человек выходит из зоны действия и заходит обратно. Свет в это время включен. Когда человек из комнаты выйдет свет должен оставатся включеным 20 минут после ухода.
Т.е. реле должно включится по фронту сигнала от датчика и выключится через X минут после спада сигнала от датчика.
В любом случае спасибо, идей подкинули, буду разбиратся.
Надо чтоб по факту срабатывания датчика активировалось реле, если датчик повторно срабатывает в течении времени когда реле активовано, отсчет задежки должен начинатся сначала.
Вот так, навскидку:
#define RELAY_WORK_TIME 10000 // сколько миллисекунд на работу реле при срабатывания датчика unsigned long relayTimer = 0; // таймер времени начала работы реле bool isRelayOn = false; // флаг того, что реле включено void relayOn() { if(isRelayOn) return; // тут включаем реле isRelayOn = true; } void relayOff() { if(!isRelayOn) return; // тут выключаем реле isRelayOn = false; } void loop() { if(analogRead(A0) > 500) // сработал датчик { relayTimer = millis(); // сбрасываем таймер начала работы relayOn(); // включаем реле } // если реле включено и прошло нужное время - вырубаем его if(isRelayOn && millis() - relayTimer > RELAY_WORK_TIME) { relayOff(); // выключаем реле } }Логика проста: при любом срабатывании датчика сбрасываем таймер начала работы реле. Если датчик не срабатывал долгое время - реле выключится после истечения нужного интервала.
Спасибо огромное! Это то что надо, проверю завтра еще раз на свежую голову, но сейчас все выглядит хорошо, посмотрел таймер в мониторе, работает как надо, при нажатой кнопке добавляется. В общем спасибо!
Код такой сейчас:
/* ARDUINI NANO * PIR Sensor[PIN GND] -> Arduino Nano[PIN GND] * PIR Sensor[PIN 5V] -> Arduino Nano[PIN 5V] * PIR Sensor[PIN OUT] -> Arduino Nano[PIN A0] * Relay Module[PIN IN] -> Arduino Nano[PIN 13] */ #define RELAY_WORK_TIME 1000 // сколько миллисекунд на работу реле при срабатывания датчика unsigned long relayTimer = 0; // таймер времени начала работы реле bool isRelayOn = false; // флаг того, что реле включено const int relout = 13;//relout - пин(выходной сигнал) для модуля реле void setup() { Serial.begin(9600); } void relayOn() { if(isRelayOn) return; isRelayOn = true; // тут включаем реле digitalWrite(relout, HIGH); } void relayOff() { if(!isRelayOn) return; isRelayOn = false;// тут выключаем реле digitalWrite(relout, LOW); } void loop() { Serial.println ("relayTimer"); Serial.println (relayTimer); if(analogRead(A0) > 500) // сработал датчик { relayTimer = millis(); // сбрасываем таймер начала работы relayOn(); // включаем реле } if(isRelayOn && millis() - relayTimer > RELAY_WORK_TIME) // если реле включено и прошло нужное время - вырубаем его { relayOff(); // выключаем реле } }Легким движением руки ...
/**/ const byte sensPin =/*пин сенсора*/A0; const byte relPin =/*пин реле*/ 13; bool rel; unsigned long past; const int time = 1000; //---------------------------------------------------------- void setup() { pinMode(relPin, OUTPUT); digitalWrite(relPin, rel = 0); } void loop() { // сработка если уровень снизится ниже 500 if (analogRead(sensPin) < 500) { digitalWrite(relPin, rel = 1); past = millis(); } if (rel && millis() - past > time) { digitalWrite(relPin, rel = 0); } } /**/пс:тоже самое что написали вы.:)
Строго говоря, подобные вещи лучше делать без ардуины вообще - на NE555, например. Тот же датчик движения китайский уже умеет в задержку: при срабатывании на выходе появляется сигнал, который может пропадать через определённое настраиваемое потенциометром время, при повторных срабатываниях, ессно, это время отодвигается в будущее. Никакой ардуины - чистая магия :)
Строго говоря, подобные вещи лучше делать без ардуины вообще - на NE555, например. Тот же датчик движения китайский уже умеет в задержку: при срабатывании на выходе появляется сигнал, который может пропадать через определённое настраиваемое потенциометром время, при повторных срабатываниях, ессно, это время отодвигается в будущее. Никакой ардуины - чистая магия :)
Да, конечно, но в учебных целях и если нужны задежки по пол часа, ардуино мне больше нравица :) Длинные задежки плохо реализуются без цифры. Ну и одна ардуина вполне может работать с датчиками в 3-4 помещениях отрабатывая выдежки хоть по часу, что мне собственно и надо.
Ну для нескольких пар сенсор-реле лучше всего так написать.
/**/ //-----Cl_SensRel------------------------------- class Cl_SensRel { protected: const byte sensPin; const byte relPin; const unsigned long time; bool rel; unsigned long past; public: /*конструктор Cl_SensRel() описание :создать объект вход: _sensPin: пин сенсора _relPin: пин реле _time: длительность удержания */ Cl_SensRel(byte _sensPin, byte _relPin, unsigned int _time = 1000) : sensPin(_sensPin), relPin(_relPin), time(_time) {} /*функция init() описание :иницирование объекта/ вставить в setup() */ void init() { pinMode(relPin, OUTPUT); digitalWrite(relPin, rel = 0); } /*функция run() описание :работа объекта/ вставить в loop() */ void run() { if (analogRead(sensPin) < 500) { digitalWrite(relPin, rel = 1); past = millis(); } if (rel && millis() - past > time) { digitalWrite(relPin, rel = 0); } } }; //-------Компоновка----------------------------- const unsigned long time_1s = 1000; //задержка 1сек Cl_SensRel SensRel_1(/*пин сенсора*/A0,/*пин реле*/ 13,/*время задержки*/time_1s); Cl_SensRel SensRel_2(/*пин сенсора*/A1,/*пин реле*/ 12,/*время задержки*/time_1s); Cl_SensRel SensRel_3(/*пин сенсора*/A2,/*пин реле*/ 11,/*время задержки*/time_1s); //------main()------------------------------ void setup() { SensRel_1.init(); SensRel_2.init(); SensRel_3.init(); } void loop() { SensRel_1.run(); SensRel_2.run(); SensRel_3.run(); } /**/Спасибо, как добавлю сенсоров попробую.