Плавное включение светодиодов

Alex_Mirko
Alex_Mirko аватар
Offline
Зарегистрирован: 16.05.2016

Здравствуйте форумчане, в ходе экспериментов с диодной лентой получил некоторые результаты и хочу ими поделиться, может кому-то они пригодятся)

Думаю многие знают что зависимость скважности ШИМ и яркости свечения светодиода не линейна и используя цикл такого вида мы плавного включения не получим

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 можно добиться необходимой скорости включения.

Строго не судите, пост пишу в первый раз)

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Alex_Mirko пишет:

Думаю многие знают что зависимость скважности ШИМ и яркости свечения светодиода не линейна и используя цикл такого вида мы плавного включения не получим

Блин автор жеет. Как раз линейна зависимость . Это же ШИМ - Широтно импульсная модуляция . Если включен светодиод на 50 % процентов времени, то и насветит на эти 50% Ведь яркость зависит от напряжения включения. А при ШИМе светодиод или выключен или включен. Он не может светить меньше.  А вот глаз он и нелинееен. Глазу легче определить что ярче вдвое или тусклее вдвое, но не темнее на 5%. 

Клапауций 112
Клапауций 112 аватар
Offline
Зарегистрирован: 01.03.2017

qwone пишет:

Alex_Mirko пишет:

Думаю многие знают что зависимость скважности ШИМ и яркости свечения светодиода не линейна и используя цикл такого вида мы плавного включения не получим

Блин автор жеет. Как раз линейна зависимость . Это же ШИМ - Широтно импульсная модуляция . Если включен светодиод на 50 % процентов времени, то и насветит на эти 50% Ведь яркость зависит от напряжения включения. А при ШИМе светодиод или выключен или включен. Он не может светить меньше.  А вот глаз он и нелинееен. Глазу легче определить что ярче вдвое или тусклее вдвое, но не темнее на 5%. 

нужно перешивать глаза.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Та ладно. Может скоро народ начнет собирать деньги на "плавное включение Солнца" А то резкое "включение" Солнца утром и "выключение" вечером приведет что Солнце быстро "перегорит". Или вообще поменять Солнце на "энеросберегающее" с "приятным для глаза свечением".

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Alex_Mirko,

правильно, что Вы пробуете, но Вы зря предварительно не изучили матчасть в плане физиологии зрения.

Отсюда у Вас ненужные поиски, то квадрат, то квадрат делённый на куб. На самом деле глаз воспринимет изменения совещённогсти как равномерное тогда, когда оно изменяется по показательному закону, имейте это в виду на будущее.

Точно также ухо воспринимает изменение громкости, отсюда регуляторы громкости имеют показательную харакетристику.

Alex_Mirko
Alex_Mirko аватар
Offline
Зарегистрирован: 16.05.2016

ЕвгенийП, Я привел конкретные примеры полученные опытным путем, они просты в реализации, результат их использования меня вполне устроил, восприятие яркости сложная тема, и углубляться в нее для создания моргалки я не собираюсь. Если у вас есть примеры применения показательного закона так поделитесь ими.

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

a*=1.07 ;
Вместо 1.07 подбор по вкусу. Про это и написал Евгений. Такие примеры есть у каждого. И не нужно огород городить.

Alex_Mirko
Alex_Mirko аватар
Offline
Зарегистрирован: 16.05.2016

wdrakula, теперь все встало на свои места, спасибо)

Logik
Offline
Зарегистрирован: 05.08.2014

Тема уже не раз подымалась. И варианты решения известны: аппаратное изменение тока, переход на ШИМ высокого разрешения(аппаратный или програмный) и переключение на програмный ШИМ при малой яркости и аппарвтный при большой.

И светодиод нелинейный. Он вобще весь нелинейный принципиально. ШИМ линейный но напряжение не тождественно световому потоку.

/// Если включен светодиод на 50 % процентов времени, то и насветит на эти 50% Ведь яркость зависит от напряжения включения. А при ШИМе светодиод или выключен или включен.

