Arduino — GPIO, Кнопки и PWM

Всем привет это второй урок об Arduino. В первом уроке мы говорили об азах программирования Arduino. Сегодня мы будем говорить о GPIO у Arduino и PWM сигналах. Мы будем использовать кнопки и управлять яркостью светодиода с помощью PWM сигнала. Также мы будем использовать функции в среде программирования Arduino.

Для начала давайте попробуем управлять светодиодом с помощью кнопки.

Нам понадобятся:

  1. Резистор номиналом около 100-400 ом. Для ограничения тока, который идет через светодиод, чтобы не сжечь его.
  2. Резистор номиналом около 10 ком. Для подтягивания логических уровней на входе Arduino. Если его не ставить то наша кнопка будет работать очень нестабильно, т.к. на входе Arduino вместо полезного сигнала будут помехи.
  3. Светодиод АЛ307 или любой который вам понравиться. Собственно его мы и будем зажигать.
  4. Тактовая кнопка IT-1102 или любая другая. Будет использоваться для управления светодиодом.

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

Схема подключения светодиода и кнопки к Arduino

Схема подключения светодиода и кнопки к Arduino

Светодиод подключен через токоограничительный резистор 200 ом к 10 выходу Arduino, номинал резистора можно поставить 200 ом — 500 ом, от этого будет меняться ток, идущий через светодиод и соответственно его яркость. Если вы подключите светодиод напрямую то это закончится плохо, через светодиод пойдет большой ток, в результате чего либо сам светодиод либо выход Arduino выйдет из строя. Необходимо также учесть что светодиод, это как никак диод, у него есть полярность!

Полярность светодиода

Полярность светодиода

Если вы подключите светодиод неправильно, он не загорится, потому что ток через него не пойдет (он просто будет закрыт). Определить полярность светодиода легко, короткая нога светодиода это минус (т.е. ноль или GND), а длинная это +.

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

Итак, настало время написать программу для Arduino. Для начала давайте будем держать включенным светодиод до тех пор, пока нажата кнопка. Конечно решить такую задачу очень легко без микроконтроллера, но ведь нам нужно с чего-то начать. Открываем среду программирования Arduino (как программировать Arduino подробно изложено в уроке №1) и начинаем писать код:

 

 

 

/*
Урок 2. GPIO, Кнопки и PWM у Arduino
Мигаем светодиодом.
Будем держать включенным светодиод до тех пор, пока нажата кнопка.
Этот демонстрационный код был скачан с сайта www.trunagol.ru
*/

int switchPin = 10; // Для удобства задаем имя «switchPin» для 10 вывода
int ledPin = 13; // Для удобства задаем имя «ledPin» для 13 вывода

void setup() // Блок «Setup» запускается только 1 раз при запуске Arduino, он нужен для инициализации.
{
pinMode(switchPin, INPUT); // Конфигурируем 10 вывод Arduino на вход. Т.к. мы будем считывать состояние кнопки.
pinMode(ledPin, OUTPUT); // Конфигурируем 13 вывод Arduino на выход. С помощью него мы будем включать светодиод.
}

void loop() // Блок «loop» это цикл, т.е. код который работает раз за разом бесконечно
{
if (digitalRead(switchPin) == HIGH) // Если кнопка нажата, наша переменная switchPin будет иметь значение HIGH (логическую 1) и выполниться код на след. строке
{
digitalWrite(ledPin, HIGH); // Зажигаем светодиод, выставив логическую 1 (уровень HIGH) на выходе 13
}
else // Если кнопка не нажата выполниться код идущий ниже.
{
digitalWrite(ledPin, LOW); // Выключаем светодиод
}
}

 

 

 

Ну что работает?! :)

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

Наш код для этих целей будет выглядеть  так:

 

 

 

/*
Урок 2. GPIO, Кнопки и PWM у Arduino
Включаем/выключаем светодиод.
Будем включать светодиод после нажатия кнопки и выключать после второго нажатия.
Этот демонстрационный код был скачан с сайта www.trunagol.ru
*/

