Главная » Статьи » Arduino с нуля » Работа с Arduino

Урок 3. Часть 1. Управление яркостью светодиода программным методом.

 

Иногда, при конструировании устройства, нужно применять плавное увеличение яркости, или наоборот - плавное ее уменьшение.

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

 

 

Есть большое количество способов реализации подобной идеи. Мы расскажем вам о трех основных, это:

  1. Программный метод управления яркостью (рассматривается в данном уроке);
  2. Управление яркостью с помощью фоторезистора (яркость управляется автоматически, в зависимости от освещения);
  3. Управление яркостью с помощью переменного резистора (ручной метод изменения яркости).

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

 

Суть метода хотелось бы пояснить на небольшом, но очень актуальном примере:

Имеется кинотеатр. Во время всего сеанса, свет в зале выключен, и зрители смотрят фильм. Как только фильм заканчивается, по сути, должен включаться свет. Если он включится резко, то это очень негативно скажется на зрении зрителей. Поэтому в большинстве кинотеатров, такая ситуация предусмотрена. После сеанса, свет включается плавным нарастанием яркости. Вот чтобы достичь такого эффекта, с помощью Arduino, или других цифровых устройств, рациональнее будет использовать изменение яркости программным методом. 

 

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

Теперь давайте подробнее разберем данный способ.

 

В основе метода лежит широтно-импульсная модуляция, она же ШИМ. Если вы не сталкивались с этим понятием, или не понимаете его суть, то советую для начала прочитать эту статью.

Для этого урока понадобятся следующие компоненты:

 

  1. Платформа Arduino
  2. Breadboard 
  3. Светодиод 1шт.
  4. Резистор (220 Ом) 1шт.
  5. Соединительные провода "папа - папа" 2шт. 

 

Подключаем светодиоды к Arduino по схеме представленной ниже:

Та же самая схема, только в другом представлении:

Вы можете использовать любой пин Arduino, в номере которого имеется знак тильды "~". Именно в этих пинах может использоваться ШИМ. 

Схема в сборе:

 

Теперь, когда схема собрана. Перейдем в программную часть. 

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

 

Открываем программу Arduino IDE и пишем следующий код:

int led_1 = 3; //Номер пина первого светодиода

void setup() {
 pinMode (led_1 , OUTPUT); //режим пина led_1 на выход
}

void loop() {
 analogWrite (led_1 , 20);  //Выставляем значение уровня пина led_1 равный 20
 delay (400);  //Выжидаем паузу в 400мс 
 analogWrite (led_1 , 50);  //Выставляем значение уровня пина led_1 равный 50
 delay (400);  //Выжидаем паузу в 400мс
 analogWrite (led_1 , 110); //Выставляем значение уровня пина led_1 равный 110
 delay (400);  //Выжидаем паузу в 400мс
 analogWrite (led_1 , 170);  //Выставляем значение уровня пина led_1 равный 170
 delay(400);  //Выжидаем паузу в 400мс
 analogWrite (led_1 , 230); //Выставляем значение уровня пина led_1 равный 230
 delay(400);  //Выжидаем паузу в 400мс
 analogWrite (led_1 , 255);  //Выставляем значение уровня пина led_1 равный 255
 delay(400);  //Выжидаем паузу в 400мс
}

Как мы видим, появилась новая функция analogWrite(pin , value). Функция выдает аналоговую величину (value) на порт вход/выхода (pin).

  • pin: порт вход/выхода на который подаем ШИМ сигнал.
  • value: период рабочего цикла значение между 0 (полностью выключено) и 255 (сигнал подан постоянно).

Таким образом, с помощью данной функции, мы можем контролировать яркость нашего светодиода, подавая значения от 0 (минимум 0В) до 255 (максимум 5В).

Если пробежаться по алгоритму, то мы видим, что в начале мы выставляем значение уровня нашего пина равное 20.

 analogWrite (led_1 , 20);

Потом, через небольшую задержку (400мс),

delay (400);

мы изменяем уровень на 50,

analogWrite (led_1 , 50); 

и потом через задержку до уровня 255.

После того, как уровень стал равен 255 (соответствующее максимальному значению 5В),

analogWrite (led_1 , 255);

происходит задержка, после чего программа переходит в начало. И все повторяется снова. 

 

Видео работы такого устройства:

 

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

  1. Для этого можно использовать маленькую задержку (что не всегда хорошо);
  2. Можно добавить промежуточные значения яркости.

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