Нет. Кроме времени когда он включен или выключен есть время на его переключение. Собственно как и у других полупроводниковых приборов. У обычных светодиодов порядка десятых мсек, что очевидно при частое ШИМ в КГц на малой яркости сказывается. Идут процессы заряда-разряда емкости перехода, диффузии носителей и т.д. Он в это время не светит по полной пока не наступит диамическое равновесие генерации и рекомбинации. Вобще как он светит при переходных - ХЗ, но ясно что если часть энергии уходит на заряд емкости, то она не уходит в свет. Вот занятная статейка http://www.rlocman.ru/shem/schematics.html?di=112354 не совсем по теме, но график емкости от напряжения наглядно показывает степень нелинейности процессов, а по величине емкости можна и время заряда оценить.

Сомневающимся - простой опыт, светодиод к генератору прямоугольных импульсов. Напряжение и скважность фиксируем частоту меняем в широких пределах, наблюдаем изменение яркости.

ПС. Все это не отменяет нелинейность светочувствительности глаза, только дополняет.

Megawollt
Offline
Зарегистрирован: 06.12.2015

Программно есть формула логарифма для 255 значений. У меня где то на работе записана. Я на ней сделал с десяток контроллеров. Работает, но разрядность теряется

Клапауций 112
Клапауций 112 аватар
Offline
Зарегистрирован: 01.03.2017

Megawollt пишет:

Работает, но разрядность теряется

куда теряется?

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Megawollt пишет:

Программно есть формула логарифма для 255 значений. У меня где то на работе записана. Я на ней сделал с десяток контроллеров. Работает, но разрядность теряется

это писец какой-то. 0х01 х02 0х04 0x08 0х10 х20 0х40 0x80 нормальная шкала логарифмов с основанием 2. Но видимо народ мозг терят когда дело касается логарифмов . Для народа логарифмы с основанием 10 и основанием e. Хотя думаю к  поледнему относится как к богу, или верит, или не знает. ;) 

Megawollt
Offline
Зарегистрирован: 06.12.2015

Клапауций 112 пишет:

Megawollt пишет:

Работает, но разрядность теряется

куда теряется?

В никуда.

На самом деле я не вникал тогда в логику рассчетов логарифма, так как проект надо было сдавать срочно, и в математике я не особо силен. Тогда я нашел дейвствующий пример на каком то англоязычном сайте и он меня вполне устроил.

 

Теряется я думаю не разрядность, а некоторые значения. Кстати по этой же формуле я делал торможение мачты с нагрузкой в 300кг и это помогло, хотя в линейном варианте тормозило неудачно 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

qwone пишет:

это писец какой-то. 0х01 х02 0х04 0x08 0х10 х20 0х40 0x80 нормальная шкала логарифмов...

Одно значение на октаву Вы считаете нормальной шкалой?

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

andriano пишет:

qwone пишет:

это писец какой-то. 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)

Клапауций 112
Клапауций 112 аватар
Offline
Зарегистрирован: 01.03.2017

qwone пишет:

ПС: Если по теме, то проще использовать такой метод для плавного зажигания светодиода:(255>>8),(255>>7),(255>>6),(255>>5),(255>>4),(255>>3),(255>>2),(255>>1),(255>>0)

не смотря на элегантность решения - ну, нихера это не плавное зажигание.

8 ступенек вместо 255, которые тоже заметны, если обращать внимание.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

qwone пишет:

А что в Ардуино есть октавы @_@. Обычно это называют байтом. Но спутать 8 значений с одним . Советую вам отдохнуть. 

Октавы есть везде, где есть логарифмическая шкала. И байтами их никогда не называли. Даже в шутку.

Megawollt
Offline
Зарегистрирован: 06.12.2015

Ступени все равно будут заметны на 8ми битах, как ни крути. Просто логарифмическое регулирование дает более линейное(на глаз) нарастание яркости.

Убрать скачки можно конденсатором в затворе ключевого транзистора, но подбирать надо индивидуально под каждый тип ленты или диодов

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

qwone пишет:

А что в Ардуино есть октавы @_@. Обычно это называют байтом. Но спутать 8 значений с одним . Советую вам отдохнуть. 

Вы же, как мне казалось, неплохой программист и имеете какое-то образование, так зачем позориться?

"отличается на октаву" тождественно "отличается в два раза". Выглядит так, будто вы этого не знали.

Пошло, конечно, из музыки, где,  например, "Ля" первой октавы = 440Гц, второй = 880Гц, а малой, соответственно = 220Гц.

Изначально разница в октаву по высоте звука ранялась разнице в высоте полной струны и половины струны.

ask1
Offline
Зарегистрирован: 16.01.2020

Разобрался:

