- Платформа Arduino
- Arduino UNO
- Концепція програмування
- Підключення світлодіода
- Використання керуючих елементів, перемикачів
- Використання потенціометрів
- Послідовний інтерфейс обміну даними
- Аналоговий датчик температури TMP36
- Використання бібліотек
- Керування сервоприводами
- Семисегментний світлодіодний індикатор
- Використання ультразвукового далекоміра
- Рідкокристалічний дисплей (LCD) 1602
- Піроелектричний датчик руху (PIR)
- Керування навантаженням постійного струму
- Функція millis()
- Апаратні переривання
- Цифровий датчик температури
- П’єзодинамік
- Керування кроковими двигунами
- Фоторезистори
- Керування двигунами постійного струму
- Використання адресних світлодіодних стрічок
Платформа Arduino
Arduino – торгова марка апаратно-програмних засобів для побудови простих систем автоматики і робототехніки, орієнтованих на непрофесійних користувачів.
Апаратна частина включає набір змонтованих друкованих плат, що продаються як офіційним виробником, так і сторонніми виробниками. Повністю відкрита архітектура системи дозволяє вільно копіювати або доповнювати лінійку продукції Arduino.
Більшість плат з мікроконтролером забезпечені мінімально необхідним набором компонентів для нормальної роботи мікроконтролера (стабілізатор живлення, кварцовий резонатор, ланцюжки скидання і т.п.).
Мікроконтролери для Arduino відрізняються наявністю попередньо прошитого в них завантажувача. За допомогою цього завантажувача користувач завантажує свою програму в мікроконтролер без використання традиційних окремих апаратних програматорів.
Програмна частина являє собою безкоштовну програмну оболонку для написання програм, їх компіляції та програмування апаратних засобів.
Arduino UNO
Arduino Uno – це широко використовувана плата мікроконтролерів з відкритим кодом на базі мікроконтролера ATmega328P. До її складу входить все необхідне для зручної роботи з мікроконтролером. Для початку роботи з пристроєм досить просто подати живлення від AC/DC-адаптера чи батарейки, або підключити його до комп'ютера за допомогою USB-кабелю.
Кожен з 14 цифрових пінів Arduino Uno може працювати в якості входу або виходу. Рівень напруги на виходах обмежений 5В. Максимальний струм, який може віддавати або споживати один пін, становить 40 мА. Крім цього, деякі піни Аrduino можуть виконувати додаткові функції:
- Послідовний інтерфейс: піни 0 (RX) та 1 (TX). Використовуються для отримання (RX) і передачі (TX) даних по послідовному інтерфейсу. Ці піни з'єднані з відповідними виходами мікросхеми ATmega8U2 (CH340 або FT232 у клонів), яка виконує роль перетворювача USB-UART.
- Зовнішні переривання: піни 2 і 3. Чи можуть служити джерелами переривань, що виникають при високому, низькому або зміні сигналу на них.
- ШІМ (широтно-імпульсна модуляція): піни 3, 5, 6, 9, 10 і 11. За допомогою функції analogWrite() можуть виводити 8-бітні аналогові значення в вигляді ШІМ-сигналу.
Широтно-імпульсна модуляція – процес керування середнім значенням вихідної напруги шляхом зміни тривалості замкнутого стану електронного ключа (пульсуючого увімкнення і вимкнення споживача енергії).
- Світлодіод: 13. Вбудований світлодіод, приєднаний до 13 піна. При відправці значення HIGH світлодіод вмикається, при відправці LOW – вимикається.
В Arduino Uno також є 6 аналогових входів (A0 – A5), кожен з яких може представити аналогову напругу у вигляді 10-бітного числа (1024 значення). За замовчуванням, вимір напруги здійснюється в діапазоні від 0 до 5 В. Проте, верхню межу цього діапазону можна змінити, використовуючи вихід AREF. Крім цього, деякі з аналогових входів мають додаткові функції:
- I2C: вихід A4 або SDA і вихід A5 або SCL. З використанням бібліотеки Wire дані виходи можуть здійснювати зв'язок по інтерфейсу I2C.
Крім перерахованих на платі існує ще кілька виходів:
- AREF. Опорна напруга для аналогових входів.
- Reset. Формування низького рівня (LOW) на цьому виході призведе до перезавантаження мікроконтролера. Зазвичай цей вихід служить для функціонування кнопки скидання на платах розширення.
Arduino Uno може живитися від USB або від зовнішнього джерела живлення – тип джерела вибирається автоматично.
В якості зовнішнього джерела живлення (не USB) може використовуватися мережевий AC/DC-адаптер або акумулятор/батарея. Штекер адаптера (діаметр – 2.1 мм, центральний контакт – позитивний) необхідно вставити у відповідний роз'єм живлення на платі. В разі живлення від акумулятора/батареї, її необхідно під'єднати до виходів GND та VIN.
Напруга зовнішнього джерела живлення може бути в межах від 6 до 20 В. Однак, зменшення напруги живлення нижче 7В призводить до зменшення напруги на виході 5V, що може стати причиною нестабільної роботи пристрою. Використання напруги більше 12В може призводити до перегріву стабілізатора напруги і виходу плати з ладу. З огляду на це, рекомендується використовувати джерело живлення з напругою в діапазоні від 7 до 12В.
Нижче перераховані виходи живлення, розташовані на платі:
- VIN. Напруга, що надходить в Arduino безпосередньо від зовнішнього джерела живлення. Через цей вихід можна як подавати зовнішнє живлення, так і споживати струм, коли пристрій живиться від зовнішнього адаптера.
- 5V. На вихід подається напруга 5В від стабілізатора напруги на платі, незалежно від того, як живиться пристрій: від адаптера (7 – 12В), від USB (5В) або через вихід VIN (7 – 12В). Живити пристрій через вихід 5V або 3V3 не рекомендується, оскільки в цьому випадку не використовується стабілізатор напруги, що може привести до виходу плати з ладу.
- 3V3. 3.3В, що надходять від стабілізатора напруги на платі. Максимальний струм становить 50 мА.
- GND. Вихід землі.
- IOREF. Цей вихід надає платам розширення інформацію про робочу напругу мікроконтролера Arduino. Залежно від напруги, отриманої з виходу IOREF, плата розширення може перейти на відповідне джерело живлення або задіяти перетворювачі рівнів, що дозволить їй працювати як з 5В, так і з 3.3В-пристроями.
Об’єм флеш-пам'яті ATmega328 становить 32 КБ (з яких 0.5 КБ використовуються завантажувачем). Мікроконтролер також має 2 КБ пам'яті SRAM і 1 КБ EEPROM.
Концепція програмування
Мова програмування Arduino є стандартною мовою C++ (використовується компілятор AVR-GCC) з деякими особливостями, які полегшують новачкам написання програм.
Найпростіша Ардуіно-програма складається з двох функцій:
- setup() – функція викликається одноразово при старті мікроконтролера.
- loop() – функція викликається після setup() в нескінченному циклі весь час роботи мікроконтролера.
Прикладом простої програми для платформи Arduino може слугувати код, для мигання вбудованим світлодіодом:
int ledPin = 13; //LED приєднаний до виходу 13
void setup() {
pinMode(ledPin, OUTPUT); //встановлюємо контакт 13 як вихід
}
void loop() {
digitalWrite(ledPin, HIGH); //вмикаємо LED
delay(1000); //пауза 1 секунда
digitalWrite(ledPin, LOW); //вимикаємо LED
delay(1000); //пауза 1 секунда
}
Контролер Arduino вже містить резистор і LED-світлодіод, підключений до 13 виходу, тому ніяких інших зовнішніх радіоелементів не знадобиться.
Для налаштування середовища Arduino IDE з конкретною платформою Arduino – необхідно вибрати назву моделі Arduino та номер присвоєного платі COM-порту.
Для встановлення моделі плати Arduino необхідно зайти в меню: Інструменти – Плата і вибрати плату (наприклад, «Arduino Uno»).
Для вибору номера COM-порту потрібно перейти в меню: Інструменти – Порт і вибрати потрібний порт. Тепер середовище Arduino IDE налаштовано для прошивки плати.
Функція pinMode
pinMode в Arduino допомагає встановити режим роботи піна для виконання операцій зчитування або запису. Як правило, ця функція використовується всередині методу setup() і виконується один раз при запуску програми. Неправильне встановлення режиму входів і виходів Arduino може позначитись на працездатності проекту та плати. Синтаксис функції:
pinMode(pin, type)
Параметр pin вказується порт, який потрібно конфігурувати. Як правило, функція використовується для налаштування цифрових пінів, тому що аналогові піни найчастіше використовуються як вхідні, а вхідний режим використовується Arduino за замовчуванням.
Параметр type вказується тип режиму роботи піна: INPUT, OUTPUT, INPUT_PULLUP.
Для встановлення режиму роботи Arduino в основному використовується два варіанти параметрів: INPUT та OUTPUT. Але іноді при роботі з датчиками потрібно виставити пін в режим з неявно підключеним внутрішнім резистором, тому використовується ще одна константа, яка визначає тип піна INPUT_PULLUP.
Режим INPUT визначає стан піна для роботи з зовнішніми джерелами сигналів (як правило, це різні варіанти датчиків, від яких надходять покази).
В режимі OUTPUT Arduino підтримує пін в стані, при якому на зовнішній пристрій видається максимально можливий струм (плата стає джерелом струму). В цьому режимі зазвичай працюють піни Arduino з підключеними світлодіодами, малопотужними сервоприводами, реле, драйверами двигунів та іншими зовнішніми пристроями.
За замовчуванням, всі піни Arduino встановлені в режим INPUT, тому вказувати це явно не потрібно.
Функція digitalWrite
Функція digitalWrite() – одна з найпопулярніших функцій Arduino. Вона зустрічається практично в будь-якому проекті, де потрібно подати сигнали на підключені пристрої.
Функція дозволяє керувати підключеним обладнанням шляхом подачі або зняття робочої напруги (в більшості випадків – 5В) на піни. Подаючи напругу на підключені пристрої, ми змушуємо їх щось робити: наприклад, вмикати світло, видавати звуки, вмикати двигун. Крім того, за допомогою digitalWrite можна подавати імпульси і передавати інформацію закодованими сигналами і повідомленнями.
Дана функція може сформувати тільки цифровий сигнал в двійковому коді (1 – висока напруга, 0 – низька напруга). На відміну від аналогового сигналу, не можна точно виставити на виході, наприклад, 4,15 вольт. Можливі тільки два значення напруги: мінімальне і максимальне робоче (наприклад, 0 В і 5 В відповідно).
Незважаючи на свою назву, функція може керувати також і аналоговими пінами, виставляючи в них на виході 0 або 5 вольт.
Синтаксис функції:
digitalWrite(pin, value)
pin – будь-який з пінів підключеної плати Arduino.
value – 1 або 0 (краще використовувати константи HIGH і LOW відповідно).
Використання функції delay
Функція delay являється найпростішою командою і її найчастіше використовують новачки. По суті вона робить затримку, яка призупиняє роботу програми, на вказане в дужках число мілісекунд. Максимальне значення може бути рівне 4294967295 мс, що приблизно дорівнює 50 діб.
Підключення світлодіода
Світлодіод – це напівпровідниковий прилад, який створює оптичне випромінювання при пропусканні через нього електричного струму. Світлодіод випромінює світло тільки при проходженні струму в прямому напрямку, завдяки чому при його підключенні необхідно дотримуватись полярності. При цьому сила випромінювання безпосередньо залежить від сили струму. Однак не можна перевищувати максимально допустимий струм, встановлений для світлодіода його характеристиками, інакше світлодіод вийде з ладу.
Також світлодіод характеризується падінням напруги при проходженні струму в прямому напрямку. Падіння напруги істотно вище ніж у звичайних діодів і становить 2-3 вольта, в залежності від кольору світлодіода. Це означає, що світлодіод не буде світитися якщо подана на нього напруга менша цього значення. Але якщо на світлодіод подати більшу напругу, то через нього потече максимально можливий струм, і світлодіод вийде з ладу. Що б цього не сталося світлодіод необхідно підключати через струмообмежуючий резистор.
Розрахунок опору струмообмежувального резистора проводиться за наступною формулою:
Rсв = (Vкер - Vсв)/Iсв;
Vкер – напруга керування, це напруга на виході мікроконтролера, рівна 5 В;
Vсв – падіння напруги на світлодіоді, вказане в характеристиках;
Iсв – сила струму світлодіода, зазначена в характеристиках, зазвичай в межах 10-20 мА.
Для звичайних світлодіодів падіння напруги становить 2 В і рекомендований струм світіння 15 мА. При підключенні до виходу Arduino, живиться від напруги 5 В:
Rсв = (5 - 2) / 0.015 = 200 Ом;
З урахуванням допуску можна використовувати резистори номіналом 220 Ом.
Використання керуючих елементів, перемикачів
Кнопка (або перемикач) – найпростіший і найдоступніший з усіх видів датчиків. Натиснувши на неї, ви подаєте контролеру сигнал, який потім призводить до виконання певних дій: вмикаються світлодіоди, видаються звуки, запускаються двигуни.
Кнопка – це пристрій, що замикає й розмикає електричну мережу. Виконувати це замикання/розмикання можна в різних режимах. Відповідно, всі кнопки можна поділити на дві великі групи:
- Кнопки-перемикачі з фіксацією – вони фіксуються і залишаються в тому положенні, в якому їх залишили.
- Кнопки без фіксації (тактові кнопки) – вони повертаються в початковий стан після того, як їх відпустили. В залежності від початкового стану поділяють на нормально-замкнуті і нормально-розімкнуті кнопки.
Найчастіше в проектах використовуються прості тактові кнопки з 4 ніжками. Кнопка є перемикачем з двома парами контактів. Контакти в одній парі з'єднані між собою, тому більше одного вимикача в схемі реалізувати не вийде, але можна одночасно керувати двома паралельними сегментами, що деколи буває корисно.
Зазвичай, перший раз, кнопку намагаються підключити наступним чином:
Це НЕПРАВИЛЬНЕ підключення!
Справа в тому, що пін мікроконтролера (в режимі входу) повинен мати заздалегідь відомий стан (1 або 0).
У «підвішеному» стані він буде збирати зовнішні наводки (статичні, електричні і електромагнітні випромінювання). Щоб привести пін в заздалегідь відомий стан використовують підтягуючі резистори.
Вони бувають двох видів: верхні (pull-up) підключаються до плюса живлення і нижні (pull-down) – до мінуса.
Саме тому підключати кнопку до Arduino потрібно так, щоб можна було зчитувати в скетчі її стан. Для цього використовується схема, представлена нижче:
Слід звернути увагу на резистор 10 кОм, який використовується в цій схемі.
В даному випадку, коли кнопка відключена, пін буде підключений до землі через резистор, опір якого є менший за внутрішній опір піна. Наводка, що потрапила на пін, піде в землю. Якщо ж підключений корисний сигнал (+ 5В) то він буде «стікати» в пін (незначна частина сигналу піде в землю через підтяжку).
В підсумку, при натисненій кнопці, у нас буде стабільний сигнал (+5В), а при відпущеній кнопці – стабільний нуль.
Розглянемо простий програмний приклад, який вмикатиме вбудований світлодіод, коли кнопка натиснена:
void setup() {
pinMode(13, OUTPUT);
}
void loop() {
if (digitalRead(14) == HIGH){ //якщо кнопка натиснута
digitalWrite(13, HIGH); //вмикаємо світлодіод
} else { //якщо не натиснена...
digitalWrite(13, LOW); //вимикаємо
}
}
Функція digitalRead()
Функція призначена для зчитування значення з заданого входу – HIGH або LOW. Синтаксис функції:
digitalRead(pin)
де pin – номер входу/виходу, з якого буде зчитано сигнал.
Аналогові входи також можуть бути використані як цифрові входи. Звернення до них відбувається за номерами від 14 (для аналогового входу 0) до 19 (для аналогового входу 5).
Внутрішній підтягуючий резистор
В мікроконтролерах ATmega168 та ATmega328 є внутрішні підтягуючі резистори. Вони мають номінал 20 кОм і включаються програмно. Потрібно мати на увазі що внутрішня підтяжка прив’язує пін тільки до +5В. У зв'язку з цим потрібно інвертувати логіку.
В раніше розглянутому прикладі одна нога кнопки підключена до +5В, друга до піну, а пін до GND (через зовнішню підтяжку). З внутрішньої підтяжкою все навпаки.
Одна нога кнопки підключається до GND, інша до піну (ніяких зовнішніх резисторів не потрібно).
В якості режиму роботи піну потрібно встановити INPUT_PULLUP в функції pinMode. У цьому випадку 1 на цифровому вході означає відсутність сигналу а 0 – його наявність.
Використання потенціометрів
Потенціометр – це резистор з трьома виходами, один із яких рухомий, що використовується, як дільник напруги.
Електричний струм проходить між кінцевими контактами, а потрібна споживачеві напруга знімається з повзунка, положення якого можна механічно змінювати.
Потенціометри використовуються в якості регуляторів параметрів (гучності звуку, потужності, вихідної напруги і т.д.). Також потенціометри можна використовувати як змінний резистор, задіюючи лише два виходи – один із кінцевих і повзунок.
Підключення потенціометра до Arduino виконується відповідно до наступної схеми:
Для цього три виходи потенціометра необхідно з'єднати з зазначеними виходами плати:
- Чорний – GND;
- Червоний – живлення 5В;
- Зелений – від центрального виходу до аналогового входу (наприклад, А0).
Змінюючи положення ротора підключеного потенціометра, відбувається зміна параметру опору, яка викликає зміна показника на нульовому піні плати Arduino.
Мікроконтролер на платі Arduino має вбудований аналого-цифровий перетворювач, здатний зчитувати напругу і переводити його в цифрові показники зі значенням від нуля до 1023. При повороті ручки до кінцевого положення в одному з двох можливих напрямків, напруга на виході дорівнює нулю, а, отже, напруга, яке буде генеруватися становить 0 В. При повороті ротора до кінця в протилежному напрямку на пін надходить напруга величиною 5В, а значить числове значення становитиме 1023.
Розглянемо приклад скетчу, за допомогою якого здійснюється регулювання яскравості підключеного до Arduino світлодіоду за допомогою потенціометра:
#define led 11 //пін підключення світлодіода
#define pot A0 //пін підключення потенціометра
void setup() {
pinMode(led, OUTPUT);
}
void loop() {
int rotate, bright; //визначаємо змінні типу int
rotate = analogRead(pot); // отримуємо значення з потенціометра
bright = rotat / 4; //перетворюємо 10-бітне значення у 8-бітне
analogWrite(led, bright); // задаємо яскравість світлодіода
}
Директива #define
#define це зручна директива, який дозволяє задати ім'я константі перед тим як програма буде скомпільована. Визначені цією директивою константи не займають програмної пам'яті (на відміну від використання змінних), оскільки компілятор замінює всі звернення до них їх значеннями на етапі компіляції, відповідно вони служать виключно для зручності програміста. Синтаксис:
#define constantName value
Компілятор замінить будь-яке згадування constantName в тексті програми на значення value.
Функція analogRead()
Функція зчитує величину напруги з зазначеного аналогового входу. У складі Arduino є 6-канальний (8-канальний – в Mini та Nano, 16 – в Mega) 10-бітний аналогово-цифровий перетворювач, який перетворює вхідну напругу з діапазону від 0 до 5В в цілочисельні значення в межах від 0 до 1023 відповідно. Синтаксис функції:
analogRead(pin)
де pin – номер аналогового входу, з якого буде зчитуватися напруга.
Функція analogWrite()
Функція формує задану аналогову напругу на виході у вигляді ШІМ-сигналу. Може використовуватися для зміни яскравості світлодіода або керування швидкістю обертання двигуна. Після виклику analogWrite(), на виході буде безперервно генеруватися ШІМ-сигнал з заданим коефіцієнтом заповнення до наступного виклику функції analogWrite() (або до моменту виклику digitalRead() або digitalWrite()) на цьому ж виході.
На більшості плат Arduino (на базі мікроконтролерів ATmega168 або ATmega328) функція analogWrite() працює з виходами 3, 5, 6, 9, 10 і 11. На Arduino Mega функція працює з виходами з 2 по 13.
При роботі з analogWrite() попередній виклик функції pinMode() для перемикання пінів в режим «вихід» не потрібний.
Функція analogWrite() не має нічого спільного з аналоговими входами і функцією analogRead(). Синтаксис функції:
analogWrite(pin, value)
pin – вихід, на якому буде формуватися напругу.
value – коефіцієнт заповнення (лежить в межах від 0 до 255).
RGB-світлодіоди
Триколірний світлодіод або RGB-світлодіод – це поєднані в одному корпусі світлодіоди червоного, зеленого та синього кольорів.
Світлодіод має 4 контакти: 3 аноди, що відповідають окремим кольорам та один загальний катод (або 3 катоди та один спільний анод). Подаючи сигнал на один з анодів, можна отримати один з кольорів. Використовуючи ШІМ (PWM-сигнал) для всіх анодів одночасно, можна отримати світіння довільним кольором.
Загальний катод на RGB-світлодіоді – другий за рахунком, найдовший контакт. Цей контакт підключається до землі (GND).
Для кожного світлодіода потрібен власний резистор на 220 Ом, щоб запобігти можливості протікання надто великих струмів. Ці резистори встановлюються в ланцюг між анодом (червоний, зелений і синій) і керуючими пінами (ШІМ) на Arduino.
Послідовний інтерфейс обміну даними
Послідовний інтерфейс (Serial Interface) – двонаправлений канал зв’язку, призначений для обміну байтовою інформацією. Послідовний тому, що інформація через нього передається по одному біту, біт за бітом. Найчастіше використовується для зв'язку з апаратними засобами обчислювальних систем.
Клас Serial
Клас Serial використовується для зв'язку плати Arduino з комп'ютером або іншими пристроями. Всі плати Arduino мають, принаймні, один послідовний інтерфейс (також відомий як UART або USART): Serial. Він прив’язаний до цифрових виходів 0 (RX) та 1 (TX), а також використовується для зв'язку з комп'ютером через USB. Таким чином, під час використання послідовного порту, піни 0 і 1 не можуть використовуватися в якості цифрових входів або виходів.
Для зв’язку з Arduino можна використовувати спеціальну програму моніторингу послідовного порту, вбудовану в програмне забезпечення Arduino. Для виклику програми потрібно натиснути відповідну кнопку на панелі інструментів та встановити ту ж швидкість передачі, що вказується в програмі при виклику методу begin().
Arduino Mega має три додаткових послідовних порти: Serial1 з виходами 19 (RX) та 18 (TX), Serial2 з виходами 17 (RX) та 16 (TX), Serial3 з виходами 15 (RX) та 14 (TX).
Функції Serial.begin() та Serial.end()
Функція Serial.begin() ініціює послідовне з’єднання і задає швидкість передачі даних в біт/c (бод). Для обміну даними з комп'ютером використовуються наступні значення: 300, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600 або 115200. При з'єднання через порти входу/виходу 0 і 1 можуть бути використані і інші значення швидкості, необхідні пристрою з яким буде здійснюватися обмін даними. Синтаксис функції:
Serial.begin(speed)
де speed – швидкість в біт/c (бод).
Функція Serial.end() закриває послідовне з'єднання, порти RX і TX звільняються і можуть бути використані для введення/виведення.
Функція Serial.available()
Функція отримує кількість байт (символів) доступних для читання з послідовного інтерфейсу зв’язку. Це ті байти, які вже надійшли і записані в буфер послідовного порту. Буфер може зберігати до 64 байт.
Функція не приймає жодних параметрів, однак повертає кількість байт, доступних до читання.
Функція Serial.read()
Функція зчитує черговий доступний байт з буферу послідовного з'єднання. Функція не приймає жодних параметрів, але повертає доступний байт або значення -1, якщо його немає.
Функції Serial.print(), Serial.println(), Serial.write()
Функція передає дані через послідовний порт як ASCII текст. Ця функція може приймати різні типи даних. Так цілі числа виводяться відповідними їм символами ASCII. Дійсні числа виводяться за допомогою двох ASCII символів, для цілої і дробової частини. Байти передаються як символ з відповідним номером. Симоволи і рядки відсилаються як є. Приклад:
Serial.print(78) передається як "78"
Serial.print(1.23456) передається як "1.23"
Serial.print(byte(78)) передається як "N" (в таблиці ASCII "N" під 78 номером)
Serial.print('N') передається як "N"
Serial.print("Hello world.") Передається як "Hello world."
За допомогою другого опціонально параметра можна задати базис (систему числення) для чисел. Допустимі значення BIN (двійковий), OCT (вісімковий), DEC (десятковий), HEX (шістнадцятковий). Для дійсних (дрібних) чисел другий параметр задає кількість знаків після коми. Приклад:
Serial.print(78, BIN) виводить "1001110"
Serial.print(78, OCT) виводить "116"
Serial.print(78, DEC) виводить "78"
Serial.print(78, HEX) виводить "4E"
Serial.print(1.23456, 0) виводить "1"
Serial.print(1.23456, 2) виводить "1.23"
Serial.print(1.23456, 4) виводить "1.2346"
Функція Serial.println() повністю аналогічна функції Serial.print(), але передає дані через послідовне з'єднання з наступним за ним символом розриву рядків (ASCII символ 13 або ‘\r’) і символом нового рядка (ASCII 10 або ‘\n’).
Функція Serial.write() передає дані як бінарний код через послідовне з'єднання. Дані відправляються як один або серія байтів. Для того, щоб передати дані як символи слід використовувати функцію print().
Розглянемо приклад використання послідовного інтерфейсу:
void setup() {
Serial.begin(9600); //відкриваємо з'єднання з швидкістю 9600 біт/с
}
void loop() {
if (Serial.available() > 0) { //перевіряємо об'єм буферу вхідних даних
int inByte = Serial.read(); //зчитуємо черговий байт даних
Serial.println(inByte); //передаємо отримане раніше значення
}
}
Аналоговий датчик температури TMP36
Аналоговий датчик температури TMP36 простий в освоєнні, дешевий і при цьому дозволяє в режимі реального часу контролювати температуру навколишнього середовища.
В цих датчиках немає рухомих частин, вони точні, практично не зношуються, не вимагають калібрування, можуть працювати в різних несприятливих умовах.
Діапазон вимірюваних температур: від -40 °C до 150 °C.
Діапазон сигналу на виході: від 0.1В (-40 °C) до 2.0В (150 °C), але точність падає після 125 °C.
Для використання TMP36 достатньо підключити лівий вихід до джерела живлення (2.7 – 5.5В), правий ¬– до землі, а з середнього виходу ми будемо знімати аналогове значення напруги, яке прямо пропорційне температурі. Значення аналогової напруги не залежить від джерела живлення.
Для перетворення напруги в температуру використовується залежність:
Температура в °C = [(Вихідна напруга в мВ) – 500] / 10
Тобто, наприклад, якщо напруга на виході дорівнює 1 В, температура рівна:
((1000 мВ – 500) / 10) = 50 °C
Якщо використовується вихід 5В Arduino, можна використовувати наступні формули для перетворення 10-бітових аналогових значень в температуру:
Напруга на піні в мілівольтах = (значення з аналогового піна) * (5000 / 1024)
За допомогою цієї залежності числове значення в діапазоні 0–1023 з аналогового піна перетворюється в 0 – 5000 мілівольт.
Використання бібліотек
В певний момент часу, при освоєнні середовища Arduino IDE виникає необхідність розширити можливості за допомогою використання додаткових бібліотек.
Бібліотека – це набір функцій, призначених для того, щоб максимально спростити роботу з різними датчиками, РК-екранами, модулями та ін. Наприклад, вбудована бібліотека LiquidCrystal дозволяє доволі просто взаємодіяти з символьними LCD-дисплеями. Існують сотні додаткових бібліотек, які можна завантажити з мережі Інтернет. Але перед тим, як використовувати додаткові бібліотеки, необхідно спершу їх встановити.
Встановлення сторонніх бібліотек
Найчастіше бібліотеки доступні у вигляді ZIP-архіву або просто папки. Назва цієї папки є назвою бібліотеки. Всередині папки буде файл з розширенням .cpp, файл з розширенням .h, а також текстовий файл keywords.txt, папка з прикладами examples та інші файли, необхідні бібліотеці.
Починаючи з версії Arduino IDE 1.0.5, встановлювати сторонні бібліотеки можна прямо в середовищі розробки. Розпаковувати при цьому архів не потрібно.
В середовищі розробки потрібно вибрати пункт меню Скетч – Включити бібліотеку – Додати .ZIP-бібліотеку...
З'явиться діалогове вікно, яке запропонує вибрати бібліотеку, яку потрібно додати. Потрібно лише перейти до завантаженого zip-файлу та відкрити його.
Якщо тепер знову відкрити меню Скетч – Включити бібліотеку, додана бібліотека вже буде в самому низу списку. Тепер бібліотеку можна використовувати в програмах.
Після перезавантаження середовища приклади з встановленої бібліотеки з'являться в меню Файл – Приклади.
Керування сервоприводами
Сервопривід – це двигун, положенням валу якого можна керувати. Від звичайного двигуна він відрізняється тим, що йому можна точно в градусах задати положення, в яке стане вал. Сервоприводи використовуються для моделювання різних механічних рухів.
Конструкція сервоприводу складається з двигуна, датчика позиціонування і керуючої системи. Сервоприводи нерідко використовуються в таких сферах як обробка матеріалів, виробництво транспортного устаткування, обробка деревини, виготовлення металевих листів, виробництво будматеріалів та інші.
Принцип роботи сервоприводу заснований на зворотному зв'язку з одним або декількома системними сигналами. Найпростішим варіантів реалізації датчика позиціонування є потенціометр, який керується вихідним валом – при зміні параметрів резистора змінюються параметри струму, що живить двигун.
Виділяють два основних види серводвигунів – з безперервним обертанням та з фіксованим кутом (найчастіше, 180 або 270 градусів). Відмінність сервоприводів обмеженого обертання полягає в механічних елементах конструкції, які можуть блокувати рух валу поза межами заданих параметрами кутів. Досягнувши кута 180°, вал вплине на обмежувач, а той «віддасть» команду на вимикання двигуна. У серводвигунів безперервного обертання таких обмежувачів немає.
Широке використання сервоприводів пов'язано з тим, що вони володіють стабільною роботою, високою стійкістю до перешкод, малими габаритами і широким діапазоном регулювання швидкості. Важливими особливостями сервоприводів є здатність збільшувати потужність і забезпечення зворотного інформаційного зв'язку.
Зазвичай сервопривід має три контакти різних кольорів. Коричневий провід підключається до землі, червоний – до живлення +5В, провід оранжевого або жовтого кольору – сигнальний. Помаранчевий провід (сигнальний) підключається до цифрового ШІМ-піну.
Для того, щоб спростити керування сервоприводом за допомогою Arduino, використовується вбудована бібліотека Servo. Розглянемо простий приклад використання Servo:
#include <Servo.h> //підключення бібліотеки Servo
Servo servo; //створення об’єкту класу Servo
void setup() {
servo.attach(6); //вибір піна підключення сервопривода
servo.write(0); //встановлення початкового положення 0°
}
void loop() {
servo.write(90); //поворот валу на 90°
delay(1000); //затримка 1 секунду
servo.write(135); //поворот валу на 135°
delay(100);
servo.write(180); //поворот валу на 180°
delay(1000);
servo.write(0);
delay(1000);
}
Директива #include
#include використовується для підключення сторонніх бібліотек в код програми. Це дає доступ до великої кількості стандартних бібліотек С (бібліотекою називають групи попередньо написаних функцій), і бібліотек написаних спеціально для Arduino.
Варто звернути увагу на те, що #include, так само як і #define, не вимагає крапки з комою в кінці рядка, якщо ж її додати компілятор видасть критичну помилку.
Бібліотека Servo
Ця бібліотека надає набір функцій для керування сервоприводами. Стандартні сервоприводи дозволяють повертати привід на визначений кут від 0 до 180 градусів, зазвичай. Деякі сервоприводи дозволяють здійснювати повні оберти на заданій швидкості.
Основні функції:
- attach(pin) – підключає Servo до зазначеного виходу, з якого здійснюється керування приводом;
- write(angle) – передає значення для керування приводом. Для стандартного сервоприводу це кут повороту. Для приводу постійного обертання, функція задає швидкість обертання (0 – для максимальної швидкості обертання в одну сторону, 180 – для максимальної швидкості в іншу сторону і близько 90 для нерухомого стану);
- read() – зчитує значення поточного положення сервоприводу.
Семисегментний світлодіодний індикатор
Семисегментний індикатор – пристрій відображення цифрової інформації. Семисегментний індикатор, як зрозуміло з його назви, складається з семи елементів індикації (сегментів), що вмикаються і вимикаються окремо. Вмикаючи їх в різних комбінаціях, з них можна скласти спрощені зображення арабських цифр.
Сегменти позначаються літерами від A до G; восьмий сегмент – десяткова точка (decimal point, DP), призначена для відображення дробових чисел.
В сучасних індикаторах світлодіоди виготовляють у формі сегментів, тому світлодіодні індикатори мають гранично просту, уніфіковану форму: чим менше різних світлодіодів, тим дешевший пристрій.
У звичайному світлодіодному індикаторі дев'ять виходів: один іде до катодів всіх сегментів, а інші вісім – до аноду кожного з сегментів. Ця схема називається «схема із загальним катодом», існують також схеми із загальним анодом. Часто роблять не один, а два загальні виходи на різних кінцях цоколя.
Для підключення семисегментного індикатора до Arduino напряму, підходять лише індикатори із загальним катодом.
Згідно схеми, сегмент анод сегмента A під’єднується до 2 піна Arduino, сегмент B – до 3 і т.д., через резистор номіналом 220 Ом.
Однак така схема підключення доволі незручна: задіюється велика кількість виходів (і це лише для одного такого індикатора), для керування таким індикатором потрібно прописувати велику кількість команд (кожен сегмент виступає як окремий світлодіод і потрібно керувати одночасно всіма 8 такими світлодіодами).
Для реалізації більш простої схеми підключення та зручнішого керування використовується регістр зсуву.
74HC595 – восьмирозрядний регістр зсуву з послідовним введеням, послідовним або паралельним виведенням інформації, з тригером і трьома станами на виході.
Іншими словами цей регістр дозволяє контролювати 8 виходів, використовуючи всього кілька виходів на самому контролері. При цьому кілька таких регістрів можна об'єднувати послідовно для каскадування.
В даній схемі використовується принцип синхронізованої послідовної передачі сигналів. Необхідні значення сигналу (біти HIGH або LOW) передаються в регістр один за іншим у вигляді 1 байта інформації (8 послідовних біт).
Нижче зображено схему розміщення виходів регістра зсуву 74HC595:
Розглянемо схему підключення до Arduino семисегментного індикатора із загальним анодом через регістр зсуву 74HC595:
- виходи GND (8) та OE (13) підключаються на землю;
- виходи Vcc (16) та MR (10) підключаються до піна 5V (через резистор);
- вихід DS (14) підключається до 8 цифрового піна;
- вихід SH_CP (11) підключається до 10 цифрового піна;
- вихід ST_CP (12) підключається до 9 цифрового піна;
- вихід Common індикатора підключається до піна 5V (через резистор);
- - виходи сегментів індикатора підключаються до відповідних паралельних виходів регістра (A – Q0, B – Q1, …, DP – Q7) через резистори 560 Ом.
Для відправки інформації на індикатор у вигляді двійкового коду через регістр, зручно використовувати таблицю сумісності, де 0 – означають, що сегмент буде світитись, а 1 – не буде (із загальним катодом – навпаки).
| Цифра | Сегмент | |||||||
|---|---|---|---|---|---|---|---|---|
| A | B | C | D | E | F | G | DP | |
| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
| 1 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 |
| 2 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 1 |
| 3 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 1 |
| 4 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | 1 |
| 5 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 1 |
| 6 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 |
| 7 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 |
| 8 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
| 9 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 |
Відправляючи таку послідовність бітів на регістр зсуву, отримуємо необхідний результат.
Розглянемо приклад коду, який використовується для виведення на індикатор послідовно всіх цифр від 0 до 9:
int SH_CP = 10; //пін підключення виходу SH_CP
int ST_CP = 9; //пін підключення виходу ST_CP
int DS = 8; //пін підключення виходу DS
static uint8_t digit[10] = { //масив бітових послідовностей для цифр
0b00000011, // 0
0b10011111, // 1
0b00100101, // 2
0b00001101, // 3
0b10011001, // 4
0b01001001, // 5
0b01000001, // 6
0b00011111, // 7
0b00000001, // 8
0b00001001 // 9
};
void setup() {
pinMode(SH_CP, OUTPUT);
pinMode(ST_CP, OUTPUT);
pinMode(DS, OUTPUT);
}
void loop() {
for (int i = 0; i < 10; i++) { //послідовна відправка значень масиву на регістр
digitalWrite(ST_CP, LOW); //виклик початку прийому даних
shiftOut(DS, SH_CP, LSBFIRST, digit[i]); //передача даних на вихід DS
digitalWrite(ST_CP, HIGH); //завершення прийому
delay(1000);
}
}
Для того, щоб під’єднати кілька індикаторів підряд, задіюються додаткові регістри зсуву. Схема підключення залишається такою ж, однак вихід DS регістра для передачі підключається вже не до Arduino, а до «старшого регістра» (пін Q7S), як показано на схемі.
Програмно зміни незначні: потрібно лише відправляти дані спочатку на «молодший» регістр, а потім на «старший»:
void loop() {
for (int i = 0; i < 100; i++) { //перебір значень від 0 до 99 (менше 100)
digitalWrite(ST_CP, LOW); //виклик початку прийому даних
int od = i % 10; //знаходження остачі від ділення на 10 (одиниці)
int des = i / 10; //знаходження цілої частини від ділення на 10 (десятки)
shiftOut(DS, SH_CP, LSBFIRST, digit[od]); //"молодший" регістр (одиниці)
shiftOut(DS, SH_CP, LSBFIRST, digit[des]); //"старший" регістр (десятки)
digitalWrite(ST_CP, HIGH); //завершення прийому
delay(1000);
}
}
Конструкція for
Конструкція for використовується для повторення блоку операторів, заключених у фігурні дужки. Оператор for підходить для будь-яких дій, що повторюються і часто використовується в поєднанні з масивами колекцій даних.
Заголовок циклу for складається з трьох частин:
for (initialization; condition; increment) {оператори, що виконуються в циклі}
Ініціалізація (initialization) виконується з самого початку та всього один раз. Кожен раз в циклі перевіряється умова (condition), якщо вона вірна, виконується блок операторів і приріст (increment), потім умова перевіряється знову. Коли логічне значення умови стає хибним, цикл завершується.
Наприклад, для організації циклу, який буде виконуватись 10 разів необхідно записати наступний код:
for (int i = 0; i < 10; i++)
де int i = 0 – оголошення змінної i та присвоєння їй значення рівного 0;
i < 10 – задання умови (поки значення i буде меншим 10);
i++ – збільшення значення змінної i на 1.
Функція shiftOut()
Функція виводить байт інформації на порт вводу/виводу послідовно (побітово). Виведення може здійснюватися як з першого (лівого), так і з останнього (правого) біта. Кожен біт послідовно подається на заданий порт, після чого подається сигнал на синхронізуючий порт вводу/виводу, інформуючи про доступність зчитування біта.
Такий спосіб передачі даних називають послідовним протоколом з синхронізацією. Він часто використовується для взаємодії мікроконтролерів з датчиками і сенсорами, а також іншими мікроконтролерами. Послідовна передача з синхронізацією дозволяє пристроям зв'язуватися на максимальній швидкості. Синтаксис функції:
shiftOut (dataPin, clockPin, bitOrder, value)
dataPin: номер порту вводу/виводу, на який виводяться біти (int);
clockPin: номер порту, за яким здійснюється синхронізація (int);
bitOrder: використовувана послідовність виведення бітів. MSBFIRST (Most Significant Bit First) – зліва чи LSBFIRST (Least Significant Bit First) – справа;
value: значення для виведення (byte).
Використання ультразвукового далекоміра
Далекомір – це пристрій для вимірювання відстані до деякого предмету. Далекомір використовується в різних ситуаціях. Простий колісний робот може використовувати цей прилад для виявлення перешкод. Літаючий дрон використовує далекомір для польоту над землею на заданій висоті. За допомогою далекоміра можна навіть побудувати карту приміщення, застосувавши спеціальний алгоритм SLAM.
Принцип роботи далекомірів
Розглянемо принцип роботи одного з найпопулярніших датчиків – ультразвукового (УЗ) далекоміра. Існує багато різних модифікацій подібних пристроїв, але всі вони працюють за принципом вимірювання часу проходження відбитого звуку. Тобто датчик відправляє звуковий сигнал в заданому напрямку, потім ловить відбите відлуння і обчислює час польоту звуку від датчика до перешкоди і назад.
Швидкість звуку в деякому середовищі величина постійна. Знаючи швидкість звуку в повітрі і час польоту звуку до перешкоди, можна розрахувати пройдену звуком відстань за формулою:
S = v ⋅ t
де v – швидкість звуку в м/с, а t – час в секундах.
Щоб впоратися зі своїм завданням, далекомір має дві важливі конструктивні особливості. По-перше, щоб звук добре відбивався від перешкод, датчик випускає ультразвук з частотою 40 кГц. Для цього в датчику є п'єзокерамічний випромінювач, який здатний генерувати звук такої високої частоти. По-друге, випромінювач влаштований таким чином, що звук поширюється не на всі боки (як це буває у звичайних динаміків), а у вузькому напрямку. Нижче представлена діаграма спрямованості типового УЗ далекоміра.
Як видно з діаграми, кут огляду самого простого УЗ далекоміра становить приблизно 50-60 градусів. Для типового варіанту використання, коли датчик визначає перешкоди перед собою, такий кут огляду цілком прийнятний.
Також варто зазначити два серйозні недоліки УЗ далекоміра. Перший полягає в тому, що поверхні, які мають пористу структуру добре поглинають ультразвук, і датчик не може виміряти відстань до них. Такі ж проблеми виникають при вимірюванні відстані до стіни покритої поролоном. Другий недолік пов'язаний зі швидкістю звукової хвилі. Ця швидкість недостатньо висока, щоб вимірювати відстань до об’єктів, що швидко рухаються.
Ультразвуковий далекомір HC-SR04
Далекомір HC-SR04 є найдешевшим далекоміром для використання в любительських проектах. При малій ціні має непогані характеристики, здатний вимірювати відстань в діапазоні від 2 до 450см з точністю 0.5 – 1 см.
Принцип роботи датчика можна умовно розділити на 4 етапи:
- Подача імпульсу тривалістю 10 мкс, на вихід Trig.
- Всередині далекоміра вхідний імпульс перетворюється в 8 імпульсів частотою 40 кГц і надсилається вперед через передавач.
- Дійшовши до перешкоди, послані імпульси відбиваються і потрапляють на приймач. Отримується вихідний сигнал на виході Echo.
- Безпосередньо на стороні контролера отриманий сигнал переводиться у відстань за формулою:
ширина імпульсу (мкс) / 58 = дистанція (см)
Модуль підключається за допомогою чотирьох провідників. Контакти VCC та GND служать для підключення живлення, а Trig та Echo – для відправки та прийому сигналів далекоміра, підключивши їх, наприклад до 2 та 3 пінів плати Arduino.
Код скетчу для отримання даних з далекоміра та передача їх через послідовний інтерфейс:
int echoPin = 2; //пін Echo дальноміра
int trigPin = 3; //пін Trig дальноміра
int duration, cm; //змінні для проміжних обрахунків
void setup() {
Serial.begin(9600); //встановлення пслідовного з'єднання
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
}
void loop() {
digitalWrite(trigPin, HIGH); //початок передачі імпульсу
delayMicroseconds(10); //затримка в 40 мкс
digitalWrite(trigPin, LOW); //завершення передачі
duration = pulseIn(echoPin, HIGH); //отримання довжини імпульсу
cm = duration / 58; //розрахунок відстані
Serial.print(cm); //виведення значення довжини
delay(100);
}
Функція delayMicroseconds() зупиняє виконання програми на задану в параметрі кількість мікросекунд. Максимальна пауза, яка коректно відтворюється – 16383. Для зупинки виконання програми більш ніж на кілька тисяч мікросекунд рекомендується використовувати функцію delay().
Функція pulseIn()
Функція зчитує довжину сигналу на заданому вході (HIGH або LOW). Наприклад, якщо задано зчитування HIGH функцією pulseIn(), функція чекає поки на заданому порту не з'явилося HIGH. Коли HIGH отримано, включається таймер, який буде зупинений коли на вході буде LOW. Функція pulseIn() повертає довжину сигналу в мікросекундах. Функція повертає 0, якщо протягом заданого часу (таймауту) не зафіксований сигнал на вході.
Можливі деякі похибки в вимірюванні довгих сигналів. Функція може вимірювати сигнали довжиною від 10 мікросекунд до 3 хвилин. Синтаксис функції:
pulseIn(pin, value)
pulseIn(pin, value, timeout)
де pin – номер входу, на якому буде очікуватися сигнал;
value – тип очікуваного сигналу (HIGH або LOW);
timeout (опціонально) – час очікування сигналу (таймаут) в мікросекундах; за замовчуванням – одна секунда.
Рідкокристалічний дисплей (LCD) 1602
LCD-дисплей 1602 використовується для роботи з Arduino. Має два рядки по 16 символів в кожному. Працює зі стандартною бібліотекою LiquidCrystal, що йде в комплекті з Arduino IDE.
Технічні характеристики:
- розміри: 80 x 36 мм;
- розмір символу: 4.35 x 2.95мм;
- розміри точки: 0.5 x 0.5мм;
- інтерфейс: HD44780;
- видима область: 64.5 x 13.8мм;
- живлення: 5В.
Дані дисплеї мають два варіанти виконання: жовта підсвітка з чорними символами та синя підсвітка з білими символами (зустрічається частіше). Існують також дисплеї для виведення 4 рядків по 20 символів.
Більшість дисплеїв не мають підтримки кирилиці, мають її лише дисплеї з маркуванням CTK. Однак цю проблему можна частково вирішити, використовуючи власні символи.
Дисплей має 16 контактів для підключення:
- 1 (VSS) – живлення контролера (-);
- 2 (VDD) – живлення контролера (+);
- 3 (VO) – вихід керування контрастом;
- 4 (RS) – вибір регістру;
- 5 (R/W) – читання/запис (режим запису при з'єднанні з землею);
- 6 (E) – Еnable;
- 7-10 (DB0-DB3) – молодші біти 8-бітного інтерфейсу;
- 11-14 (DB4-DB7) – старші біти інтерфейсу;
- 15 (A) – анод (+) живлення підсвітки;
- 16 (K) – катод (-) живлення підсвітки.
Для налаштування контрастності слід використовувати потенціометр на 10 кОм. Крайні контакти потенціометра з’єднуються з виходами +5V та GND, центральний контакт з'єднується з виходом VO.
Після подачі живлення на схему необхідно налаштувати правильний контраст, якщо він буде налаштований не вірно, то на екрані нічого не буде відображатися. Налаштування контрасту здійснюється потенціометром.
Сам же дисплей може працювати в двох режимах:
- 8-бітний режим – для цього використовуються і молодші і старші біти (BB0–DB7);
- 4-бітний режим – для цього використовуються і тільки молодші біти (BB4–DB7).
Використання 8-бітного режиму на даному дисплеї не доцільно. Для його роботи потрібно на 4 контакти більше, а виграшу у швидкості практично немає.
Для виведення тексту необхідно підключити контакти RS, E, DB4, DB5, DB6, DB7 до виходів контролера. Їх можна підключати до будь-яких виходів Arduino, головне в коді задати правильну послідовність.
Код програми, яка виводить на екран дисплею надпис «Hello, world!»:
#include <LiquidCrystal.h>
LiquidCrystal lcd(2, 3, 4, 5, 6, 7); //вказуємо виходи RS, E, DB4, DB5, DB6, DB7
void setup() {
lcd.begin(16, 2); //задаємо розмірність дисплею
lcd.setCursor(0, 0); //встановлюємо курсор на початок першого рядка
lcd.print("Hello, world!"); //виводим текст
}
void loop(){}
Літери англійського алфавіту зашиті в пам'ять контролера дисплею. Однак існує можливість необхідний символ зробити вручну (всього до 8-ми символів).
Комірка для відображення символу має розширення 5х8 точок. Задача по створенню символу зводиться до того, щоб написати бітову маску і розставити в ній одинички в місцях де повинні світитись точки. У нижче наведеному прикладі прикладі показано яким чином формується смайлик.
Залишається перенести бітову маску в код програми та передати її в пам’ять контролера дисплею.
#include <LiquidCrystal.h>
byte smile[8] = //бітова маска смайлика
{
B00010,
B00001,
B11001,
B00001,
B11001,
B00001,
B00010,
};
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);
void setup(){
lcd.begin(16, 2);
lcd.createChar(1, smile); //створення символу під номером 1
lcd.setCursor(0, 0);
lcd.print("\1"); //виводиться символ під номером 1
}
void loop() {}
Бібліотека LiquidCrystal
Дана бібліотека дозволяє Arduino керувати різними рідкокристалічними дисплеями (LCD), побудованими на базі контролера Hitachi HD44780 (або сумісного). У бібліотеці реалізований як 4-х, так і 8-бітний режими роботи (тобто є можливість використовувати 4 або 8 каналів для передачі даних).
LiquidCrystal() – створює змінну типу LiquidCrystal. Синтаксис функції:
LiquidCrystal(rs, enable, d4, d5, d6, d7)
LiquidCrystal(rs, rw, enable, d4, d5, d6, d7)
LiquidCrystal(rs, enable, d0, d1, d2, d3, d4, d5, d6, d7)
LiquidCrystal(rs, rw, enable, d0, d1, d2, d3, d4, d5, d6, d7)
rs – номер виходу Arduino, з'єднаного з виходом RS LCD-дисплею;
rw – номер виходу Arduino, з'єднаного з виходом RW LCD- дисплею;
enable – номер виходу Arduino, з'єднаного з виходом E LCD- дисплею;
d0, d1, d2, d3, d4, d5, d6, d7 – номера виходів Arduino, які підключені до відповідних цифровим виходів LCD-дисплею.
У випадку 4-бітного режиму роботи слід пропустити параметри d0-d3, залишивши відповідні виходи не підключеними. Вихід RW можна також не підключати до Arduino, а з'єднати його безпосередньо з землею. У цьому випадку параметр rw в функції можна не вказувати.
begin() – ініціалізує інтерфейс для взаємодії з LCD-екраном і задає розміри (ширину і висоту) області виведення екрану. При роботі з LCD-дисплеєм, функція begin() повинна викликатися першої. Синтаксис функції:
lcd.begin(cols, rows)
lcd – змінна типу LiquidCrystal;
cols – кількість стовпців екрану;
rows – кількість рядків екрану.
clear() – очищає LCD-дисплей та переміщує курсор в лівий верхній кут. Синтаксис функції:
lcd.clear()
setCursor() – дозволяє задати позицію курсора на LCD-дисплеї; тобто встановлює позицію, в якій буде виводитися наступний текст. Синтаксис функції:
lcd.setCursor(col, row)
col – координата X позиції курсора (0 означає перший стовпець);
row – координата Y позиції курсора (0 означає перший рядок).
print() – виводить текст на LCD-дисплей. Синтаксис функції:
lcd.print(data)
data – дані, які необхідно вивести (типу char, byte, int, long або string).
noDisplay() – вимикає LCD-дисплей. Текст, що відображається на екрані, зберігається в пам'яті. Синтаксис функції:
lcd.noDisplay()
display() – функція вмикає LCD-дисплей після того, як він був вимкнений функцією noDisplay(). Після виконання цієї функції на екрані відобразиться текст (і курсор), які були на ньому до вимнення. Синтаксис функції:
lcd.display()
cursor() – відображає на LCD-дисплеї курсор: символ підкреслення в тій позиції, куди буде виведено наступний символ. Синтаксис функції:
lcd.cursor()
noCursor() – функція відключає відображення курсора на LCD-дисплеї. Синтаксис функції:
lcd.noCursor()
createChar() – функція створює користувальницький символ. Дисплей підтримує до 8 користувальницьких символів (пронумерованих від 0 до 7) розміром 5х8 пікселів. Зовнішній вигляд кожного символу задається масивом з восьми байт, кожен з яких характеризує відповідний рядок. П'ять молодших біт кожного байту визначають стан пікселів у відповідному рядку. Синтаксис функції:
lcd.createChar(num, data)
num – номер призначеного для користувача символу, який необхідно створити (від 0 до 7);
data – дані про пікселі призначеного для користувача символу.
Адаптер I2C
Для спрощення підключення та зменшення кількості провідників часто використовуються додаткові інтерфейсні модулі:
Такі модулі будуються на базі мікросхеми PCF8574T або MCP23008 та дозволяють використати для підключення до Arduino інтерфейс I2C, що в свою чергу задіює всього 2 піни мікроконтролера. На модулі також присутній потенціометр для регулювання контрастності дисплею.
Приклад схеми підключення дисплею LCD 1602 з інтерфейсним модулем:
Код програми, яка виводить на екран дисплею надпис «Hello, world!»:
#include <Adafruit_LiquidCrystal.h> //підключення бібліотеки для роботи з LCD
Adafruit_LiquidCrystal lcd(0); //вказуємо виходи адресу інтерфейсу (0 – 0x32)
void setup() {
lcd.begin(16, 2); //задаємо розмірність дисплею
lcd.setCursor(0, 0); //встановлюємо курсор на початок першого рядка
lcd.print("Hello, world!"); // виводим текст
}
void loop() {}
Піроелектричний датчик руху (PIR)
Піроелектричний датчик руху (PIR, passive infrared) – датчик руху на основі піроелектричного ефекту. Такі датчики часто використовуються в охоронних системах і в ході виявлення руху в приміщеннях. Наприклад, на основі виявлення руху, створюються автоматичні системи вмикання світла. Піроелектричні датчики доволі просто влаштовані, недорогі і невибагливі у встановленні та обслуговуванні.
Піроелектрики – це діелектрики, які створюють електричне поле при зміні їх температури. На основі піроелектриків роблять датчики вимірювання температури, наприклад, LHI778 або IRA-E700. Кожен такий датчик містить два чутливих елементи розміром 1 × 2 мм, підключених з протилежною полярністю. І наявність саме двох елементів допомагає визначити рух.
Зверху піроелектрик оточений півсферою, розбитою на кілька сегментів. Кожен сегмент цієї сфери є лінзою, яка фокусує теплове випромінювання на різні ділянки PIR-датчика.
Принцип роботи датчик руху наступний: поки датчик знаходиться в порожній кімнаті, кожен чутливий елемент отримує постійну дозу випромінювання, а значить і напруга на них має постійне значення.
Коли в кімнату заходить людина, вона потрапляє спочатку в зону огляду першого елемента, що призводить до появи позитивного електричного імпульсу на ньому.
Людина рухається, і її теплове випромінювання через лінзи потрапляє вже на другий PIR-елемент, який генерує негативний імпульс. Електронна схема реєструє ці різноспрямовані імпульси і робить висновки про те, що в поле зору датчика потрапила людина. На виході датчика генерується позитивний імпульс.
Датчик HC-SR501 містить два змінних резистора і перемичку для налаштування режиму. Один з потенціометрів регулює чутливість приладу. Чим вона вища, тим далі «бачить» датчик. Також чутливість впливає на розмір об'єкта, на який він реагує. Наприклад, можна виключити спрацювання на собаку або кішку.
Другий потенціометр регулює час спрацьовування T. Якщо датчик виявив рух, він генерує на виході позитивний імпульс тривалістю T.
Третій елемент керування – перемичка, яка перемикає режим роботи датчика. У положенні L датчик веде відлік Т від самого першого спрацьовування. Наприклад, якщо людина зайде у кімнату, вона викличе спрацьовування датчика, і світло ввімкнеться рівно на час Т. Після закінчення цього періоду, сигнал на виході повернеться в початковий стан, і датчик буде чекати наступного спрацьовування.
У положенні H датчик починає відлік часу T кожен раз після виявлення руху. Іншими словами, будь-який рух людини викличе онулення таймеру відліку Т. За замовчуванням, перемичка знаходиться в стані H.
Підключення піроелектричного датчика руху до Arduino здійснюється згідно схеми, показаної нижче:
Контакт живлення (VCC) підключається до виходу 5V, контакт землі – на GND, контакт OUT – до одного з цифрових виходів Arduino (наприклад, 2). На цифровому виході буде генеруватися високий рівень сигналу (HIGH) при спрацюванні датчика.
void setup() {
Serial.begin(9600); //з'єднання з послідовним портом
}
void loop() {
int val = digitalRead(2); //отримання значення сигналу
Serial.println(val); //вивід значення на послідовний порт
delay(100);
}
Керування навантаженням постійного струму
Часто виникає ситуація, коли необхідно здійснити керування такими пристроями як реле, лампочки розжарювання, соленоїди, двигуни, відразу кілька світлодіодів або надпотужний силовий світлодіод-прожектор, тобто все, що споживає більше 15 мА та/або вимагає напруги живлення більше 5 вольт.
Наприклад, реле BS-115C має струм обмотки порядку 80 мА, напруга обмотки 12 вольт. При підключенні такого реле до контролера виникає проблема – мікроконтролер не може забезпечити потужність необхідну для нормальної роботи котушки. Максимальний струм який може пропустити через себе вихід контролера рідко перевищує 20 мА, а зазвичай – не більше 10 мА. Крім того, напруга мікроконтролера не перевищує 5 вольт, а для реле потрібно цілих 12.
Однак існує непоганий спосіб керувати потужним постійним навантаженням – польові МОН (MOSFET) транзистори.
Транзистор – радіоелектронний компонент з напівпровідникового матеріалу, зазвичай з трьома виходами, здатний від невеликого вхідного сигналу керувати значним струмом у вихідному ланцюзі, що дозволяє його використовувати для посилення, генерування, комутації та перетворення електричних сигналів.
Польовий транзистор працює як звичайний транзистор – слабким сигналом на затворі керує потужним потоком через канал. Але, на відміну від біполярних транзисторів, тут керування здійснюється не струмом, а напругою.
МОН (MOSFET) розшифровується як Метал-Оксид-Напівпровідник. В даних транзисторах є напівпровідниковий канал який виступає в ролі однієї обкладки конденсатора, а друга обкладка – металевий електрод, розділений шаром оксиду кремнію, який є діелектриком (рис. 7.6). Коли на затвор (gate) подають напругу, то цей конденсатор заряджається, а електричне поле затвора підтягує до каналу заряди, в результаті чого в каналі виникають рухливі заряди, здатні утворити електричний струм і опір стоку (drain) – витоку (source) різко падає, відкриваючи канал.
Навантаження включається в коло стоку, хоча, в теорії, польовому транзистору без різниці що вважати у нього джерелом, а що стоком. Але на практиці для поліпшення характеристик витік і сток роблять різної величини і конструкції, плюс до всього, в потужних MOSFET-транзисторах часто є зворотний діод.
Характеристики, на які варто звернути увагу при виборі MOSFET – напруга та струм, які здатний пропустити транзистор через себе. Ці значення можна брати з великим запасом, за ціною вони не сильно відрізняються.
Третій важливий параметр це порогова напруга на затворі, вона повинна бути менше 5 вольт, зазвичай близько 3. Це напруга, якою керується транзистор. MOSFET з такою напругою іноді іменуються як транзистори з логічним рівнем (серія IRL та IRF).
Четвертий параметр визначає ефективність, це опір транзистора у відкритому стані. Чим менше це значення, тим менше транзистор буде нагріватися і тим меншими будуть втрати в колі.
Прикладом може слугувати MOSFET-транзистор IRF3205, який здатний пропустити через себе напругу до 55 В та постійний струм до 110 А. Опір у відкритому стані при цьому становить 8 мОм. Однак максимальної продуктивності (без перегріву) можна досягти, використовуючи напругу керування 10 вольт. У випадку, коли керуюча напруга становить 5 вольт (від мікроконтролера) максимальна сила струму становить 30 А (як видно з графіку).
До Arduino підключається керуюча нога (затвор) транзистора, інші ставляться в розрив кола. Між керуючим піном Arduino та ногою транзистора варто встановити захисний резистор номіналом 100 Ом, для захисту виходу Arduino, а між крайніми ногами встановити стягуючий резистор на 10 кОм, для захисту від мимовільного спрацювання і замикання кола.
На представленій вище схемі показано як здійснюється підключення до Arduino лампи розжарювання (12 В, 250 мА), яка використовує зовнішнє джерело живлення на 12 вольт, але керується за допомогою мікроконтролера, через MOSFET-транзистор.
Для керування використовується та ж програма, що і для звичайних світлодіодів, тобто змінюється лише схема підключення.
Функція millis()
Одна з основних помилок новачків при програмуванні Arduino – надмірне використання функції delay().
Ця функція зупиняє виконання програми на вказану кількість мілісекунд. Однак часто може виникнути ситуація, коли її використання створює проблеми. Наприклад, якщо підключити до Arduino дві кнопку та два світлодіоди та запрограмувати їх так, щоб при натисканні на першу кнопку загорявся перший світлодіод на 3 секунди, а при натисканні другої – другий світлодіод.
В цьому випадку програма коректно працювати не буде, оскільки при натисканні на першу кнопку виконання коду зупиниться на 3 секунди на цей час друга кнопка спрацьовувати не буде.
Для вирішення цієї проблеми можна використовувати функцію millis(), яка повертає кількість мілісекунд, які пройшли з моменту запуску скетчу. Ця кількість скидається на нуль, в наслідок переповнення значення, приблизно через 50 днів.
Якщо потрібно дізнатися, скільки минуло часу, можна:
- зберегти у змінній потрібний проміжок часу;
- періодично перевіряти (наприклад, в тілі циклу loop), різницю між початковим часом і фактичним на даний момент.
Приклад використання функції millis():
unsigned long ledTime = 0; //змінна для зберігання часу
int ledState = HIGH; //змінна для зберігання стану світлодіода
void setup() {
pinMode(13, OUTPUT);
digitalWrite(13, HIGH);
}
void loop() {
if (millis() - ledTime > 1000) { //якщо пройшло більше 1000 мс
ledState = !ledState; //зміна стану світлодіода
digitalWrite(13, ledState); //подача стану на світлодіод
ledTime = millis(); //визначення нової точки відліку часу
}
}
На відміну від коду, представленого раніше, цей код не зупиняє роботу програми, виконуючи ті ж функції, а всі інші команди, що не будуть стосуватися роботи зі світлодіодом, будуть працювати без зупинки.
Апаратні переривання
Переривання – це сигнали, що зупиняють нормальний перебіг програми. Переривання зазвичай використовуються для апаратних пристроїв, що вимагають негайної реакції на появу подій. Наприклад, система послідовного порту мікроконтролера повинна бути обслужена при отриманні нового символу. Якщо цього не зробити швидко, новий символ може бути втрачений.
Це ж відноситься і до великої кількості різних датчиків, що видають короткий імпульс. В таких завданнях використання зовнішніх переривань дозволяє розвантажити процесор для інших операцій і не пропустити очікуваний сигнал.
Функція attachInterrupt()
Дана функція визначає іншу функцію, призначену для обробки зовнішнього переривання, тобто функція, яка буде викликана по зовнішньому перериванню. Більшість контролерів Arduino вміють обробляти до двох зовнішніх переривань, пронумерованих як: 0 (на цифровому виході 2) та 1 (на цифровому виході 3). Arduino Mega обробляє додатково ще чотири переривання: 2 (пін 21), 3 (пін 20), 4 (пін 19) і 5 (пін 18).
Синтаксис функції:
attachInterrupt(interrupt, function, mode)
де interrupt – номер переривання;
function – назва функції, що викликається перериванням. Функція повинна бути без параметрів і не повертати значень.
mode – задає режим обробки переривання. Можливе використання наступних значень:
- LOW – викликає переривання, коли на виході сигнал LOW;
- CHANGE – переривання викликається при зміні значення на виході, з LOW на HIGH і навпаки;
- RISING – переривання викликається тільки при зміні значення на виході з LOW на HIGH;
- FALLING – переривання викликається тільки при зміні значення на виході з HIGH на LOW.
Всередині функції обробки переривання не працює delay(), значення, що повертаються millis() не змінюються. Змінні, що задіюються в функції, повинні бути оголошені як volatile.
Приклад використання переривань:
volatile int ledState = LOW; //змінна для стану світлодіода
void setup() {
pinMode(13, OUTPUT);
attachInterrupt(0, blink, CHANGE); //виклик функції blink для 0 переривання
}
void loop() {
digitalWrite(13, ledState);
}
void blink() { //функція для переривання
ledState = !ledState; //зміна стану для світлодіода
}
У представленому коді, описана задача, коли при натисненні на кнопку змінюється стан світлодіода. Однак, в даному випадку опрацювання натискання кнопки прив’язано до апаратного переривання, а це означає, що на якому б етапі виконання не знаходилася б програма, вона буде призупинена, поки не зміниться стан світлодіода, навіть якщо на даний момент має виконуватись затримка роботи мікроконтролера функцією delay().
Цифровий датчик температури
Цифровий датчик DS18B20 є одним із найпопулярніших температурних датчиків. Він часто виконується у водонепроникному корпусі для вимірювання температури води або інших рідин.
DS18B20 – це цифровий температурний датчик, що має багато корисних функцій. По суті, DS18B20 – це цілий мікроконтролер, який може зберігати значення вимірювань, сигналізувати про вихід температури за встановлені межі (самі межі можна встановлювати та змінювати), змінювати точність вимірювань, спосіб взаємодії з контролером та багато іншого.
Мікросхема зазвичай має три виходи, з яких для даних використовується лише один, два інших – це земля та живлення. До одного контакту з даними можна підключити одразу кілька датчиків DS18B20.
Температурний датчик DS18B20 має різноманітні види корпусів. Можна вибрати один із трьох доступних варіантів – 8-контактний SO, 8-контактний µSOP, та 3-контактний TO-92. Останній є найпоширенішим і часто виготовляється в спеціальному вологозахисному корпусі. Кожен датчик має 3 контакти для підключення до мікроконтролера.
Основні характеристики цифрового датчика DS18B20:
- похибка вимірювання не більше 0,5 °С (для температур від –10 °С до +85 °С), що дозволяє точно визначити значення температури. Не потрібне додаткове калібрування;
- температурний діапазон вимірювань в межах від –55 до +125 °С;
- напруга живлення від 3,3 до 5 В;
- можна програмно задати максимальну роздільну здатність до 0,0625 °С;
- функція тривожного сигналу;
- кожен датчик має свій унікальний серійний код;
- додаткові зовнішні елементи не потрібні;
- можна підключити одразу до 127 датчиків до однієї лінії звʼязку;
- інформація передається за протоколом 1-Wire.
Нижче наведена схема підключення цифрового датчика температури DS18B20 до плати Arduino UNO: контакт GND датчика приєднується до контакту GND Arduino, VDD – до контакту 5V, DQ – до будь-якого цифрового контакту. Також додаткова між контактами VDD та DQ потрібно встановити резистор номіналом 4,7 кОм.
Алгоритм отримання інформації про температуру з датчика DS18B20 складається з наступних етапів:
- визначення адреси датчика, перевірка його підключення;
- на датчик подається команда з вимогою прочитати температуру та записати виміряне значення у регістр;
- подається команда на читання інформації з регістру та відправлення отриманого значення на монітор порту;
- якщо потрібно, то здійснюється конвертація в градуси Цельсія/Фаренгейта.
Приклад скетчу для отримання даних з датчика DS18B20:
#include <OneWire.h> //бібліотека для роботи з інтерфейсом 1-Wire
OneWire ds(2); //вказуємо вхід, до якого підключений датчик
void setup() {
Serial.begin(9600); //підключаємо послідовний порт
}
void loop() {
byte data[2]; //створюємо масив для зберігання отриманих даних
ds.reset(); //скидаємо всі попередні параметри та налаштування
ds.write(0xCC); //даємо команду здійснити пошук датчика за адресою
ds.write(0x44); //даємо команду отримати значення температури
delay(1000); //чекаємо, поки будуть отримані дані
ds.reset();
ds.write(0xCC);
ds.write(0xBE); //робимо запит на отримання значення температури
data[0] = ds.read(); //зчитуємо молодший байт даних
data[1] = ds.read(); //зчитуємо старший байт даних
//обраховуємо температуру: обʼєднуємо значення старшого та меншого байтів
//множимо отримане значення на коефіцієнт роздільної здатності
float temperature = ((data[1] << 8) | data[0]) * 0.0625;
Serial.println(temperature); //виводимо отримане значення в послідовний порт
}
Можна також використовувати бібліотеку DallasTemperature, яка спрощує деякі аспекти роботи з датчиком DS18B20 по 1-Wire:
#include <DallasTemperature.h>
OneWire ds(2); //вказуємо вхід, до якого підключений датчик
DallasTemperature sensors(&ds); //створюємо обʼєкт DallasTemperature
void setup() {
Serial.begin(9600); //підключаємо послідовний порт
sensors.begin(); //ініціюємо роботу з датчиком
}
void loop() {
sensors.requestTemperatures(); //відправляємо команду на отримання даних
//отримуємо значення температури в градусах Цельсія
float tempC = sensors.getTempCByIndex(0);
Serial.println(tempC); //виводимо отримане значення в послідовний порт
}
Бібліотека DallasTemperature
Бібліотека розроблена компанією Dallas, розробником цифрового датчика температури DS18B20, та призначена для спрощення роботи з ним, з використанням інтерфейсу 1-Wire. Включає наступні функції:
- begin() – ініціює початок роботи з одним або кількома датчиками температури. Виконується лише оди раз при старті програми;
- getDeviceCount() – визначає кількість підключених датчиків;
- getAddress(address, index) – отримує адресу пристрою (та записує її в змінну address типу DeviceAddress), який знаходиться під порядковим номером index;
- isConnected(address) – перевіряє, чи підключений датчик з адресою address;
- setResolution(address, resolution) – задає роздільну здатність (точність вимірювання) resolution (значення в бітах – 9, 10, 11 або 12) для датчика за адресою address;
- requestTemperatures() – надсилає датчику команду для замірів поточного значення температури;
- getTempC(address) – отримує значення температури в градусах Цельсія з датчика за адресою address;
- getTempF(address) – отримує значення температури в градусах Фаренгейта з датчика за адресою address;
- getTempCByIndex(index) – отримує значення температури в градусах Цельсія з датчика під номером index;
- getTempFByIndex(index) – отримує значення температури в градусах Фаренгейта з датчика під номером index.
П’єзодинамік
П’єзоелектричний випромінювач (п’єзодинамік або бузер) – це електроакустичний прилад, здатний відтворювати звукові хвилі завдяки зворотному п’єзоелектричному ефекту.
П’єзодинамік складається з шару п’єзоелектрика (або декількох шарів), який нанесений на металеву пластину (мембрану) товщиною до 1.5мм. П’єзоелектрик виготовлений з діелектричних матеріалів (п’єзокераміки), які мають властивість п’єзоефекту. Зовнішня сторона п’єзоелектрика покривається струмопровідним напиленням.
Металева пластина і напилення є контактними виходами п’єзодинаміка. До них підводиться живлення за допомогою проводів або контактних груп.
Для посилення звуковипромінюючих властивостей п’єзодинамік можуть поміщати в корпус, який служить свого роду рупором. Корпус для п’єзодинаміка може бути пластиковий, керамічний або металевий. Конфігурація в основному однотипна: заглиблення в корпусі, яке створює додатковий резонанс та отвір в центрі – для виходу звукових хвиль.
Деякі моделі доповнюють дифузором або діафрагмою, які безпосередньо пов’язані з мембраною і повторюють її коливання. Можуть бути додані елементи для кріплення і вбудовані чіпи.
При подачі напруги на п’єзодинамік, шар п’єзоелектрика деформується, то зменшуючи, то збільшуючи відстань до мембрани. Таким чином створюється ефект конденсатора, де між двома обкладинками накопичується електричний заряд. У момент зарядки і розрядки він випромінює звукову хвилю.
Звукове сповіщення – сама елементарна функція п’єзодинаміка. Цю властивість застосовують у виробництві побутової техніки. Наприклад, пральна машина, по закінченню прання, заграє веселу мелодію. Комп’ютер при включенні інформує про стан всіх модулів коротким сигналом. Будильник «пищить» в заданий час.
Типова схема підключення пʼєзодинаміка до Arduino:
Приклад коду для керування пʼєзодинаміком показано нижче:
void setup() {
pinMode(3, OUTPUT); //встановлюємо 3 пін в якості виходу
}
void loop() {
tone(3, 261); //виводимо звуковий сигнал на динамік на частоті 261 Гц
delay(1000);
noTone(3); //припиняємо подачу звукового сигналу
delay(100);
}
Керування кроковими двигунами
Кроковий двигун – електричний двигун, в якому імпульсне живлення електричним струмом призводить до того, що його ротор не обертається неперервно, а виконує щоразу обертальний рух на заданий кут. Завдяки цьому, кут повороту ротора залежить від числа поданих імпульсів струму, а кутова швидкість ротора точно рівна частоті імпульсів помноженій на кут повороту ротора за один цикл роботи двигуна.
Кут повороту двигуна під впливом одного імпульсу може мати різні значення, залежні від конструкції двигуна, – як правило це значення в діапазоні від декількох градусів до декілька десятків градусів. Крокові двигуни, залежно від призначення пристосовані до виконання від частки оберту на хвилину, до декількох тисяч обертів на хвилину.
Маючи невеликі габарити, кроковий двигун може бути досить потужним, з високим моментом обертання та тяговою силою. Відсутність щіток у двигуна суттєво впливають на його термін експлуатації. Швидкий розгін та майже миттєве гальмування, робить цей тип двигуна незамінним у точних системах.
Однак для використання крокового двигуна та керування потрібно використовувати спеціальне додаткове обладнання – драйвер. Драйвер для крокових двигунів дозволяє перетворювати струм в імпульси, завдяки яким і здійснюється обертання валу на певний кут. Якість драйверу безпосередньо впливає на точність обертання та загальну роботу двигунів.
Крокові двигуни можуть оснащуватися додатковими можливостями. Наприклад, існують крокові двигуни з енкодером – цей тип двигуна відслідковує положення валу, тим самим не даючи втрачати кроки при роботі. Крокові двигуни з електрогальмами – в момент коли живлення не подається на двигун, вал фіксується в тому положенні, в якому він знаходився в момент вимкнення.
Кроковий двигун 28BYJ-48
Пʼятивольтовий кроковий двигун 28BYJ-48 5В часто використовується в робототехніці, DIY-пристроях, поворотних жалюзі кондиціонерів, невеликих вентиляторах і т.п.
Основні характеристики:
- номінальна напруга живлення: 5 В (постійний струм);
- кількість фаз: 4;
- кількість кроків: 64;
- кількість мікрокроків: 4096;
- крок: 5.625 градусів;
- піковий струм однієї обмотки: близько 320 мА;
- крутний момент: 34,3 мН/м.
Для роботи з даним кроковим двигуном зазвичай використовується драйвер ULN2003.
Даний драйвер дозволяє працювати як з 5В так і з 12В уніполярними двигунами. Сумісний зі стандартною бібліотекою Arduino Stepper. Має 4 світлодіоди для індикації роботи (по світлодіоду на кожен канал).
Нижче показано схему підключення крокового двигуна 28BYJ-48 до Arduino з використанням драйвера ULN2003:
Контакти IN1 – IN4 драйвера крокового двигуна з’єднуються з контактами 8 – 11 плати Arduino. Живлення на драйвер має подаватися з окремого джерела живлення, оскільки Arduino не може забезпечити необхідної потужності.
Приклад коду для керування кроковим двигуном:
#include <AccelStepper.h> //підключення бібліотеки
#define IN1 8
#define IN2 9
#define IN3 10
#define IN4 11
AccelStepper s28BYJ-48(4, IN1, IN3, IN2, IN4); //визначаємо контакти підключення
void setup() {
s28BYJ-48.setMaxSpeed(900.0); //встановлення максимальної швидкості
s28BYJ-48.setAcceleration(100.0); //встановлення прискорення
s28BYJ-48.setSpeed(200); //встановлення швидкості
s28BYJ-48.moveTo(2000); //переміститися в абсолютну вказану позицію
}
void loop() {
//змінюємо напрямок після проходження заданої кількості кроків
if (s28BYJ-48.distanceToGo() == 0)
s28BYJ-48.moveTo(-stepper1.currentPosition());
s28BYJ-48.run(); //запуск двигуна
delay(1000);
}
Бібліотека AccelStepper
Бібліотека AccelStepper для Arduino дозволяє керувати кроковими двигунами і, на відміну від стандартної бібліотеки Stepper, має наступні переваги:
- підтримка прискорення та уповільнення;
- підтримка одночасної роботи кількох крокових двигунів із незалежною роботою кожного;
- неблокуючі функції;
- підтримка різних типів крокових двигунів та мікрокрокових режимів;
- підтримка дуже маленьких швидкостей.
Основні функції бібліотеки AccelStepper:
- Визначення і конфігурація двигунів:
- AccelStepper mystepper(1, pinStep, pinDirection) – кроковий двигун, керований драйвером;
- AccelStepper mystepper(2, pinA, pinB) – біполярний кроковий двигун, що керується Н-мостом;
- AccelStepper mystepper(4, pinA1, pinA2, pinB1, pinB2) – уніполярний двигун, керований чотирма транзисторами;
- mystepper.setMaxSpeed(stepsPerSecond) – встановлення максимальної швидкості (в кроках за секунду). Швидкість за замовчанням дуже низька, тому її потрібно перевизначити. Під час руху кроковий двигун прискорюватиметься до цієї максимальної швидкості і сповільнюватиметься при підході до кінця руху;
- mystepper.setAcceleration(stepsPerSecondSquared) – встановлення прискорення, в кроках за секунду в квадраті.
- Керування положенням:
- mystepper.moveTo(targetPosition) – переміститися у абсолютне вказане положення (в кроках від 0). Сам рух запускається функцією run();
- mystepper.move(distance) – переміститися у відносне вказане положення. Сам рух запускається функцією run(). Значення distance може бути більшим або меншим за нуль;
- mystepper.currentPosition() – визначити поточне абсолютне положення;
- mystepper.distanceToGo() – визначити відстань до вказаного положення. Може використовуватися для перевірки, чи досягнув двигун зазначеної кінцевої точки;
- mystepper.run() – розпочати рух. Для продовження руху двигуна слід викликати функцію повторно;
- mystepper.runToPosition() – розпочати рух і почекати, коли двигун досягне зазначеної точки. Функція не здійснює повернення поки двигун не зупиниться.
- Керування швидкістю:
- mystepper.setSpeed(stepsPerSecond) – встановити швидкість в кроках за секунду. Сам рух запускається функцією runSpeed();
- mystepper.runSpeed() – розпочати рух. Для продовження руху двигуна слід викликати функцію повторно.
Фоторезистори
Датчики освітленості, побудовані на базі фоторезисторів, досить часто використовуються в реальних IoT-проектах. Вони відносно прості, недорогі, їх легко знайти та купити у будь-якому інтернет-магазині. Фоторезистор дозволяє контролювати рівень освітленості та реагувати на його зміну.
Фоторезистор, як випливає з назви, має пряме відношення до резисторів, які часто зустрічаються практично в будь-яких електронних схемах. Основною характеристикою звичайного резистора є величина його опору. Від нього залежить напруга і струм, за допомогою резистора ми виставляємо потрібні режими роботи інших компонентів. Як правило, значення опору у резистора в тих самих умовах експлуатації практично не змінюється.
На відміну від звичайного резистора, фоторезистор може змінювати опір в залежності від рівня навколишнього освітлення. Це означає, що в електронній схемі постійно змінюватимуться параметри, в першу чергу нас цікавить напруга, що падає на фоторезисторі. Фіксуючи ці зміни напруги на аналогових пінах Arduino, ми можемо змінювати логіку роботи схеми.
Найпоширеніший варіант застосування – ліхтарі вуличного освітлення. Якщо на місто опускається ніч або стає похмуро, то світло вмикається автоматично. Можна зробити за допомогою фоторезистора економну лампу для будинку, що вмикається не за розкладом, а залежно від освітлення. На базі датчика освітленості можна зробити навіть охоронну систему, яка спрацьовуватиме відразу після того, як зачинений сейф відкрили та в нього потрапило світло.
Схема підключення датчика освітлення до Arduino доволі проста. Якщо використовується фоторезистор, то за схемою підключення датчик реалізований як дільник напруги. Одне плече змінюється від рівня освітленості, друге подає напругу на аналоговий вхід. У мікросхемі контролера ця напруга перетворюється на цифрові дані через аналогово-цифровий перетворювач (АЦП).
Залежно від того, в якому плечі дільника ми поставили фоторезистор, на аналоговий вхід подаватиметься або підвищена або зменшена напруга. У тому випадку, якщо одна нога фоторезистора підключена до +5В, то максимальне значення напруги буде відповідати гарному освітленню (опір фоторезистора мінімальний), а мінімальне – темряві (опір максимальний). Якщо ми підключимо плече фоторезистора до землі – поведінка буде протилежною.
Отримане значення на аналоговому вході буде варіюватися від 0 до 1023 в залежності від схеми підключення та рівня освітленості.
Керування двигунами постійного струму
Доволі часто для проектів з робототехніки використовуються двигуни постійного струму. Такі двигуни мають два контакти для подачі живлення та обертаються в певну сторону, в залежності від полярності підключення.
Підключення такого двигуна до проекту не дозволяє змінювати напрямок обертання без зміни схеми підключення. Для вирішення цієї проблеми можна використовувати мікросхему L293D в якості драйвера. Основна його перевага – можливість керування двома двигунами одночасно.
Характеристики мікросхеми L293D:
- напруга живлення двигунів (Vs) – 4,5...36V;
- напруга живлення мікросхеми (Vss) – 5V;
- допустимий струм навантаження – 600 mA (на кожен канал);
- піковий (максимальний) струм на виході – 1,2A (на кожен канал);
- логічний 0 вхідної напруги – до 1,5V;
- логічна 1 вхідної напруги – 2,3...7V;
- захист від перегріву.
Схема виходів мікросхеми:
- Входи EN1 та EN2 відповідають за увімкнення кожного з драйверів, що входять до складу мікросхеми.
- Входи IN1 та IN2 керують двигуном, підключеним до виходів OUT1 та OUT2.
- Входи IN3 та IN4 керують двигуном, підключеним до виходів OUT3 та OUT4.
- Контакт +Vmotor з’єднують із позитивним полюсом джерела живлення двигунів.
- Контакт +V з’єднують із позитивним полюсом джерела живлення. Цей контакт забезпечує живлення самої мікросхеми.
- Чотири контакти 0V з’єднують із землею (загальним проводом або негативним полюсом джерела живлення).
Нижче наведена схема підключення двигуна постійного струму до Arduino з використанням мікросхеми драйвера. Також в схемі використовується потенціометр для керуванням швидкістю обертання та кнопка для зміни напрямку обертання валу двигуна.
Нижче наведено код керування двигуном:
int enablePin = 11; //пін увімкнення драйвера
int in1Pin = 10; //пін керування
int in2Pin = 9; //пін керування
int switchPin = 7; //вхід кнопки
int potPin = 14; //вхід потенціометра
void setup() {
pinMode(in1Pin, OUTPUT);
pinMode(in2Pin, OUTPUT);
pinMode(enablePin, OUTPUT);
pinMode(switchPin, INPUT_PULLUP);
}
void loop() {
int speed = analogRead(potPin)/4; //визначаємо швидкість обертання
bool reverse = digitalRead(switchPin); //визначаємо напрямок
setMotor(speed, reverse); //задаємо параметри роботи двигуна
}
void setMotor(int speed, boolean reverse){ //зміна параметрів двигуна
analogWrite(enablePin, speed); //встановлюємо швидкість
digitalWrite(in1Pin, !reverse); //задаємо напрямок обертання
digitalWrite(in2Pin, reverse); //задаємо напрямок обертання
}
Піни ініціалізуються та виставляються їх режими роботи в межах функції setup.
В межах функції loop обраховується швидкість обертання двигуна. Швидкість визначається за допомогою поділу аналогових значень від потенціометра на 4.
Якщо кнопка натиснута, мотор рухатиметься вперед, якщо не натиснута – у протилежному напрямку. Значення змінної reverse прирівнюється до значення, яке зчитується з піна switchPin із кнопкою.
Швидкість і значення реверсу проходять через функцію під назвою setMotor, яка налаштовує відповідні керуючі сигнали на драйвері, щоб керувати двигуном.
Спочатку швидкість встановлюється з використанням analogWrite на контакт enable. Контакт enable на драйвері L293 просто вмикає-вимикає двигун залежно від налаштувань пінів in1 та in2 на чіпі L293.
Для керування напрямом обертання двигуна, піни in1 та in2 повинні мати протилежні значення.
Якщо in1 має значення HIGH, а in2 – LOW, двигун буде рухатися в одному напрямку, якщо in1 приймає значення LOW, а in2 – HIGH, двигун почне обертатися в протилежному напрямку.
Використання адресних світлодіодних стрічок
Звичайна світлодіодна стрічка являє собою стрічкою з розміщеними на ній світлодіодами та резисторами, а також двома провідниками для живлення: плюс та мінус. Напруга живлення може бути 5 та 12 В постійного струму або 220 В змінного. Для 5 та 12 В стрічок потрібно використовувати відповідно блоки живлення. Світить така стрічка одним кольором, який залежить від світлодіодів.
RGB світлодіодні стрічки містять RGB-світлодіоди. Такий світлодіод має вже 4 виходи, один загальний +12 (анод), і три мінуси (катод) для кожного кольору, тобто. всередині одного світлодіода знаходиться три світлодіоди різних кольорів. Відповідно такі ж виходи має і стрічка: 12, G, R, B. Подаючи живлення на загальний 12 та будь-який з кольорів, ми вмикаємо цей колір. Якщо подати живлення на всі три – отримаємо білий, зелений і червоний дадуть жовтий і т.д. Для таких стрічок існують контролери з пультами, типовий контролер має три польові транзистори на кожен колір і мікроконтролер, який керує транзисторами, таким чином даючи можливість включити будь-який колір.
Однак така стрічка світиться заданим кольором по всій довжині.
Адресна світлодіодна стрічка – вершина еволюції світлодіодних стрічок. Вона містить адресні діоди, кожен з яких складається з RGB-світлодіода і контролера. Завдяки цьому є можливість керувати кольором та яскравістю будь-якого світлодіода у стрічці. Адресна стрічка має 3-4 контакти для підключення, два з яких завжди живлення (5V і GND наприклад), та інші (один або два) – логічні, для керування.
Стрічка керується за спеціальним цифровим протоколом. Це означає, що якщо просто підключити до стрічки живлення не станеться абсолютно нічого, тобто перевірити стрічку без керуючого контролера не можна. Для керування стрічкою можуть використовуються готові контролери, але також можна керувати стрічкою вручну, використовуючи, наприклад, платформу Arduino, для чого стрічку потрібно правильно підключити.
Особливості підключення:
- Команди в стрічці передаються від діода до діода, послідовно. У стрічки є початок і кінець, напрямок руху команд на деяких моделях вказано стрілочками. Наприклад розглянемо WS2812b, у неї є три контакти. Два для живлення, а третій на початку стрічки називається DI (digital input), а в кінці – DO (digital output). Стрічка приймає команди на контакт DI. Контакт DO потрібен для підключення додаткових фрагментів стрічки чи з’єднання матриць.
- Якщо в схемі можлива ситуація, при якій на стрічку не подаватиметься живлення 5V, але відправлятиметься сигнал з мікроконтролера – стрічка почне живитися від дата-піну. У цьому випадку може згоріти як перший світлодіод у стрічці, так і пін контролера. Тому на цей пін потрібно поставити обмежуючий резистор з опором 200-500 Ом.
- Якщо між стрічкою і контролером (Arduino) велика відстань (довше 50 см), то сигнальний провід і провід землі потрібно скрутити в косичку для захисту від наведень, так як протокол звʼязку у стрічки досить швидкісний (800 кГц), на нього сильно впливають зовнішні наведення, а екранування скруткою допоможе цього уникнути.
- Контакт стрічки GND і пін GND Arduino (будь-який з наявних) повинні бути обов’язково з’єднані.
- Один колір одного світлодіода при максимальній яскравості споживає 12 мА. В одному світлодіоді три кольори, всього ~36 мА на діод. Для стрічки із щільністю 60 діодів/м споживання становитиме приблизно 2.1 А при максимальній яскравості білого кольору, відповідно, потрібно брати блок живлення, який з цим впорається. Треба також врахувати те, що для такого струму потрібно підібрати відповідні провідники.
В жодному випадку не можна живити стрічку напряму від Arduino!
Схема підключення адресної стрічки до Arduino показано нижче. Використовується окреме джерело живлення для стрічки.
Нижче наведено код, за допомогою якого почергово засвічуються світлодіоди зеленим кольором:
#include <Adafruit_NeoPixel.h> //бібліотека для керування стрічкою
#define PIN 13 //пін підключення
#define NUMPIXELS 6 //кількість світлодіодів
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
void setup() {
pixels.begin(); //ініціалізація стрічки
}
void loop() {
pixels.clear(); //очищення стрічки
for(int i=0; i < NUMPIXELS; i++) {
pixels.setPixelColor(i, pixels.Color(0, 150, 0)); //визачення кольору світлодіода
pixels.show(); //показати результат
delay(500);
}
}
Бібліотека Adafruit NeoPixel
Бібліотека Adafruit NeoPixel призначена для роботи з різними світлодіодними стрічками та кільцями (NeoPixel Ring) на базі світлодіодів WS2812 та WS2811. Підтримуються мікроконтролери Arduino, ESP32 та інші популярні платформи.
Бібліотека NeoPixel резервує 3 байти оперативної пам’яті на кожен світлодіод. Це може бути критично для Arduino UNO при використанні великих стрічок (від 200 світлодіодів і більше).
Конструктор ініціалізації має три параметри:
- NUMPIXELS – кількість світлодіодів у стрічці;
- PIN – порт, до якого підключено стрічку. За замовчуванням використовується пін 6;
- NEO_GRB + NEO_KHZ800 – додаткові прапорці. Можуть набувати наступні значення (наводиться лише частина з можливих варіантів):
- NEO_KHZ800 – за замовчуванням. Передача даних на частоті 800 кГц (для стрічок на світлодіодах WS2812);
- NEO_KHZ400 – передача даних на частоті 400 кГц (для стрічок на світлодіодах WS2811);
- NEO_GRB – послідовність кольорів під час передачі даних: зелений, червоний, синій;
- NEO_RGB – послідовність кольорів під час передачі даних (червоний, зелений, синій);
- NEO_GRBW та NEO_RGBW – використовуються додаткові білі світлодіоди.
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
Основні функції:
- begin() – початок роботи зі стрічкою;
- numPixels() – повертає кількість світлодіодів у стрічці. Використовується в циклах або під час роботи з декількома світлодіодними стрічками;
- updateLength() – оновити довжину стрічки;
- updateType() – оновити тип стрічки;
- show() – передає дані у стрічку. Функцію необхідно викликати щоразу після того, як змінилися кольори або налаштування стрічки;
- setPin() – задає пін підключення мікроконтролера;
- getPixelColor() – повертає колір світлодіода у вигляді 32-бітного числа. У єдиному параметрі функції вказується номер світлодіода;
- setPixelColor() – задає колір вказаному світлодіоду;
- fill() – заповнити діапазон світлодіодів визначим кольором;
- ColorHSV() – задає колір за схемою HSV (відтінок, насиченість, яскравість);
- setBrightness() – задає загальну яскравість світлодіодної стрічки. Не рекомендується використовувати під час створення світлових ефектів, слід викликати її один раз у функції setup(). Зміни набирають чинності лише після виклику функції show();
- getBrightness() – отримати яскравість;
- clear() – вимкнути всі світлоідоди.
Функція setPixelColor()
Функція setPixelColor() дозволяє задати будь-якому світлодіоду стрічки певний колір. Існує три перевантаження функції.
Перша версія. У першому параметрі n вказується номер світлодіода у стрічці (відлік із 0). У параметрі red вказується число від 0 до 255, що визначає яскравість червоного кольору, green – число від 0 до 255, що визначає яскравість зеленого кольору, blue – число від 0 до 255, що визначає яскравість синього кольору. Встановлюючи різну яскравість, ми змішуємо три кольори – червоний, зелений та синій, отримуючи інші кольори та відтінки.
Друга версія подібна до першої, тільки додається додатковий параметр white. Використовується в RGBW-стрічках, в яких, крім трьохколірних світлодіодів, встановлені ще й білі світлодіоди, і цим параметром встановлюється їхня яскравість. Під час створення обʼєкта в останньому параметрі необхідно вказати NEO_GRBW або NEO_RGBW.
Третя версія задає колір у вигляді 32-бітного числа. Найзручніший варіант для створення різних ефектів.
pixels.setPixelColor(n, red, green, blue);
pixels.setPixelColor(n, red, green, blue, white);
pixels.setPixelColor(n, pixels.Color(0, 0, 1));