Мы можем добавить в наш код еще несколько подобных строк:

 analogWrite (led_1 , value);  
 delay (400);

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

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

 

Поэтому делаем следующее:

добавьте следующий код в новом проекте Arduino IDE (или измените старый):

 

int led_1 = 3; //Номер пина первого светодиода

void setup() {
 pinMode (led_1 , OUTPUT); //режим пина led_1 на выход
}

void loop() {

 for (int i = 0; i <= 255 ; i++)
 {
 analogWrite(led_1 , i);
 delay (20);
 }
}

 

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

 for (int i = 0; i <= 255 ; i++)
 {
 analogWrite(led_1 , i);
 delay (20);
 }

 

Давайте же разберемся что это за строки. 

for() - это цикл. Цикл - это многократное прохождение по одному и тому же коду программы. 

В общем виде цикл for записывается так:

 for (выражение 1; выражение 2; выражение 3)
 {
 один оператор или блок операторов
 }
  • Выражение 1. В основном объявляется переменная, отвечающая за начальное значение;
  • Выражение 2. Условие. Пока оно будет истинно true (например 2+2 = 4), программа внутри { } будет выполняться. Как только условие станет ложным false (например 3 < 1), цикл завершится;
  • Выражение 3. Шаг цикла. 

Если рассмотреть цикл на примере нашего случая, то алгоритм действий будет таков:

  • Первым делом мы объявляем переменную целого типа (int) i равную 0.
    int i = 0;
  • Далее мы проверяем условие, если истинно, то выполняем блок операторов, если нет - заканчиваем цикл.
    i <= 255 ;
    Т.к i, на данном этапе, меньше или равно 255 (0<=255), то выполняем операции в { }. А именно:
     analogWrite(led_1 , i);
     delay (20);
    Таким образом, мы на порт led_1 подаем уровень i (которое сейчас равно 0). И включаем задержку на 20мсек.
     
  • После задержки, мы переходим снова в начало цикла, и изменяем значение i:
    i++
    Данная строчка эквивалента записи i = i+1. Т.е мы увеличили значение i на единицу. Было равно 0, стало равно единице. 
  • Снова проверяем условие. 
    i <= 255 
    Т.к и это значение у нас меньше или равно 255 (1<=255), то снова выполняем операции в { }. 
     analogWrite(led_1 , i);
     delay (20);
    Подставив теперь вместо i единицу. Таким образом, мы на порт led_1 подаем уровень i (которое сейчас равно 1). И включаем задержку на 20мсек.

И так далее. До тех пор, пока i не станет равно 256. Условие станет ложным (256 < =255) и цикл прервется. Получается, что последнюю операцию, которую выполнит программа, будет подача на pin led_1 значение уровня 255. И потом все повторится сначала - с уровня 0. 

 

Давайте же посмотрим, как будет работать наше устройство с таким алгоритмом:

Как мы видим, применение цикла привело к тому, что нарастание яркости стало очень плавным и приятным на взгляд. А также, уменьшило объем занимаемой памяти микроконтроллера (что в больших проектах очень важно).

 

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

 

Задание для самостоятельного выполнения:

Задание к данному уроку будет только одно: постарайтесь сделать так, что при достижении максимального значения уровня яркости (255 5В), светодиод начал плавно затухать. 

Это можно реализовать добавлением еще одного такого цикла, только с другими параметрами. 

 

Третий урок проекта "Arduino с нуля" подошел к концу. Надеюсь тема была для вас полезной, и вы узнали что-нибудь новое. Также надеюсь, что при выполнении задания у вас не возникнет вопросов и вы справитесь самостоятельно.

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

 

Если Вам понравился наш урок, поделитесь им с друзьями.

 

 


←Предыдущий урок | Следующий урок→


 

Категория: Работа с Arduino | Добавил: GM (12.10.2015)
Просмотров: 7566 | Комментарии: 10 | Рейтинг: 5.0/5
Всего комментариев: 10
avatar
1 Stradivarius • 19:49, 28.10.2015
Спасибо за урок! Доступно и легко для понимания!!! prof
avatar
2 Алексей Севрюк • 15:37, 10.10.2016
Огромное спасибо за уроки. 
С программированием небольшие проблемы, точнее только базовое понимание и воспоминания 10ти летней давности. 
Такой вопрос: каким образом использовать цикл for для нескольких светодиодов, чтобы сначала 1-й горел с определенной яркостью, затем 2-й с той же, затем 3-й и т.д. После этого чтобы они становились ярче и так по кругу, пока не достигнут порогового значения? 