int switchPin = 10; // Для удобства задаем имя «switchPin» для 10 вывода
int ledPin = 13; // Для удобства задаем имя «ledPin» для 13 вывода
boolean lastButton = LOW; // В этой переменной мы будем хранить состояние кнопки во время предыдущей обработки нашего цикла, а также установим его в ноль.
boolean ledOn = false; // В этой переменной мы будем хранить состояние светодиода, чтобы мы могли переключать его
void setup() // Блок «Setup» запускается только 1 раз при запуске Arduino, он нужен для инициализации.
{
pinMode(switchPin, INPUT); // Конфигурируем 10 вывод Arduino на вход. Т.к. мы будем считывать состояние кнопки.
pinMode(ledPin, OUTPUT); // Конфигурируем 13 вывод Arduino на выход. С помощью него мы будем включать светодиод.
}

void loop() // Блок «loop» это цикл, т.е. код который работает раз за разом бесконечно
{
if (digitalRead(switchPin) == HIGH && lastButton == LOW) // Если кнопка нажата, и последнее состояние кнопки было «не нажата», тогда выполняем следующий код
{
ledOn = !ledOn; // Меняем значение ledOn на противоположное
lastButton = HIGH; // Меняем значение lastButton на логическую единицу
}
else
{
lastButton = digitalRead(switchPin); // Устанавливаем в переменную lastButton такое же значение как в переменной switchPin
}
digitalWrite(ledPin, ledOn); // Собственно эта строчка будет зажигать и гасить светодиод
}

 

 

 

Ну как работает?! Хмм… Странно.. Иногда у нас все срабатывает как ожидается, а иногда нет… Почему так могло произойти? Всё дело в эффекте «дребезга контактов»:

Дребезг контактов

Дребезг контактов

Как вы видите на этой осциллограмме на самом деле наша кнопка срабатывает не идеально… И если мы с большой частотой опрашиваем кнопку, то в переходный момент мы можем считать как единицу так и ноль. Лучше было бы использовать аппаратные решения проблемы, но речь сейчас идет о нашем коде. Чтобы избежать этого дребезга нам придется доработать программу и просто ввести задержку по времени:

 

 

/*
Урок 2. GPIO, Кнопки и PWM у Arduino
Включаем/выключаем светодиод.
Будем включать светодиод после нажатия кнопки и выключать после второго нажатия и устраняем дребезг кнопок.
Этот демонстрационный код был скачан с сайта www.trunagol.ru

*/

int switchPin = 10; // Для удобства задаем имя «switchPin» для 10 вывода
int ledPin = 13; // Для удобства задаем имя «ledPin» для 13 вывода
boolean lastButton = LOW; // В этой переменной мы будем хранить состояние кнопки во время предыдущей обработки нашего цикла, а также установим его в ноль.
boolean ledOn = false; // В этой переменной мы будем хранить состояние светодиода, чтобы мы могли переключать его
boolean currentButton = LOW; // Переменная для нашей функции debounce

void setup() // Блок «Setup» запускается только 1 раз при запуске Arduino, он нужен для инициализации.
{
pinMode(switchPin, INPUT); // Конфигурируем 10 вывод Arduino на вход. Т.к. мы будем считывать состояние кнопки.
pinMode(ledPin, OUTPUT); // Конфигурируем 13 вывод Arduino на выход. С помощью него мы будем включать светодиод.
}

 

boolean debounce(boolean last) //функция для устранения дребезга контактов кнопки, будет возвращать предыдущее её состояние
{
boolean current = digitalRead(switchPin); // Пишем в current текущее состояние кнопки
if (last != current) // Проверяем изменилось ли состояние кнопки
{
delay(5); // Если да, делаем задержку 5 миллисекунд, для того чтобы кнопка перестала «дребезжать»
current = digitalRead(switchPin); // Считываем значение кнопки после паузы, сейчас дребезг уже должен пройти
}
return current; // возвращаем стабильное значение кнопки
}

 

void loop() // Блок «loop» это цикл, т.е. код который работает раз за разом бесконечно

{
currentButton = debounce(lastButton); // передаем в currentButton результат работы функции debounce с переданным в него состоянием кнопки
if (lastButton == LOW && currentButton == HIGH) // Проверяем была ли нажата кнопка
{
ledOn = !ledOn; // Меняем значение ledOn на противоположное
}
lastButton = currentButton; // Устанавливаем в переменную lastButton такое же значение как в переменной currentButton
digitalWrite(ledPin, ledOn); // Собственно эта строчка будет зажигать и гасить светодиод
}

 

