Підключення приладів вводу/виводу до мікроконтролера

Базова взаємодія вбудованої системи з користувачем через GPIO

В цій статті будемо розбиратися як підключати перемикачі й світлодіоди до мікроконтролера. Ми використовуватимемо перемикачі для введення даних, а світлодіоди — для виведення результатів. Таким чином ми побачимо основні принципи, за якими зовнішні пристрої підключаються до мікроконтролера. Вам знадобиться міцне розуміння закону Ома, тож, можливо, варто пригадати основи струму, напруги, потужності й опору (див. статті Основні поняття з електроніки. Закон Ома, Основи розрахунку електричних кіл).

Введення даних за допомогою кнопок/перемикачів

Пристрої введення та виведення є критично важливими компонентами вбудованої системи. Найпростішим прикладом пристрою введення даних є перемикач. Він дозволяє людині вводити двійкову інформацію до комп’ютера. Зазвичай ми визначаємо активний стан, або логічну «1», коли перемикач натиснуто. Контактні перемикачі також можуть використовуватись у машинах для виявлення механічного контакту (наприклад, коли дві частини торкаються одна одної, наявність паперу в принтері або коли колеса знаходяться на землі тощо).

Зображення на схемі контактів перемикачівОднополюсний однопозиційний перемикач (SPST) має лише два виводи й працює за принципом простого замикання або розмикання кола. У нормально розімкненому стані опір між контактами практично нескінченний (понад 100 МОм), що означає відсутність електричного з’єднання. Коли ж перемикач натискають, опір різко зменшується до нуля (менше ніж 0,1 Ом), забезпечуючи провідність між контактами (див. рисунок 1). Щоб перетворити такий змінний опір на зрозумілий мікроконтролеру цифровий сигнал, перемикач підключають через підтягувальний резистор — до землі (pull-down) або до позитивної напруги живлення, наприклад +3.3 В (pull-up). Така схема дозволяє мікроконтролеру однозначно розпізнавати стан перемикача навіть у моменти, коли контакт розімкнений (див. рисунок 2).

Підтягувальні резистори

Підключення кнопок до входу мікроконтролераПричина використання підтягувального резистора полягає в тому, що вхід мікроконтролера за замовчуванням перебуває у плаваючому стані. Якщо на нього не подати ані напругу живлення, ані «землю», то під час зчитування його стану в програмі можна отримати випадкові, непередбачувані значення. Наприклад, якщо прибрати підключення до «землі» через резистор R1 (див. рисунок 2, ліворуч), то під час натискання кнопки SW1 програма визначить логічний рівень як “1”, а коли кнопка відпущена — стан піна стане невизначеним. Щоб уникнути цього, потрібно забезпечити, аби при ненатиснутій кнопці на вході був стабільний низький рівень (логічний 0). Проте пряме з’єднання піна із «землею» без резистора призведе до короткого замикання між живленням і землею під час натискання кнопки, що може пошкодити схему або саму кнопку. Тому єдино правильним рішенням є використання підтягувального резистора, який забезпечує безпечну та стабільну роботу схеми.

Щоб правильно підібрати номінал pull-up або pull-down резистора, потрібно знайти баланс між стабільністю сигналу та енергоспоживанням. Якщо опір занадто великий, лінія стає чутливою до електричних завад і може випадково змінювати логічний стан. Якщо ж опір занадто малий, через резистор протікає надмірний струм, що збільшує споживання енергії і створює додаткове навантаження на джерело живлення. Для більшості мікроконтролерів оптимальним вважається діапазон від 4,7 кОм до 10 кОм — такі значення забезпечують надійне формування логічного рівня при мінімальному струмі. У випадках, коли лінія довга або в середовищі багато шумів, опір доцільно зменшити до 1–4,7 кОм, а якщо важлива економія енергії — збільшити до 20–50 кОм.

Позитивна та негативна логіка

