Плавное включение светодиодов
- Войдите на сайт для отправки комментариев
Здравствуйте форумчане, в ходе экспериментов с диодной лентой получил некоторые результаты и хочу ими поделиться, может кому-то они пригодятся)
Думаю многие знают что зависимость скважности ШИМ и яркости свечения светодиода не линейна и используя цикл такого вида мы плавного включения не получим
for(int i = 0; i <= 255; i++){ analogWrite(analogOutPin, i); }
Для устранения нелинейности в большинстве случаев подойдет функция параболы y=x2/a, ее легко применить в цикле
for (unsigned int i = 0; i <= 255; i++) { analogWrite(analogOutPin, pow(i,2)/255); delay(3); }
Но в таком виде наш 8ми битный шим будет задействован не полностью, в цикле включения будет использовано 196 из 256 разных значений скважности, использовать все 256 значений позволит такой цикл
for (unsigned int i = 0; i <= 505; i++) { analogWrite(analogOutPin, pow(i,2)/1000); delay(3); }
Так же можно использовать функцию такого вида y=x^3/a^2, вот графики двух этих функций
Как видно на графике вторая функция(синего цвета) дает более плавный старт, но использовать ее лучше в таком виде, тогда нет резких скачков в конце цикла
for (unsigned int i = 0; i <= 630; i++) { analogWrite(analogOutPin, pow(i,3)/980100); delay(3); }
Если стоит задача просто плавно включить и выключить светодиод, можно использовать программный ШИМ, его мне подсказал форумчанин dimax, правда пришлось его код переделать под себя, с его помощью можно получить большую плавность за счет увеличенной разрядности, и оставить аппаратный ШИМ на другие нужды
#define Bitrate 1500 #define Speed 1 void setup() { Serial.begin(9600); pinMode(12, OUTPUT); } void loop() { led_ON(); delay(2000); led_OFF(); delay(2000); } void led_ON() { for(uint16_t i = 0; i<Bitrate; i+=Speed) { uint16_t del = pow(i,2) / Bitrate; PORTB |= 1 << PB4; //включение 12й ноги delayMicroseconds(del); PORTB &= ~(1 << PB4); //выключение 12й ноги delayMicroseconds(Bitrate - del); } PORTB |= 1 << PB4; } void led_OFF() { for(uint16_t i = Bitrate; i>Speed; i-=Speed) { uint16_t del = pow(i,2) / Bitrate; PORTB |= 1 << PB4; //включение 12й ноги delayMicroseconds(del); PORTB &= ~(1 << PB4); //выключение 12й ноги delayMicroseconds(Bitrate - del); } PORTB &= ~(1 << PB4); }
Изменением параметров Bitrate и Speed можно добиться необходимой скорости включения.
Строго не судите, пост пишу в первый раз)
Думаю многие знают что зависимость скважности ШИМ и яркости свечения светодиода не линейна и используя цикл такого вида мы плавного включения не получим
Думаю многие знают что зависимость скважности ШИМ и яркости свечения светодиода не линейна и используя цикл такого вида мы плавного включения не получим
нужно перешивать глаза.
Та ладно. Может скоро народ начнет собирать деньги на "плавное включение Солнца" А то резкое "включение" Солнца утром и "выключение" вечером приведет что Солнце быстро "перегорит". Или вообще поменять Солнце на "энеросберегающее" с "приятным для глаза свечением".
Alex_Mirko,
правильно, что Вы пробуете, но Вы зря предварительно не изучили матчасть в плане физиологии зрения.
Отсюда у Вас ненужные поиски, то квадрат, то квадрат делённый на куб. На самом деле глаз воспринимет изменения совещённогсти как равномерное тогда, когда оно изменяется по показательному закону, имейте это в виду на будущее.
Точно также ухо воспринимает изменение громкости, отсюда регуляторы громкости имеют показательную харакетристику.
ЕвгенийП, Я привел конкретные примеры полученные опытным путем, они просты в реализации, результат их использования меня вполне устроил, восприятие яркости сложная тема, и углубляться в нее для создания моргалки я не собираюсь. Если у вас есть примеры применения показательного закона так поделитесь ими.
a*=1.07 ;
Вместо 1.07 подбор по вкусу. Про это и написал Евгений. Такие примеры есть у каждого. И не нужно огород городить.
wdrakula, теперь все встало на свои места, спасибо)
Тема уже не раз подымалась. И варианты решения известны: аппаратное изменение тока, переход на ШИМ высокого разрешения(аппаратный или програмный) и переключение на програмный ШИМ при малой яркости и аппарвтный при большой.
И светодиод нелинейный. Он вобще весь нелинейный принципиально. ШИМ линейный но напряжение не тождественно световому потоку.
/// Если включен светодиод на 50 % процентов времени, то и насветит на эти 50% Ведь яркость зависит от напряжения включения. А при ШИМе светодиод или выключен или включен.
Нет. Кроме времени когда он включен или выключен есть время на его переключение. Собственно как и у других полупроводниковых приборов. У обычных светодиодов порядка десятых мсек, что очевидно при частое ШИМ в КГц на малой яркости сказывается. Идут процессы заряда-разряда емкости перехода, диффузии носителей и т.д. Он в это время не светит по полной пока не наступит диамическое равновесие генерации и рекомбинации. Вобще как он светит при переходных - ХЗ, но ясно что если часть энергии уходит на заряд емкости, то она не уходит в свет. Вот занятная статейка http://www.rlocman.ru/shem/schematics.html?di=112354 не совсем по теме, но график емкости от напряжения наглядно показывает степень нелинейности процессов, а по величине емкости можна и время заряда оценить.
Сомневающимся - простой опыт, светодиод к генератору прямоугольных импульсов. Напряжение и скважность фиксируем частоту меняем в широких пределах, наблюдаем изменение яркости.
ПС. Все это не отменяет нелинейность светочувствительности глаза, только дополняет.
Программно есть формула логарифма для 255 значений. У меня где то на работе записана. Я на ней сделал с десяток контроллеров. Работает, но разрядность теряется
Работает, но разрядность теряется
куда теряется?
Программно есть формула логарифма для 255 значений. У меня где то на работе записана. Я на ней сделал с десяток контроллеров. Работает, но разрядность теряется
это писец какой-то. 0х01 х02 0х04 0x08 0х10 х20 0х40 0x80 нормальная шкала логарифмов с основанием 2. Но видимо народ мозг терят когда дело касается логарифмов . Для народа логарифмы с основанием 10 и основанием e. Хотя думаю к поледнему относится как к богу, или верит, или не знает. ;)
Работает, но разрядность теряется
куда теряется?
В никуда.
На самом деле я не вникал тогда в логику рассчетов логарифма, так как проект надо было сдавать срочно, и в математике я не особо силен. Тогда я нашел дейвствующий пример на каком то англоязычном сайте и он меня вполне устроил.
Теряется я думаю не разрядность, а некоторые значения. Кстати по этой же формуле я делал торможение мачты с нагрузкой в 300кг и это помогло, хотя в линейном варианте тормозило неудачно
это писец какой-то. 0х01 х02 0х04 0x08 0х10 х20 0х40 0x80 нормальная шкала логарифмов...
Одно значение на октаву Вы считаете нормальной шкалой?
это писец какой-то. 0х01 х02 0х04 0x08 0х10 х20 0х40 0x80 нормальная шкала логарифмов...
Одно значение на октаву Вы считаете нормальной шкалой?
А что в Ардуино есть октавы @_@. Обычно это называют байтом. Но спутать 8 значений с одним . Советую вам отдохнуть.
ПС: Если по теме, то проще использовать такой метод для плавного зажигания светодиода:(255>>8),(255>>7),(255>>6),(255>>5),(255>>4),(255>>3),(255>>2),(255>>1),(255>>0)
ПС: Если по теме, то проще использовать такой метод для плавного зажигания светодиода:(255>>8),(255>>7),(255>>6),(255>>5),(255>>4),(255>>3),(255>>2),(255>>1),(255>>0)
не смотря на элегантность решения - ну, нихера это не плавное зажигание.
8 ступенек вместо 255, которые тоже заметны, если обращать внимание.
А что в Ардуино есть октавы @_@. Обычно это называют байтом. Но спутать 8 значений с одним . Советую вам отдохнуть.
Октавы есть везде, где есть логарифмическая шкала. И байтами их никогда не называли. Даже в шутку.
Ступени все равно будут заметны на 8ми битах, как ни крути. Просто логарифмическое регулирование дает более линейное(на глаз) нарастание яркости.
Убрать скачки можно конденсатором в затворе ключевого транзистора, но подбирать надо индивидуально под каждый тип ленты или диодов
А что в Ардуино есть октавы @_@. Обычно это называют байтом. Но спутать 8 значений с одним . Советую вам отдохнуть.
Вы же, как мне казалось, неплохой программист и имеете какое-то образование, так зачем позориться?
"отличается на октаву" тождественно "отличается в два раза". Выглядит так, будто вы этого не знали.
Пошло, конечно, из музыки, где, например, "Ля" первой октавы = 440Гц, второй = 880Гц, а малой, соответственно = 220Гц.
Изначально разница в октаву по высоте звука ранялась разнице в высоте полной струны и половины струны.
Разобрался:
число 980100 нужно, чтобы получить 255 - максимум, доступный для этого ШИМ-порта.
Но обнаружилось странное. У 10-битных ШИМов на 255 тоже включается максимум. Может кто подскажет почему?
Разобрался: ... Может кто подскажет почему?
Теме три года. Вы уж говорите поподробнее в чём именно Вы разобрались и что Вам нужно подсказывать.
Вы уж говорите поподробнее в чём именно Вы разобрались и что Вам нужно подсказывать.
У 10-битных ШИМов на 255 тоже включается максимум. Может кто подскажет почему?
Максимум у 10-битного ШИМа должен быть при 1023, но также максимальный уровень (стопроцентное заполнение, как мне кажется на глаз) будет если задать значение 255 в analogWrite.
Может это связано с тем, что у меня изменена частота ШИМа:
Максимум у 10-битного ШИМа должен быть при 1023, но также максимальный уровень (стопроцентное заполнение, как мне кажется на глаз) будет если задать значение 255 в analogWrite.
У analogWrite максимум всегда достигается при 255, независимо от того, какой там таймер. Откройте файл Arduino.h и убедитесь, что у неё параметр восьмибитный
Тогда почему значение 256 ярче, чем 254? По такой логике значение 256 должно гасить до нуля, так как младшие 8 бит равны нулю.
На самом деле, первый параметр обозначает порт(ногу/пин/и т.п.), а второй параметр - int - двухбайтный. Но это не объясняет, почему 255 выдает максимум.
Приведите минимальный полный код, иллюстрирующий "дефект".
На самом деле, первый параметр обозначает порт
Это да, это я чё-то не того ... бес попутал. Прошу прощения,
Но первая фраза всё равно верна - 255 у него максимум независимо от таймера.
А то, что у Вас там видно, так я не вижу ни этого эффекта, ни Вашего скетча, откуда мне знать.
И да, обязательно скажите, что у Вас за ардуина (памятуя о вчерашней теме)
Я пробовал на 7.8 или 15.6 кГц для 10 бит - оба варианта дают такой "мырг" на 255.
что у Вас за ардуина (памятуя о вчерашней теме)
Китайская Arduino Nano с CH340. Светодиоды подключены через модуль XY-MOS с двумя GA6L.
Ну, так бы сразу и говорили, что у Вас настройки свои, а для управления Вы зачем-то используете штатную analogWrite!!!
А теперь посмотрите в текст analogWrite. Вы удивитесь, но при 255 она тупо выключает PWM и фигачит туда постоянный HIGH-уровень. Теперь всё понятно? Больше нет вопросов?
Тогда почему значение 256 ярче, чем 254? По такой логике значение 256 должно гасить до нуля, так как младшие 8 бит равны нулю.
потому что 254 и 256 - обычные значения, а 255 "особое". 254 и 256 дают на выходе сигнал скважности, соответственно 254/1023 и 256/1023 - примерно 25%
А для 255 (и для 0)в коде analoWrite() есть специальное условие
Добавка - проверил сейчас на осциллографе - при ваших настройках таймера все значения от 0 до 1023 (кроме 255) работают верно, 300 дает ШИМ примерно 30%, 512 - 50%
Встройте в свой код обработку особого случая - 255 - и все будет работать и с analogWrite() тоже
Встройте в свой код обработку особого случая - 255 - и все будет работать и с analogWrite() тоже
Так и получилось. Проверяю, если 255 и выставляю 256. Там не должно быть заметно на глаз такое небольшое расхождение. Как-то печально это.
Как-то печально это.
и что в этом печального ? :)
А что печально? В Ардуино максимум, что можно передать analogWrite - это 255. Вы полезли с ручными настройками, которые несовместимы с настройками среды Ардуино - сам себе злобный буратино. Не пользуйтесь analogWrite, а продолжайте работать напрямую с регистрами и будет Вам счастье.
Теперь надо прикрутить плавное изменение между произвольными точками яркости (косинусоидное, наверное) поверх плавного изменения по всей шкале, ориентированного на неравномерность свечения светодиодов в зависимости от ШИМ. Пока плавности удалось достичь при полном проходе от минимума до максимума, но если нужно остановиться где-то в середине шкалы, то выглядит немного грубо.
Вроде Х лет назад я где-то этот косинус применял зачем-то, а теперь не могу вспомнить, как это посчитать: плавное повышение в начале, нарастание скорости в середине и плавное замедление к концу. Косинус вроде простая вещь, катет на гипотенузу/радиус поделить, но мозгов не хватает. Может кто подскажет?
Нужно взять шкалу типа этого:
А сверху на эти значения наложить плавное изменение, например, с 500 до 200. Вот так:
Тогда яркость будет плавно меняться на любом диапазоне, а не только включаться и выключаться.
В Ардуино максимум, что можно передать analogWrite - это 255.
Евгений, это не так. Я там выше писал - значения выше 255 правильно работают в analogWrite
А что печально? В Ардуино максимум, что можно передать analogWrite - это 255. Вы полезли с ручными настройками, которые несовместимы с настройками среды Ардуино - сам себе злобный буратино. Не пользуйтесь analogWrite, а продолжайте работать напрямую с регистрами и будет Вам счастье.
Да я просто со светом полез экспериментировать. Это вторая мысль уменя для чего всю это технологию "доступного микроконтроллера" можно было использовать. Ну то есть я всего неделю в этом разбираюсь. Насмотрелся на ютубе как все супер-просто и даже для самых тупых доступно, а значит и мне по силам. Но, оказалось, сходу несколько проблем (оказывается загрузчик нужно поменять, иначе оно вообще не работает), оказывается ШИМ меньше килогерца по умолчанию, ну и всякое такое. Все эти штуки, вроде как, решает среда Arduino IDE и готовые платы, в том числе, с программатором на борту. Просто не хотелось в ассемблер лезть, был такой опыт и знаю, что времени нужно больше, и более тщательно продумывать логику работы. Эх, возможно придется все-таки углубляться.
Ну ладно, спойлера здесь нет, немного не в тему. Спасибо, что разъяснили.
В Ардуино максимум, что можно передать analogWrite - это 255.
Евгений, это не так. Я там выше писал - значения выше 255 правильно работают в analogWrite
чет Петрович меня пугает сегодня :).
В Ардуино максимум, что можно передать analogWrite - это 255.
Евгений, это не так. Я там выше писал - значения выше 255 правильно работают в analogWrite
Вы не поняли о чём я (ТС, похоже тоже).
В Ардуино (именно в среде ардуино, без лазанья грязными руками в регистры, как это сделал ТС) низзя, т.к. ШИМ восьмибитовый всегда, на любых таймерах. Поэтому то, что там 255 заменяется на HIGH, багом в среде ардуино не является.
Но ТС решил, настройки сделать "грязными руками", и при этом продолжать пользовать analogWrite - и нарвался. А теперь среда ардуино виновата :-)
Прошу помощи не получается сделать плавное достижение значения на PWM после получения значения по MQTT
Может кто помочь с доделкой...
Смотрел вот такую конструкцию но по итогу ничего не изменилось у меня может что то не верно делал..
Смотрел вот такую конструкцию но по итогу ничего не изменилось у меня может что то не верно делал..
1. стр. 06: "В Ардуино максимум, что можно передать analogWrite - это 255." (#31).
2. стр. 08. например, после 1021 следующее значение stled - 1024. 1023, может быть, когда-то будет - но когда?
Так у меня модуль ESP я так понял у него значения от 0 до 1023...
он у меня по факту сейчас в MQTT передаешь значение яркость меняется но не плавно а хотелось бы плавно...
или я что то не понимаю и нужно управлять до 255
sergei_a88@bk.r - главаная проблема - неправильное условие в строчках 8-10. Вместо проверки на равенство поставьте "больше-равно" и "меньше-равно"
Без изменений также изменяется рыками яркость
я имел в виду вставить в кусок кода в сообщении #38. а не в ваш.
Ваш код из #41 в принципе неверный, там никакого "плавного затухания" вообще не может быть, потому что вы не увеличиваете и уменьшаете яркость, а на каждом шаге читаете ее значение из сети заново
Выкиньте из этого кода работу с MQTT вовсе - и затухание заработает
спасибо
На самом деле функция отличная - что бы я делал без математики и людей шарящих в ней...
Ребят, я конечно хз, сидит ли кто на форуме, но честно говоря думаю что с моей проблемой многие сталкивались:
Мне нужно было состряпать плавное включение/выключение светодиода по нажатии на одну и ту же кнопку. Я с этой проблемой е**лся 5 часов в связи с полным отсутствием у себя нормальной базы в знаниях ArduinoIDE. Но всё же благодаря этому доброму человеку из 2017 я состряпал-таки эту прогу.
Прошу ко вниманию нуждающихся в ней:
void setup{
поделюсь старым баяном которым пользуюсь: