Умови if і else в Arduino. Arduino - керуючі оператори Arduino перехід на початок програми за умовою

Конструкція forвикористовується для повторення блоку операторів, укладених у фігурні дужки. Лічильник збільшення зазвичай використовується для збільшення і завершення циклу. Оператор forпідходить для будь-яких повторюваних дій і часто використовується у поєднанні з масивами колекцій даних/висновків.

Заголовок циклу forскладається з трьох частин:

for (initialization ; condition ; increment) (оператори, що виконуються в циклі)

Ініціалізація (Initialization) виконується найпершою та один раз. Щоразу у циклі перевіряється умова (condition), якщо вона вірно, виконується блок операторів і збільшення (increment), потім умова перевіряється знову. Коли логічне значення умови стає хибним, цикл завершується.

приклад

// затемнення світлодіода з використанням ШІМ-виведення int PWMpin = 10; // Світлодіод послідовно з резистором 470 ом на 10 висновків void setup() ( // налаштування не потрібна) void loop() ( for (int i=0; i<= 255; i++){ analogWrite(PWMpin, i); delay(10); } }

Цикл forу Сі набагато більш гнучкий, ніж цикли forв інших мовах програмування, наприклад, у Бейсику. Будь-який із трьох або всі три елементи заголовка можуть бути опущені, хоча точки з комою обов'язкові. Також оператори для ініціалізації, умови та збільшення циклу можуть бути будь-яким допустимим у Сі операторами з незалежними змінними, і використовувати будь-який тип даних Сі, включаючи дані з плаваючою точкою (floats). Ці незвичайні для циклу for типи операторів дозволяють забезпечити програмне вирішення деяких нестандартних проблем.

Наприклад, використання множення в операторі лічильника циклу дозволяє створювати логарифмічну прогресію:

For(int x = 2; x< 100; x = x * 1.5){ println(x); }

Генерується: 2,3,4,6,9,13,19,28,42,63,94

Інший приклад, плавне зменшення або збільшення рівня сигналу на світлодіод за допомогою одного циклу for:

