Цифровая электроника для начинающих - страница 10

стр.

.


Функция loop(), в отличие от setup, выполняется постоянно, бесконечное число раз. В ней мы и размещаем всю логику работы программы. В данном случае, логика проста - мы посылаем в порт логическую “1” командой digitalWrite(led, HIGH), затем ждем одну секунду с помощью вызова delay(1000), затем посылаем логический “0”, опять ждем. Данный цикл будет автоматически повторяться, пока плата включена и работает.


Огромный плюс использования микроконтроллеров - в их огромной гибкости, изменяя код, мы можем полностью менять логику работы программы. Например, несложно сделать чтобы светодиод мигал в режиме “2 коротких, 1 длинный”, для этого достаточно лишь изменить текст кода:

void loop() {

digitalWrite(led, HIGH);

delay(500);

digitalWrite(led, LOW);

delay(500);

digitalWrite(led, HIGH);

delay(500);

digitalWrite(led, LOW);

delay(500);

digitalWrite(led, HIGH);

delay(2000);

digitalWrite(led, LOW);

delay(2000);

}


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


Кстати, зачем нужен вызов функции delay? Все просто, без нее программа тоже будет работать - но светодиод будет переключаться со скоростью тысячи раз в секунду, что будет неразличимо глазом. Тактовая частота процессора составляет несколько мегагерц, и без пауз программа будет работать слишком быстро.


Можно ли подключить светодиод к другому выводу, или подключить несколько светодиодов? Разумеется, можно. Для этого нужно найти инструкцию к плате, где будут указаны номера выводов (номера подписаны и на самой плате). Для Arduino Uno такая схема выглядит примерно так:



Далее, достаточно подключить к нужному выводу (например это может быть пин “10”) светодиод, не забыв и ограничительный резистор. Вторым выводом будет общий вывод, или GND (это аналог вывода “-” в схеме с батарейкой из первой части книги). На плате несколько выводов GND, можно использовать любой из них, они соединены вместе.


Схема целиком на макетной плате будет выглядеть так:


Разумеется, текст кода тоже придется изменить, поменяв номер вывода с 13 на 10.


Самостоятельная работа #1: Замедлить скорость мигания светодиодов до 5-10с. Тестером померять напряжение на выходе Arduino, и убедиться что оно изменяется от 0 до 5В с соответствующей частотой.


Самостоятельная работа #2: подключить 2-3 дополнительных светодиода, каждый через свой токоограничительный резистор. Добавить код для их переключения, можно также поэкспериментировать с различными световыми эффектами (поочередное или параллельное мигание и пр).



2.4 Мигаем светодиодом: широтно-импульсная модуляция

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

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


int led = 13;


int pwm = 0;


void setup() {

pinMode(led, OUTPUT);

}


void loop() {

for(int i=0; i<1000; i++) {

digitalWrite(led, HIGH);

delayMicroseconds(pwm);

digitalWrite(led, LOW);

delayMicroseconds(100 - pwm);

}

pwm += 1;

if (pwm > 100) pwm = 0;

}


Мы создали глобальную переменную pwm, в которой сохраняется текущее значение уровня заполнения в процентах. Дальше мы включаем “высокое” и “низкое” состояние вывода, в соответствии с этим значением - когда одно значение велико, второе, наоборот, мало. Цикл “for(int i=0; i<1000; i++)” повторяет участок кода 1000 раз - без него светодиод менял бы яркость слишком быстро.


Если загрузить этот код, мы увидим плавно увеличивающий яркость светодиод. Но у вышеприведенного кода есть недостатки. Во-первых, он довольно-таки громоздкий - слишком много строк для переключения только одного вывода. Во-вторых, процессор занят только переключением светодиода, любая другая задача нарушит согласованность временных интервалов. К счастью для нас, разработчики процессора пошли навстречу пользователям, и формирование ШИМ может выполняться автоматически, на аппаратном уровне. Для этого достаточно использовать функцию analogWrite, в качестве параметра указав степень заполнения в виде параметра 0..255.