Я думаю теперь у всех все заработало так, как и задумывалось ;)

Теперь настало время изменить нашу программу таким образом, чтобы после каждого нажатия кнопки менялась яркость светодиода, для этого мы будем использовать ШИМ сигнал или как его еще называют PWM. Если вы хотите узнать подробнее про ШИМ, можете почитать об этом в ВИКИ. А для нас на текущий момент достаточно знать лишь то, что меняя логические значения 0 и 1 в определенной последовательности можно заставить светодиод светиться по разному, но сути он просто будет по разному мигать, но так как частота миганий высокая, глазу будет казаться что он просто меняет яркость.

Но к сожалению не все выходы Arduino поддерживают PWM, поддержка PWM обозначена значком ~ рядом с номером контакта на шелкографии Arduino. Одним из таких контактов является контакт №11, а текущий наш контакт №13 не поддерживает PWM, следовательно нам нужно изменить схему подключения следующим образом:

Схема подключения светодиода и кнопки к Arduino c PWM

Схема подключения светодиода и кнопки к Arduino c PWM

А также внести изменения в программный код, а именно нужно изменить номер контакта и добавить использование ШИМ:

 

 

 

/*
Урок 2. GPIO, Кнопки и PWM у Arduino
Меняем яркость светодиода.
Будем менять яркость свечения светодиода после каждого нажатия кнопки.
Этот демонстрационный код был скачан с сайта www.trunagol.ru
*/

int switchPin = 10; // Для удобства задаем имя «switchPin» для 10 вывода
int ledPin = 11; // Для удобства задаем имя «ledPin» для 11 вывода
boolean lastButton = LOW; // В этой переменной мы будем хранить состояние кнопки во время предыдущей обработки нашего цикла, а также установим его в ноль.
int ledLevel = 0; // В этой переменной мы будем хранить яркость свечения светодиода, яркость может иметь значение от 0 до 255, в момент инициализации установим его в 0, чтобы светодиод не светился
boolean currentButton = LOW; // Переменная для нашей функции debounce

void setup() // Блок «Setup» запускается только 1 раз при запуске Arduino, он нужен для инициализации.
{
pinMode(switchPin, INPUT); // Конфигурируем 10 вывод Arduino на вход. Т.к. мы будем считывать состояние кнопки.
pinMode(ledPin, OUTPUT); // Конфигурируем 13 вывод Arduino на выход. С помощью него мы будем включать светодиод.
}

boolean debounce(boolean last) //функция для устранения дребезга контактов кнопки, будет возвращать предыдущее её состояние
{
boolean current = digitalRead(switchPin); // Пишем в current текущее состояние кнопки
if (last != current) // Проверяем изменилось ли состояние кнопки
{
delay(5); // Если да, делаем задержку 5 миллисекунд, для того чтобы кнопка перестала «дребезжать»
current = digitalRead(switchPin); // Считываем значение кнопки после паузы, сейчас дребезг уже должен пройти
}
return current; // возвращаем стабильное значение кнопки
}

void loop() // Блок «loop» это цикл, т.е. код который работает раз за разом бесконечно
{
currentButton = debounce(lastButton); // передаем в currentButton результат работы функции debounce с переданным в него состоянием кнопки
if (lastButton == LOW && currentButton == HIGH) // Проверяем была ли нажата кнопка
{
ledLevel = ledLevel + 51; // Меняем значение яркости на 51
}
lastButton = currentButton; // Устанавливаем в переменную lastButton такое же значение как в переменной currentButton

if (ledLevel > 255) ledLevel = 0; // Ограничиваем макс. значение в 255
analogWrite(ledPin, ledLevel); // Собственно эта строчка будет зажигать светодиод с нужной яркостью
}

 

Надеюсь у вас все заработало. Это конец урока.

Вы можете задать вопросы и спросить совета в комментариях.

Код программ из урока для загрузки доступен здесь: Примеры из второго урока

Вы можете оставить отзыв, или трекбек со своего сайта.

2 комментария на “Arduino — GPIO, Кнопки и PWM”

  1. Евгений:

    Спасибо за инструкцию!

  2. Константин:

    Спасибо! Познавательно

Оставьте отзыв