» »

Arduino проекты. Уроки, программирование, управление и подключение ардуино

20.07.2023

Аппаратное обеспечение:

- плата
- макетная плата
- светодиод
- резистор 220 Ом

Электрическая цепь:

Соедините анод (длинный вывод) вашего светодиода с цифровым выводом 9 Arduino через резистор 220 Ом. Соедините катод (короткий вывод) с землей (GND) Arduino.



Схема:


Код:

В функции setup() нужно назначить вывод 9 выходом.
Функция analogWrite() которую вы будете использовать в основном цикле имеет два аргумента: первый говорит функции какой вывод использовать, во второй записывают значение для ШИМ.
Для того чтобы плавно увеличить яркость светодиода, а потом плавно уменьшить вам нужно сначала увеличивать значение ШИМ от 0 (светодиод выключен) до 255 (максимальная яркость), а потом наоборот. В нашей программе переменная отвечающая за значение ШИМ будет называться brightness. В каждом цикле эта переменная будет изменятся на значение fadeAmount.
Как только brightness достигнет значения 255 или 0 fadeAmount изменит свой знак. Таким способом мы сможем поменять увеличения яркости на понижение и наоборот.
analogWrite() изменяет значение ШИМ очень быстро, потому нужна задержка для контроля скорости изменения яркости. Вы можете сами изменять значения задержки и смотреть как это скажется на работе.

Полный текст программы:

/*

Этот пример показывает как изменять яркость светодиода на выводе 9

используя функцию analogWrite().

*/

int led = 9; // вывод светодиода 9

int brightness = 0; // переменная отвечающая за яркость

int fadeAmount = 5; // переменная, которая задает скорость изменения яркости за цикл

// настройки:

