Наступает вечер. За окном сгущаются сумерки. Но вот на улице зажглись фонари. Кто их включил? А кто выключит их утром, когда взойдет солнце? А как автоматически включается свет в подъездах? Думаете, сидит где-то усатый дяденька, смотрит на часы и щелкает выключателем в нужный момент? Ошибаетесь! Эту работу давно выполняют роботы, но обо всем по порядку…
Первым источником света для человека был огонь: лес, костер, хищники прячутся в окружающей темноте, а люди сидят возле пламени, греются и готовят пищу. Однако с развитием городов и появлением транспорта возникла необходимость в освещении не только собственного жилища, но и улиц. Самые первые городские фонари появились в XV веке в Лондоне. А в начале XVI столетия жителей Парижа обязывали выставлять светильники к окнам, которые выходили на улицу.
В России история городского освещения ведет свое начало с 1706 года, когда в Санкт-Петербурге на фасадах некоторых домов около Петропавловской крепости были вывешены светильники. Первые же стационарные фонари появились на столичных улицах в 1718 году. А «днем рождения» московского освещения считается 25 октября 1730 года, когда магистрат издал указ «О сделании для освещения в Москве стеклянных фонарей».
Впрочем, закончим на этом экскурс в прошлое, поскольку подробный материал о посещении интереснейшего музея «Огни Москвы», где представлены все этапы развития городского освещения, был опубликован в прошлом номере журнала. Лучше сразу перенесемся в 1926 год, когда группа немецких инженеров предложила покрывать внутреннюю поверхность ртутных ламп люминофором — веществом, которое способно поглощать ультрафиолет и переизлучать свет в видимом диапазоне. Так возникла люминесцентная лампа, она же — лампа «дневного света». А в 1960-е годы появились первые промышленно значимые светодиоды. На первых порах это были источники красного (реже — желто-зеленого) света, которые использовались в различных индикаторах. Эффективность их оставляла желать лучшего — всего 1-2 люмена на ватт, что чуть ли не на порядок ниже традиционных ламп накаливания. Тремя десятилетиями позже этот показатель возрос до 30, а к концу тысячелетия — уже до 60 люменов на ватт.
Светодиод — это полупроводниковый прибор, излучающий свет при пропускании через него электрического тока. Причем излучать светодиод может только в очень узком диапазоне спектра, определяемом составом полупроводника. Поэтому для создания белых светодиодов в любом случае используются люминофоры (те самые, открытые в начале прошлого века). Долгое время серьезным препятствием для массового внедрения светодиодного освещения оставалась высокая стоимость, но по мере появления новых полупроводниковых материалов и увеличения объемов производства их цена снижалась.
Посмотрим еще раз в окно на уличные фонари, которые сами включаются, как только стемнело. Умное освещение — это технология, направленная на увеличение энергоэффективности и комфорта использования искусственных источников света, достигаемое благодаря использованию автоматизированного управления и датчиков освещенности. Первые системы автоматизации внедрялись еще в конце XX века, но появление действительно «умного» освещения можно приурочить лишь к нашему времени, когда началось активное использование LED-ламп (светодиодов). Технология LED позволила не менее чем в пять раз снизить энергозатратность освещения по сравнению с лампами накаливания, а также весьма значительно (до 100 раз) увеличить долговечность одного используемого источника света. Благодаря этим свойствам светодиоды повсеместно вытесняют сегодня даже люминесцентные лампы. А использование с ними датчиков освещенности позволяет реализовать простейшую функцию «умного освещения» — самостоятельно включать и выключать освещение тогда, когда это нужно.
Ну а теперь перейдем к практической части занятия и научимся управлять яркостью светодиода в зависимости от освещения.
ЛАМПОЧКА, ЗАЖГИСЬ!
На прошлых уроках мы работали со светодиодами, а, точнее, освоили, как программно включать и выключать их с заданной периодичностью. Для этого мы пользовались цифровым сигналом, то есть сигналом, который хранит в себе два состояния: 1 — есть напряжение, 2 — нет напряжения. Казалось бы, этого достаточно для того, чтобы управлять различными электронными компонентами. Однако как быть, если необходимо не только включать/выключать светодиод, но и менять его яркость? Или регулировать скорость вращения вала электродвигателя, например? Для этого нужен аналоговый сигнал и широтно-импульсная модуляция (ШИМ). К цифровому сигналу (повторим, у него всего два состояния: есть напряжение (5 В) и нет напряжения (0 В)), добавляется аналоговый — а это уже множество состояний, то есть напряжение меняется от 0 В до 5 В в нашем случае (может быть и другой диапазон).
Если мы подадим 3 В на светодиод, то он будет светить очень тускло, а если 4 В — ярче. Следовательно, чтобы управлять яркостью светодиода, на него нужно подавать разное напряжение (в пределах рабочего, понятно). Однако микроконтроллер не способен давать «чуть-чуть поменьше» или «чуть-чуть побольше» тока, он умеет работать только с «единицами» и «нулями» — то есть, «есть напряжение» или «нет напряжения», соответственно. Решить данную задачу нам поможет ШИМ. Что это и как работает?
Представим, что светодиод подключен к плате Arduino, одну секунду он горит, другую — гаснет. Такой режим можно назвать миганием — оно заметно глазу. А если светодиод будет выключаться и включаться 40 раз в секунду? Без приборов заметить такое мигание будет практически невозможно — оно сольется в одно действие, как будто светодиод горит «в полнакала». В этом и есть суть ШИМ-сигнала — он управляет промежутком времени включения/ выключения какого-либо вывода (пина) микроконтроллера. А теперь давайте воспользуемся этими знаниями и рассмотрим структуру программы «пульсации» светодиода: его яркость будет увеличиваться до максимума, а потом уменьшаться до минимума.
Вот пример такого скетча:
int bright = 0; //яркость
int change = 5; //значение на которое будет изменяться яркость
int ms = 20; //время задержки
int led = 9; //номер пина к которому подключен светодиод
void setup() {
pinMode(led, OUTPUT);
}
void loop() {
analogWrite(led, bright);
bright = bright + change;
if(bright = 0 || bright = 255){
change = -change;
}
delay(ms);
}
Пройдемся по коду программы сверху вниз, чтобы разобраться, как она работает. В первых четырех строчках мы объявляем переменные. Об этом уже говорилось на предыдущих занятиях. Не понимаете, что означает двойной слэш? Это один из способов написания комментария. Комментарий — это слова, которые не считывает компилятор, а значит, и не загружает их на плату. Комментарии пишутся авторами скетчей для того, чтобы ими мог воспользоваться и изменить другой программист, или же чтобы самому не запутаться в коде при его большом объеме. Существует два вида комментариев:
Однострочный: //комментарий
Многострочный: /*комментарий*/
При написании кода можно не соблюдать табуляцию, перевод строки, но с комментариями не все так просто. Например, если вы хотите написать комментарий в несколько строк, то нужно воспользоваться вторым способом.
В данном случае в качестве комментариев даны пояснения назначений переменных. Так, например, переменная bright отвечает за яркость свечения светодиода и т.д.:
int bright = 0; //яркость
int change = 5; //значение на которое будет изменяться яркость
int ms = 20; //время задержки
int led = 9; //номер пина к которому подключен светодиод
Далее в процедуре настройки платы мы обозначаем режим работы пина, к которому подключен светодиод.
Добрались до процедуры loop. Первая строчка и сразу не понятно? Это новая функция — analogWrite(). Ничего не напоминает? Правильно, она похожа на digitalWrite(), и выполняет те же действия, только чуточку побольше. Выглядит функция так:
analogWrite(номep пина, значение)
Она способна выдавать на пин напряжение от 0 до 5 В с помощью ШИМ-сигнала. Значение напряжения можно указывать в диапазоне 0 — 255, где 0 — это 0 В, 255 — 5 В, а 128 — это половина (то 0 В, то 5 В). Но не каждый пин поддерживает ШИМ. Чтобы понять, какой из них имеет данную функцию, надо на него взглянуть — он помечен символом «~» (тильда).
В качестве аргументов функции analogWrite() мы использовали в коде переменную, которая хранит номер пина светодиода, и переменную, которая хранит значение напряжения. И, как уже могли догадаться, мы будем изменять значение bright для того, чтобы увеличивать/уменьшать яркость светодиода:
bright = bright + change;
При каждой итерации loop(), bright увеличится на change. Когда значение дойдет до максимума или минимума, изменим знак числа, хранящегося в переменной change:
change = -change;
Например, если значение дошло до 255, то change должен стать «-5», чтобы bright уменьшался.
Итак, разобрались, как программа будет изменять яркость светодиода. А как она будет отслеживать то, что bright дошла до порога диапазона? В этом поможет оператор if:
if(условие){
}
Он проверяет условие, написанное в круглых скобках на истинность, и выполняет действия в фигурных скобках в случае правильности выполнения условия. У него существует необязательное дополнение, которое выполняет действия в скобках, в случае ложности условия if:
else{
}
Наше условие должно звучать так: если bright равняется 0 (дошел до минимума) или bright равняется 255 (дошел до максимума). Чтобы записать это синтаксически правильно, понадобится оператор сравнения «==» и логический оператор «или» — «||» («дабл бар», «вертикальная палочка», «вертикальный слэш» или «дабл пайп»):
if(bright = 0 || bright = 255) {
change = -change;
}
Осталось только прописать delay(), чтобы все выполнялось не моментально. Вот наша программа и готова.
Мы научились выводить аналоговый сигнал. А что если мы захотим считать его? Для этого понадобится функция analogRead():
analogRead(номер пина)
Но чтобы считывать аналоговый сигнал, нужны пины с аналоговоцифровым преобразователем (АЦП) -это пины с буквой А перед номером. Функция analogRead() возвращает число в диапазоне 0 — 1023, соответствующее напряжению, на считываемом пине (0 В — это 0, 5 В — это 1023). Обратите внимание, что pinMode() для аналоговых входов прописывать не требуется.
Зачем может понадобиться данная функция? Вспомним из школьного курса физики переменные резисторы — это электронные компоненты, которые изменяют свое сопротивление при определенных условиях. Существуют различные типы таких устройств. К примеру, есть потенциометр. Поворачиваем его рукоятку или смещаем «движок», соответственно меняем длину дорожки между выводами: чем она длиннее, тем больше сопротивление. Обычно у потенциометров три ножки, одна из которых — это выход с ползунка. С него и будем считывать изменения напряжения, а другие ножки подключим к пинам 5V и GND.
Напишем программу, которая при изменении положения ползунка управляет яркостью светодиода:
int pot = Al; //пин потенциометра
int led = 9; //пин светодиода
int val = 0; //значения с потенциометра
void setup(){
pinMode(led, OUTPUT);
}
void loop(){
val = analogRead(pot);
//считываем значение с потенциометра и закидываем в переменную val val = val/4;
/*т.к. мы хотим val использовать в качестве ШИМ-сигнала (0-255), а в нем хранится значение 0-1023 то данное значение нужно поделить на 4 */
analogWrite(led, val);
/*выводим на светодиод ШИМ-сигнап, пропорциональный сигналу с потенциометра */
}
Поворачивая бегунок переменного резистора, мы изменяем напряжение на аналоговом входе. В результате меняется яркость светодиода.
Ну а теперь — самое интересное! Ведь переменный резистор может быть не только потенциометром с вращающейся рукояткой, но и фоторезистором, меняющим свое сопротивление в зависимости от уровня освещенности. Вот и давайте напишем программу «ночника», как модели системы умного уличного освещения, с которого и начался урок:
int photo = A1; //пин фоторезистора
int led = 9; //пин светодиода
void setup(){
pinMode(led, OUTPUT);
}
void loop(){
/*считываем показания фоторезистора сравниваем их со значением принятым за темноту
для примера взято значение 30 */
if(analogRead(photo) > 30) {
// если освещенность низкая, включаем светодиод
digitalWrite(led, HIGH);
}
else{
// иначе светодиод выключен digitalWrite(led, LOW);
}
delay(100);
}
Наш «ночник» будет включатся в сумерках. В темноте фоторезистор имеет сопротивление 100 кОм, а когда освещен — 10 кОм. Соответственно, в пару ему понадобится резистор номиналом 100 кОм.
А что нужно, чтобы создать программу, которая в зависимости от освещенности не только включает/выключает светодиод, но изменяет его яркость? Для этого достаточно немного доработать последний скетч или версию с потенциометром. А точнее, добавить переменную, которая будет хранить в себе считанные значения с фоторезистора. Попробуйте написать программу самостоятельно -это и станет домашним заданием. Ответ на него будет опубликован в следующем номере.