Під час використання резистора pull-down цифровий сигнал матиме низький рівень, коли перемикач розімкнений, і високий рівень — коли він натиснутий (див. Рисунок 2, зліва). Така схема відповідає позитивній логіці, оскільки активному стану відповідає логічна «1». Навпаки, у випадку з pull-up резистором сигнал перебуває у високому стані, доки перемикач не натиснутий, і переходить у низький стан під час натискання (Рисунок 2, справа). Це приклад негативної логіки, коли активному стану відповідає логічний «0».

Вибір між позитивною та негативною логікою залежить від того, який рівень сигналу вважається “активним” у вашій схемі. Якщо зручніше, щоб натискання кнопки або спрацьовування датчика відповідало логічній “1”, — обирають позитивну логіку з резистором pull-down. Якщо ж активний стан повинен відповідати логічному “0” (наприклад, коли пристрій має бути активним при низькому рівні), — застосовують негативну логіку з резистором pull-up.

У більшості мікроконтролерів використання pull-up резисторів є зручнішим рішенням, оскільки багато входів уже мають вбудовані підтягувальні резистори, які можна активувати програмно. Дізнатися про їх наявність можна з datasheet мікроконтролера — у розділі про конфігурацію портів вводу/виводу. Зазвичай активація виконується через встановлення відповідного біта в регістрі або спеціальну команду, наприклад, в Arduino це робиться просто — pinMode(pin, INPUT_PULLUP);.  Це дозволяє обійтися без зовнішніх компонентів і спрощує схему підключення — достатньо просто під’єднати кнопку або датчик між вхідним піном і «землею». У такому випадку, коли контакт розімкнений, внутрішній резистор утримує пін у логічному “1”, а при натисканні кнопки він замикається на “0”. Такий підхід не лише економить місце на платі, а й зменшує кількість деталей, спрощує трасування доріжок і знижує ризик помилок у з’єднаннях.

Обробка натискання кнопок в коді

Щоб перемикач працював коректно, у коді потрібно ініціалізувати відповідний пін як вхідний. Під час ініціалізації вмикається тактування порту, встановлюється режим «вхід» у регістрі напрямку, вимикається альтернативна функція та активується сам пін. Важливо, що програмна реалізація виконана обережно — змінюється лише біт конкретного піна, не зачіпаючи інші біти порту. Функція зчитування стану входу (digitalRead) отримує поточне значення піна та повертає true, якщо перемикач натиснуто, або false, якщо він відпущений.

В прикладі нижче наведено приклад на бібліотеці Arduino. Воно містить функцію ініціалізації, яка викликається автоматично один раз, і другу функцію, яка викликається в циклі для зчитування поточного стану перемикача.

#include <Arduino.h>  //підключаємо бібліотеку Arduino

void setup() { //ця функція викликається 1 раз при запуску
pinMode(PB0, INPUT); //переводимо 0-вий пін порта B в режим вводу
}

void loop() { //основний цикл програми
//зчитуємо значення з піну кнопки
//коли кнопка натиснута - 1 (високий рівень), інакше - 0 (низький рівень)
bool btnPressed = digitalRead(PB0);
}

Проблема брязкоту контактів (debounce)

У реальних кнопках під час натискання контакти замикаються не миттєво, а кілька разів «підскакують», утворюючи серію коротких імпульсів. Якщо просто зчитувати стан піна, мікроконтролер може сприйняти одне натискання як кілька.

Щоб уникнути цього, використовують програмне усунення брязкоту контактів (debounce). Найпростіший спосіб — після фіксації зміни стану кнопки зробити коротку паузу (10–50 мс), щоб сигнали стабілізувались:

if (digitalRead(PB0)) {  // якщо кнопка натиснута
  delay(20);           // невелика пауза
  if (digitalRead(PB0)) {  // перевірити ще раз
        ... //виконуємо дію
    }
}

Тепер натискання обробляється один раз і не викликає «миготіння» чи помилкових спрацьовувань.

Виведення даних за допомогою LED

Світлодіод (LED) випромінює світло, коли через нього проходить електричний струм. Світлодіоди, як і звичайні діоди, мають полярність - струм повинен текти від анода до катода, щоб світлодіод засвітився. Анод позначається як a або "+", а катод — як k або "−". Катод має коротший вивід, і на корпусі круглих світлодіодів зазвичай є невелике плоске місце, що також позначає катод. Для управління роботою світлодіода його підключають до вивода мікроконтролера і з коду керують ним, встановлюючи високий або низький рівень на піні за потреби. Але просто так підключити світлодіод до виводу не вийде, так як напруга і струм виводу частіше за все не відповідають робочій напрузі і струму діода.