число 980100 нужно, чтобы получить 255 - максимум, доступный для этого ШИМ-порта.

Но обнаружилось странное. У 10-битных ШИМов на 255 тоже включается максимум. Может кто подскажет почему?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

ask1 пишет:

Разобрался: ... Может кто подскажет почему?

Теме три года. Вы уж говорите поподробнее в чём именно Вы разобрались и что Вам нужно подсказывать.

ask1
Offline
Зарегистрирован: 16.01.2020

ЕвгенийП пишет:

Вы уж говорите поподробнее в чём именно Вы разобрались и что Вам нужно подсказывать.

У 10-битных ШИМов на 255 тоже включается максимум. Может кто подскажет почему?

Максимум у 10-битного ШИМа должен быть при 1023, но также максимальный уровень (стопроцентное заполнение, как мне кажется на глаз) будет если задать значение 255 в analogWrite.

Может это связано с тем, что у меня изменена частота ШИМа:

// Пины D9 и D10 - 15.6 кГц 10bit // не стабильно, моргает на минимуме
TCCR1A = 0b00000011; // 10bit
TCCR1B = 0b00001001; // x1 fast pwm

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

ask1 пишет:

Максимум у 10-битного ШИМа должен быть при 1023, но также максимальный уровень (стопроцентное заполнение, как мне кажется на глаз) будет если задать значение 255 в analogWrite.

У analogWrite максимум всегда достигается при 255, независимо от того, какой там таймер. Откройте файл Arduino.h и убедитесь, что у неё параметр восьмибитный

void analogWrite(uint8_t, int);

 

ask1
Offline
Зарегистрирован: 16.01.2020

ЕвгенийП пишет:

У analogWrite максимум всегда достигается при 255, независимо от того, какой там таймер. Откройте файл Arduino.h и убедитесь, что у неё параметр восьмибитный

void analogWrite(uint8_t, int);

Тогда почему значение 256 ярче, чем 254? По такой логике значение 256 должно гасить до нуля, так как младшие 8 бит равны нулю.

На самом деле, первый параметр обозначает порт(ногу/пин/и т.п.), а второй параметр - int - двухбайтный. Но это не объясняет, почему 255 выдает максимум.

sadman41
Offline
Зарегистрирован: 19.10.2016

Приведите минимальный полный код, иллюстрирующий "дефект".

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

ask1 пишет:

На самом деле, первый параметр обозначает порт

Это да, это я чё-то не того ... бес попутал. Прошу прощения, 

Но первая фраза всё равно верна - 255 у него максимум независимо от таймера.

А то, что у Вас там видно, так я не вижу ни этого эффекта, ни Вашего скетча, откуда мне знать.

И да, обязательно скажите, что у Вас за ардуина (памятуя о вчерашней теме)

ask1
Offline
Зарегистрирован: 16.01.2020

sadman41 пишет:
Приведите минимальный полный код, иллюстрирующий "дефект".

void setup() {
    // Пины D9 и D10 - 15.6 кГц 10bit
    TCCR1A = 0b00000011; // 10bit
    TCCR1B = 0b00001001; // x1 fast pwm

/*
    // Пины D9 и D10 - 7.8 кГц 10bit
    TCCR1A = 0b00000011; // 10bit
    TCCR1B = 0b00000001; // x1 phase correct
*/

    pinMode (9, OUTPUT);
}

void loop() {
    int i;

    for (i=0;i<1024;i++)
    {
      // if ( i == 255 ) continue;  // если добавить, то сразу видно, что моргает именно на 255
      analogWrite (9, i);
      delay (10);
    }
}

Я пробовал на 7.8 или 15.6 кГц для 10 бит - оба варианта дают такой "мырг" на 255.

 

ЕвгенийП пишет:

что у Вас за ардуина (памятуя о вчерашней теме)

Китайская Arduino Nano с CH340. Светодиоды подключены через модуль XY-MOS с двумя GA6L.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, так бы сразу и говорили, что у Вас настройки свои, а для управления Вы зачем-то используете штатную analogWrite!!!

А теперь посмотрите в текст analogWrite. Вы удивитесь, но при 255 она тупо выключает PWM и фигачит туда постоянный HIGH-уровень. Теперь всё понятно? Больше нет вопросов?

b707
Offline
Зарегистрирован: 26.05.2017

ask1 пишет:

