Как выполнить код только 1 раз в цикле loop?
- Войдите на сайт для отправки комментариев
Пнд, 03/06/2019 - 12:42
Всем привет. Решил переделать автоматический освежитель воздуха. Идея такова, что после выключения света в туалете освежитель пшикает один раз и переходит в режим ожидания до следующего включения и выключения света. Для этого в схеме использовал фоторезистор и реле (потом заменю на транзистор), которое приводит в движение привод.
Так вот, я хочу, чтобы после выключения света, реле срабатывало только 1 раз (1 пшик), а затем переходило в режим ожидания.
Написал такой простенький код, однако после выключения света код в цикле loop не останавливается, реле, то включается, то выключается. Подскажите, пожалуйта, как реализовать эту затею? Спасибо!
const int photo = A0;
const int motor = 13;
int raw = 0;
void setup() {
pinMode( photo, INPUT );
pinMode( motor, OUTPUT );
}
void loop() {
raw = analogRead( photo );
if( raw < 500)
digitalWrite( motor, HIGH );
delay(1000);
digitalWrite( motor, LOW );
delay(1000);
}
Например завести еще одну переменную-флаг и добавить в условие. Если флаг false - щелкаем реле и делаем флаг = true, после этого условие перестанет выполняться. Чтобы это все сработало в следующий раз при включении/выключении света придется добавить еще одно отдельное условие, которое будет делать флаг = false когда светло.
Изменил код с условием true/false, теперь реле срабатывает 1 раз как положено, но второй раз отказывается. После перезагрузки все повторяется. Подскажите, как включать реле подобным образом без перезагрузки?
const int photo = A0; const int motor = 13; int raw = 0; boolean is_once /* = true*/; void setup() { pinMode( photo, INPUT ); pinMode( motor, OUTPUT ); is_once = true; } void loop() { raw = analogRead( photo ); if( raw < 500) if (is_once) { digitalWrite( motor, HIGH ); delay(1000); digitalWrite( motor, LOW ); delay(1000); is_once = false; }}while(analogRead( photo ) > 500){} //тормозим пока свет включен
while(analogRead( photo ) < 500){} //тормозим пока свет вЫключен
Эти строки (одну или две) нужно вставить в loop(). Пробуйте.
if (raw > 700) { readyToRun = true; } if (readyToRun && raw < 500) { ...; readyToRun = false; }Подскажите, как включать реле подобным образом без перезагрузки?
Может... прочитать совет до конца ? :)
Изменил код с условием true/false, теперь реле срабатывает 1 раз как положено, но второй раз отказывается. После перезагрузки все повторяется. Подскажите, как включать реле подобным образом без перезагрузки?
const int photo = A0; const int motor = 13; int raw = 0; boolean is_once /* = true*/; void setup() { pinMode( photo, INPUT ); pinMode( motor, OUTPUT ); is_once = true; } void loop() { raw = analogRead( photo ); if( raw < 500) if (is_once) { digitalWrite( motor, HIGH ); delay(1000); digitalWrite( motor, LOW ); delay(1000); is_once = false; }}чуть чуть не хватило, я думаю если бы расставили комментарии сами дописали как надо.
const int photo = A0; const int motor = 13; int raw = 0; boolean is_once /* = true*/; void setup() { pinMode( photo, INPUT ); pinMode( motor, OUTPUT ); is_once = true; } void loop() { raw = analogRead( photo ); // читаем датчик if ( raw < 500) { // света - нет if (is_once) { // уже пшикали ? digitalWrite( motor, HIGH ); // нет, пшикаем delay(1000); digitalWrite( motor, LOW ); delay(1000); is_once = false; // очищаем флаг, пшикнули } } else { is_once = true; // зажгли свет, взводим флаг } }Спасибо большое! Все работает практически как надо. Вот только иногда случаются ложные срабатывания, все дело в отсутствии гистерезиса. Я думал, что проще всего в код, приведенный выше, добавить опрос фоторезистора не постоянно, а с задержкой, например, раз в 5 секунд. Delay не подходит, так как начинает тормозить другой код программы.
В интернете похожей реализации нигде не нашел (((
Такую сложную и редкую задачу в интернетах не рассматривают.
Значит добавить опрос будет сложно. А что если добавить задержку, (кроме delay), например, если свет включен более 5 секунд, то после выключения света, включить реле. Если менее 5 секунд, то ничего не делать.
... Delay не подходит, так как начинает тормозить другой код программы.
А вот про это в первом посте не было...
А вот про это в первом посте не было...
Сам участок кода с delay
меня устраивает. Хотелось бы добавить что то наподобие гистерезиса - опроса датчика раз в 5 секунд, а не постоянное((
Что подразумевается под гистерезисом?
Срабатывание реле не сразу после того, как значение датчика опустилось, например до 300. А если значение равно 300 и меньше в течение 5 сек, то включить реле. Если менее, то не включать. И наоборот.
Это я про свой пример выше - аналог delay()
Вот почти готовый пример. Попробуйте вставить в свой код. Название функции и переменных поменяйте.
//=========== вызов каждые 100-300 мс byte controlFireGas(){//возвращ. 0 если нет пламени byte static stateFlame = 1; stateFlame <<= 1; if(analogRead(PIN_FIRE_GAZ) > 50){//есть запал stateFlame |= 1; } return stateFlame; } в loop() if(stateFlame == 0){//потухло пламя-//нет пламени за 8 чтений //что-то делаем }else if(stateFlame == 0xFF){//есть пламя стабильное //что-то делаем }else{ //есть пламя НЕстабильное //что-то делаем }Спасибо! Кстати, в моем коде вот эта функция считывает показания порта, к которому подключен фоторезистор:
И считывает постоянно, можно ли сделать опросы периодами? Например, те же раз 5 сек.
тока дай палец...
Спасибо! Кстати, в моем коде вот эта функция считывает показания порта, к которому подключен фоторезистор:
И считывает постоянно, можно ли сделать опросы периодами? Например, те же раз 5 сек.
Можно. Используйте millis()
const int photo = A0; const int motor = 13; int raw = 0; boolean is_once /* = true*/; void setup() { pinMode( photo, INPUT ); pinMode( motor, OUTPUT ); is_once = true; } void dataRaw(){ raw = analogRead( photo ); // читаем датчик } void loop() { dataRaw(); if (is_once && raw < 500) { // света - нет delay(100); // Типа Антидребезг dataRaw(); // читаем датчик if(raw < 500) { digitalWrite( motor, HIGH ); // нет, пшикаем delay(1000); digitalWrite( motor, LOW ); delay(1000); is_once = false; // очищаем флаг, пшикнули } } if (raw > 500 && !is_once) { delay(100); // Типа Антидребезг dataRaw(); // читаем датчик if(raw > 500) is_once = true; // зажгли свет, взводим флаг } }делей надо искоренить!! когда же вы начнете использовать хотябы миллис вместо делеев!!
Долой delay() ! Хватит это терпеть ! :)
И считывает постоянно, можно ли сделать опросы периодами? Например, те же раз 5 сек.
Лучше сделать усреднение, но считывать и правда можно пореже.
както так на вскидку
#define photo A0 #define motor 13 uint8_t raw = 0; boolean is_once = 1; /* = true*/ uint32_t cMs , pMs1; // таймеры void setup() { pinMode( photo, INPUT ); pinMode( motor, OUTPUT ); } void Pshik(){ digitalWrite( motor, HIGH ); // нет, пшикаем delay(1000); digitalWrite( motor, LOW ); delay(1000); } void loop() { cMs = millis(); //текущее время /******************** опрос датчикa *********************/ if ( pMs1 + 5000UL <= cMs ){ pMs1 = cMs; // срабатывает каждые 5 секунд raw = analogRead( photo ); // читаем датчик } /*******************************************************/ if(raw < 500) { // свет if (is_once) {Pshik(); !is_once; } } else { // нет света - сброс ключа !is_once; } }ну или даже так
#define photo A0 #define motor 13 #define svet 5 //лампочка в туалете uint32_t raw = 0; uint32_t cMs , pMs1; // счетчики времени void setup() { pinMode( photo, INPUT ); pinMode( motor, OUTPUT ); pinMode( svet , OUTPUT ); //реле на отключение лампочки } void Pshik(){ // ваша пшикалка digitalWrite( motor, HIGH ); // нет, пшикаем delay(1000); digitalWrite( motor, LOW ); delay(1000); } void loop() { cMs = millis(); //текущее время, если надо несколько таймеров будет... /******************** опрос датчикa *********************/ if ( cMs - pMs1 > 1000UL ){ pMs1 = cMs; // срабатывает каждые 1 секунду if (analogRead( photo ) > 500 ) raw++; else raw=0; //считает число срабатываний } /*******************************************************/ if(raw == 5 || raw == 600 ) { // свет включен 5 секунд и повтор через 600 секунд (10 мин) Pshik(); } if(raw > 1000) digitalWrite( svet, 1); //ибо нефик так долго занимать помещение! }Жесть какая-то. ТС гистерезис не может даже в этом посте найти, как он в ваших скетчах-то разберётся...
if( pMs1 + 5000UL <= cMs ){ pMs1 = cMs;// срабатывает каждые 5 секундЩас шо будеть...))ПЕРЕПОЛНЕНИЕ ! Всем в укрытие ! oO
:) :) :)
да, переполнение - а предложите свой вариант? )
Минуснуть противоположную сторону.
супер - и получить раз в 65 секунд переполнение миллеса... и глюк на следующие 65 сукунд (а то и на всегда до рестарта)
Уже попробовали ?
супер - и получить раз в 65 секунд переполнение миллеса...
Свидетели секты святого переполнения миилиса опять на форуме...
P.S. А вот нехер складывать, чтобы переполнения не было. Отнимать надо!
P.P.S. Обязательно к прочтению - http://arduino.ru/forum/programmirovanie/velikoe-perepolnenie-millis
Я в ней был, там хорошо :)
ок...
millis 65с до переполнения и с 0, допустим сейчас 30с набежало timing = 0 if (millis() - timing > 9){ timing = millis(); } 30 - 0 > 9 (true) timing = 30 31 - 30 > 9 (false) .... 39 - 30 > 9 (false) 40 - 30 > 9 (true) timing = 40 .... 50 - 40 > 9 (true) timing = 50 .... 60 - 50 > 9 (true) timing = 60 61 - 60 > 9 (false) 62 - 60 > 9 (false) 63 - 60 > 9 (false) 65 - 60 > 9 (false) 0 - 60 > 9 (false) 1 - 60 > 9 (false) 2 - 60 > 9 (false) 3 - 60 > 9 (false) 4 - 60 > 9 (false) 5 - 60 > 9 (false) .... .... .... 20 - 60 > 9 (false)и что в итоге?... - код больше никогда не сработает
и что в итоге?... - код больше никогда не сработает
Обязательно к прочтению - http://arduino.ru/forum/programmirovanie/velikoe-perepolnenie-millis
и что в итоге?... - код больше никогда не сработает
Дак всё правильно. Название топика какое? "Как выполнить код только 1 раз в цикле loop". Всё в соответствии с требованиям.
вся разница в том, что переполнение 50 суток а не 65 секунд, ну перепутал с микрос...
читал я те изыскания и пробовал - лучше лишнее срабатывание , чем полный отвел....
и что в итоге?... - код больше никогда не сработает
Дак всё правильно. Название топика какое? "Как выполнить код только 1 раз в цикле loop". Всё в соответствии с требованиям.
ну да, но ему надо и "сброс" иметь, а не вечное зависание...
хотя можно и софтресет делать при выключении свет... asm("JMP 0");
ELITE - родолжаете блистать как знаток Си? :)
Запустите свой же код в ардуине и убедитесь, что переполнения нет
ну да, но ему надо и "сброс" иметь, а не вечное зависание...
Это требование противоречит основному . Придётся что-то одно выбрать.
Лучше аппаратный WatchDog - он надёжней.
Лучше аппаратный WatchDog - он надёжней.
ELITE - родолжаете блистать как знаток Си? :)
Запустите свой же код в ардуине и убедитесь, что переполнения нет
у меня уже пол года на аналогичном коде холодильник фурычит, и если бы он был не верный - то пивасик у еня был бы теплый уже на 2й месяц.... а шашлык протух бы
ок, тс пусь будет "правильное" ( cMs - pMs1 > 1000UL )
ок...
millis 65с до переполнения и с 0, допустим сейчас 30с набежало timing = 0 if (millis() - timing > 9){ timing = millis(); } 30 - 0 > 9 (true) timing = 30 31 - 30 > 9 (false) .... 39 - 30 > 9 (false) 40 - 30 > 9 (true) timing = 40 .... 50 - 40 > 9 (true) timing = 50 .... 60 - 50 > 9 (true) timing = 60 61 - 60 > 9 (false) 62 - 60 > 9 (false) 63 - 60 > 9 (false) 65 - 60 > 9 (false) 0 - 60 > 9 (false) 1 - 60 > 9 (false) 2 - 60 > 9 (false) 3 - 60 > 9 (false) 4 - 60 > 9 (false) 5 - 60 > 9 (false) .... .... .... 20 - 60 > 9 (false)и что в итоге?... - код больше никогда не сработает
;)))))
какой зайчеГ!!!!
В твоем примере - 4 - 60 > 9(Sic!) и 5-60 и 6-60, все они больше 9 (по модулю 66). Неожиданно?
Прочти строчку выше столько раз, сколько нужно для просветления! Может быть тогда поймёшь, как работает вычисление простых операций в кАмпутере... ну там плюсик, минусик и т.п.
делей надо искоренить!! когда же вы начнете использовать хотябы миллис вместо делеев!!
void Pshik(){ // ваша пшикалка digitalWrite( motor, HIGH ); // нет, пшикаем delay(1000); digitalWrite( motor, LOW ); delay(1000); }Это элитный т.к. ради этих 4х строчек все и задумано :)
делей надо искоренить!! когда же вы начнете использовать хотябы миллис вместо делеев!!
теперь у нас появился "настоящий" искоренитель делеев, доказавший это собственными примерами.
и тут меня пугает слово "хотябы", что нас ждет в дальнейшем страшно подумать.
А что, Вы, хотели? Не кажный удостоился отдельного пункта (3), в "Песочнице".
а если рассмотреть хардовый вариант решения вопроса?
использовать несколько фотоэлементов + полевик и все это на ногу дога.
взять транзистор "попроще" Р-канальный с небольшим начальным напряжением открытия, открывать его примерно так, а после работы отправлять всю богодельню спать для экономии заряда батареи. еще, продают в китае очень интересные игрухи на солнечных батарейках, можно ее на ногу дога без транзистора...
тода весь код можно в луп закинуть, а просыпаться когда дог тяфкнет.
:))) ну мы же не ищем простых решений, а этот вариант жизнеспособный и интересный. ИМХО
Ух как тема разрослась)) Мне подсказали на другом форуме, что для добавления гистерезиса нужно всего лишь добавить простую строку (как ж я не смог догадаться!!), теперь все нормально работает:
if( raw < 450 ) { //действие } if( raw >= 550 ) { //действие }Не хочу создавать новую тему. Поэтому хотелось бы поинтересоваться здесь. Как написать код, чтобы включалась блокировка времени повторного срабатывания пшика без delay? Например, зачем пшикать, если свет в туалете часто включается, почему бы не сделать блокировку минут на 10? Спасибо)
Писали вроде уже - через millis(). Запоминаете millis() в момент "пшика" в переменную t и ждете, когда millis() - 600000 > t, это условие можно добавить к raw >= 550,