Световой эффект плавно бегущего огонька с помощью PWM

prosto_andriy
Offline
Зарегистрирован: 09.12.2012

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

Наглядно, я думаю, это выглядело бы так:

maksim
Offline
Зарегистрирован: 12.02.2012
#define LED_1 9
#define LED_2 10
#define LED_3 11

int br_led_1 =   0, br_led_2 =   200, br_led_3 =    0;   
int fade_led_1 = 1, fade_led_2 =  -1, fade_led_3 = -1;    

void setup()  
{ 
  pinMode(LED_1, OUTPUT);
  pinMode(LED_2, OUTPUT);
  pinMode(LED_3, OUTPUT);
} 

void loop()  
{ 
  Fading(LED_1, br_led_1, fade_led_1, -200);
  Fading(LED_2, br_led_2, fade_led_2,    0);
  Fading(LED_3, br_led_3, fade_led_3, -200);
  delay(10);                            
}

void Fading(int LED, int &brightness, int &fadeAmount, int minimum)
{
  if(brightness >= 0) analogWrite(LED, brightness);  
  brightness += fadeAmount; 
  if (brightness == minimum || brightness == 200)  fadeAmount = -fadeAmount;  
}

 

prosto_andriy
Offline
Зарегистрирован: 09.12.2012

Большое спасибо! Я и не думал, что  такого типа алгоритм можно уместить в столь компактный код!

prosto_andriy
Offline
Зарегистрирован: 09.12.2012

Напишите пожалуйста кто нибудь, почему здесь в переменную "fade_led_3" заносится "-1". Ведь, насколько я понял эта переменная

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

Это значение для LED3  задается переменной "br_led_3", в которую изначально заносится "0".   Получается, что

 контроллер определяет яркость, вычитая её значение из нуля ??? Или я ошибаюсь?

И еще мне непонятно, что это за закарючки перед словами и зачем их сюда добавлять.

int &brightness, int &fadeAmount

Пожалуйста, если не трудно, объясните кто-нибудь, обязательно ли их писать перед этими переменными.

Заранее спасибо всем ответившим!

 

 

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

int &parameter

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

Вообще, есть рекомендации не использовать такие конструкции, а лучше использовать передачу параметра в форме:

int *parameter_pointer

тогда сразу видно, что содержимое переменной, передаваемой в качестве параметра может измениться.

Есть несколько других соображений на эту тему.

Это всё философия, я, обычно, придерживаюсь рекомендаций. Но это не обязательно.

Пример:

void function( int &parameter)
{
  parameter = 5;
}

void loop()
{
  int value = 3;
  function(value);
  Serial.printLn(value);
}

При выполнении этого куска, в Serial будет выведено:

5

 

maksim
Offline
Зарегистрирован: 12.02.2012

В 25 строке стоит проверка if(brightness >= 0) analogWrite(LED, brightness); которая как раз и не дает в функцию analogWrite попасть отрицательным значениям, так что все время пока br_led_Х имеет отрицательное значение яркость светодиода равна нулю.

prosto_andriy
Offline
Зарегистрирован: 09.12.2012

 

Еще раз хочу поблагодарить всех ответивших на  мои вопросы!

Хотелось бы еще узнать, можно ли обойтись в этой программе только операторами IF  и ELSE, зажигая и выключая каждый из светодиодов в зависимости от состояния напряжения на двух остальных.

Алгоритм примерно такой:

1. Начать увеличивать яркость на диоде LED3

2. Когда яркость LED3 достигнет максимума, начать её снижение, при  этом одновременно повышая напряжение на диоде LED2

4. Когда яркость LED2 достигнет максимума начать её снижение, при  этом одновременно повышая напряжение на диоде LED1

5. Когда яркость LED1 достигнет порогового значения, начать снижать её одновременно повышая напряжение на LED2

6. Когда яркость LED2  достигнет порогового значения, начать снижать её одновременно повышая напряжение на LED3    (это уже, наверное, будет началом нового цикла)

Вовуся
Offline
Зарегистрирован: 11.04.2014

maksim,

думал-думал, как четвертый светодиод добавить, не додумался :(

Поможете? :)