Тогда почему значение 256 ярче, чем 254? По такой логике значение 256 должно гасить до нуля, так как младшие 8 бит равны нулю.

потому что 254 и 256 - обычные значения, а 255 "особое". 254 и 256 дают на выходе сигнал скважности, соответственно 254/1023 и 256/1023 - примерно 25%

А для 255 (и для 0)в коде analoWrite() есть специальное условие

if (val == 0)
	{
		digitalWrite(pin, LOW);
	}
	else if (val == 255)
	{
		digitalWrite(pin, HIGH);
	} 

 

Добавка - проверил сейчас на осциллографе - при ваших настройках таймера все значения от 0 до 1023 (кроме 255) работают верно, 300 дает ШИМ примерно 30%, 512 - 50%

Встройте в свой код обработку особого случая - 255 - и все будет работать и с analogWrite() тоже

ask1
Offline
Зарегистрирован: 16.01.2020

b707 пишет:

Встройте в свой код обработку особого случая - 255 - и все будет работать и с analogWrite() тоже

Так и получилось. Проверяю, если 255 и выставляю 256. Там не должно быть заметно на глаз такое небольшое расхождение. Как-то печально это.

b707
Offline
Зарегистрирован: 26.05.2017

ask1 пишет:

Как-то печально это.

 и что в этом печального ? :)

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

А что печально? В Ардуино максимум, что можно передать analogWrite - это 255. Вы полезли с ручными настройками, которые несовместимы с настройками среды Ардуино - сам себе злобный буратино. Не пользуйтесь analogWrite, а продолжайте работать напрямую с регистрами и будет Вам счастье.

ask1
Offline
Зарегистрирован: 16.01.2020

Теперь надо прикрутить плавное изменение между произвольными точками яркости (косинусоидное, наверное) поверх плавного изменения по всей шкале, ориентированного на неравномерность свечения светодиодов в зависимости от ШИМ. Пока плавности удалось достичь при полном проходе от минимума до максимума, но если нужно остановиться где-то в середине шкалы, то выглядит немного грубо.

Вроде Х лет назад я где-то этот косинус применял зачем-то, а теперь не могу вспомнить, как это посчитать: плавное повышение в начале, нарастание скорости в середине и плавное замедление к концу. Косинус вроде простая вещь, катет на гипотенузу/радиус поделить, но мозгов не хватает. Может кто подскажет?

Нужно взять шкалу типа этого:

for (unsigned int i = 0; i <= 630; i++) {
    analogWrite(analogOutPin, pow(i,3)/980100);
    delay(3);
  }

А сверху на эти значения наложить плавное изменение, например, с 500 до 200. Вот так:

Тогда яркость будет плавно меняться на любом диапазоне, а не только включаться и выключаться.

 

 

b707
Offline
Зарегистрирован: 26.05.2017

ЕвгенийП пишет:

В Ардуино максимум, что можно передать analogWrite - это 255.

Евгений, это не так. Я там выше писал - значения выше 255 правильно работают в analogWrite

ask1
Offline
Зарегистрирован: 16.01.2020

ЕвгенийП пишет:

А что печально? В Ардуино максимум, что можно передать analogWrite - это 255. Вы полезли с ручными настройками, которые несовместимы с настройками среды Ардуино - сам себе злобный буратино. Не пользуйтесь analogWrite, а продолжайте работать напрямую с регистрами и будет Вам счастье.

Да я просто со светом полез экспериментировать. Это вторая мысль уменя для чего всю это технологию "доступного микроконтроллера" можно было использовать. Ну то есть я всего неделю в этом разбираюсь. Насмотрелся на ютубе как все супер-просто и даже для самых тупых доступно, а значит и мне по силам. Но, оказалось, сходу несколько проблем (оказывается загрузчик нужно поменять, иначе оно вообще не работает), оказывается ШИМ меньше килогерца по умолчанию, ну и всякое такое. Все эти штуки, вроде как, решает среда Arduino IDE и готовые платы, в том числе, с программатором на борту. Просто не хотелось в ассемблер лезть, был такой опыт и знаю, что времени нужно больше, и более тщательно продумывать логику работы. Эх, возможно придется все-таки углубляться.

Ну ладно, спойлера здесь нет, немного не в тему. Спасибо, что разъяснили.

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

b707 пишет:

ЕвгенийП пишет:

В Ардуино максимум, что можно передать analogWrite - это 255.

