Ух как тема разрослась)) Мне подсказали на другом форуме, что для добавления гистерезиса нужно всего лишь добавить простую строку (как ж я не смог догадаться!!),
Писали вроде уже - через millis(). Запоминаете millis() в момент "пшика" в переменную t и ждете, когда millis() - 600000 > t, это условие можно добавить к raw >= 550,
Простите, Ардуино начал изучать только неделю назад. Вот дописал код с millis для блокировки повторного срабатывания пшика в течение 5 мин, однако Ардуино этого времени не дожидается и начинает пшикать сразу после повторного включения и выключения света. Вот пример кода, подскажите, что здесь не так?
const int photo = A0;
const int motor = 13;
unsigned long led1OnTime;
int raw = 0;
bool led1On;
boolean is_once /* = true*/;
void setup() {
pinMode( photo, INPUT );
pinMode( motor, OUTPUT );
is_once = true;
led1On = false;
}
void loop() {
raw = analogRead( photo ); // читаем датчик
if ( raw < 450) { // света - нет
if (is_once) { // уже пшикали ?
digitalWrite( motor, HIGH ); // нет, пшикаем
delay(1000);
digitalWrite( motor, LOW );
is_once = false; // очищаем флаг, пшикнули
led1On = true;
led1OnTime = millis();
}
}
if ( raw > 550) {
is_once = true; // зажгли свет, взводим флаг
}
if (millis() - led1OnTime > 30000) {
led1On = false;
}
}
}
отвечает за то, если свет включится на 5 секунд, то после выключения пшикнуть?
Если нет, то хотелось бы еще функцию срабатывания пшика по таймеру. То есть, в среднем на посрать времени тратится около 5 минут, обоссать унитаз около минуты. Если свет был включен до 3 минут, не пшикать. Так вот, этот код, что выше сможет ли реализовать задуманное?)))
отвечает за то, если свет включится на 5 секунд, то после выключения пшикнуть?
Если нет, то хотелось бы еще функцию срабатывания пшика по таймеру. То есть, в среднем на посрать времени тратится около 5 минут, а по маленькому около минуты. Поэтому, если свет был включен до 3 минут, не пшикать. Так вот, этот код, что выше сможет ли реализовать задуманное или придется переписывать?)))
Millis, я как понимаю, не сбрасывает таймер, если он не дошел до заданного.
отвечает за то, если свет включится на 5 секунд, то после выключения пшикнуть?
Если нет, то хотелось бы еще функцию срабатывания пшика по таймеру. То есть, в среднем на посрать времени тратится около 5 минут, а по маленькому около минуты. Поэтому, если свет был включен до 3 минут, не пшикать. Так вот, этот код, что выше сможет ли реализовать задуманное или придется переписывать?)))
Millis, я как понимаю, не сбрасывает таймер, если он не дошел до заданного.
Да, через 5 сек и 600 сек будет дана команда пшикать Тут вы можете задать своё время, как одно, так и несколько ( в примере два интервала) Только строку поправьте на if( (raw == 5 || raw == 600 )&& Pshik==0 )
только не забудьте паузу в последней строке сделать больше самого большого повтора
Разобрался в принципе действия вашего кода, но мне нужно, чтобы пшик был сразу после выключения света, а не во время включенного. Дописал фунццию analogRead( photo ) < 400 в строку 28. Однако после выключения света пшик срабатывает через раз. Без этой функции все отлично работает. Монитор порта Serial.println(Pshik); показывает, что флаг Pshik иногда не переходит после 1 в состояние 2, а сразу на 0, когда переходит на 2, все срабатывает. Судя по монитору порта Вот сам код
#define photo A1
#define motor 6
uint32_t raw = 0;
uint32_t cMs , pMs1, pMs2; // счетчики времени
uint8_t Pshik = 0;
void setup() {
pinMode( photo, INPUT );
pinMode( motor, OUTPUT );
Serial.begin(9600);
}
void loop() {
//Serial.println(analogRead( photo )); delay (100);
cMs = millis(); //текущее время, если надо несколько таймеров будет...
/******************** опрос датчикa *********************/
if ( cMs - pMs1 > 1000UL ) {
pMs1 = cMs; // срабатывает каждые 1 секунду
if (analogRead( photo ) > 500 ) raw++; else raw = 0; //считает число срабатываний
}
/*******************************************************/
if (raw == 5 ) { // свет включен 5 секунд и повтор через 600 секунд (10 мин)
Pshik = 1; //флаг что надо побрызгать
pMs2 = cMs; // таймер брызгалки старт
}
if (analogRead( photo ) < 400 && cMs - pMs2 > 1000UL && Pshik == 1) {
digitalWrite( motor, 1 ); //нажали
Pshik = 2;
}
if ( cMs - pMs2 > 1800UL && Pshik == 2) {
digitalWrite( motor, 0 ); //отпустили
Pshik = 3;
}
if ( cMs - pMs2 > 300UL && Pshik == 3) {
Pshik = 0; //сброс флага
}
}
и да, строка 36 - это время ДО СБРОСА флага - вы его сделали МЕНЬШЕ, чем время срабатывания пшикалки! а оно должно быть БОЛЬШЕ его, иначе возможны глюки в работе кода
да, этот код можно (да и нужно) оптимизировать путем изменения условий при выключении света - не повторять действия, а взводить на старт 2й таймер и поменять флаг на нужный - дабы система уже повторно прошла цикл пшиканья и по его окончании уже сбросилась для новой работы
#define photo A0
#define motor 13
uint32_t raw = 0;
uint32_t cMs , pMs1, pMs2; // счетчики времени
uint8_t Pshik = 0;
void setup()
{
pinMode( photo, INPUT );
pinMode( motor, OUTPUT );
}
void loop() {
cMs = millis(); //текущее время, если надо несколько таймеров будет...
/******************** опрос датчикa *********************/
if ( cMs - pMs1 > 100UL ){ pMs1 = cMs; // срабатывает каждые 0.1 секунду
if (analogRead( photo ) > 500 ) raw++; else raw=0; //считает число срабатываний //если свет погасили - сброс
}
/*******************************************************/
if( raw == 5 && Pshik==0 ) { // свет включен 0,5 секунд - гистериз от ложных срабатываний
Pshik = 1; //флаг что надо побрызгать
pMs2 = cMs; // таймер брызгалки старт
}
if ( Pshik==1) {digitalWrite( motor, 1 ); Pshik=2; } //нажали
if ( cMs - pMs2 > 800UL && Pshik==2) {digitalWrite( motor, 0 ); Pshik=3; } //отпустили (через 0.8с после нажатия)
if ( cMs - pMs2 > 300000UL && raw == 0 && Pshik==3) {digitalWrite( motor, 1 ); Pshik=4; } //нажали через 5 минут, если свет выключен
if ( cMs - pMs2 > 300800UL && Pshik==4) {digitalWrite( motor, 0 ); Pshik=5; } //отпустили через 5 минут 0.8 сек
if ( cMs - pMs2 > 600000UL && (Pshik==5 || Pshik==3) ) { Pshik=0; } //сброс флага через 600 сек (10 минут) даже если свет продолжает гореть
}
вроде нигде не запутал ничего
Этот код сбрасывает флаг 3 автоматически на 0 при прошествии более 3 секунд и пшика после "выключения света" не происходит. Если это сделать до 3 секунд, то флаг 3 переходит на 4, потом 5 и 0.
Такая же фигня происходила и с прежним кодом. Если сразу после включения флага 1 выключить свет, то он перейдет к 2, 3, 0. Но если после включени флага 1 выключить свет, например, через 10 секунд, то он сразу переходит в 0. Целый день уже ябусь. Уже думаю оставить включение пшикалки со включенным светом(((
#define photo A1
#define motor 6
uint32_t raw = 0;
uint32_t cMs , pMs1, pMs2; // счетчики времени
uint8_t Pshik = 0;
void setup() {
pinMode( photo, INPUT );
pinMode( motor, OUTPUT );
Serial.begin(9600);
}
void loop() {
Serial.println(pMs2); delay (10);
cMs = millis(); //текущее время, если надо несколько таймеров будет...
/******************** опрос датчикa *********************/
if ( cMs - pMs1 > 1000UL ) {
pMs1 = cMs; // срабатывает каждые 1 секунду
if (analogRead( photo ) > 500 ) {
raw++;
} else {
raw = 0;
}
}
/*******************************************************/
if (raw == 5) { // свет включен 5 секунд и повтор через 600 секунд (10 мин)
Pshik = 1; //флаг что надо побрызгать
pMs2 = cMs; // таймер брызгалки старт
}
if (raw == 0 && cMs - pMs2 > 2000UL && Pshik == 1) {
digitalWrite( motor, 1 ); //нажали
Pshik = 2;
}
if ( cMs - pMs2 > 2800UL && Pshik == 2) {
digitalWrite( motor, 0 ); //отпустили
Pshik = 3;
}
if ( cMs - pMs2 > 5000UL && Pshik == 3) {
Pshik = 0; //сброс флага
raw = 0;
}
}
Она в принципе работает, за исключением одного но! Если по достижении таймера pMs1 - 5 секунд (смотрел по монитору порта) тут же "выключить свет", то флаг Pshik срабатывает как положено по времени (2 > 3 > 0). А на 6 секунде и далее происходит моментное обнуление флага Pshik.
Судя по монитору, таймер pMs2 запускается сразу после достижения 5 секунд pMs1 и останавливается сам по себе на значении 6037 (через пару секунд после запуска), даже с выпиленными последними тремя функциями. То есть loop заканчивается на запуске этого таймера. Может быть из-за этого и флаг Pshik обнуляется?
Просто хочется докопаться до причины, я не успокоюсь)) Без этого же намного усложняется обучение))
P.S. Кажется понял. надо вместо (raw == 5) поставить (raw >= 5). Все работает и таймер pMs2 не останавливается сам по себе, и пшик работает через любое время.
Ааа... может это все (обнуление Pshik) за один цикл происходит. Надо потыкать вывод в порт внутрь всех if где Pshik меняется (вывести Pshik и значение таймера) - должно стать виднее.
вот же.... да за это время я на двух (может трех) триггерах без МК уже собрал бы эту пшикалку... перечитайте пост 68 и напишите таблицу переходов... всех дел-то собрать 2 одновибратора по "и"
создайте кучу флагов:
свет выключили Y1 = 1
если свет выключили и уже прошло время ... Y2 = 1 иначе Y1 = 0
прошло t1>x1 =1
пшыкали t2> x2 = 1
если все нужные флаги ==1, пшыкаем, скидываем и взводим нужные флаги.
UPD лучше блоксхему нарисовать - мне они болше таблиц нравятся, но не всегда возможно их подробно нарисовать...
вот же.... да за это время я на двух (может трех) триггерах без МК уже собрал бы эту пшикалку... перечитайте пост 68 и напишите таблицу переходов... всех дел-то собрать 2 одновибратора по "и"
Не, Гриш, это не наш метод. Элита очень преподавать любит, в последний его серьезный заход, "Работа с кнопками..." от комментариев прикрыли.
Элита очень преподавать любит, в последний его серьезный заход, "
docendo discimus... я редко задаю вопросы на форуме и редко отвечаю, банальная нехватка времени писать ... ИМХО не стоит отбивать благие намеренья, даже не совсем правильные, а вместе с кем-то учиться легче...
2ТС - вспомнил еще способ -
UPD. Был знаком с двумя товарищами, один умел писать код, другой схемотехник и электроник... в одной из задачь схемотехник объяснил программеру алгоритм работы устройства (для написания кода прогером) на листе бумаги - он расписал 150 тактов!!! А потом прогер просто написал с этих листов программу и все заработало!!!
нет, если там будет >= то он будет при каждой итерации сбрасывать флаг на 1 и таймер
строка 28 замените на if( raw == 5 && Pshik == 0 )
в 18 строка изменить на if( (cMs - pMs1 > 1000UL) && Pshik == 0 )
Вообще не работает этот вариант. Таймер pMs2 останавливается наверно на 6 секунде и ничего не работает как мне кажется из-за того, что if ( raw == 5 ), а на 6 секунде уже не ровно 5. Но когда я поставил знак >= таймер pMs2 стал останавливаться после выключения света и продолжал отчет на 5 секунде после включения света.
Не знаю, что такое интерация, но пшик срабатывает снова и снова. Может должно пройти больше времени после того как начнутся глюки.
Размещаю весь код моей пшикалки, который у меня получился. На данный момент все задуманное испытано и работает. Всем спасибо за помощь! Для новичка это очень хорошо, хоть и код получился корявым)))
Принцип действия таков. На корпусе есть переключатель - OFF > MANUAL (только кнопка) > AUTO / MANUAL (кнопка и автоматика). В последнем режиме после включения света в туалете, запускается таймер готовности пшика (3 мин), до этого времени мигает синий светодиод (стоит RGB). Если прошло менее 3 минут и свет отключился (это время обычно затрачивается на коричневые дела), то после повторного включения он начинает идти заново. Но если прошло 3 минуты синий светодиод начинает гореть постоянно, это означает, что после выключения света произойдет распыление освежителя.
Во время распыления (0,8 сек) включится зеленый светодиод и сменится мигающим красным, это блокировка повторного нажатия в течение 30 минут (запах освежителя обычно столько и держится). Также блокируется и кнопка ручного распыления.
В ручном режиме работает только кнопка. При этом во время ключенного света синий светодиод готовности постоянно мигает (таймер жеж выключен). При нажатии на кнопку, происходят описанные выше действия.
Для увеличения срока службы батареек, светодиод полностью отключается в тот момент, когда в туалете темно.
Также присутствует защита от переразряда батареек (2 Ni-Mh последовательно). Если заряд опустится ниже 1,9В, то работа распылителя будет заблокрована полностью и включится красный светодиод, а Ардуино уйдет в сон для уменьшения эноргопотребления.
Кстати, насчет него. Для понижения энергопотребления я понизил частоту до 1 Мгц, пришлось пересчитывать таймеры. А Ардуино запитал через повышающий DC-DC, так как максимальное напряжение батареек не хватает для нормальной работы. На выходе выставил 3.4 Вольт. Чем выше, тем больше ток потребления. При 5В - 60 мА (16Мгц), при 3.4В - 5 мА (1 Мгц) в режиме ожидания (так как напряжение батареек ниже преобразованного, ток будет выше + КПД преобразователя, после него ток получился менее 1 мА, преобразователь потребляет 0,8 мА на холостом ходу). Это все равно много, по расчетам, аккумуляторы придется заряжать примерно раз в 20 дней. В связи с этом, у меня возник вопрос, можно ли как нибудь Ардуино загнать в спящий режим после выключения блокировки, а после включения света или нажатия кнопки его будить?
const int photo = A1; // фоторезистор
const int charge = A5; // вход 3В от батареек (защита от переразряда)
const int motor = 2; // привод распылителя
const int button = 3; // кнопка
const int led_block = 4; // светодиод блокировки (красный)
const int manual_mode = 5; // автоматический и ручный режимы
const int led_work = 6; // светодиод работы (зеленый)
const int led_on = 7 ; // светодиод готовности (синий)
float vout = 0.0;
float vin = 0.0;
float R1 = 7500;
float R2 = 1000;
int value = 0; // контроль батареек
int raw = 0; // переменная фоторезистора
int stlk = 1; // блокировка кнопки в течение 30 минут после срабатывания пшика по свету
int chrg = 1; // блокировка работы устройства с разряженными батарейками
int btn = 1; // блокировка нескольких пшиков при удержании кнопки
int led = 1; // индикация готовности пшика после выключения света
int pht = 1; // блокировака пшика по свету в течении 30 минут после нажатия на кнопку
int statblk = 1; // отключение счетчика stat
uint32_t stat = 1; // управление шпиком
uint32_t svet = 0; // флаг управления готовности для пшика по свету
uint32_t cMs, pMs1, blokTime; // счетчики времени по свету
uint8_t Pshik = 0; // разрешение пшика после получения готовности
bool pshikBlock; // флаг блокировки блокировка повторного пшика
int ledState = LOW; // состояние светодиода
int32_t previousMillis = 0; // храним время последнего переключения светодиода
int32_t interval = 62.5; // интервал между включение/выключением светодиода ожидания (1 секунда)
#include <avr/power.h>
#include <avr/sleep.h>
void setup() {
clock_prescale_set(clock_div_16); // понижение частоты работы микроконтроллера до 1 Мгц для экономии заряда батареек
pinMode( photo, INPUT );
pinMode( manual_mode, INPUT );
pinMode( charge, INPUT );
pinMode( motor, OUTPUT );
pinMode( button, INPUT );
pinMode( led_block, OUTPUT );
pinMode( led_work, OUTPUT );
pinMode( led_on, OUTPUT );
digitalWrite( led_block, LOW );
digitalWrite( led_work, LOW );
digitalWrite( motor, LOW );
pshikBlock = false;
}
void loop() {
cMs = millis(); // текущее время
int buttonState = digitalRead( button ); // считывание значения с пина кнопки
int manualState = digitalRead( manual_mode ); // считывание значения с пина ручного режима
raw = analogRead( photo ); // считывание значения с пина фоторезистора
value = analogRead( charge ); // считывание напряжения с пина (контроль заряда)
vout = (value * 5.0) / 1024; // конвертор в понятные единицы измерения
vin = vout / (R2 / (R1 + R2));
if (chrg == 1) { // если заряд АКБ в норме
if ( buttonState == HIGH && btn == 1 && stlk == 1) { // если кнопка нажата и не заблокирована
btn = 0; // переключить флаг защиты повторных пшиков при удержании кнопки
pht = 0; // заблокировать пшик по свету на 30 минут
digitalWrite( led_on, LOW ); // выключаем светодиод готовности
digitalWrite( led_work, HIGH ); // включаем светодиод работы
digitalWrite( motor, HIGH ); // включаем пшик
delay(50); // ждем 800 миллисекунд
digitalWrite( motor, LOW ); // выключаем пшик
digitalWrite( led_work, LOW ); // выключаем светодиод работы
pshikBlock = true; // запустить таймер блокировки повторного срабатывания на 30 минут
blokTime = millis();
} else if (btn == 0) {
if ( raw < 350 && vin <= 4.8 ) { // если в туалете темно
digitalWrite( led_block, LOW ); // выключаем светодиод блокировки
} else { // если в туалете светло
if (cMs - previousMillis > interval) { // сохраняем время последнего переключения
previousMillis = cMs;
if (ledState == LOW) // если светодиод блокировки не горит, то зажигаем, и наоборот
ledState = HIGH;
else
ledState = LOW;
digitalWrite(led_block, ledState); // устанавливаем состояния выхода, чтобы включить или выключить светодиод
}
}
} else if (stlk == 1) {
if ( raw < 350 && vin <= 4.8 ) { // если в туалете темно
digitalWrite( led_on, LOW ); // выключаем светодиод разряда батареи
} else if (led == 0) { // если наступила готовность автоматического пшика
digitalWrite( led_on, HIGH ); // светодиод готовности горит постоянно
} else {
if (cMs - previousMillis > interval) { // сохраняем время последнего переключения
previousMillis = cMs;
if (ledState == LOW) // если светодиод не горит, то зажигаем, и наоборот
ledState = HIGH;
else
ledState = LOW;
digitalWrite(led_on, ledState); // устанавливаем состояния выхода, чтобы включить или выключить светодиод
}
}
}
if ( buttonState == LOW && millis() - blokTime > 112500 ) btn = 1; // если кнопка не нажата и время блокировки прошло, разблокировать повторное нажатие
if ( manualState == HIGH ) { // если включен автометический и ручной режимы
if ( cMs - pMs1 > 62UL ) { // запускаем таймер отстчета готовности автоматического пшика
pMs1 = cMs; // время опроса фотореле каждые 1 секунду
if ( raw > 450 ) { // если в туалете светло
svet++; // запустить таймер
} else { // если темно
svet = 0; // обнулить таймер
}
}
if ( svet == 180 ) { // если свет включен 3 минуты и более
Pshik = 1; // включаем флаг разрешения пшика
led = 0; // включаем постоянное свечение светодиода готовности
}
if ( Pshik == 1 ) { // если автоматическое срабатывание пшикалки разрешено
if ( raw < 350 && stat <= 4294967295 && pht == 1 && statblk == 1 ) stat++; // если свет выключился, все блокировки выключены, запустить таймер отсчета
if ( stat == 300 ) { // после пары секунд
stat ++;
digitalWrite( led_on, LOW ); // выключаем светодиод готовности
digitalWrite( led_work, HIGH ); // включаем светодиод работы
digitalWrite( motor, HIGH ); // включаем привод
delay(50); // ждем 800 миллисекунд
digitalWrite( motor, LOW ); // выключаем привод
digitalWrite( led_work, LOW ); // выключаем светодиод работы
stlk = 0; // заблокировать кнопку на некоторое время
statblk = 0; // отключить таймер stat
pshikBlock = true; // запустить таймер блокировки повторного срабатывания на 30 минут
blokTime = millis();
} else if ( stlk == 0 ) {
if ( raw < 350 && vin <= 4.8 ) { // если в туалете темно
digitalWrite( led_block, LOW ); // выключаем светодиод блокировки
} else { // если светло
if (cMs - previousMillis > interval) { // сохраняем время последнего переключения
previousMillis = cMs;
if (ledState == LOW) // если светодиод не горит, то зажигаем, и наоборот
ledState = HIGH;
else
ledState = LOW;
digitalWrite(led_block, ledState); // устанавливаем состояния выхода, чтобы включить или выключить светодиод
}
}
}
}
}
}
if ( raw > 450 && millis() - blokTime > 112500 ) { // если в туалете светло и время блокировки вышло
digitalWrite( led_block, LOW ); // отключить светодиод блокировки
stat = 1; // разблокировать таймер
stlk = 1; // разблокировать кнопку
pht = 1; // разблокировать автоматический пшик
statblk = 1;
}
if (pshikBlock) // если блокировка активна
if (millis() - blokTime > 112500) {
digitalWrite( led_block, LOW ); // включаем светодиод блокировки
stlk = 1; // разблокировать таймер
Pshik = 0; // сбросить флаг готовности автоматического пшика
svet = 0; // сбросить таймер готовности
led = 1; // влючить мигание синим светодиодом
pshikBlock = false;
}
if ( vin <= 2.5 ) { // и если заряд батареи слабый
chrg = 0;
digitalWrite( led_on, LOW ); // выключаем светодиод готовности
digitalWrite( led_work, LOW ); // выключаем светодиод работы
digitalWrite( motor, LOW ); // включаем мотор
digitalWrite( led_block, HIGH ); // включаем светодиод разряда батареи
ADCSRA = 0;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_mode();
MCUCR = bit (BODS) | bit (BODSE); // turn on brown-out enable select
MCUCR = bit (BODS); // this must be done within 4 clock cycles of above
sleep_cpu ();
}
}
Ну почему же, если в какой то момент никаких функций от него не требуется, почему бы не усыпить ради экономии заряда. Я читал, что некоторые режимы могут в несколько раз понизить потребление)
В связи с этом, у меня возник вопрос, можно ли как нибудь Ардуино загнать в спящий режим после выключения блокировки, а после включения света или нажатия кнопки его будить?
Ух как тема разрослась)) Мне подсказали на другом форуме, что для добавления гистерезиса нужно всего лишь добавить простую строку (как ж я не смог догадаться!!),
Это вам ещё в #54 подсказали, если что.
пятерка лишняя, и это потри
Писали вроде уже - через millis(). Запоминаете millis() в момент "пшика" в переменную t и ждете, когда millis() - 600000 > t, это условие можно добавить к raw >= 550,
Простите, Ардуино начал изучать только неделю назад. Вот дописал код с millis для блокировки повторного срабатывания пшика в течение 5 мин, однако Ардуино этого времени не дожидается и начинает пшикать сразу после повторного включения и выключения света. Вот пример кода, подскажите, что здесь не так?
в строке 17 или 18 надо учесть led1On.
Можно и в 27 (не взводим флаг пока не истек интервал). led1On в этом случае лишний
или так, красиво но не понятно для ТС )
Нет, чтоб участок кода дописать, лентяи)) Я уж сам догадался.
Нет, чтоб участок кода дописать
фии... так неинтересно (
как вариант
да и гестерезис особо не нужен
как вариант
да и гестерезис особо не нужен
второй, заход )
второй, заход )
чтото тут тоже "не по феншую" ??
второй, заход )
чтото тут тоже "не по феншую" ??
пшикать надо в темноте, а не в лицо.
и не пшикать если зашли менее чем через 10 мин.
второй, заход )
чтото тут тоже "не по феншую" ??
пшикать надо в темноте, а не в лицо.
и не пшикать если зашли менее чем через 10 мин.
в тех задании стоит иначе - при входе в нос...
а задержка есть... хотя надо дополнить строку 23 и выставить нужные временные интервалы
как вариант
да и гестерезис особо не нужен
Я как понимаю, строка
if(raw == 5 || raw == 600 )
отвечает за то, если свет включится на 5 секунд, то после выключения пшикнуть?
Если нет, то хотелось бы еще функцию срабатывания пшика по таймеру. То есть, в среднем на посрать времени тратится около 5 минут, обоссать унитаз около минуты. Если свет был включен до 3 минут, не пшикать. Так вот, этот код, что выше сможет ли реализовать задуманное?)))
как вариант
да и гестерезис особо не нужен
Я как понимаю, строка
отвечает за то, если свет включится на 5 секунд, то после выключения пшикнуть?
Если нет, то хотелось бы еще функцию срабатывания пшика по таймеру. То есть, в среднем на посрать времени тратится около 5 минут, а по маленькому около минуты. Поэтому, если свет был включен до 3 минут, не пшикать. Так вот, этот код, что выше сможет ли реализовать задуманное или придется переписывать?)))
Millis, я как понимаю, не сбрасывает таймер, если он не дошел до заданного.
как вариант
да и гестерезис особо не нужен
Я как понимаю, строка
отвечает за то, если свет включится на 5 секунд, то после выключения пшикнуть?
Если нет, то хотелось бы еще функцию срабатывания пшика по таймеру. То есть, в среднем на посрать времени тратится около 5 минут, а по маленькому около минуты. Поэтому, если свет был включен до 3 минут, не пшикать. Так вот, этот код, что выше сможет ли реализовать задуманное или придется переписывать?)))
Millis, я как понимаю, не сбрасывает таймер, если он не дошел до заданного.
только не забудьте паузу в последней строке сделать больше самого большого повтора
Millis, я как понимаю, не сбрасывает таймер, если он не дошел до заданного.
все остальные действия - это запоминание в нужный момент времени и ожидание заданной разницы между запомненым и текущим временем
Урок от Евгения как можно реализовать хотелки настоящие и будущие.
http://arduino.ru/forum/programmirovanie/7-i-zonnoe-osveshchenievklvykl-...
Разобрался в принципе действия вашего кода, но мне нужно, чтобы пшик был сразу после выключения света, а не во время включенного. Дописал фунццию analogRead( photo ) < 400 в строку 28. Однако после выключения света пшик срабатывает через раз. Без этой функции все отлично работает. Монитор порта Serial.println(Pshik); показывает, что флаг Pshik иногда не переходит после 1 в состояние 2, а сразу на 0, когда переходит на 2, все срабатывает. Судя по монитору порта Вот сам код
А 5 секунд светили прежде чем затенять ? С виду вроде ниче так...
так логика работы в 28й строке у вас получилась противоречащая логике вышестоящего кода
вначале мы проверяем, что свет включен, и если выключен - то флаг снимаем
а вы проверяете, что свет выключен и при этом флаг стоит ... - но он то уже снят будет на тот момент...
---
также вы сказали чуть выше - не пшикать, если менее 3 минут
а сейчас хотите сразу пшикать...
так чего вы хотите в итоге?
---
и да, с момента включения света до момента входа в туалет пройдет несколько секунд...
хотите наверняка и быстрее
строка 18 - меняете интервал опроса датчика например на 0.1с (100мс)
и в строке 23 у вас уже будет не 5 секунд, а 0.5с (пол секунды)
А 5 секунд светили прежде чем затенять ? С виду вроде ниче так...
Все по феншую :)
и да, строка 36 - это время ДО СБРОСА флага - вы его сделали МЕНЬШЕ, чем время срабатывания пшикалки! а оно должно быть БОЛЬШЕ его, иначе возможны глюки в работе кода
вроде нигде не запутал ничего
да, этот код можно (да и нужно) оптимизировать путем изменения условий при выключении света - не повторять действия, а взводить на старт 2й таймер и поменять флаг на нужный - дабы система уже повторно прошла цикл пшиканья и по его окончании уже сбросилась для новой работы
Спасибо, нашел решение, вместо "raw++" написал "raw=1", все работает как и раньше, а также изменил:
Спасибо, нашел решение, вместо "raw++" написал "raw=1", все работает как и раньше, а также изменил:
внимательно посмотрите код постом выше - я в комментарии специально более подробно всё написал! - зачем имеенно 5 поставил, а не 1
вроде нигде не запутал ничего
Этот код сбрасывает флаг 3 автоматически на 0 при прошествии более 3 секунд и пшика после "выключения света" не происходит. Если это сделать до 3 секунд, то флаг 3 переходит на 4, потом 5 и 0.
Такая же фигня происходила и с прежним кодом. Если сразу после включения флага 1 выключить свет, то он перейдет к 2, 3, 0. Но если после включени флага 1 выключить свет, например, через 10 секунд, то он сразу переходит в 0. Целый день уже ябусь. Уже думаю оставить включение пшикалки со включенным светом(((
Монитор порта:
вы его точно скопировали? или прошлый подправлли под него?
Я всего лишь уменьшил время - 800UL, 3000UL, 3800UL, 6000UL. Чтобы долго не ждать для проверки.
а 18 строку не меняли? - попробуйте полность скопировать еще раз
вот с уменьшенным временем
Все тоже самое, сброс флага 3 через несколько секунд.
Сброс флага 3 неизбежен. А что происходит до того ? Висит 1 ?
Увидим ли мы конец этой опупеи?..
в этом коде если после 15000мс (15с) продолжает гореть свет - то через 30с будет сброс флага 3
если свет выключен будет - то будет повторный пшик и через еще 15 с будет сброс флага 5
Давайте вернемся к прежней версии кода))
Она в принципе работает, за исключением одного но! Если по достижении таймера pMs1 - 5 секунд (смотрел по монитору порта) тут же "выключить свет", то флаг Pshik срабатывает как положено по времени (2 > 3 > 0). А на 6 секунде и далее происходит моментное обнуление флага Pshik.
Судя по монитору, таймер pMs2 запускается сразу после достижения 5 секунд pMs1 и останавливается сам по себе на значении 6037 (через пару секунд после запуска), даже с выпиленными последними тремя функциями. То есть loop заканчивается на запуске этого таймера. Может быть из-за этого и флаг Pshik обнуляется?
Просто хочется докопаться до причины, я не успокоюсь)) Без этого же намного усложняется обучение))
P.S. Кажется понял. надо вместо (raw == 5) поставить (raw >= 5). Все работает и таймер pMs2 не останавливается сам по себе, и пшик работает через любое время.
P.S.2. Но это пока не точно.
Вывод в порт у вас где стоит ? Не должно ничего заканчиваться, да и варианта мгновенного обнуления Pshik без 2-3 вроде нет.
а может потому, что вы неправильно расставили вывод в порт логи
давайте сюда код, который вы заливаете в своё устройство в полном виде
Ааа... может это все (обнуление Pshik) за один цикл происходит. Надо потыкать вывод в порт внутрь всех if где Pshik меняется (вывести Pshik и значение таймера) - должно стать виднее.
а может потому, что вы неправильно расставили вывод в порт логи
давайте сюда код, который вы заливаете в своё устройство в полном виде
Он находится здесь - http://arduino.ru/forum/pesochnitsa-razdel-dlya-novichkov/kak-vypolnit-kod-tolko-1-raz-v-tsikle-loop?page=1#comment-459909
Как я уже посал в том сообщении, дело было в ошибке функции (raw == 5), нужно поставить знак >=. Тогда таймер не останавливается.
Morroc, пока все работает) Интересует, до какого значения доходит таймер pMs2, он же должен потом сброситься? Не глюкнет ли ничего после сброса?
нет, если там будет >= то он будет при каждой итерации сбрасывать флаг на 1 и таймер
строка 28 замените на if( raw == 5 && Pshik == 0 )
в 18 строка изменить на
if
( (cMs - pMs1 > 1000UL) &&
Pshik == 0 )вот же.... да за это время я на двух (может трех) триггерах без МК уже собрал бы эту пшикалку... перечитайте пост 68 и напишите таблицу переходов... всех дел-то собрать 2 одновибратора по "и"
создайте кучу флагов:
свет выключили Y1 = 1
если свет выключили и уже прошло время ... Y2 = 1 иначе Y1 = 0
прошло t1>x1 =1
пшыкали t2> x2 = 1
если все нужные флаги ==1, пшыкаем, скидываем и взводим нужные флаги.
UPD лучше блоксхему нарисовать - мне они болше таблиц нравятся, но не всегда возможно их подробно нарисовать...
вот же.... да за это время я на двух (может трех) триггерах без МК уже собрал бы эту пшикалку... перечитайте пост 68 и напишите таблицу переходов... всех дел-то собрать 2 одновибратора по "и"
Не, Гриш, это не наш метод. Элита очень преподавать любит, в последний его серьезный заход, "Работа с кнопками..." от комментариев прикрыли.
Элита очень преподавать любит, в последний его серьезный заход, "
docendo discimus... я редко задаю вопросы на форуме и редко отвечаю, банальная нехватка времени писать ... ИМХО не стоит отбивать благие намеренья, даже не совсем правильные, а вместе с кем-то учиться легче...
2ТС - вспомнил еще способ -
UPD. Был знаком с двумя товарищами, один умел писать код, другой схемотехник и электроник... в одной из задачь схемотехник объяснил программеру алгоритм работы устройства (для написания кода прогером) на листе бумаги - он расписал 150 тактов!!! А потом прогер просто написал с этих листов программу и все заработало!!!
нет, если там будет >= то он будет при каждой итерации сбрасывать флаг на 1 и таймер
строка 28 замените на if( raw == 5 && Pshik == 0 )
в 18 строка изменить на
if
( (cMs - pMs1 > 1000UL) &&
Pshik == 0 )Вообще не работает этот вариант. Таймер pMs2 останавливается наверно на 6 секунде и ничего не работает как мне кажется из-за того, что if ( raw == 5 ), а на 6 секунде уже не ровно 5. Но когда я поставил знак >= таймер pMs2 стал останавливаться после выключения света и продолжал отчет на 5 секунде после включения света.
Не знаю, что такое интерация, но пшик срабатывает снова и снова. Может должно пройти больше времени после того как начнутся глюки.
Неважно на какой секунде, но когда то 5 там будет и сразу должен запуститься "пшик", стрянно...
Для наглядности лучше вывести cMs и Pshik (и в if'ы после выполнения команд внутри тоже сунуть вывод)
Размещаю весь код моей пшикалки, который у меня получился. На данный момент все задуманное испытано и работает. Всем спасибо за помощь! Для новичка это очень хорошо, хоть и код получился корявым)))
Принцип действия таков. На корпусе есть переключатель - OFF > MANUAL (только кнопка) > AUTO / MANUAL (кнопка и автоматика). В последнем режиме после включения света в туалете, запускается таймер готовности пшика (3 мин), до этого времени мигает синий светодиод (стоит RGB). Если прошло менее 3 минут и свет отключился (это время обычно затрачивается на коричневые дела), то после повторного включения он начинает идти заново. Но если прошло 3 минуты синий светодиод начинает гореть постоянно, это означает, что после выключения света произойдет распыление освежителя.
Во время распыления (0,8 сек) включится зеленый светодиод и сменится мигающим красным, это блокировка повторного нажатия в течение 30 минут (запах освежителя обычно столько и держится). Также блокируется и кнопка ручного распыления.
В ручном режиме работает только кнопка. При этом во время ключенного света синий светодиод готовности постоянно мигает (таймер жеж выключен). При нажатии на кнопку, происходят описанные выше действия.
Для увеличения срока службы батареек, светодиод полностью отключается в тот момент, когда в туалете темно.
Также присутствует защита от переразряда батареек (2 Ni-Mh последовательно). Если заряд опустится ниже 1,9В, то работа распылителя будет заблокрована полностью и включится красный светодиод, а Ардуино уйдет в сон для уменьшения эноргопотребления.
Кстати, насчет него. Для понижения энергопотребления я понизил частоту до 1 Мгц, пришлось пересчитывать таймеры. А Ардуино запитал через повышающий DC-DC, так как максимальное напряжение батареек не хватает для нормальной работы. На выходе выставил 3.4 Вольт. Чем выше, тем больше ток потребления. При 5В - 60 мА (16Мгц), при 3.4В - 5 мА (1 Мгц) в режиме ожидания (так как напряжение батареек ниже преобразованного, ток будет выше + КПД преобразователя, после него ток получился менее 1 мА, преобразователь потребляет 0,8 мА на холостом ходу). Это все равно много, по расчетам, аккумуляторы придется заряжать примерно раз в 20 дней. В связи с этом, у меня возник вопрос, можно ли как нибудь Ардуино загнать в спящий режим после выключения блокировки, а после включения света или нажатия кнопки его будить?
Ардуино в спящем режиме - это как гопник в цилиндре. Смешно и бессмысленно.
Ну почему же, если в какой то момент никаких функций от него не требуется, почему бы не усыпить ради экономии заряда. Я читал, что некоторые режимы могут в несколько раз понизить потребление)
Так выключайте все, а по кнопке включайте :) "Загнать" можно, но придется копнуть поглубже https://tsibrov.blogspot.com/2018/02/arduino-power-down.html