Розрахунок схеми підключення світлодіода до мікроконтролера

Вольт-амперна характеристика діодуЯскравість світлодіода залежить від прикладеної електричної потужності (P = I × V). На рисунку 3, зліва зображено графік залежності струму діода від прикладеної до нього напруги. Легко помітити, що до значення 1,6В струм через діод майже нульовий - діод закритий і не світиться. Після цього струм починає експоненційно зростати і вже після 2,4В струм практично наближається до нескінченності. Таким чином, ледь змінюючи напругу діода досить сильно змінюється його струм. Це важливо розуміти при розрахунках схем підключення. Щоб розібратися з розрахунками, розглянемо декілька ситуацій.

У всіх ситуаціях ми маємо мікроконтролер з напругою виводу 3,3В і максимальним струмом виводу 20мА (0,02А).

Ситуація 1. Нам необхідно під'єднати світлодіод з робочою напругою 3,3В і робочим струмом 20мА. Це ідеально підходить під наш чіп, можна просто підключати анодом до виводу, а катодом до "землі". І тепер, при подачі високого рівня на пін, світлодіод світиться, при низькому рівні - ні. Це ідеальна ситуація і майже ніколи не виникає. Схема зображена на рисунку 4а.

Ситуація 2. Робоча напруга і струм діода нижчі за напругу і струм виводу мікроконтролера. В такому випадку необхідно послідовно діоду підключити резистор для гасіння надлишкової напруги. Номінал резистора розраховують за формулою:

Rгас = (Uвив - Uдіо) / I

Тут Rгас - опір резистора гасіння, Uвив - напруга виводу мікроконтролера, Uдіо - напруга, що має бути на діоді при бажаному струмі, I - струм в колі вивод-резистор-діод (Рис. 4б).

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

Спочатку ми визначаємось зі струмом, який нам необхідний. Наприклад, струм діода 15мА, а максимальний струм виводу - 20мА. Беремо найменший показник - 15. Напруга діода - 2,2В, а напруга виводу - 3,3В. Тож, рахуємо: (3,3 - 2,2) / 0,015 = 100 (Ом). Отже, резистор гасіння має бути 100 Ом. Якщо нам потрібно щоб діод світився в півнакала - дивимось його вольт-амперну характеристику і знаходимо необхідний струм і напругу діода. Враховуючи нелінійність кривої ВАХ, зазвичай достатньо лише трохи збільшити опір резистора для падіння потужності в 2 рази.

Ситуація 3. Якщо робоча напруга та/або струм діода перевищують струм і напругу виводу, то потрібно використовувати допоміжні пристрої: механічні реле, електронні реле, так звані драйвери і т.д. Існують світлодіоди, вже скомпоновані з електронікою керування. Це відноситься до будь якого потужного пристрою, не тільки діодів. Я не буду тут приводити точний розрахунок такої схеми, так як це ціла окрема тема, приклади підключень через керуючі пристрої зображені на Рисунку 4в.

Керування світлодіодом в коді

Для керування світлодіодом необхідний пін ініціалізується як пін виводу, далі в основному циклі програми встановлюється необхідне значення виводу: "HIGH" для ввімкнення діоду, "LOW" для вимкнення. Приклад вказаний з використанням бібліотеки Arduino:

#include <Arduino.h>  //підключаємо бібліотеку Arduino

void setup() { //ця функція викликається 1 раз при запуску
pinMode(PB0, OUTPUT); //переводимо 0-вий пін порта B в режим ВИВОДУ
}

void loop() { //основний цикл програми
digitalWrite(PB0, HIGH);
delay(1000);

 digitalWrite(PB0, LOW);
delay(1000);

}

Приклад простої, але повноцінної схеми керування LED-індикацією за допомогою кнопки можна подивитись можна подивитись в статті Простий лічильник на Arduino Nano