Робимо вогні, що біжать, зі світлодіодів на Arduino. У даному випадку використовується Arduino Mega 2560, який потенційно здатний керувати доріжкою, що біжить, з 54-х світлодіодів. Але схема та програма не зміняться, якщо ви використовуватимете інші контролери з платформи Arduino такого типу (UNO, Leonardo...)
Схема підключення світлодіодів до Ардуїно Мега 2560
Так виглядає скетч у вікні стандартної програми для програмування Ардуїно.
Текст програми для реалізації вогнів, що біжать на платформі ардуїно.
int first_out = 11; //перший дискретний вихід
int last_out = 13; //останній дискретний вихід
//блок для ініціалізації входів-виходів та інших вихідних даних
last_out = last_out + 1; //додаємо одиницю для коректного використання у циклах
//Визначення 11-го, 12-го і 13-го дискретних висновків плати Ардуїно як виходи
for (i = first_out; i< last_out; i++) { pinMode(i, OUTPUT); }
for (t = first_out; t< last_out; t++) { //перебираем номера дискретных выходов 11,12,13 поочереди
digitalWrite(t, HIGH); //Запалювання наступного світлодіода
delay(500); //Затримка 500мсек
for (i = first_out; i< last_out; i++) { digitalWrite(i, LOW); }//гасим все светодиоды
Для збільшення кількості керованих світлодіодів у гірлянді, у програмі потрібно буде просто замінити значення змінних first_out та last_out. Перша змінна зберігає початковий дискретний вихід контролера, а друга останній із групи виходів, що йдуть поспіль. Наприклад, якщо ми хочемо підключити 10 світлодіодів у гірлянду, вводимо такі значення: first_out = 4, last_out = 13. І світлодіоди до висновків по порядку з 4-го до 13-го. А перший і другий висновок дискретних входів-виходів краще не чіпати, оскільки їм заважає USB-порт, підключений до комп'ютера.
У цьому уроці ми продовжимо роботу зі світлодіодами, але кількість світлодіодів збільшимо до 5. І зробимо ефект вогню, що біжить. Для управління світлодіодами використовуватимемо маніпуляції з портами Arduino. Ми безпосередньо записуватимемо дані в порти Arduino. Це краще, ніж працювати з конкретними входами/виходами контролера. Це дозволить встановити значення для світлодіодів за допомогою лише однієї операції.
Arduino UNO має 3 порти:
B (цифрові входу/виходу з 8 по 13)
C (аналогові входи)
D (цифрові входи/виходи з 0 по 7)
Кожен порт управляється 3 регістрами. Реєстр DDRвизначає чим буде нога (pin) входом чи виходом. За допомогою регістру PORT можна встановити pin у стан HIGHабо LOW. За допомогою регістра PIN можна вважати стан ніжок Arduino, коли вони працюють на вхід.
Ми будемо використовувати порт B. Спочатку ми повинні встановити всі ніжки порту B як цифрові виходу. У порту B є лише 6 ніжок. Біти регістру для порту DDRB повинні бути встановлені в 1, якщо нога буде використовуватися як вихід (OUTPUT), і в 0, якщо нога буде використовувати як вхід (INPUT). Біти портів нумеруються з 0 до 7, але не завжди містять всі 8 ніг.
Приклад:
DDRB = B00111110; // встановити ніжки порту з 1 по 5 як виходу, а 0 як вхід.
Зверніть увагу, що у мікроконтролерах фірми Microchip все навпаки. 0 біт – нога працює як вихід, а 1 – як вхід.
У нашому проекті вогню, що біжить, ми будемо використовувати 5 виходів:
DDRB = B00011111; // встановити ноги порту з 0 по 4 як виходу
Для запису значень у порт необхідно використовувати регістр PORTB.
Засвітити перший світлодіод можна командою:
PORTB = B00000001;
перший та четвертий:
PORTB = B00001001;
Тепер ви бачите, як легко ми можемо вмикати та вимикати світлодіоди. Тепер розповімо вам про операторів зсуву
Є 2 оператори двійкового зсуву: оператор зсуву вліво<< и оператор сдвига вправо >>. Оператор зсуву вліво<< заставляет все биты сдвигаться влево, соответственно оператор сдвига вправо >> Зсув біти вправо.
Приклад:
varA = 1; // 00000001
varA = 1<< 0; // 00000001
varA = 1<< 1; // 00000010
varA = 1<< 2; // 00000100
Тепер повернемося до нашої програми, яка показана нижче.
Нам потрібно ввести 2 змінні:перша upDown буде містити значення куди рухатися - вгору чи вниз, а друга cylon - які світлодіоди запалювати.
У функції setup()ми визначаємо які ніжки мають працювати як виходу.
У головному циклі програми loop(), світлодіоди по черзі загоряються вгору шляхом збільшення змінної cylon, а коли доходить до найвищого, то змінної upDownприсвоюється 0 і світлодіоди спалахують вниз по черзі.
/* Вогонь, що біжить. 5 світлодіодів */ unsigned char upDown=1; // починаємо з руху нагору unsigned char cylon=0; // визначає черговість LED void setup() ( DDRB = B00011111; // встановлюємо порт B з 0 по 4 як виходу ) void loop() ( if(upDown==1)( // якщо йдемо вгору, то cylon++; if( cylon>=4) upDown=0;// коли досягнутий найбільший номер LED, то в наступному циклі йдемо вниз) else (cylon--; if(cylon==0) upDown=1; // коли досягнуть найменший номер LED, то в наступному циклі йдемо вгору) PORTB = 1<< cylon; //сдвиг delay(200); // пауза 200 мс }
У цьому уроці ми продовжимо роботу зі світлодіодами, але кількість світлодіодів збільшимо до 5. І зробимо ефект вогню, що біжить. Для управління світлодіодами використовуватимемо маніпуляції з портами Arduino. Ми безпосередньо записуватимемо дані в порти Arduino. Це краще, ніж працювати з конкретними входами/виходами контролера. Це дозволить встановити значення для світлодіодів за допомогою лише однієї операції.
Arduino UNO має 3 порти:
- B (цифрові входу/виходу з 8 по 13)
- C (аналогові входи)
- D (цифрові входи/виходи з 0 по 7)
Кожен порт управляється 3 регістрами. Регістр DDR визначає, чим буде нога (pin) входом або виходом. За допомогою регістру PORT можна встановити pin у стан HIGH або LOW. За допомогою регістра PIN можна вважати стан ніжок Arduino, коли вони працюють на вхід.
Ми будемо використовувати порт B. Спочатку ми повинні встановити всі ніжки порту B як цифрові виходу. У порту B є лише 6 ніжок. Біти регістру для порту DDRB повинні бути встановлені в 1, якщо нога буде використовуватися як вихід (OUTPUT), і в 0, якщо нога буде використовувати як вхід (INPUT). Біти портів нумеруються з 0 до 7, але не завжди містять всі 8 ніг.
приклад:
DDRB = B00111110; // встановити ніжки порту з 1 по 5 як виходу, а 0 як вхід.
Зверніть увагу, що у мікроконтролерах фірми Microchip все навпаки. 0 біт – нога працює як вихід, а 1 – як вхід.
У нашому проекті вогню, що біжить, ми будемо використовувати 5 виходів:
DDRB = B00011111; // встановити ноги порту з 0 по 4 як виходу
Для запису значень у порт необхідно використовувати регістр PORTB. Засвітити перший світлодіод можна командою:
PORTB = B00000001;
перший та четвертий:
PORTB = B00001001;
Тепер ви бачите, як легко ми можемо вмикати та вимикати світлодіоди. Тепер розповімо вам про операторів зсуву
Є 2 оператори двійкового зсуву: оператор зсуву вліво<< и оператор сдвига вправо >>. Оператор зсуву вліво<< заставляет все биты сдвигаться влево, соответственно оператор сдвига вправо >> Зсув біти вправо.
Приклад:
VarA = 1; // 00000001
varA = 1<< 0; // 00000001
varA = 1<< 1; // 00000010
varA = 1<< 2; // 00000100
Тепер повернемося до нашої програми, яка показана нижче. Нам потрібно ввести 2 змінні: перша upDownміститиме значення куди рухатися - вгору чи вниз, а друга cylonякі світлодіоди запалювати.
У функції setup()ми визначаємо які ніжки мають працювати як виходу.
У головному циклі програми loop(), світлодіоди по черзі загоряються вгору шляхом збільшення змінної cylon, а коли доходить до найвищого, то змінної upDownприсвоюється 0 і світлодіоди спалахують вниз по черзі.
Ардуїно початківцям
У цьому уроці ми продовжимо роботу зі світлодіодами, але кількість світлодіодів збільшимо до 5. І зробимо ефект вогню, що біжить. Для управління світлодіодами використовуватимемо маніпуляції з портами Arduino. Ми безпосередньо записуватимемо дані в порти Arduino. Це краще, ніж працювати з конкретними входами/виходами контролера. Це дозволить встановити значення для світлодіодів за допомогою лише однієї операції.
Arduino UNO має 3 порти:
- B (цифрові входу/виходу з 8 по 13)
- C (аналогові входи)
- D (цифрові входи/виходи з 0 по 7)
Кожен порт управляється 3 регістрами. Регістр DDR визначає, чим буде нога (pin) входом або виходом. За допомогою регістру PORT можна встановити pin у стан HIGH або LOW. За допомогою регістра PIN можна вважати стан ніжок Arduino, коли вони працюють на вхід.
Ми будемо використовувати порт B. Спочатку ми повинні встановити всі ніжки порту B як цифрові виходу. У порту B є лише 6 ніжок. Біти регістру для порту DDRB повинні бути встановлені в 1, якщо нога буде використовуватися як вихід (OUTPUT), і в 0, якщо нога буде використовувати як вхід (INPUT). Біти портів нумеруються з 0 до 7, але не завжди містять всі 8 ніг.
Приклад:
DDRB = B00111110; // встановити ніжки порту з 1 по 5 як виходу, а 0 як вхід.
Зверніть увагу, що у мікроконтролерах фірми Microchip все навпаки. 0 біт – нога працює як вихід, а 1 – як вхід.
У нашому проекті вогню, що біжить, ми будемо використовувати 5 виходів:
DDRB = B00011111; // встановити ноги порту з 0 по 4 як виходу
Для запису значень у порт необхідно використовувати регістр PORTB. Засвітити перший світлодіод можна командою:
PORTB = B00000001;
перший та четвертий:
PORTB = B00001001;
Тепер ви бачите, як легко ми можемо вмикати та вимикати світлодіоди. Тепер розповімо вам про операторів зсуву
Є 2 оператори двійкового зсуву: оператор зсуву вліво<< и оператор сдвига вправо >>. Оператор зсуву вліво<< заставляет все биты сдвигаться влево, соответственно оператор сдвига вправо >> Зсув біти вправо.
Приклад:
varA = 1; // 00000001
varA = 1<< 0; // 00000001
varA = 1<< 1; // 00000010
varA = 1<< 2; // 00000100
Тепер повернемося до нашої програми, яка показана нижче. Нам потрібно ввести 2 змінні: перша upDownміститиме значення куди рухатися - вгору чи вниз, а друга cylonякі світлодіоди запалювати.
У функції setup()ми визначаємо які ніжки мають працювати як виходу.
У головному циклі програми loop(), світлодіоди по черзі загоряються вгору шляхом збільшення змінної cylon, а коли доходить до найвищого, то змінної upDownприсвоюється 0 і світлодіоди спалахують вниз по черзі.
Код: /* Вогонь, що біжить. 5 світлодіодів */ unsigned char upDown=1; // починаємо з руху нагору unsigned char cylon=0; // визначає черговість LED void setup() ( DDRB = B00011111; // встановлюємо порт B з 0 по 4 як виходу ) void loop() ( if(upDown==1)( // якщо йдемо вгору, то cylon++; if( cylon>=4) upDown=0;// коли досягнутий найбільший номер LED, то в наступному циклі йдемо вниз) else (cylon--; if(cylon==0) upDown=1; // коли досягнуть найменший номер LED, то в наступному циклі йдемо вгору) PORTB = 1<< cylon; //сдвиг delay(200); // пауза 200 мс
У цьому експерименті ми змушуємо вогник бігти за світлодіодною шкалою.
СПИСОК ДЕТАЛІВ ДЛЯ ЕКСПЕРИМЕНТУ
- 1 плата Arduino Uno;
- 1 безпайкова макетна плата;
- 1 світлодіодна шкала;
- 10 резисторів номіналом 220 Ом;
- 11 дротів «тато-тато».
ПРИНЦИПОВА СХЕМА
СХЕМА НА МАКЕТНІЙ ПЛАТІ
СКЕТЧ
скачати для Arduino IDE// Світлодіодна шкала підключена до групи пінів розташованих // підряд. Даємо зрозумілі імена першому і останньому пінам #define FIRST_LED_PIN 2 #define LAST_LED_PIN 11 void setup() ( // у шкалі 10 світлодіодів. Ми могли б написати pinMode 10 // раз: для кожного з пінів, але це б роздуло код і // зробило його зміну більш проблематичним.// Тому краще скористатися циклом.Ми виконуємо // pinMode для (англ. for) кожного піна (змінна pin) // від першого (= FIRST_LED_PIN) до останнього включно // (<= LAST_LED_PIN), всякий раз продвигаясь к следующему // (++pin увеличивает значение pin на единицу) // Так все пины от 2-го по 11-й друг за другом станут выходами for (int pin = FIRST_LED_PIN; pin <= LAST_LED_PIN; ++pin) pinMode(pin, OUTPUT); } void loop() { // получаем время в миллисекундах, прошедшее с момента // включения микроконтроллера unsigned int ms = millis(); // нехитрой арифметикой вычисляем, какой светодиод // должен гореть именно сейчас. Смена будет происходить // каждые 120 миллисекунд. Y % X — это остаток от // деления Y на X; плюс, минус, скобки — как в алгебре. int pin = FIRST_LED_PIN + (ms / 120) % 10; // включаем нужный светодиод на 10 миллисекунд, затем — // выключаем. На следующем проходе цикла он снова включится, // если гореть его черёд, и мы вообще не заметим отключения digitalWrite(pin, HIGH); delay(10); digitalWrite(pin, LOW); }
ПОЯСНЕННЯ ДО КОДУ
- За допомогою виразу forми організуємо цикл із лічильником
. У цьому випадку для налаштування портів на вихід. Щоб зробити такий цикл, потрібно:
- Ініціалізувати змінну-лічильник, надавши їй первісне значення. У нашому випадку: int pin = FIRST_LED_ PIN ;
- Вказати умову, до досягнення якої повторюватиметься цикл. У нашому випадку: pin<= LAST_LED_ PIN ;
- Визначити правило, яким буде змінюватися лічильник. У нашому випадку ++pin(Див. нижче про оператора ++ ).
- Наприклад, можна зробити цикл for (int i = 10; i > 0; i = i - 1). В цьому випадку:
- Змінної i надається значення 10 ;
- Це значення задовольняє умову i > 0 ;
- Тому блок коду, поміщений цикл, виконується перший раз;
- Значення iзменшується на одиницю, згідно з заданим правилом, і набуває значення 9 ;
- Блок коду виконується вдруге;
- Все повторюється знову і знову аж до значення iрівного 0 ;
- Коли iстане рівна 0 , умова i > 0не виконається, та виконання циклу закінчиться;
- Контролер перейде до коду, наступного за циклом for ;
- Поміщайте код, який потрібно зациклити між парою фігурних дужок. {} якщо в ньому більше однієї інструкції;
- Змінна-лічильник, що оголошується в операторі forможе використовуватися всередині циклу. Наприклад, у цьому експерименті pinпослідовно приймає значення від 2 до 11 і, будучи переданою в pinModeдозволяє налаштувати 10 портів одним рядком, поміщеною в цикл;
- Змінні-лічильники видно лише всередині циклу. Тобто. якщо звернутися до pinдо або після циклу компілятор видасть помилку про неоголошену змінну;
- Конструкція i = i - 1у поясненні вище не є рівнянням! Ми використовуємо оператор присвоєння = для того, щоб у змінну iпомістити значення, що дорівнює поточному значенню i, зменшеному на 1 ;
- Вираз ++pin- Це т.зв. оператор інкремента , застосований до змінної pin. Ця інструкція дасть той самий результат, що pin = pin + 1;
- Аналогічно інкременту працює оператор декременту - - , що зменшує значення на одиницю. Докладніше про це у статті про арифметичні операції;
- Тип даних unsigned intвикористовують із зберігання цілих чисел без знака, тобто. тільки невід'ємних . За рахунок зайвого біта, який тепер не використовується для зберігання знака, ми можемо зберігати у змінній такого типу значення до 65 535 ;
- Функція millisповертає кількість мілісекунд, що пройшли з моменту включення або перезавантаження мікроконтролера. Тут ми використовуємо її для відліку часу між перемикання світлодіодів;
- За допомогою виразу (ms/120) % 10ми визначаємо, який із 10 світлодіодів має горіти зараз. Перефразовуючи, ми визначаємо який відрізок завдовжки 120 мс йде зараз і який його номер усередині поточного десятка. Ми додаємо порядковий номер відрізка до номера порту, який у поточному наборі виступає першим;
- Те, що ми гасимо світлодіод за допомогою digitalWrite(pin, LOW)всього через 10 мс після включення непомітно оку, т.к. дуже скоро буде знову обчислено, який із світлодіодів включати, і він буде включений - щойно погашений або наступний.
ПИТАННЯ ДЛЯ ПЕРЕВІРКИ СЕБЕ
- Чому в цьому експерименті ми підключаємо світлодіодну шкалу, не використовуючи транзистор?
- Якби ми включали світлодіоди лише на портах 5, 6, 7, 8, 9, що потрібно було б змінити у програмі?
- За допомогою якоїсь іншої інструкції можна виконати дію, еквівалентну ++pin ?
- У чому різниця між змінними типами intі unsigned int ?
- Що повертає функція millis() ?
- Як у цьому експерименті ми обчислюємо номер порту, у якому потрібно включити світлодіод?
ЗАВДАННЯ ДЛЯ САМОСТІЙНОГО РІШЕННЯ
- Змініть код так, щоб світлодіоди перемикалися раз на секунду.
- Не вимикаючи порти, зробіть так, щоб вогник біг тільки по чотирьох розподілах шкали.
- Переробіть програму так, щоб замість int pin = FIRST_LED_ PIN + (ms/120) % 10переміщенням вогника керував цикл for .
- Не змінюючи місцями дроти, змініть програму так, щоб вогник бігав у зворотному напрямку.