Евгений, это не так. Я там выше писал - значения выше 255 правильно работают в analogWrite

чет Петрович меня пугает сегодня :).

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

b707 пишет:

ЕвгенийП пишет:

В Ардуино максимум, что можно передать analogWrite - это 255.

Евгений, это не так. Я там выше писал - значения выше 255 правильно работают в analogWrite

Вы не поняли о чём я (ТС, похоже тоже).

В Ардуино (именно в среде ардуино, без лазанья грязными руками в регистры, как это сделал ТС) низзя, т.к. ШИМ восьмибитовый всегда, на любых таймерах. Поэтому то, что там 255 заменяется на HIGH, багом в среде ардуино не является.

Но ТС решил, настройки сделать "грязными руками", и при этом продолжать пользовать analogWrite - и нарвался. А теперь среда ардуино виновата :-)

sergei_a88@bk.ru
Offline
Зарегистрирован: 22.09.2019

Прошу помощи не получается сделать плавное достижение значения на PWM после получения значения по MQTT

Может кто помочь с доделкой...

#include <ESP8266WiFi.h>
#include <PubSubClient.h>

const char *ssid =  "***";  //название сети
const char *password =  "****";            //пароль сети
const char *mqtt_server = "****";       //адрес mqtt брокера

WiFiClient espClient;           //инициализация вифи
PubSubClient client(espClient); //инициализация mqtt клиента

#define LEDPIN 2 //устанавливаем пин с лед лентой

 // функция получения топиков от брокера
