Здравствуйте, уважаемые форумчане! Есть проблема и прошу вашей помощи в ее решении. Итак. Имею Arduino pro mini 5v (Atmega328) и мосфет IRFZ44N. Мосфет управляется ШИМ с 10-го ПИНа и коммутирует 12В LED-ленту. Ну, еще экранчик, часы и кнопки, но это не суть. Задача - организация рассвета и заката т.е. плавного (очень плавного - в течение часа примерно) включения-выключения LED. Все в общем-то работает, но... При почти закрытом транзисторе (analogWrite - 5-15) - и почти выключенной LED соответственно - становятся видны "ступеньки" изменения яркости. Можно ли как-то сделать изменение света более плавным?
вот уж спасибо так спасибо! А я встречал только "родную" функцию AnalogWriteResolution(), но она, к сожалению, только для Due.
глаз воспринимает изменение яркости по логарифмическому принципу, поэтому первые 60% диапазона воспринимаются ступеньками, а последние 15% неотличимы по воспринимаемому уровню яркости. Выход - использовать регулировку яркости не линейному, а по логарифмическому алгоритму.
Да, то что восприятие не соответствует реальным процентам - заметно, но сейчас не в этом соль была. Спасибо за ссылку. Внимательно пока не вчитывался, но общий смысл ясен. Функцию писать буду.
Спасибо ответившим за подсказки! Сделал 16-битный ШИМ и логарифмическое изменение яркости. В COM выводит красиво, вечером опробую на реальной нагрузке
Побаловался с разными вариантами... Мой выбор - парабола. Наиболее "естественное для глаза" затухание-разгорание, по-моему. Хотя в готовом контроллере оставил возможность выбора кривой (линейная ф-я, логарифм и парабола).
Да там, в общем-то ничего особенного. Без вывертов. Код (C++): <...> switch (lightingValues[16]) { case 0: maxFuncArg = pow(1.1, 6.5535); // Для логарифма break; case 1: maxFuncArg = sqrt(65535); // Для параболы break; } minFuncArg = (lightingValues[16] == 0 ? 1 : 0); funcRange = maxFuncArg - minFuncArg; startMorning = (lightingValues[0] * 3600l + lightingValues[1] * 60l) * 1000l; //Время начала рассвета в миллисекундах от начала суток stopMorning = (lightingValues[2] * 3600l + lightingValues[3] * 60l) * 1000l; //Время конца рассвета в миллисекундах от начала суток startEvening = (lightingValues[9] * 3600l + lightingValues[10] * 60l) * 1000l; //Время начала заката в миллисекундах от начала суток stopEvening = (lightingValues[11] * 3600l + lightingValues[12] * 60l) * 1000l; //Время конца заката в миллисекундах от начала суток funcFactor[0] = (stopMorning - startMorning) / funcRange; //Множитель для получения аргумента функции затухания при увеличении яркости во время расвета funcFactor[1] = (stopEvening - startEvening) / funcRange; //Множитель для получения аргумента функции затухания при уменьшении яркости время заката <...> <...> if (currentMilliSecond >= startMorning && currentMilliSecond <= stopMorning) currentFuncArg = (lightingValues[13] != 0 ? (currentMilliSecond - startMorning) / funcFactor[0] + minFuncArg : maxFuncArg); else if (currentMilliSecond >= startEvening && currentMilliSecond <= stopEvening) currentFuncArg = (lightingValues[15] != 0 ? maxFuncArg - (currentMilliSecond - startEvening) / funcFactor[1] + minFuncArg : maxFuncArg); else if (currentMilliSecond >= stopMorning && currentMilliSecond <= startEvening) currentFuncArg = maxFuncArg; else currentFuncArg = minFuncArg; switch (lightingValues[16]) { case 0: analogWrite16(Pin_LED, log(currentFuncArg) / log(1.1) * 10000); break; case 1: analogWrite16(Pin_LED, sq(currentFuncArg)); break; } <...> В lightingValues хранятся настройки, currentMilliSecond - текущая миллисекунда (отсчитывается от начала суток, т.е. 00.00)
Вот экспоненту не пробовал. Но, в принципе, и логарифм работает неплохо. Тут дело вкуса, что называется. Потому я и оставил возможность выбора. Мне, как я уже писал, парабола понравилась. Полностью отвечает моим ожиданиям.