Спасибо.
avatar
1
3 GM • 17:20, 10.10.2016
Здравствуйте, Алексей! Большое спасибо за Ваш комментарий. Мы рады, что наши уроки полезны людям, для этого наш проект и существует. По Вашему вопросу:

В данном уроке есть использование цикла for для одного светодиода. Вот код:

Код
int led_1 = 3; //Номер пина первого светодиода
void setup()    
{
    pinMode (led_1 , OUTPUT); //режим пина led_1 на выход
}
void loop()
    {
    for (int i = 0; i <= 255 ; i++)

    {
    analogWrite(led_1 , i); delay (20);

    }
}

Чтобы использовать несколько светодиодов в одном цикле, необходимо для начала их объявить, для этого добавим следующие строки:
Код
int led_1 = 3; //Номер пина первого светодиода
int led_2 = 4; //Номер пина второго светодиода
int led_3 = 5; //Номер пина третьего светодиода

Далее, идет инициализация пинов, в функции setup(). Этот пункт мы пропустим пока. Дальше идет сам цикл for. Теперь нужно понять что Вы хотите получить. 1) Если Вы хотите, чтобы светодиоды одновременно меняли свою яркость, то delay() необходимо убрать между функциями analogWrite(), и оставить паузу только в конце.  2) Если же Вы хотите чтобы они меняли яркость по очереди, то delay()  необходимо добавить.
Я приведу в пример второй вариант. Вот так будет выглядеть конечный вариант программы:

Код
int led_1 = 3; //Номер пина первого светодиода
int led_2 = 4; //Номер пина второго светодиода
int led_3 = 5; //Номер пина третьего светодиода
void setup()
{
pinMode (led_1 , OUTPUT); //режим пина led_1 на выход
pinMode (led_2 , OUTPUT); //режим пина led_2 на выход
pinMode (led_3 , OUTPUT); //режим пина led_3 на выход
}
void loop()
{
for (int i = 0; i <= 255 ; i++)
{
analogWrite(led_1 , i);
delay (20);
analogWrite(led_2 , i);
delay (20);
analogWrite(led_3 , i);
delay (200);
}
}

Вот в принципе и все. Надеюсь мы смогли ответить на Ваш вопрос smile Если будут еще вопросы, не стесняйтесь - задавайте. Мы будем рады помочь smile
avatar
4 Алексей Севрюк • 19:12, 10.10.2016
Во я глупый  biggrin

analogWrite(led_1 , i); 
delay (20); 
analogWrite(led_2 , i); 
delay (20); 
analogWrite(led_3 , i); 

Как я сам не дошел то.

Спасибо огромное.
Завтра на работе всё испытаю.

И отдельное спасибо за отзывчивость и желание помочь.
avatar
0
5 GM • 22:34, 10.10.2016
Ну ничего, на ошибках учатся biggrin Тогда завтра же и отпишитесь о проделанной работе, надеюсь у Вас все получится biggrin
avatar
6 Алексей Севрюк • 22:40, 10.10.2016
Обязательно smile

последний раз программировал на дэлфи, паскале и визуал бэсике, а было это году в 2006, память за это время координально подтёрлась
avatar
0
7 GM • 22:47, 10.10.2016
Ну на делфи и бейсике я не программировал. А вот паскаль - это основа. С чего большинство и начинают. Ардуино это все равно нечто другое. Там упрощенный C++. Главное понимать саму суть, как и что делать, чтобы что-то получить. Знание языка это не главное, это со временем придет smile
avatar
8 P$ychoSoci@L • 10:13, 11.10.2016
Это точно.

Сейчас буду собирать конструктор.
Глянул ещё раз на код, наверное всё таки задаём пины не 3, 4 и 5, а 3, 5 и 6 ))

Всё заработало.
Единственное, на высокой скорости не понятно что вообще происходит, ну а если увеличить время и добавить парочку светодиодов, то видна вся последовательность действий.

Ещё раз спасибо.
Буду дальше самообразовываться smile
avatar
0
9 GM • 11:46, 11.10.2016
Да, извините, на счет пинов Вы правы. Просто когда писал я не смотрел на ардуино, писал как пример. Конечно, 20 мсек это очень быстро. Необходимо подбирать именно то значение, которое будет видно глазу biggrin
avatar
10 P$ychoSoci@L • 11:57, 11.10.2016
Ничего страшного.
Поправил на всякий случай.

А по времени, с любыми диапазонами можно что-нибудь да и сообразить))
avatar