Подсветка лестницы по датчику движения
- Войдите на сайт для отправки комментариев
Вс, 19/06/2022 - 01:44
Была задача сделать подсветку лестницы по датчикам движения и по кнопке. Реализовано два режима работы. Плавно зажигаем ленту и горим(первый режим), ждем датчики и фоторезистор (днем не работаем по датчикам) в остальном плавно гасим. При удержании кнопки меняем яркость и сохраняем в постоянную память значение яркости.
Проблема в крайней кривизне кода и что самое главное делеи тормозящие. Первый мой скетч не судите строго, буду очень брагодарен подсказкам по оптимизации.
#include <EEPROM.h> #define pirA 7 // PIR датчик #define pirB 6 #define mosfet 9 // мосфет #define foto A0 // фоторезистор #define sw 3 // кнопка #define nightVAL 100 // порог включения #define smooth 35 // скорость затухания byte pwm = 150; // максимальное значение яркости int brightness = 0; // текущее значение яркости const long period = 10000; // время свечения при срабатывании датчика unsigned long last_press; boolean butt_flag = 0; boolean butt; boolean led_flag = 0; bool lightOff=true; bool lightOn=false; volatile int mode = 1; int i; void changeMode() { mode = mode + 1; if(mode > 2) { mode = 1; } } void setup() { Serial.begin(9600); pinMode (pirB, INPUT); pinMode (pirA, INPUT); pinMode (mosfet, OUTPUT); pinMode (sw, INPUT_PULLUP); brightness = EEPROM.read( 0 ); TCCR1A = TCCR1A & 0xe0 | 1; TCCR1B = TCCR1B & 0xe0 | 0x09; } void loop(){ int foto = analogRead (0); if(Serial.available() > 0){ int in_data = Serial.parseInt(); Serial.println(foto); } if (mode == 1) { effect1(); } if (mode == 2) { effect2(); } } void effect1() { delay(100); if ((digitalRead(pirA) || (digitalRead(pirB)) == HIGH) && (analogRead(foto) < (nightVAL))){ if (lightOff){ for (i = 0; i <= brightness; i++){ analogWrite(mosfet, i); delay(smooth); } lightOff = false; lightOn = true; delay(period); } } if (!lightOff){ analogWrite(mosfet, brightness); for (i = brightness; i >= 0; i--){ analogWrite(mosfet, i); delay(smooth); } lightOff = true; lightOn = false; } else { if (lightOn) { for (i = brightness; i >= 0; i--){ analogWrite(mosfet, i); delay(smooth); } lightOff = true; lightOn = false; } } } void effect2() { delay(smooth); if (lightOff){ for (i = 0; i < brightness; i++){ analogWrite(mosfet, i); delay(smooth*1.5); } } lightOff = false; lightOn = true; } void yield() { butt = !digitalRead(sw); if (butt == 1 && butt_flag == 0 && millis() - last_press > 100) { butt_flag = 1; led_flag = !led_flag; last_press = millis(); } if (butt == 0 && butt_flag == 1) { butt_flag = 0; mode = mode +1; if(mode > 2) { mode = 1; } } if (butt == 1 && millis() - last_press > 700) { brightness = brightness + 10; analogWrite(mosfet, brightness); if (brightness > pwm) { brightness = 20; EEPROM.write(0, brightness); } last_press = millis(); } }
1) Ваш код работает или нет? Если не работает или работает не так, нужно сделать, чтобы работал как надо. Это не оптимизация, это исправление ошибок.
2) Если код работает, то какую цель Вы преследуете, пытаясь его оптимизировать. Пример оптимизации: Вы хотите добавить в скетч ещё функционал, а он в память не влезает. А у Вас какая цель?
3) Что Вы понимаете под "Проблема в крайней кривизне кода и что самое главное делеи тормозящие." ?
4) Вы понимаете, что делают строки 37-38? Знаете, где и когда вызывается Ваша функция yield()?
5) Предлагаю в качестве первой оптимизации написать этот скетч самому, используя только хорошо понятные базовые инструменты (это вполне реально). В качестве теоретической подготовки можно поискать в сети (в том числе и прямо на этом форуме) статьи на тему использования конечных автоматов в ардуино.
1)Код работает. Но в редких случаях не реагирует на кнопку, вот и грешу на делеи, но хотел победить эту проблему с помощью yield.
2)Хотел что бы бородатые дядьки тыкнули носом в ошибки, а в идеале показали как правильно.
3)Код был собран из кусков чужих наработок и уже шлифован под мои задачи.
4)37-38 мы увеличиваем частоту шим сигнала. Где и когда вызывается наша функция yield() не знаю. Уведел у Гайвера костыль и преминил.
5)Ну всетаки етот код мой хоть и +- понимаю что он делает. По поводу "использования конечных автоматов" спасибо.
yield() вызывается именно внутри функции delay. Попробуйте ещё явный вызов yield(); в цикл loop добавить. Самой первой или самой последней строкой. Может это как раз и перекроет редкие случаи несрабатывания.
Доброго времени суток. Явный вызов yield(); в цикле loop помог. Немного почистил скетч, появилась новая задача. Как сделать так что бы в первом режиме работы(ждем сработки датчиков) если датчики сработали повторно до стадии выключения то пауза начала щитаться заново но без морганий.
ну если уж в цикл по mode = 2 вставили yield(), то и по mode=1 тоже ставьте, для симметрии...
А вообще yield() - это костыль. По нормальному надо эффекты переписать через миллис. А в итоге получился код из одних костылей...
Если не сложно покажите как правильно, а то что бы и плавно засвечивалось и обновлялся таймер свечения без делеев и yield() как то слишком для меня. Уже голова кипит...
На каждом лупе добавлять по 1% к яркости, например.
Не реализована фича одна котороя мне важна. Испульзую PIR AM312. Нужно что бы при срабатывании датчика плавно загорался свет и светил скажем 10сек, НО при повторном срабатывании датчика отсчет начинался сначала. По прошествию 10 сек свет плавно угасал до 0. НО при сработке датчика начал загораться стого места где закончил угасать(что бы не мигал).
А в чем затруднение?
Имейте переменную "яркость". Сработал датчик, начинайте каждые N ms плюсовать к ней переменную с положительным значением M. До 100 досчитали, Вместо М записали в переменную нуль. Оно плюсуется, но яркость не меняется. Ждете 10сек. В переменную кладете -M. Счёт пошёл вниз. До 0 дошли, в переменную положили 0. Сработал датчик - в переменную кладёте +M. Так оно и будет мотаться туда-сюда.
Затрудниени в том что не знаю как это правильно написать и внедрить. Не могу найти похожие реализации а с нуля все сделать знаний и времени не хватает. Благодарен тем кто ответил в теме, но не пойму почему никто не покажет как нужно сделать, может проект слишком простой для местной аудитории ...
br += step
If (br <= 0) { step = 0 ; }
If (br >= 100) { step = -2 ; }
...
И тд. Какие ещё примеры тут нужны?
А время ваше никто экономить не будет. Кроме алиэкспресса. Но он строго за деньги работает.
Нашел схожую реализацию задачи от ЕвгенийП, да простит он меня за такую интерпретацию)
Нашел схожую реализацию задачи от ЕвгенийП
мне кажется, вряд ли он обрадуется, что этот код приписывают ему :)