Статьи

Цикли FOR і WHILE в Arduino

  1. Цикл WHILE і нескінченний цикл в Ардуіно
  2. синтаксис WHILE
  3. Цикл FOR в Ардуіно
  4. Синтаксис циклу FOR
  5. Цикл do while
  6. Оператори continue і break
  7. Вкладені цикли в Ардуіно
  8. Детальніше про циклах
  9. Навіщо потрібен цикл
  10. Правила синтаксису
  11. висновок

Цикли з використанням операторів for і while є однією з найважливіших конструкцій мови C ++, що лежить в основі Ардуіно. Вони зустрічаються абсолютно в кожному скечте, навіть якщо ви не підозрюєте про це. У цій статті ми познайомимося ближче з циклами, дізнаємося, в чому відмінність for від while, як можна спростити написання програми з їх допомогою і яких помилок слід уникати.

Цикл WHILE і нескінченний цикл в Ардуіно

Якщо ви поки ще програміст і хочете зрозуміти, що взагалі таке цикл і навіщо він потрібен - подивіться наступний розділ цієї статті з докладним описом.

Оператор WHILE використовується в C ++ і Ардуіно для організації повтору одних і тих команд довільне кількості раз. У порівнянні з FOR цикл WHILE виглядає простіше, він зазвичай використовується там, де нам не потрібен підрахунок числа ітерацій в змінної, а просто потрібно повторювати код, поки щось не зміниться, не наступить якісь подія.

синтаксис WHILE

синтаксис WHILE

while (<умова або список умов>)
{
<Програмний блок, який буде повторюватися>
}

В якості умов може використовуватися будь-яка конструкція мови, яка повертає логічне значення. Умовами можуть бути операції порівняння, функції, константи, змінні. Як і при будь-яких інших логічних операціях в Ардуіно будь-яке значення, крім нуля буде сприйматися як істина (true), нуль - брехня (false).

приклад:

// Нескінченний цикл while (true) {Serial.println ( "Waiting ..."); } // Цикл, що виконується до зміни значення функції checkSignal () while (! CheckSignal ()) {Serial.println ( "Waiting ..."); }

Зверніть увагу, що оператор while може використовуватися без виділення блоку фігурними дужками, в цьому випадку повторюватися буде перша команда, зустрінута після циклу. Вкрай не рекомендується використовувати while без фігурних дужок, тому що в цьому випадку можна дуже легко припуститися помилки. приклад:

while (true) Serial.print ( "Waiting for interruption"); delay (1000);

В даному випадку напис буде виводитися в нескінченному циклі без пауз, тому що команда delay (1000) повторюватися не буде. Ви можете витратити багато часу, виявляючи такі помилки - набагато простіше використовувати фігурну дужку.

Приклад використання циклу while

Найчастіше while використовується для очікування якої-небудь події. Наприклад, готовності об'єкта Serial до роботи.