void setup() {

// назначим вывод 9 выходом :

pinMode (led, OUTPUT);

// основной цикл :

void loop () {

// устанавливаем яркость светодиода на выводе 9:

analogWrite (led, brightness);

// изменим значение яркости для следующего прохода цикла:

brightness = brightness + fadeAmount;

// поменяем направление изменения яркости :

if (brightness == 0 || brightness == 255) {

fadeAmount = -fadeAmount ;

// ждем 30 миллисекунд для наблюдения эффекта диммирования:

delay (30);




- полный каталог плат

Список деталей для эксперимента

Для дополнительного задания

    еще 1 светодиод

    еще 1 резистор номиналом 220 Ом

    еще 2 провода

Принципиальная схема

Схема на макетке

Обратите внимание

    Мы подключили «землю» светодиода и переменного резистора (потенциометра) к длинной рельсе «-» макетной платы, и уже ее соединили с входом GND микроконтроллера. Таким образом мы использовали меньше входов и от макетки к контроллеру тянется меньше проводов.

    Подписи «+» и «-» на макетке не обязывают вас использовать их строго для питания, просто чаще всего они используются именно так и маркировка нам помогает

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

    Для считывания аналогового сигнала, принимающего широкий спектр значений, а не просто 0 или 1, как цифровой, подходят только порты, помеченные на плате как «ANALOG IN» и пронумерованные с префиксом A . Для Arduino Uno - это A0-A5.

Скетч

p030_pot_light.ino // даём разумные имена для пинов со светодиодом // и потенциометром (англ potentiometer или просто «pot») #define LED_PIN 9 #define POT_PIN A0 void setup() { // пин со светодиодом - выход, как и раньше... pinMode(LED_PIN, OUTPUT) ; // ...а вот пин с потенциометром должен быть входом // (англ. «input»): мы хотим считывать напряжение, // выдаваемое им pinMode(POT_PIN, INPUT) ; } void loop() { // заявляем, что далее мы будем использовать 2 переменные с // именами rotation и brightness, и что хранить в них будем // целые числа (англ. «integer», сокращённо просто «int») int rotation, brightness; // считываем в rotation напряжение с потенциометра: // микроконтроллер выдаст число от 0 до 1023 // пропорциональное углу поворота ручки rotation = analogRead(POT_PIN) ; // в brightness записываем полученное ранее значение rotation // делённое на 4. Поскольку в переменных мы пожелали хранить // целые значения, дробная часть от деления будет отброшена. // В итоге мы получим целое число от 0 до 255 brightness = rotation / 4 ; // выдаём результат на светодиод analogWrite(LED_PIN, brightness) ; }

Пояснения к коду

    С помощью директивы #define мы сказали компилятору заменять идентификатор POT_PIN на A0 - номер аналогового входа. Вы можете встретить код, где обращение к аналоговому порту будет по номеру без индекса A . Такой код будет работать, но во избежание путаницы с цифровыми портами используйте индекс.

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

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

int rotation, brightness;

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

    Функция analogRead(pinA) возвращает целочисленное значение в диапазоне от 0 до 1023, пропорциональное напряжению, поданному на аналоговый вход, номер которого мы передаем функции в качестве параметра pinA

    Обратите внимание, как мы получили значение, возвращенное функцией analogRead() : мы просто поместили его в переменную rotation с помощью оператора присваивания = , который записывает то, что находится справа от него в ту переменную, которая стоит слева

Вопросы для проверки себя

    Можем ли мы при сборке схемы подключить светодиод и потенциометр напрямую к разным входам GND микроконтроллера?

    В какую сторону нужно крутить переменный резистор для увеличения яркости светодиода?

    Что будет, если стереть из программы строчку pinMode(LED_PIN, OUTPUT) ? строчку pinMode(POT_PIN, INPUT) ?

    Зачем мы делим значение, полученное с аналогового входа перед тем, как задать яркость светодиода? что будет, если этого не сделать?

Функция analogWrite() используется для затухания свтодиода и его постепенного включения.

AnalogWrite использует широтно-импульсную модуляцию (PWM), которая дает возможность включать/включать цифровой пин с большой скоростью, генерируя эффект затухания.

Что вам понадобится для проекта

  • Плата Arduino
  • Макетная плата (breadboard)
  • Светодиод
  • Резистор на 220 Ом

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

Подключите анод (более длинная, позитивная нога) светодиода к цифровому пину 9 платы Arduino через резистор 220 Ом. Подключите катод (более короткая, нога с отрицательным зарядом) к земле.

Электросхема подключенного к Arduino светодиода


Вариант шилда со светодиодом для Arduino

Описание программы для Arduino

После объявления 9 пина в качестве ledPin, тело функции setup() можно не наполнять.

Функция analogWrite() которую вы будете использовать в главном цикле main, требует два аргумента: один для определения пина, на который будут записываться и второй - для отображения записываемого ШИМ-значения.

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

Если brightness достигает своего предельного значения (0 или 255), fadeAmount меняет свое значение на отрицательное. Другими словами, если fadeAmount равно 5, его значение меняется на -5. При следующей итерации цикла это приводит к изменению переменной brightness.

analogWrite() обеспечивает быструю смену ШИМ значения, так что задержка в конце скетча контролирует скорость затухания. Попробуйте изменить значение задержки задержки и отследить, как отработает программа.

Скетч для Arduino IDE

Данный пример показывает как обеспечить затухание на 9 пине с использованием функции analogWrite().

int led = 9; // пин, к которому подключен светодиод

int brightness = 0; // яркость светодиода

int fadeAmount = 5; // на сколько увеличить яркость светодиода

// функция setup отрабатывает один раз после перезагрузки платы:

// объявляет 9 пин в качестве выхода:

pinMode(led, OUTPUT);

// цикл loop повторяется бесконечно:

// устанавливает яркость 9 пина:

analogWrite(led, brightness);

// изменение яркости на следующей итерации с помощью цикла:

brightness = brightness + fadeAmount;

// меняет значение затухания на аналогичное с противоположным знаком при граничных значениях:

if (brightness == 0 || brightness == 255) {

fadeAmount = -fadeAmount ;

// задержка в 30 для отслеживания эффекта затухания

Как рождаются программы

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

Сегодня мы с вами будем решать следующую задачу: есть 2 светодиода их надо подключить к Arduino и реализовать возможность регулировать яркость их горения.

Приступим!

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

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

Для простоты понимания как он устроен внутри я приложу схему внутренних соединений:

Подключение светодиодов к Arduino

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

Как избежать порчи светодиода из-за большого тока? Все очень просто: нужно использовать токоограничивающий резистор, который надо рассчитывать для каждого светодиода в зависимости от его характеристик. Расчет резисторов для светодиода - это тема для отдельной статьи и сегодня мы не будем углубляться в эту тему так как скорей всего вы не знаете характеристик светодиода, который вы где-то нашли. На этот случай я использую маленькое правило: если светодиод не яркий, то я запитываю его через резистор сопротивлением от 220 до 400 ом в зависимости от того какой резистор был под рукой. Главное запомнить правило – лучше больше чем меньше. При большем сопротивлении чем требуется светодиоду, он просто будет гореть тусклее нормы.

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

Что такое ШИМ

ШИМ (широтно-импульсная модуляция) – это изменение скважности сигнала на определенном отрезке времени. Шим сигнал имеет следующий вид по сравнению с постоянным сигналом:

На этой картинке 100% рабочего цикла это отсутствие ШИМ как такового, сигнал идет без изменений, как будто вывод просто подключен к 5 вольтам.

0% рабочего цикла это отсутствие какого-либо сигнала, как будто провод никуда не подключен.

Остальные режимы работы - это быстрое переключение режимов работы что заставляет светодиод как бы моргать с большой скоростью не заметной глазу человека (100 раз в секунду) что и заставляет его гореть с не полной яркостью. Arduino в зависимости от версии используемого чипа имеет разное количество ШИМ выходов, на плате они помечены знаком ~ из прошлой статьи мы знаем что это 6 выходов 3, 5, 6, 9, 10, и 11 мы будем использовать 10 и 11 выводы.

Давайте наконец то подключим светодиоды к плате. Надеваем на Arduino наш lcd shield и собираем следующею схему для которой нам понадобится бредборд, 2 светодиода, 2 резистора на 250 ом, и 3-4 провода папа- папа. Схема будет иметь следующий вид:

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

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

В этом эксперименте мы добавляем порцию яркости светодиоду одной кнопкой и убавляем другой.

СПИСОК ДЕТАЛЕЙ ДЛЯ ЭКСПЕРИМЕНТА

- 1 плата Arduino Uno;

- 1 беспаечная макетная плата;

- 2 тактовых кнопки;

- 1 резистор номиналом 220 Ом;

- 1 светодиод;

- 7 проводов «папа-папа».

ПРИНЦИПИАЛЬНАЯ СХЕМА

СХЕМА НА МАКЕТНОЙ ПЛАТЕ

ОБРАТИТЕ ВНИМАНИЕ

  • Если вы переделываете схему из схемы предыдущего эксперимента, обратите внимание, что на этот раз нам нужно подключить светодиод к порту, поддерживающему ШИМ.

СКЕТЧ

скачать скетч для Arduino IDE
#define PLUS_BUTTON_PIN 2 #define MINUS_BUTTON_PIN 3 #define LED_PIN 9 int brightness = 100; boolean plusUp = true; boolean minusUp = true; void setup() { pinMode(LED_PIN, OUTPUT); pinMode(PLUS_BUTTON_PIN, INPUT_PULLUP); pinMode(MINUS_BUTTON_PIN, INPUT_PULLUP); } void loop() { analogWrite(LED_PIN, brightness); // реагируем на нажатия с помощью функции, написанной нами plusUp = handleClick(PLUS_BUTTON_PIN, plusUp, +35); minusUp = handleClick(MINUS_BUTTON_PIN, minusUp, -35); } // Собственная функция с 3 параметрами: номером пина с кнопкой // (buttonPin), состоянием до проверки (wasUp) и градацией // яркости при клике на кнопку (delta). Функция возвращает // (англ. return) обратно новое, текущее состояние кнопки boolean handleClick(int buttonPin, boolean wasUp, int delta) { boolean isUp = digitalRead(buttonPin); if (wasUp && !isUp) { delay(10); isUp = digitalRead(buttonPin); // если был клик, меняем яркость в пределах от 0 до 255 if (!isUp) brightness = constrain(brightness + delta, 0, 255); } return isUp; // возвращаем значение обратно, в вызывающий код }

ПОЯСНЕНИЯ К КОДУ

  • Мы можем пользоваться не только встроенными функциями, но и создавать собственные. Это обоснованно, когда нам нужно повторять одни и те же действия в разных местах кода или, например, нужно выполнять одни и те же действия над разными данными, как в данном случае: обработать сигнал с цифровых портов 2 и 3.
  • Определять собственные функции можно в любом месте кода вне кода других функций. В нашем примере, мы определили функцию после loop .
  • Чтобы определить собственную функцию, нам нужно:
    • Объявить, какой тип данных она будет возвращать. В нашем случае это boolean . Если функция только выполняет какие-то действия и не возвращает никакого значения, используйте ключевое слово void
    • Назначить функции имя — идентификатор. Здесь действуют те же правила, что при именовании переменных и констант. Называть функции принято в том же стиле какПеременные .
    • В круглых скобках перечислить передаваемые в функцию параметры, указав тип каждого. Это является объявлением переменных, видимых внутри вновь создаваемой функции, и только внутри нее. Например, если в данном эксперименте мы попробуем обратиться к wasUp или isUp из loop() получим от компилятора сообщение об ошибке. Точно так же, переменные, объявленные в loop , другим функциям не видны, но их значения можно передать в качестве параметров.
    • Между парой фигурных скобой написать код, выполняемый функцией
    • Если функция должна вернуть какое-то значение, с помощью ключевого слова return указать, какое значение возвращать. Это значение должно быть того типа, который мы объявили
  • Так называемые глобальные переменные, т.е. переменные, к которым можно обратиться из любой функции, обычно объявляются в начале программы. В нашем случае — это brightness .
  • Внутри созданной нами функции handleClick происходит всё то же самое, что в эксперименте .
  • Поскольку при шаге прироста яркости 35 не более чем через восемь нажатий подряд на одну из кнопок значение выражения brightness + delta выйдет за пределы интервала . С помощью функции constrain мы ограничиваем допустимые значения для переменной brightness указанными границами интервала.
  • В выражении plusUp = handleClick(PLUS_BUTTON_ PIN , plusUp, +35) мы обращаемся к переменной plusUp дважды. Поскольку = помещает значение правого операнда в левый, сначала вычисляется, что вернет handleClick . Поэтому когда мы передаем ей plusUp в качестве параметра, она имеет еще старое значение, вычисленное при прошлом вызове handleClick .
  • Внутри handleClick мы вычисляем новое значение яркости светодиода и записываем его в глобальную переменную brightness , которая на каждой итерации loop просто передается в analogWrite .

ВОПРОСЫ ДЛЯ ПРОВЕРКИ СЕБЯ

  1. Что означает ключевое слово void ?
  2. Как ведет себя программа при упоминании одной переменной с разных сторон от оператора присваивания = ?

ЗАДАНИЯ ДЛЯ САМОСТОЯТЕЛЬНОГО РЕШЕНИЯ

  1. Доработайте код таким образом, чтобы шаг изменения яркости настраивался в одном месте.
  2. Создайте еще одну функцию и переделайте код так, чтобы одна функция отвечала за отслеживание нажатий, а другая — за вычисление яркости светодиода и возвращала его в analogWrite .