Void loop()( int x = 1; for (int i = 0; i > -1; i = i + x)( analogWrite(PWMpin, i); if (i == 255) x = -1; // перемикання управління на максимумі delay(10); ) )

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

Arduino IDE запозичив з C/C++ більшість необхідних елементів керування. Їх синтаксис ідентичний з C. Нижче ми двома словами опишемо їх синтаксис.

Оператор if

Оператор if дозволяє виконати певний фрагмент програми, залежно від результату перевірки певної умови. Якщо умова виконується, код програми буде виконано, якщо ж умова не виконується, то код програми буде пропущено. Синтаксис команди if виглядає так:

If(умова) ( інструкція1; інструкція2; )

Умовою може бути будь-яке порівняння змінної або значення, що повертається функцією. Основним критерієм умови if є те, що відповідь завжди має бути або істиною (true) або брехнею (false). Приклади умов для оператора if:

If(a!=2) ( ) if(x<10) { } if(znak==’B’) { }

Всередині дужок, прописаних всередині умови, можна виконати код.

Люди, які приступають до вивчення програмування, часто роблять помилку, прирівнюючи значення вказаної змінної за допомогою одного знака =. Такий запис однозначно вказує на присвоєння значення змінно, і, отже, умова буде «true», тобто виконуватися. Перевірка того, що змінна дорівнює певному значенню, завжди позначається подвійним знаком (==).

Як умову можна використовувати стан функції, наприклад:

If(init()) ( Serial.print(«ок»); )

Наведений вище приклад буде виконано наступним чином: першому етапі викликається функція init(). Ця функція повертає значення, яке буде інтерпретовано як true або false. Залежно від результату порівняння буде надіслано текст «ок» або нічого не буде надіслано.

Оператор if…else

Розширеним оператором if є оператор if...else. Він забезпечує виконання одного фрагмента коду, коли умова виконується (true), і другий фрагмент коду, якщо умова не виконується (false). Синтаксис операторf if….else виглядає так:

If (умова) (// команда A) else (// команда B)

Команди «A» виконуватимуться лише в тому випадку, якщо умова виконана, команда «B» виконуватиметься, коли умова не виконана. Одночасне виконання команди «A» та «B» неможливе. Наступний приклад показує, як використовувати синтаксис if…else:

If (init()) ( Serial.print(«ок»); ) else ( Serial.print(«помилка»); )

Подібним чином можна перевірити правильність виконання функції та інформувати про це користувача.

Звичайною практикою є заперечення умови. Це пов'язано з тим, що функція, яка виконана правильно повертає значення 0, а функція, яка неправильно відпрацювала з якоїсь причини, повертає ненульове значення.

Пояснення такого «ускладнення життя» просто. Якщо функція виконана правильно, це єдина інформація, яка нам потрібна. У разі помилки, варто іноді зрозуміти, що пішло не так, чому функція не виконана правильно. І тут на допомогу приходять числа, відмінні від нуля, тобто за допомогою цифрових кодів ми можемо визначити тип помилки. Наприклад, 1 — проблема з читанням якогось значення, 2 — немає місця у пам'яті чи диску тощо.

В останньому зміненому прикладі показано, як викликати функцію, яка повертає нуль при правильному виконанні:

If (!init()) ( Serial.print(«ок»); ) else ( Serial.print(«помилка»); )

Оператор switch case

Оператор if дозволяє перевірити лише одну умову. Іноді необхідно виконати одну з дій залежно від значення, що повертається або прочитаного. Для цього ідеально підходить оператор множинного вибору switch. Нижче показано синтаксис команди switch:

Switch (var) ( case 1: // інструкція для var=1 break; case 2: // інструкція для var=2 break; default: // інструкція за замовчуванням (якщо var відрізняється від 1 і 2) )

Залежно від значення змінної var виконуються інструкції у певних блоках. Мітка case означає початок блоку для вказаного значення. Наприклад, case 1: означає, що даний блок буде виконаний для значення змінної var, що дорівнює один.

Кожен блок має бути завершений за допомогою команди Break. Він перериває подальше виконання оператора switch. Якщо команду break пропустити, інструкції будуть виконуватися і в наступних блоках до команди break. Мітка default не є обов'язковою, як і else у команді if. Інструкції, розташовані в блоці default, виконуються тільки тоді, коли значення змінної var не підходить до жодного шаблону.

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

Switch (x) ( case 1: // інструкція для x=1 break; case 2: case 3: case 5: // інструкція для x=2 або 3 або 4 break; case 4: // інструкція для x=4 break case 6: // інструкція для x = 6 break;

Залежно від значення змінної x буде виконано відповідний блок вказівок. Повторення case 2: case 3: case 5: інформує компілятор про те, що якщо змінна x має значення 2 або 3 або 5, то буде виконано той самий фрагмент коду.

Оператор for

Оператор for використовується для багаторазового виконання одного й того ж коду. Часто необхідно виконати одні й самі інструкції, змінивши лише значення якийсь змінної. Для цього ідеально підходить цикл for. Синтаксис команди виглядає так:

Int i; for(i=0;i<10;i++) { // инструкции для выполнения в цикле }

Перший параметр, який наводиться в інструкції for — початкове значення змінної. Ще один елемент – це перевірка умови продовження виконання циклу. Цикл виконується доти, доки виконується умова. Останній елемент – це зміна значення змінної. Найчастіше ми збільшуємо або зменшуємо її значення (за потребою). У цьому прикладі інструкції, що містяться в циклі будуть виконуватися при i=0…9.

Часто змінна, що використовується в циклі, оголошується там же:

For(int i=0;i<10;i++) { // инструкции для выполнения в цикле }

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

For(int i=10;i>0;i—) ( Serial.print(i); // відправляться номери 10,9,8,7,6,5,4,3,2,1 )

Оператор while

Цикл для ідеально підходить там, де ми хочемо виконати підрахунок. У ситуації, коли необхідно виконати певні дії в результаті якоїсь події, яка не обов'язково є передбачуваною (наприклад, ми чекаємо натискання кнопки), ми можемо використовувати оператор while, який виконує блок оператора доти, доки виконується умова. Синтаксис оператора while виглядає так:

While (умова) ( // блок інструкцій для виконання)

Важливо, щоб перевірка стану відбувалася на початку циклу. Може статися так, що інструкції всередині циклу while не виконуватися ніколи. Крім того, можливе створення нескінченного циклу. Давайте подивимося два приклади:

Int x=2; while(x>5) ( Serial.print(x); ) —————————————- int y=5; while(y>0) ( Serial.print(y); )

Перший блок операторів, розташований усередині while, не виконається ніколи. Змінна x має значення два і вона не стане більшою за 5. У другому прикладі ми маємо справу з нескінченним циклом. Змінна «y» має значення 5, тобто більше нуля. Усередині циклу не відбувається жодної зміни змінної "y", тому цикл ніколи не буде завершено.

Це поширена помилка, коли ми забуваємо про зміну параметра, що викликає припинення циклу. Нижче наведено два правильні приклади застосування циклу while:

Int x=0; while(x<10) { //блок инструкций x++; } —————————————- while(true) { if(условие) break; // блок инструкций }

У першому прикладі ми подбали про зміну значення змінної, яка перевіряється за умови. В результаті цикл колись завершиться. У другому прикладі було навмисно створено нескінченний цикл. Цей цикл еквівалентний функції loop() в Arduino IDE. Крім того, всередині циклу введено перевірку умови, після виконання якого цикл завершується командою break.

Оператор do…while

Різновидом циклу while є цикл do…while. Крім синтаксису, він відрізняється місцем перевірки умови. У разі do…while перевірка умови провадиться після виконання блоку інструкцій. Це означає, що блок інструкцій у тілі циклу виконається хоча б один раз. Нижче наведено синтаксис команди do…while:

Do ( // блок інструкцій ) while (умова)

Все, що написано про оператора while стосується також і do…while. Нижче наведено приклад використання циклу do…while:

Int x=10; do ( // блок інструкцій x-; ) while (x> 0); —————————————- do (// блок інструкцій if(умова) break; ) while(true);

Оператор break

Оператор break дозволяє вийти з циклу (do ... while, for, while) і вийти з опції switch. У наступному прикладі розглянемо виконання команди break:

For(i=0;i<10;i++) { if(i==5) break; Serial.print(i); }

Цикл має бути виконаний для чисел від 0 до 9, але для числа 5 виконується умова, яку запускає оператор break. Це призведе до виходу із циклу. В результаті до послідовного порту (Serial.print) буде відправлено лише числа 0,1,2,3,4.

Оператор continue

Оператор continue викликає припинення виконання інструкцій циклу (do ... while, for, while) для поточного значення та перехід до виконання наступного кроку циклу. У наступному прикладі показано, як працює оператор continue:

For(i=0;i<10;i++) { if(i==5) continue; Serial.print(i); }

Як не важко помітити, цикл буде виконаний для значення від 0 до 9. Для значення 5 виконається команда continue, в результаті чого інструкції після цієї команди виконані не будуть. В результаті до послідовного порту (Serial.print) будуть відправлені числа 0,1,2,3,4,6,7,8,9.

Оператор return

Оператор return завершує виконання викликаної функції та повертає значення певного типу. Як параметр команди можна вказати число, символ або змінну певного типу. Важливо, щоб значення, що повертається відповідає типу заявленої функції. У цьому прикладі показано, як використовувати оператор return:

Int checkSensor()( if (analogRead(0) > 400) ( // читання аналогового входу return 1; // Для значень більше 400 повертається 1 else( return 0; // для інших повертається 0 ) )

Як ви можете бачити, в одній функції можна використовувати кілька операторів return, але завжди спрацює тільки один з них. Допустиме використання оператора return без параметрів. Це дозволяє достроково припинити роботу функції, яка повертає ніякого значення.

Void имя_функции() ( інструкція1; if(x==0) return; інструкція2; інструкція3; )

У наведеному вище прикладі інструкція1 виконуватиме завжди, коли викликається функція. Виконання ж інструкція2 та інструкція3 залежить від результату команди if. Якщо умова буде виконана (true), то буде виконана команда return та функція завершить роботу.

У випадку, коли умова не виконана, команда return так само не виконується, а виконуються інструкції інструкція2 та інструкція3, і після цього функція завершує свою роботу.

Оператор goto

З ідеологічних міркувань необхідно пропустити цей опис… Оператор goto є командою, яку слід використовувати у звичайному програмуванні. Він викликає ускладнення коду та є поганою звичкою у програмуванні. Рекомендуємо не використовувати цю команду у своїх програмах. Через те, що goto є в офіційній документації на сайті arduino.cc, наведемо його короткий опис. Синтаксис команди goto:

…. goto metka; // Перейдіть на рядок із написом 'metka' ….. …. …. metka: // мітка, з якою програма продовжить роботу.

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

Оператори if і else в Arduino використовуються створення блоків умов у тексті програми. З їхньою допомогою можна створювати інтелектуальні системи, які самостійно приймають рішення про те, що має робити програма залежно від поточних умов. У цій статті ми розглянемо синтаксис if в Ардуїно, а також приклади застосування умов у різних ситуаціях.

if – це оператор мови C++, який активно використовується і в Arduino. Для позначення умов ардуїно використовується така конструкція:

If (умова) ( // У цьому блоці список команд, що виконуються, якщо умова істино або має значення, відмінне від 0 ) else ( // У цьому блоці список команд, що виконуються, якщо умова хибна або має значення, що дорівнює 0 )

Умова - це деякий логічний вираз, що повертає істину (TRUE)або брехня (FALSE). В одній умові можна використовувати декілька виразів, поєднуючи їх спеціальними логічними операторами. Ми докладно розглянемо ці оператори трохи згодом. Приклади умов:

  • if(a) – поверне істину, якщо значення змінної a не дорівнює 0 чи FALSE
  • if(a==5 && b>5) – поверне істину, якщо значення a дорівнює 5, а b більше 5.
  • if(!a) – поверне істину, якщо a дотримає 0 або FALSE.

Якщо послідовність команд складається з однієї команди, то символи ( ) можна не ставити (хоча категорично рекомендується ставити їх завжди, щоб уникнути дурних помилок):

if ( умова)

// Команда

// Команда

Можна обійтися без блоку elseякщо ви хочете робити щось тільки при виконанні умови і не будете нічого робити, якщо умова не виконалася.

if( умова)

// Команди

У наступних розділах ми познайомимося з конкретними прикладами та розглянемо варіанти синтаксису. Але спершу давайте трохи поговоримо про те, що таке умови і для чого вони потрібні в Arduino. Якщо ви вже мали досвід написання програм, можете сміливо розмістити цей розділ.

Умови у тексті програми Arduino

Що таке умова

Уявіть себе на хвилину чемним роботом, який дуже любить смачні апельсини. До вас можуть підходити різні люди і дарувати зовсім різні солодощі, але ви повинні залишати собі лише круглі предмети оранжевого кольору. Який алгоритм ви вибрали б для своєї програми?

Найпростіший варіант, що спадає на думку, виглядає так:

  1. Отримати предмет із рук людини.
  2. Визначити колір.
  3. Якщо колір помаранчевий, то взяти.
  4. Інакше (якщо колір не помаранчевий), то не брати, але сказати спасибі.

У цьому тексті ми з вами використовували слово «якщо», що входить до складу будь-якої умови. Якщо йде дощ, треба взяти парасольку. Якщо біля світла горить червоний, треба стояти і чекати. Якщо натиснути на вимикач, буде ясно. Ми користуємось умовами постійно, вони допомагають нам виробити якесь правило поведінки, коли є кілька варіантів дій, а ми маємо вибрати один із них. У нашому конкретному прикладі ми маємо два варіанти дій після перевірки умови. Перший варіант виникає коли умова виконалася (колір помаранчевий) – ми запускаємо послідовність дій із приймання предмета. Якщо умова не виконалася (колір будь-який, але не помаранчевий), то запускаємо процес повернення та подяки.

Як же тепер відобразити ці умови у програмі для Ардуїно?

Умова та розгалуження в тексті програми

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

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

Найпростішим варіантом запису умов було використання графічних методів. На мові блок-схем ми просто провели лінію для кожного з варіантів.

На одному аркуші можна намалювати безліч гілок та зобразити логіку ухвалення рішення. Але коли ми пишемо програму в Arduino IDE, графічного способу ми не маємо. Розбити текст на кілька стовпчиків ми теж не можемо. Єдиний варіант - якось помітити ті чи інші послідовності команд за допомогою спеціальних конструкцій. Саме для цього і служать блоки if і else.

За допомогою if і else ми розділяємо список команд на ті, які будуть виконуватися за одних умов і ті, які виконуватимуть за інших. Ми розгалужуємо програму, тому блок умов часто називають реалізацією розгалуження.

Розглянемо ще раз синтаксис та пояснимо значення кожного оператора:

if(умова)(

  • if (умова)- тут ми формулюємо умову, яка при запуску програми може виконатися (тоді результат буде TRUE або будь-яке число, що не дорівнює 0) чи ні (тоді результат буде FALSE або 0).
  • У разі TRUE буде виконано команди з першого блоку у фігурних дужках.
  • Якщо умова поверне FALSE, буде виконано блок у фігурних дужках після слова else.

Давайте розглянемо приклади використання if else в реальному коді ардуїно.

Приклади if і else в Ардуїно

Простий приклад блоку умови

Найпростіший приклад використання умов:

If(1)( Serial.println("True"); )else( Serial.println("False"); )

У моніторі порту у нас з'явиться напис True, тому що умова завжди видасть 1 і завжди буде виконуватися тільки перший блок. Написавши if(0), ми змусимо постійно виконуватись другий блок після else.

Приклад безглуздий, тому що завжди буде виконуватися певний блок і можна обійтися і без if. Але нам потрібно подивитись приклади синтаксису, тому зійде і такий варіант.

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

Boolean b = true; if(b)( Serial.println("True"); )

Приклад if з digitalRead

А ось тепер розглянемо перший осмислений приклад. Ми отримаємо значення цифрового датчика та просигналізуємо світлодіодом, якщо digitalRead поверне значення високого рівня сигналу.

If(digitalRead(10))( digitalWrite(13, HIGH); )else( digitalWrite(13, LOW); )

Зверніть увагу, ми не знаємо в момент написання коду, який варіант буде виконаний - адже значення датчика (або рівень шуму) на вході можуть бути зовсім різними. У момент виконання коду сам контролер вирішить, які команди будуть виконані, виходячи з тих значень, які будуть на вході в той момент.

Приклад if з роботом

Давайте спробуємо реалізувати приклад з нашим люблячим апельсини роботом в Ардуїно. Для спрощення завдання будемо вважати, що ми маємо функцію isOrange(), що повертає істину, якщо колір помаранчевий.

If (getOrange()) ( Serial.println("Thank you! I like it!"); ) else ( Serial.println("Thank you! But I don't like it!"); )

Якщо функція isOrange() поверне true, то буде виконано перший блок, інакше другий. Замість виведення на екран можна додати інші команди, наприклад, управління сервоприводами, що контролюють маніпулятори.

Приклад if та порівняння діапазонів

Давайте розглянемо приклад if з функцією analogRead(). Ми отримаємо значення з датчика та порівняємо його з деяким граничним значенням.

if(analogRead(A0)>500)(

Serial.println("Ok!");

Тут ардуїно у блоці ifвикличе , отримає значення сигналу на піні A0 і вибере перший чи другий варіант дій залежно від значення. Для порівняння значення ми використовуємо символ ">". Нам доступні й інші варіанти:

  • ">" - поверне істину, якщо значення "більше".
  • «>-» – поверне істину, якщо значення «більше або дорівнює вказаному».
  • «<» – вернет истину, если значение меньше
  • «<=» – вернет истину, если значение меньше или равно
  • «!=» – поверне істину, якщо значення однаково зазначеному, тобто. Більше або менше

Логічні оператори в умовах

У блоці умов можна вставляти кілька логічних виразів. Наприклад, для того, щоб вимагати не лише помаранчевий, а й ікруглий об'єкт, ми повинні об'єднати дві умови за допомогою оператора && (потрібно вказати саме два символи). Використання цього оператора визначає жорсткі умови, коли для виконання логічного виразу нам потрібно обов'язково виконати всі внутрішні вирази. Розглянемо приклад для нашого робота (вважаємо, що у нас є функції isOrange() та isSphere()):

If(isOrange() && isSphere())( Serial.println("Thank you! I like it!"); )

Список операторів умов:

  • && – умова І
  • || - Умова АБО
  • ! - Заперечення умови

Докладніше логічні умови розглянуті у статті про логічні оператори

Декілька пов'язаних умов

Завершимо нашу розповідь про if в ардуїно описом ситуації, коли ми по-різному маємо реагувати не на два, а на більшу кількість варіантів умов. Наприклад, для робота ардуїно з датчиком відстані потрібно виконати такі умови:

  • Відстань робота до перешкоди більше 2 метрів – їдемо на максимальній швидкості
  • Відстань робота до перешкоди менше 2 метрів, але більше 1 метра – зменшуємо швидкість
  • Відстань робота до перешкод менше ніж 1 метр – ще раз зменшуємо швидкість.
  • Відстань робота до перешкоди менше 20 см – зупиняємось та повертаємо.

В Arduino такі множинні «умови» реалізуються поєднанням оператора else та if. Давайте розглянемо його на прикладі. Нехай у нас визначено функцію getDistance(), яка повертає відстань у сантиметрах. Тоді умова виглядатиме так:

If (getDistance() > 200) ( // Не зменшуємо швидкість, їдемо вперед ) else if (getDistance() >= 100) ( /* У цій умові ми повіряємо, чи не більше значення 100. В принципі, 200 або 300 теж більше 100, але перший блок виконається першим, тому відпрацювання за умови >200 вже буде виконано.Якби значення було більше 200, то до нашого блоку управління просто не дійшло.Тому в цьому блоці ми будемо розглядати ситуацію, коли значення менше 200, але більше 100. Робот зменшить швидкість – він відчує, що незабаром перешкода. Пригальмуємо, готуючись до перешкоди. */ ) else ( /* А ось тепер уже все зрозуміло. Відстань менша за 20 (інакше всі верхні блоки спрацювали б). Тому сміливо вважаємо, що перед нами перешкоду і повертаємо. */ )

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

Висновок

Умови у будь-якій мові програмування мають дуже важливе значення. Жодна серйозна програма на Ардуїно не обходиться без умов if else. Саме в блоках умов проявляється інтелект робота, автоматичного пристрою та програміста, який його програмує. Саме в умовах відпрацьовуються всі тонкощі алгоритмів і саме там заховано більшість логічних помилок алгоритмів. Обов'язково постарайтеся зрозуміти та відпрацювати навички роботи з блоком if на реальних прикладах. І звертайтеся до підручників, якщо залишаться якісь неясності та нерозуміння.

Сьогодні вивчатимемо не менш важливу частину мови програмування, як цикли. Навіщо вони потрібні? Наприклад, поставимо собі за мету. Потрібно запалювати шість світлодіодів по черзі з періодом 50 мс, а потім по черзі їх гасити з тим же інтервалом. Ну, що може бути простіше. Пишемо наступний код:
void setup() ( pinMode(2, OUTPUT); pinMode(3, OUTPUT); pinMode(4, OUTPUT); pinMode(5, OUTPUT); pinMode(6, OUTPUT); pinMode(7, OUTPUT); ) void loop () ( digitalWrite(2, HIGH); delay(50); digitalWrite(3, HIGH); delay(50); digitalWrite(4, HIGH); delay(50); digitalWrite(5, HIGH); delay(50) digitalWrite(6, HIGH), delay(50); digitalWrite(7, HIGH); delay(50); digitalWrite(2, LOW); delay(50); digitalWrite(3, LOW); delay(50); (4, LOW); delay(50); digitalWrite(5, LOW); delay(50); digitalWrite(6, LOW); delay(50); про ініціалізували шість цифрових висновків з другого по сьомий як виходи, а в основній програмі по черзі написали включення світлодіода, затримка і так шість разів. Після те саме але щоразу вимикали світлодіод. Тепер заливаємо в Arduino та радіємо роботою. Але все-таки тут щось не так. Якщо уважно поглянути на код програми, можна помітити що є частини коду які повторюються протягом усієї програми. Наприклад, повинно відразу кинеться в очі повторення паузи. А за ініціалізації висновків змінюється лише його номер. При включенні та вимкненні також змінюється лише номер. Для такої маленької програми звичайно можна і так залишити, контролер зжере це і не поперхнеться, а от якщо потрібно виконати код, що повторюється, ну наприклад 1000 разів. Я думаю терпіння набивати його вистачить, а чи вистачить пам'яті у МК? Звичайно можна запитати, а на який фіг нам 1000 однакових операцій? Ну так, важко уявити.) Але не завдання, а якщо у нас є масив на 1000 осередків. Таке часто буває, наприклад, кілька датчиків записують параметри в масив і як скажете розбиратися в цьому бардаку. Треба б якось розібрати його за будь-якими параметрами. Ось для таких казусів і вигадали цикли. Цикл - це частина коду яка виконується певну кількість разів. Одна виконана частина програми у циклі називається ітерація. Кількість ітерацій може бути від 0 до нескінченності. Для виконання циклів у мові програмування передбачено три варіанти циклу. Повірте, але цього вистачає очі на будь-який витончений кодинг. Давай те ка це все розглянемо детальніше.
  • while (умова) ()
  • do () while (умова);
  • for(лічильна змінна; умова; збільшення лічильної змінної) ()
Перший цикл while (умова) (). Як він працює. Після слова whileу дужках має бути умова. Умова може бути будь-якою, аби була істинною. Як тільки умова стане хибною, цикл припинить свою роботу і програма продовжить працювати з наступного рядка після циклу. Давайте з прикладу.
char i = 0; while(iВласне, що тут у нас написано. Спочатку ми ініціалізуємо лічильну змінну iі обнуляємо її. Далі заходимо в цикл і починаємо перевіряти умову у дужках. Якщо значення iменше 10, то виконати тіло циклу. У самому тілі циклу просто збільшуємо значення лічильної змінної на одиницю і знову перевіряємо умову. У нашому випадку цикл буде виконуватись 10 разів. Тобто спочатку значення iодно нулю. Нуль менше ніж десять. Далі збільшили змінну на одиницю та порівняли, одиниця менше ніж десять тощо. Як тільки лічильна змінна дорівнюватиме десяти, то перевіряємо, десять менше ніж десять? Звичайно, ні і після перевірки цикл припинить роботу. Ось так працює цей цикл. А що робити якщо потрібно по кожному разу виконати код у тілі циклу, навіть якщо він не влаштовує умову. Для цього є друг цикл, під назвою do () while (умова). Працює він так само як і попередній цикл, за винятком одного але. У цьому циклі спочатку виконується тіло циклу, потім відбувається перевірка. Давайте подивимося, як це виглядає в коді.
char i = 0; do ( i++; ) while((i > 0) & (iДивіться, як цікаво. Спочатку ми як і минулого разу ініціалізуємо лічильну змінну нулем, але за умови записали щоб iбуло більше нуля та менше десяти. Тобто значення змінної має лежати у діапазоні від одиниці до дев'яти. Якби ми так написали із застосуванням попереднього циклу, то він не разу не виконався б. Але ми маємо чарівне слово do. Тобто, що станеться. Спочатку в тілі циклу значення лічильної змінної збільшиться і стане одиницею, а це більше ніж нуль, умова стане істинною. відповідно цикл продовжуватиме виконуватися поки лічильна змінна не буде дорівнює десяти. І на останок третій варіант циклу. Як він працює:
char i; for(i = 0; iЯк це працює. Спочатку знову ініціюємо лічильну змінну, але вже без конкретного значення. Далі пишемо слово for, а ось у дужках пишемо спочатку нашу лічильну змінну і присвоюємо їй початкове значення. Потім перевіряємо умову і якщо вона істинна, то виконуємо тіло циклу та збільшуємо значення лічильної змінної. По суті, це теж саме що і while() ()тому який цикл використовувати це вже на вашу думку. Кілька слів про деякі моменти. Якщо, наприклад, написати while(1);, цикл буде виконуватися вічно. Або якщо з for, то це буде виглядати так for(;;);. Будьте уважні. Іноді при виконанні циклу просто дуже хочеться все кинути і вийти з нього, а умова не дозволяє. Як бути? Для цього є ще одна команда break;. Як тільки в тілі циклу МК наткнеться на цю команду, він відразу вийде з циклу і продовжить виконання програми з наступного рядка після циклу. А от якщо у нас при роботі циклу виникає умова, що не задовольняє умову або, наприклад, момент при якому нам не потрібно продовжувати виконувати кінець тіла циклу? Тут нам допоможе команда continue;. Як тільки МК натрапить на цю команду, він кидає все та переходить до виконання наступної ітерації циклу. Сподіваюся, я все зрозуміло пояснив. Тепер отримавши дані знання, перепишемо нашу програму, але вже використовуючи цикли.
void setup() ( byte i = 2; // Рахункова змінна while(i // Якщо i менше 8, то виконуємо тіло циклу (pinMode(i, OUTPUT)); // Ініціалізація висновків починаючи з 2 i++; // Збільшуємо лічильну змінну на одиницю) ) void loop() ( byte i = 2; while(iДавайте розглянемо ближче. Спочатку ми ініціалізували лічильну змінну iі надали їй значення два. Чому два? А тому, що я спеціально вибрав піни з другого по сьомий, щоб переконатися, що початкове значення не має жодного значення. Каламбур якийсь вийшов) Ну, зрозуміло, так. Далі пишемо умову циклу. Нам потрібно зробити шість ітерацій, оскільки ми маємо шість світлодіодів. Чудово, рахуємо два плюс шість буде вісім. Ага, значить нам потрібно перевіряти рахункову змінну доти, доки вона буде меншою за вісім. Так і написали while(i . Тепер у нас цикл відпрацює шість разів. Що нам потрібно зробити всередині тіла циклу. Та нічого складного, просто вписати функцію ініціалізації виведення на вихід, тільки замість номера виводу підставити лічильну змінну. У чому фокус. Як тільки МК зайде в тіло циклу, він перед тим як виконувати функцію ініціалізації висновку, подивимося на аргументи, що передаються.Один з них повинен нести в собі номер висновку, а у нас там рахункова змінна.Що робити?А нічого, розумний МК подивиться що там змінна і гордо витягне з неї число А у нас там двійка Ну і чудово, про ініціалізуємо другий висновок Після збільшимо значення лічильної змінної ще на одиницю і перевіримо умову Ага, три менше восьми, давайте ка все знову і по хорошому, тільки в змінній тепер три. ініціалізувати висновок будемо вже третій, а потім збільшимо лічильну змінну на одиницю.От таким чином перебираючи цикл ми налаштуємо всі потрібні нам висновки.Причому збільшення на одиницю лічильну змінну це не жорстка умова. Ніхто не заважає написати наприклад так: i = ((127 * i) / 31) & 0xF4;І це теж працюватиме, якщо після виконання умова буде істинною. Для циклу не важливо, що відбувається в тілі, його цікавить чи справді умова чи ні. От і все. У наступному уроці розбиратимемо функції, навіщо вони потрібні і спробуємо написати свою.

/ /

Оператор For

Конструкція forвикористовується для повторення блоку операторів, укладених у фігурні дужки. Лічильник збільшення зазвичай використовується для збільшення і завершення циклу. Оператор forпідходить для будь-яких повторюваних дій і часто використовується у поєднанні з масивами колекцій даних/висновків.

Заголовок циклу forскладається з трьох частин:

for (initialization; condition; increment) (оператори, що виконуються в циклі)

Ініціалізація (Initialization) виконується найпершою та один раз. Щоразу у циклі перевіряється умова (condition), якщо вона вірно, виконується блок операторів і збільшення (increment), потім умова перевіряється знову. Коли логічне значення умови стає хибним, цикл завершується.

приклад

// затемнення світлодіода з використанням ШІМ-виведення int PWMpin = 10; // Світлодіод послідовно з резистором 470 ом на 10 висновків void setup() ( // налаштування не потрібна) void loop() ( for (int i=0; i<= 255; i++){ analogWrite(PWMpin, i); delay(10); } }

Цикл forу Сі набагато більш гнучкий, ніж цикли forв інших мовах програмування, наприклад, у Бейсику. Будь-який із трьох або всі три елементи заголовка можуть бути опущені, хоча точки з комою обов'язкові. Також оператори для ініціалізації, умови та збільшення циклу можуть бути будь-яким допустимим у Сі операторами з незалежними змінними, і використовувати будь-який тип даних Сі, включаючи дані з плаваючою точкою (floats). Ці незвичайні для циклу forтипи операторів дозволяють забезпечити програмне вирішення деяких нестандартних проблем.

Наприклад, використання множення в операторі лічильника циклу дозволяє створювати логарифмічну прогресію:

For(int x = 2; x< 100; x = x * 1.5){ println(x); }

Генерується: 2,3,4,6,9,13,19,28,42,63,94

Інший приклад, плавне зменшення або збільшення рівня сигналу на світлодіод за допомогою одного циклу for:

Void loop()( int x = 1; for (int i = 0; i > -1; i = i + x)( analogWrite(PWMpin, i); if (i == 255) x = -1; // перемикання управління на максимумі delay(10); ) )

Поділіться з друзями або збережіть для себе:

Завантаження...