void callback(char* topic, byte* payload, unsigned int length)
{
  Serial.println();
  Serial.print(topic);   // выводим в сериал порт название топика
  Serial.print(" => ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  } // выводим в сериал порт значение полученных данных

  String strTopic = String(topic); //получаем название топика
  
  if (strTopic == "ESP03/led") //проверяем из нужного ли топика пришли данные
  {
    payload[length] = 0; //чистим от мусора, длинна строки
    String strPayload = String((char*)payload);  //считываем значение топика
    int val = strPayload.toInt(); //конвертируем для шим
    int stled = map(val, 0, 100, 1023, 0); //приводим значение 0-100 в значение 1000-0
    analogWrite(LEDPIN, stled); //устанавливаем уровень шим сигнала
    Serial.print(" => "); 
    Serial.print(stled);  // для отладки
  }
}

void setup() {
  pinMode(LEDPIN, OUTPUT); //устанвливаем ка выход
  Serial.begin(115200);
}

void loop() {

  if (WiFi.status() != WL_CONNECTED) //если нет подключения к вифи
  {
    WiFi.begin(ssid, password); //конектимся
    if (WiFi.waitForConnectResult() != WL_CONNECTED)
      return; //если не получилось то повторяем
  }
  if (WiFi.status() == WL_CONNECTED) //если подключились
  {
    if (!client.connected()) //если нет mqtt
    { // то подключаемся к mqtt
      client.setServer(mqtt_server, 1883);
      client.setCallback(callback);
      client.connect("ESP03led");        //id клиента(должно быть уникальным в сети)
      client.subscribe("ESP03/led");     //подписываемся на топик
    }
    if (client.connected()) {   // если подключились
      client.loop();            // то запускаем цикл получения топиков)))
    }
  }
}

 Смотрел вот такую конструкцию но по итогу ничего не изменилось у меня может что то не верно делал..

int fadeAmount = 3;     // шаг изменения яркости

void setup() { }

void loop()  { 
    analogWrite(LEDPIN, stled);    // устанавливаем значение 
    stled = stled + fadeAmount;   // прибавляем шаг изменения яркости, которая установится в следующем цикле
    if (stled == 0|| stled == 1023) { // Условие 
          fadeAmount = -fadeAmount ; // Меняем знак 
     //  delay(500);                  // ожидаем 1/2 секунды
    } 

   delay(50);                  // ожидаем 1/20 секунды        
}

 

SLKH
Offline
Зарегистрирован: 17.08.2015

sergei_a88@bk.ru пишет:

 

 Смотрел вот такую конструкцию но по итогу ничего не изменилось у меня может что то не верно делал..

int fadeAmount = 3;     // шаг изменения яркости

void setup() { }

void loop()  { 
    analogWrite(LEDPIN, stled);    // устанавливаем значение 
    stled = stled + fadeAmount;   // прибавляем шаг изменения яркости, которая установится в следующем цикле
    if (stled == 0|| stled == 1023) { // Условие 
          fadeAmount = -fadeAmount ; // Меняем знак 
     //  delay(500);                  // ожидаем 1/2 секунды
    } 

   delay(50);                  // ожидаем 1/20 секунды        
}

 

1.  стр. 06: "В Ардуино максимум, что можно передать analogWrite - это 255." (#31).

2. стр. 08. например, после 1021 следующее значение stled - 1024. 1023, может быть, когда-то будет - но когда?

 

sergei_a88@bk.ru
Offline
Зарегистрирован: 22.09.2019

Так у меня модуль ESP я так понял у него значения от 0 до 1023...

он у меня по факту сейчас в MQTT передаешь значение яркость меняется но не плавно а хотелось бы плавно...

или я что то не понимаю и нужно управлять до 255

 

b707
Offline
Зарегистрирован: 26.05.2017

sergei_a88@bk.r - главаная проблема - неправильное условие в строчках 8-10. Вместо проверки на равенство поставьте "больше-равно" и "меньше-равно"

sergei_a88@bk.ru
Offline
Зарегистрирован: 22.09.2019

Без изменений также изменяется рыками яркость 

#include <ESP8266WiFi.h>
#include <PubSubClient.h>

const char *ssid =  "****";  //название сети
const char *password =  "****";            //пароль сети
const char *mqtt_server = "192.168.***";       //адрес mqtt брокера


WiFiClient espClient;           //инициализация вифи
PubSubClient client(espClient); //инициализация mqtt клиента

#define LEDPIN 2 //устанавливаем пин с лед лентой
int fadeAmount = 3;     // шаг изменения яркости

// функция получения топиков от брокера
void callback(char* topic, byte* payload, unsigned int length)
{
  Serial.println();
  Serial.print(topic);   // выводим в сериал порт название топика
  Serial.print(" => ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  } // выводим в сериал порт значение полученных данных

  String strTopic = String(topic); //получаем название топика
  
  if (strTopic == "ESP03/led") //проверяем из нужного ли топика пришли данные
  {
    payload[length] = 0; //чистим от мусора, длинна строки
    String strPayload = String((char*)payload);  //считываем значение топика
    int val = strPayload.toInt(); //конвертируем для шим
    int stled = map(val, 0, 100, 1023, 0); //приводим значение 0-100 в значение 1000-0
    analogWrite(LEDPIN, stled);    // устанавливаем значение 
    stled = stled + fadeAmount;   // прибавляем шаг изменения яркости, которая установится в следующем цикле
    if (stled >= 0|| stled <= 1023) { // Условие 
          fadeAmount = -fadeAmount ; // Меняем знак 
     //  delay(500);                  // ожидаем 1/2 секунды
    } 

   delay(50);                  // ожидаем 1/20 секунды        
   
    Serial.print(" => "); 
    Serial.print(stled);  // для отладки
  }
}

void setup() {
  pinMode(LEDPIN, OUTPUT); //устанвливаем ка выход
  Serial.begin(115200);
}

void loop() {

  if (WiFi.status() != WL_CONNECTED) //если нет подключения к вифи
  {
    WiFi.begin(ssid, password); //конектимся
    if (WiFi.waitForConnectResult() != WL_CONNECTED)
      return; //если не получилось то повторяем
  }
  if (WiFi.status() == WL_CONNECTED) //если подключились
  {
    if (!client.connected()) //если нет mqtt
    { // то подключаемся к mqtt
      client.setServer(mqtt_server, 1883);
      client.setCallback(callback);
      client.connect("ESP03led");        //id клиента(должно быть уникальным в сети)
      client.subscribe("ESP03/led");     //подписываемся на топик
    }
    if (client.connected()) {   // если подключились
      client.loop();            // то запускаем цикл получения топиков)))
    }
  }
}

 

b707
Offline
Зарегистрирован: 26.05.2017

я имел в виду вставить в кусок кода в сообщении #38. а не в ваш.

Ваш код из #41 в принципе неверный, там никакого "плавного затухания" вообще не может быть, потому что вы не увеличиваете и уменьшаете яркость, а на каждом шаге читаете ее значение из сети заново

Выкиньте из этого кода работу с MQTT вовсе - и затухание заработает

sergei_a88@bk.ru
Offline
Зарегистрирован: 22.09.2019

спасибо