Serial.begin (9600); while (! Serial) {; // Для деяких плат Ардуіно потрібно чекати, поки не звільниться послідовний порт}

Приклад очікування приходу символу від зовнішніх пристроїв по UART:

while (Serial.available ()) {int byteInput = Seria.read (); // Якісь інші дії}

В даному випадку ми будемо зчитувати значення до тих пір, поки Serial.available () буде повертати не нульове значення. Як тільки всі дані в буфері закінчаться, цикл зупиниться.

Цикл FOR в Ардуіно

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

Синтаксис циклу FOR

Синтаксис циклу FOR

Тут конструкція буде трохи складніше:
for (<початкове значення лічильника>; <умова продовження виконання циклу>; <зміна значення лічильника на кожному кроці>) {
<спісок_команд>
}

Найпростіший приклад:

for (int i = 5; i <10; i ++) {// Конструкція «3 в одному» pinMode (i, OUTPUT); }

Ми відразу створили змінну, ініціалізували її, вказали, що в кінці кожного циклу значення лічильника потрібно збільшувати на одиницю. І все - тепер можна використовувати змінну всередині циклу.

Крок змінної може бути іншим. Ось приклади:

  • for (int i = 0; i <10; i = i + 2) // Крок 2
  • for (int i = 0; i <10; i + = 2) // Аналогічний попередньому
  • for (int i = 10; i> 0; i-) // Йдемо назад - від 10 до 1

Цикл do while

Цикл do while

У деяких випадках нам потрібно організувати цикл таким чином, щоб інструкції блоку виконувалися хоча б один раз, а потім вже здійснювалася перевірка. Для таких алгоритмів можна використовувати конструкцію do while. приклад:

do {Serial.println ( "Working"); } While (checkSomething ());

Ніяких складнощів цей варіант циклу не представляє - ми просто перенесли блок з умовами вниз, тому весь вміст всередині фігурних дужок після оператора do виконається до першої перевірки.

Оператори continue і break

Бувають ситуації, коли вам потрібно екстрено перервати виконання циклу всередині блоку циклу, не чекаючи до переходу до блоку перевірки умов. Для цього можна використовувати оператор break:

while (true) {if (checkSomething ()) {break; }}

Якщо ми просто хочемо зупинити хід виконання поточної ітерації, але не вийти з циклу, а перейти до блоку перевірки умов, то повинні використовувати оператор continue:

while (true) {if (checkSomething ()) {continue; }}

Оператори continue і break можуть використовуватися з усіма варіантами циклів FOR і WHILE.

Вкладені цикли в Ардуіно

Будь-які варіанти циклів можна спокійно поєднувати один з одним, роблячи вкладені конструкції. Змінні, визначені в блоці «вищого» циклу будуть доступні у внутрішньому. Самий часто зустрічається приклад такого роду циклів - обхід двовимірних масивів. У наступному прикладі ми використовуємо подвійний цикл: перший буде перебирати рядки (змінна i), другий, вкладений - стовпці (змінна j) масиву, який ми визначили в змінно arr.

int arr [10] [3]; void setup () {for (int i = 0; i <10; i ++) {for (int j = 0; j <3; j ++) {arr [i] [j] = i * j; Serial.println (arr [i] [j]); }}}

Детальніше про циклах

Якщо ви ніколи не працювали з циклами, давайте трохи зануримося в світ теорії і розберемося, що таке цикли і навіщо нам потрібні ці загадкові конструкції мови.

Навіщо потрібен цикл

Насправді, головна задача циклу - повторити одні й ті ж конструкції мови кілька разів. Така потреба виникає практично в кожній програмі і вже точно без циклу не обходиться жоден скетч Ардуіно - функція loop () теж викликається в нескінченному циклі.

Давайте розглянемо наступний приклад. Вам потрібно подати харчування одночасно на 5 світлодіодів, підключених до плати Arduino з 5 по 9 Піни. Найочевиднішим варіантом для цього буде розміщення п'яти інструкцій поспіль:

digitalWrite (5, HIGH);

digitalWrite (6, HIGH);

digitalWrite (7, HIGH);

digitalWrite (8, HIGH);

digitalWrite (9, HIGH);

Опустимо поки питання ризикованості такого дії, адже одночасне включення такого числа світлодіодів створює підвищене навантаження на схему живлення плати. Головне для нас зараз те, що ми створили п'ять рядків коду, кожна з яких відрізняється від інших лише на одну цифру. Такий підхід має наступні недоліки:

  • При будь-якій зміні доведеться вносити правки одночасно в безліч рядків. Наприклад, якщо нам знадобиться перемкнути світлодіоди на Піни з 2 по 6 або не включити, а вимкнути напругу, то доведеться зробити 5 змін в коді. А якщо інструкцій і змін буде більше?
  • Об'ємний код з великою кількістю однотипних інструкцій незручно і неприємно читати. П'ять однакових рядків - не сильно страшно. Але звичка до брудного коду згодом призведе до десяткам і сотням зайвих сторінок в лістингу, що повалить в зневіру і вас, і ваших колег.
  • У процесі «копіпастінга» майже однакових інструкцій можна легко зробити помилку, наприклад, забувши поміняти номер пинов: digitalWrite (5, HIGH); digitalWrite (5, HIGH);
  • Ви з легкістю провалите співбесіду в будь-яку нормальну софтверну компанію, показавши інтерв'юеру такий код.

Виходячи з усього цього, можна зробити висновок, що повторне багаторазове використання одних і тих же рядків майже завжди потрібно уникати і замінювати циклами. Більш того, у багатьох ситуаціях без циклів не обійтися в принципі, їх нічим замінити не вийде. Ви не зможете змінити кількість повторень коду в момент виконання програми. Наприклад, вам потрібно обробити кожен елемент масиву даних, що надійшов від зовнішніх пристроїв. Ви ніколи не передбачите, скільки буде даних, скільки разів повторити обробку і тому не зможете вставити потрібну кількість інструкцій в момент написання статті.

І тут нам на допомогу приходять цикли.

Правила синтаксису

Цикл в Ардуіно - це спеціальний програмний блок, який в момент виконання програми буде викликатися певну кількість разів. В рамках цього блоку ми описуємо і самі команди, які будуть викликатися і правила, за якими контролер буде визначати, скільки разів їх потрібно викликати.

У нашому описаному вище прикладі ми могли б сказати контролера наступне:

Повтори команду digitalWrite 5 разів

В ідеальному світі з роботами-програмістами цього б, напевно, вистачило, але так як ми розмовляємо з комп'ютером на мові C ++, нам потрібно перевести цю фразу на цю мову:

Повтори команду - потрібно використовувати спеціальні інструкції, що говорять контролера, що зараз починається щось цікаве з циклами while або for

digitalWrite - залишаємо як є, але пишемо один раз і укладаємо в фігурні дужки. Як бути з номерами пинов - трохи нижче.

5 раз - використовувати для цього лічильник, який буде збільшуватися при кожному повторенні. На початку (або наприкінці) блоку можна порівнювати значення цього лічильника з граничним значенням (в даному випадку 5) за допомогою операції порівняння.

Давайте подивимося на приклад такої «перекладеної» команди циклу з інструкцією while:

int counter = 0; // Змінна, в якій буде зберігатися значення лічильника // Ми просимо процесор повторювати конструкцію в фігурних дужках до тих пір, поки умова в круглих дужках буде повертати істину. // У нашому випадку counter - наш лічильник, 5 - граничне значення, умова значення лічильника менше 5. // Але ми можемо вказувати зовсім різні логічні оператори while (counter <5) {digitaWrite (5, HIGH); // Будемо включати світлодіод counter ++; // Збільшуємо значення лічильника} // Дійшовши до сюди, виконуючий процесор переміститься в початок блоку і знову займеться перевіркою умов. Якщо умови повернуть істину, команди в блоці між {і} виконуватися ще раз. Якщо умова не виконається - процесор переміститься до кінця блоку і піде далі. Цей цикл більше його не зацікавить.

Тим, хто помітив у наведеному коді помилку, ставимо п'ятірку і пишемо блок циклу по-іншому:

while (counter <5) {// Ось тепер ми будемо включати різні світлодіоди, з 5 (0 + 5) по 9 (4 + 5) digitalWrite (counter + 5, HIGH); counter ++; }

Такого ж результату можна досягти з використанням циклу FOR:

for (int counter = 0; counter <5; counter ++) {digitalWrite (counter + 5, HIGH); }

Як бачимо, в даному випадку ми відразу поміщаємо всі необхідні операції з лічильником в одну інструкцію FOR - це набагато зручніше, якщо вам потрібно підраховувати потрібну кількість.

Детальну інформацію про правила використання циклів ви можете отримати у відповідних розділах цієї статті.

висновок

У цій статті ми розглянули дуже важливі конструкції мови Ардуіно: цикли FOR і WHILE. Ви зможете зустріти ці оператори практично в будь-якому більш-менш складному скетчі, тому що без циклів багато операцій над даними були б неможливі. Нічого складного в синтаксисі циклів немає - ви без праці до них звикнете і зможете активно використовувати в своїх проектах.

У статті використовувалися зображення з сайту https://puzzleweb.ru/ .

А якщо інструкцій і змін буде більше?

Новости