Інтернет Windows Android

Довідник функцій arduino. Arduino - керуючі оператори

Цей симулятор найкраще працює в браузері Chrome
Давайте розглянемо Arduino по уважніше.

Arduino це не великий комп'ютер, До якого можуть підключатися зовнішні ланцюга. В Arduino Uno використовується Atmega 328P
Це найбільший чіп на платі. Цей чіп виконує програми, які зберігаються в його пам'яті. Ви можете завантажити програму через usb з допомогою Arduino IDE. Usb порт також забезпечує харчування arduino.

Є окремий роз'єм живлення. На платі є два висновки позначені 5v і 3.3v, які потрібні для того, щоб живити різні пристрої. Так само ви знайдете контакти, помічені як GND, це висновки землі (земля це 0В). Платформа Arduino, так само, має 14 цифрових висновків (пинов), помічених цифрами від 0 до 13, які підключаються до зовнішніх вузлів і мають два стани високий або низький (увімкнене). Ці контакти можуть працювати як виходи або як входи, тобто вони можуть або передавати якісь дані і управляти зовнішніми пристроями, або отримувати дані з пристроїв. Наступні висновки на платі позначені А0-А5. Це аналогові входи, які можуть приймати дані з різних датчиків. Це особливо зручно, коли вам треба виміряти якийсь діапазон, наприклад температуру. У аналогових входів є додаткові функції, Які можна задіяти окремо.

Як використовувати макетну плату.

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

У макетної платі є ряди отворів, в які ви можете вставляти деталі і дроти. Деякі з цих отворів електрично з'єднані один з одним.

Два верхніх і нижніх ряди з'єднані по - рядно уздовж всієї плати. Ці ряди використовуються, щоб подавати живлення на схему. Це може бути 5в або 3.3В, але в будь-якому випадку, перше, що вам треба зробити - це підключити 5в і GND на макетну плату, як показано на малюнку. Іноді ці сполуки рядів можуть перериватися посередині плати, тоді, якщо вам знадобиться, ви можете їх поєднати, як показано на малюнку.








Решта отвори, розташовані в середині плати, групуються по п'ять отворів. Вони використовується для з'єднання деталей схеми.


Перше, що ми підключимо до нашого микроконтроллеру, це світлодіод. Схема електричних з'єднань показана на картинці.

Для чого потрібен резистор в схемі? В даному випадку він обмежує струм, який проходить через світлодіод. Кожен світлодіод розрахований на певний струм, і якщо цей струм буде більше, то світлодіод вийде з ладу. Дізнатися, якого номіналу повинен бути резистор можна за допомогою закону ома. Для тих хто не знає або забув, закон ома каже, що існує лінійна залежність струму від напруги. Тобто, чим більше ми докладемо напруга до резистору, тим більше потече через нього струм.
V \u003d I * R
де Vнапруга на резистор
I- струм через резистор
R- опір, яке треба знайти.
По-перше, ми повинні дізнатися напруга на резистор. Більшість світлодіодів 3мм або 5мм, які ви будете використовувати, мають робочу напругу 3в. Значить, на резисторі нам треба погасити 5-3 \u003d 2в.

Потім ми обчислимо струм, що проходить через резистор.
Більшість 3 і 5 мм світлодіодів світяться повної яскравістю при струмі 20мА. Струм більше цього може вивести їх з ладу, а струм меншої сили знизить їх яскравість, не заподіявши ніякої шкоди.

Отже, ми хочемо включити світлодіод в ланцюг 5в, щоб на ньому був струм 20мА. Так як всі деталі включені в один ланцюг на резистор теж буде струм 20мА.
Ми отримуємо
2В \u003d 20 мА * R
2В \u003d 0.02A * R
R \u003d 100 Ом

100 Ом це мінімальний опір, краще використовувати трохи більше, тому, що світлодіоди мають деякий розкид характеристик.
В даному прикладі використовується резистор 220 Ом. Тільки тому, що у автора їх дуже багато: wink:.

Вставте світлодіод в отвори посередині плати таким чином, щоб його довгий висновок був з'єднаний з одним з висновків резистора. Другий кінець резистора з'єднайте з 5V, а другий висновок світлодіода з'єднайте з GND. Світлодіод повинен загорітися.

Зверніть увагу, що є різниця, як з'єднувати світлодіод. Струм тече від довшого виведення до коротшого. На схемі це можна уявити, що струм тече в ту сторону, куди спрямований трикутник. Спробуйте перевернути світлодіод і ви побачите, що він не буде світитися.

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

Анатомія Arduino Sketch.

Програми для Arduino називають sketch. Вони складаються з двох основних функцій. функція setup і функція loop
всередині цієї функції ви будете задавати всі основні настройки. Які висновки будуть працювати на вхід або вихід, які бібліотеки підключати, форматувати змінні. функція Setup () запускається тільки один раз протягом скетчу, коли стартує виконання програми.
це основна функція, яка виконується після setup (). Фактично це сама програма. Це функція буде виконуватися нескінченно, поки ви не вимкнете харчування.

Arduino блимає світлодіод



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

Ця функція використовується в setup () частини програми і служить для ініціалізації висновків, які ви будете використовувати, як вхід (INPUT) або вихід (OUTPUT). Ви не зможете вважати або записати дані з Піна, поки не встановите його відповідно в pinMode. Ця функція має два аргументи: pinNumber- це номер Піна, який ви будете використовувати.

Mode-задає, як пін буде працювати. на вхід (INPUT) або вихід (OUTPUT). Щоб запалити світлодіод ми повинні подати сигнал З Arduino. Для цього ми налаштовуємо пін на вихід.
- ця функція служить для того, щоб задати стан (State) Піна (PinNumber). Є два основні стани (взагалі їх 3), одне це HIGH, На піне буде 5в, інше це Low і на піне буде 0в. Значить, щоб запалити світлодіод нам треба на піне, з'єднаному з світлодіодом виставити високий рівень HIGH.

Затримка. Служить для затримки роботи програми на заданий в мсек період.
Нижче наведено код, який змушує блимати світлодіод.
// LED Blink int ledPin \u003d 7; // пін Arduino до якого підключений світлодіод void setup () (pinMode (ledPin, OUTPUT); // установка Піна як ВИХІД) void loop () (digitalWrite (ledPin, HIGH); // запалити світлодіод delay (1000); // затримка 1000 мсек (1 сек) digitalWrite (ledPin, LOW); // Вимкнути світлодіод delay (1000); // чекати 1 сек)

Невеликі пояснення по коду.
Рядки, які починаються з "//" це коментарі Arduino їх ігнорує.
Всі команди закінчуються крапкою з комою, якщо ви їх забудете, то отримаєте повідомлення про помилку.

ledPin- це змінна. Змінні використовуються в програмах для зберігання значень. В даному прикладі змінної ledPin присвоюється значення 7, це номер Піна Arduino. Коли Arduino в програмі зустріне рядок зі змінною ledPin , Він буде використовувати те значення, яке ми вказали раніше.
так запис pinMode (ledPin, OUTPUT) аналогічна записи pinMode (7, OUTPUT).
Але в першому випадку вам достатньо поміняти змінну і вона зміниться в кожному рядку, де використовується, а в другому випадку вам, щоб поміняти змінну, доведеться ручками в кожній команді вносити зміни.

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

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

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

У цьому прикладі ви дізнаєтеся, як керувати кількома світлодіодами. Для цього встановіть ще 3 світлодіода на плату і з'єднайте їх з резисторами і висновками Arduino, як показано нижче.

Для того, щоб включати і вимикати світлодіоди по черзі треба написати програму подібну до цієї:
// Multi LED Blink int led1Pin \u003d 4; int led2Pin \u003d 5; int led3Pin \u003d 6; int led4Pin \u003d 7; void setup () (// установка пинов як ВИХІД pinMode (led1Pin, OUTPUT); pinMode (led2Pin, OUTPUT); pinMode (led3Pin, OUTPUT); pinMode (led4Pin, OUTPUT);) void loop () (digitalWrite (led1Pin, HIGH ); // запалити світлодіод delay (1000); // затримка 1 сек digitalWrite (led1Pin, LOW); // загасити світлодіод delay (1000); // затримка 1 сек // do the same for the other 3 LEDs digitalWrite (led2Pin , HIGH); // запалити світлодіод delay (1000); // затримка 1 сек digitalWrite (led2Pin, LOW); // загасити світлодіод delay (1000); // затримка 1 сек digitalWrite (led3Pin, HIGH); // запалити світлодіод delay (1000); // затримка 1 сек digitalWrite (led3Pin, LOW); // загасити світлодіод delay (1000); // затримка 1 сек digitalWrite (led4Pin, HIGH); // запалити світлодіод delay (1000); // затримка 1 сек digitalWrite (led4Pin, LOW); // загасити світлодіод delay (1000); // затримка 1 сек)

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

DigitalWrite (led4Pin, HIGH); delay (1000); digitalWrite (led4Pin, LOW); delay (1000);
повний код скетчу у вкладенні (Завантажень: тисяча триста вісімдесят чотири)

Регулювання яскравості світлодіодів

Іноді вам треба буде міняти яскравість світлодіодів в програмі. Це можна зробити за допомогою команди analogWrite () . Ця команда так швидко вмикає і вимикає світлодіод, що око не бачить це мерехтіння. Якщо світлодіод половину часу буде включений, а половину вимкнений, то візуально буде здаватися, що він світиться в половину своєї яскравості. Це називається широтно-імпульсна модуляція (ШІМ або PWM по-англійськи). Шим застосовується досить часто, так як з її допомогою можна управляти "аналоговим" компонентом за допомогою цифрового коду. Не всі висновки Arduino підходять для цих цілей. Тільки ті висновки, біля яких намальовано таке позначення " ~ ". Ви побачите його поруч з висновками 3,5,6,9,10,11.
З'єднайте один з ваших світлодіодів з одним з висновків ШІМ (у автора це висновок 9). Тепер запустітьскетч миготіння світлодіода, але перш змініть команду digitalWrite () на analogWrite (). analogWrite () має два аргументи: перший це номер виводу, а другий-значення ШІМ (0-255), стосовно до світлодіодів це буде їх яскравість світіння, а для електродвигунів швидкість обертання. Нижче представлений код прикладу для різної яскравості світлодіода.
// Міняємо яскравість світлодіода int ledPin \u003d 9; // до цього висновку приєднаний світлодіод void setup () (pinMode (ledPin, OUTPUT); // ініціалізація Піна на висновок) void loop () (analogWrite (ledPin, 255); // повна яскравість (255/255 \u003d 1) delay (1000); // пауза 1 сек digitalWrite (ledPin, LOW); // вимкнути світлодіод delay (1000); // пауза 1 сек analogWrite (ledPin, 191); // яскравість на 3/4 (191/255 ~ \u003d 0.75) delay (1000); // пауза 1 сек digitalWrite (ledPin, LOW); // вимкнути світлодіод delay (1000); // пауза 1 сек analogWrite (ledPin, 127); // половина яскравості (127/255 ~ \u003d 0.5) delay (1000); // пауза 1 сек digitalWrite (ledPin, LOW); // вимкнути світлодіод delay (1000); // пауза 1 сек analogWrite (ledPin, 63); // чверть яскравості (63/255 ~ \u003d 0.25) delay (1000); // пауза 1 сек digitalWrite (ledPin, LOW); // вимкнути світлодіод delay (1000); // пауза 1 сек)

Спробуйте поміняти значення ШІМ в команді analogWrite (), Щоб побачити, як це впливає на яскравість.
Далі ви дізнаєтеся, як регулювати яскравість плавно від повної до нульової. Можна, звичайно, скопіювати шматок коду 255 раз
analogWrite (ledPin, brightness); delay (5); // short delay brightness \u003d brightness + 1;
Але, самі розумієте - це буде не практично. Для цього найкраще використовувати цикл FOR, який використовували раніше.
У наступному прикладі використовуються два цикли, один для зменшення яскравості від 255 до 0
for (int brightness \u003d 0; brightness \u003d 0; brightness -) (analogWrite (ledPin, brightness); delay (5);)
delay (5) використовується, щоб уповільнити швидкість наростання і зменшення яскравості 5 * 256 \u003d 1280 мсек \u003d 1.28 сек.)
У першому рядку використовується " brightness-", Для того щоб значення яскравості зменшувалася на 1, кожен раз, коли цикл повторюється. Зверніть увагу, що цикл буде працювати до тих пір, поки brightness\u003e \u003d 0.Заменів знак > на знак >= ми включили 0 в діапазон яскравості. Нижче змодельований цей скетч. // плавно міняємо яскравість int ledPin \u003d 9; // до цього піну підключений світлодіод void setup () (pinMode (ledPin, OUTPUT); // ініціалізація Піна на вихід) void loop () (// плавно збільшуємо яскравість (0 to 255 ) for (int brightness \u003d 0; brightness \u003d 0; brightness -) (analogWrite (ledPin, brightness); delay (5);) delay (1000); // чекаємо 1 сек // плавно зменшуємо яскравість (255 to 0) for (int brightness \u003d 255; brightness\u003e \u003d 0; brightness -) (analogWrite (ledPin, brightness); delay (5);) delay (1000); // чекаємо 1 сек))
Це видно не дуже добре, але ідея зрозуміла.

RGB-світлодіод і Arduino

RGB-світлодіод насправді це три світлодіода різного кольору в одному корпусі.

Включаючи різні світлодіоди з різною яскравістю можна комбінувати і отримувати різні кольори. Для Arduino, де кількість градацій яскравості одно 256 ви отримаєте 256 ^ 3 \u003d 16581375 можливих кольорів. Реально їх, звичайно, буде менше.
Світлодіод, який ми будемо використовуватися загальним катодом. Тобто всі три світлодіода конструктивно з'єднані катодами до одного висновку. Цей висновок ми подсоединим до висновку GND. Решта висновки, через обмежувальні резистори, треба приєднати до висновків ШІМ. Автор використав висновки 9-11.Такім чином можна буде управляти кожним світлодіодом окремо. У першому скетчі показано, як включити кожен світлодіод окремо.



// RGB LED - test // pin connections int red \u003d 9; int green \u003d 10; int blue \u003d 11; void setup () (pinMode (red, OUTPUT); pinMode (blue, OUTPUT); pinMode (green, OUTPUT);) void loop () (// включення / вимикання червоного світлодіод digitalWrite (red, HIGH); delay (500) ; digitalWrite (red, LOW); delay (500); // включення / вимикання зеленого світлодіода digitalWrite (green, HIGH); delay (500); digitalWrite (green, LOW); delay (500); // включення / вимикання синього світлодіода digitalWrite (blue, HIGH); delay (500); digitalWrite (blue, LOW); delay (500);)

У наступному прикладі використовуються команди analogWrite () і, щоб отримувати різні випадкові значення яскравості для світлодіодів. Ви побачите різні кольори, мінливі випадковим чином.
// RGB LED - random colors // pin connections int red \u003d 9; int green \u003d 10; int blue \u003d 11; void setup () (pinMode (red, OUTPUT); pinMode (blue, OUTPUT); pinMode (green, OUTPUT);) void loop () (// pick a random color analogWrite (red, random (256)); analogWrite ( blue, random (256)); analogWrite (green, random (256)); delay (1000); // wait one second)

Random (256)-возвращает випадкове число в діапазоні від 0 до 255.
В прикріпленому файлі скетч, який продемонструє плавні переходи кольорів від червоного до зеленого, потім до синього, червоного, зеленого і т.д. (Завантажень: 381)
Приклад скетчу працює, але є багато повторюваного коду. Можна спростити код, написавши власну допоміжну функцію, Яка буде плавно міняти один колір на інший.
Ось як вона буде виглядати: (Завантажень: 414)
Давайте розглянемо визначення функції по частинах. функція називається fader і має два аргументи. Кожен аргумент відокремлюється комою і має тип оголошений в першому рядку визначення функції: void fader (int color1, int color2). Ви бачите, що обидва аргументи оголошені як int, І їм присвоєні імена color1 і color2 в якості умовних змінних для визначення функції. Void означає, що функція не повертає ніяких значень, вона просто виконує команди. Якщо треба було б написати функцію, яка повертала результат множення це виглядало б так:
int multiplier (int number1, int number2) (int product \u003d number1 * number2; return product;)
Зверніть увагу, як ми оголосили Тип int в якості типу значення, що повертається замість
void.
Усередині функції йдуть команди, які ви вже використовували в попередньому скетчі, тільки номери висновків замінили на color1 і color2. викликається функція fader, Її аргументи обчислюються як color1 \u003d red і color2 \u003d green. В архіві повний скетч з використанням функцій (Завантажень: 313)

кнопка

У наступному скетчі буде використовуватися кнопка з нормально роз'єднаними контактами, без фіксації.


Це означає, що поки кнопка не було натиснуто, струм через неї не йде, а після відпускання, кнопка повертається у вихідне положення.
У схемі, крім кнопки використовується резистор. В даному випадку він не обмежує струм, а "підтягує" кнопку до 0в (GND). Тобто поки кнопка не було натиснуто на виведення Arduino, до якого вона підключена, буде низький рівень. Резистор, який використовується в схемі 10 кОм.


// визначаємо натискання кнопки int buttonPin \u003d 7; void setup () (pinMode (buttonPin, INPUT); // инициализируем пін на вхід Serial.begin (9600); // инициализируем послідовний порт) void loop () (if (digitalRead (buttonPin) \u003d\u003d HIGH) (// якщо кнопка натиснута Serial.println ( "pressed"); // виводимо напис "pressed") else (Serial.println ( "unpressed"); // інакше "unpressed"))
У цьому скетчі кілька нових команд.
-ця команда приймає значення High (високий рівень) і low (низький рівень), того висновку, який ми перевіряємо. Попередньо в setup () цей висновок треба налаштувати на вхід.
; // де buttonPin це номер виводу, куди приєднується кнопка.
Послідовний порт дозволяє відправляти Arduino повідомлення на комп'ютер, в той час, як сам контролер виконує програму. Це корисно для налагодження програми, відправки повідомлень на інші пристрої або програми. Щоб включити передачу даних через послідовний порт (інша назва UART або USART), треба форматувати його в setup ()

Serial.begin () має всього один аргумент-це швидкість передачі даних між Arduino і комп'ютером.
скетчі використовується команда для виведення повідомлення на екран в Arduino IDE (Tools \u003e\u003e Serial Monitor).
- конструкція дозволяють контролювати хід виконання програми, об'єднавши кілька перевірок в одному місці.
If (якщо) digitalRead повертає значення HIGH, то на моніторі виводиться слово "натиснута". Else (інакше) на моніторі виводиться слово "відтиснуті". Тепер можна спробувати включати і вимикати світлодіод після натискання кнопки.
// button press detection with LED output int buttonPin \u003d 7; int ledPin \u003d 8; void setup () (pinMode (buttonPin, INPUT); // this time we will set button pin as INPUT pinMode (ledPin, OUTPUT); Serial.begin (9600);) void loop () (if (digitalRead (buttonPin) \u003d \u003d HIGH) (digitalWrite (ledPin, HIGH); Serial.println ( "pressed");) else (digitalWrite (ledPin, LOW); Serial.println ( "unpressed");))

Аналоговий вхід.

analogRead дозволяє вважати дані з одного з аналогових висновків Arduino і виводить значення в діапазоні від 0 (0В) до 1023 (5В). Якщо напруга на аналоговому вході дорівнюватиме 2.5В, то буде надруковано 2.5 / 5 * 1023 \u003d 512
analogRead має тільки один аргумент- Це номер аналогового входу (А0-А5). У наступному скетчі наводиться код зчитування напруги з потенціометра. Для цього підключіть змінний резистор, крайніми висновками на Піни 5V і GND, а середній висновок на вхід А0.

Запустіть наступний код і подивіться в serial monitor, як змінюються значення в залежності від повороту ручки резистора.
// analog input int potPin \u003d A0; // до цього піну приєднується центральний висновок потенціометра void setup () (// аналоговий пін за замовчуванням включений на вхід, тому ініціалізація не потрібна Serial.begin (9600);) void loop () ( int potVal \u003d analogRead (potPin); // potVal is a number between 0 and 1023 Serial.println (potVal);)
Наступний скетч об'єднує скетч натискання кнопки і скетч управління яскравістю світлодіода. Світлодіод буде включатися від кнопки, і управляти яскравістю світіння буде потенціометр.
// button press detection with LED output and variable intensity int buttonPin \u003d 7; int ledPin \u003d 9; int potPin \u003d A0; void setup () (pinMode (buttonPin, INPUT); pinMode (ledPin, OUTPUT); Serial.begin (9600);) void loop () (if (digitalRead (buttonPin) \u003d\u003d HIGH) (// if button pressed int analogVal \u003d analogRead (potPin); int scaledVal \u003d map (analogVal, 0, 1 023, 0, 255); analogWrite (ledPin, scaledVal); // turn on led with intensity set by pot Serial.println ( "pressed");) else (digitalWrite (ledPin, LOW); // turn off if button is not pressed Serial.println ( "unpressed");))

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

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

оператор if

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

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

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

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

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

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

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

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 \u003d 1 break; case 2: // інструкція для var \u003d 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 \u003d 1 break; case 2: case 3: case 5: // інструкція для x \u003d 2 або 3 або 4 break; case 4: // інструкція для x \u003d 4 break ; case 6: // інструкція для x \u003d 6 break; default: // інструкція за замовчуванням (якщо х відрізняється від 1,2,3,4,5,6))

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

оператор for

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

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

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

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

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

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

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

оператор while

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

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

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

Int x \u003d 2; while (x\u003e 5) (Serial.print (x);) -------------- int y \u003d 5; while (y\u003e 0) (Serial.print (y);)

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

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

Int x \u003d 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 \u003d 10; do (// блок інструкцій x-;) while (x\u003e 0); -------------- do (// блок інструкцій if (умова) break;) while (true);

оператор break

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

For (i \u003d 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 \u003d 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)\u003e 400) (// читання аналогового входу return 1; // Для значень більше 400 повертається 1 else (return 0; // для інших повертається 0))

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

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

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

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

оператор goto

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

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

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

Цей урок дає мінімальні знання, необхідні для програмування систем Ардуіно на мові C. Можна лише переглянути його і в подальшому використовувати як довідкову інформацію. Тим, хто програмував на C в інших системах можна пропустити статтю.

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

Структура програми Ардуіно.

Структура програми Ардуіно досить проста і в мінімальному варіанті складається з двох частин setup () і loop ().

void setup () (

void loop () (

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

Після завершення setup () управління переходить до функції loop (). Вона в нескінченному циклі виконує команди, записані в її тілі (між фігурними дужками). Власне ці команди і роблять все алгоритмічні дії контролера.

Початкові правила синтаксису мови C.

; крапка з комою Вирази можуть містити як завгодно багато прогалин, переносів рядків. Ознакою завершення вираження є символ "крапка з комою".

z \u003d x + y;
z \u003d x
+ Y;

( ) фігурні дужки визначають блок функції або виразів. Наприклад, у функціях setup () і loop ().

/ * ... * / блок коментаря, Обов'язково закрити.

/ * Це блок коментаря * /

// однорядковий коментар, Закривати не треба, діє до кінця рядка.

// це один рядок коментаря

Змінні і типи даних.

Мінлива це осередок оперативної пам'яті, В якій зберігається інформація. Програма використовує змінні для зберігання проміжних даних обчислень. Для обчислень можуть бути використані дані різних форматів, різної розрядності, тому у змінних в мові C є такі типи.

Тип даних Розрядність, біт діапазон чисел
boolean 8 true, false
char 8 -128 … 127
unsigned char 8 0 … 255
byte 8 0 … 255
int 16 -32768 … 32767
unsigned int 16 0 … 65535
word 16 0 … 65535
long 32 -2147483648 … 2147483647
unsigned long 32 0 … 4294967295
short 16 -32768 … 32767
float 32 -3.4028235+38 … 3.4028235+38
double 32 -3.4028235+38 … 3.4028235+38

Типи даних вибираються виходячи з необхідної точності обчислень, форматів даних і т.п. Не варто, наприклад, для лічильника, який вважає до 100, вибирати тип long. Працювати буде, але операція займе більше пам'яті даних і програм, потребують більше часу.

Оголошення змінних.

Вказується тип даних, а потім ім'я змінної.

int x; // оголошення змінної з ім'ям x типу int
float widthBox; // оголошення змінної з ім'ям widthBox типу float

Всі змінні повинні бути оголошені до того як будуть використовуватися.

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

  • Змінні, оголошені на початку програми, до функції void setup (), вважаються глобальними і доступні в будь-якому місці програми.
  • Локальні змінні оголошуються всередині функцій або таких блоків, як цикл for, і можуть використовуватися тільки в оголошених блоках. Можливі кілька змінних з одним ім'ям, але різними областями видимості.

int mode; // змінна доступна всім функціям

void setup () (
// порожній блок, початкові установки не потрібні
}

void loop () (

long count; // змінна count доступна тільки в функції loop ()

for (int i \u003d 0; i< 10;) // переменная i доступна только внутри цикла
{
i ++;
}
}

При оголошенні змінної можна задати її початкове значення (проинициализировать).

int x \u003d 0; // оголошується змінна x з початковим значенням 0
char d \u003d 'a'; // оголошується змінна d з початковим значенням рівним коду символу "a"

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

int x; // змінна int
char y; // змінна char
int z; // змінна int

z \u003d x + (int) y; // змінна y явно перетворена в int

Арифметичні операції.

Операції відносини.

Логічні операції.

Операції над покажчиками.

Бітові операції.

& І
| АБО
^ виключає Або
~ інверсія
<< ЗСУВ ВЛЕВО
>> ЗСУВ ВПРАВО

Операції змішаного присвоювання.

Вибір варіантів, управління програмою.

оператор IF перевіряє умова в дужках і виконує наступне вираз або блок в фігурних дужках, якщо умова істинна.

if (x \u003d\u003d 5) // якщо x \u003d 5, то виконується z \u003d 0
z \u003d 0;

if (x\u003e 5) // якщо x\u003e
(Z \u003d 0; y \u003d 8;)

IF ... ELSE дозволяє зробити вибір між двох варіантів.

if (x\u003e 5) // якщо x\u003e 5, то виконується блок z \u003d 0, y \u003d 8;
{
z \u003d 0;
y \u003d 8;
}

{
z \u003d 0;
y \u003d 0;
}

ELSE IF - дозволяє зробити множинний вибір

if (x\u003e 5) // якщо x\u003e 5, то виконується блок z \u003d 0, y \u003d 8;
{
z \u003d 0;
y \u003d 8;
}

else if (x\u003e 20) // якщо x\u003e 20, виконується цей блок
{
}

else // інакше виконується цей блок
{
z \u003d 0;
y \u003d 0;
}

SWITCH CASE - множинний вибір. Дозволяє порівняти змінну (у прикладі це x) з декількома константами (в прикладі 5 і 10) і виконати блок, в якому змінна дорівнює константі.

switch (x) (

case 5:
// код виконується якщо x \u003d 5
break;

case 10:
// код виконується якщо x \u003d 10
break;

default:
// код виконується якщо не співпало жодне попереднє значення
break;
}

цикл FOR. Конструкція дозволяє організовувати цикли з заданим кількістю ітерацій. Синтаксис виглядає так:

for (дію до початку циклу;
умова продовження циклу;
дію в кінці кожної ітерації) (

// код тіла циклу

Приклад циклу з 100 ітерацій.

for (i \u003d 0; i< 100; i++) // начальное значение 0, конечное 99, шаг 1

{
sum \u003d sum + I;
}

цикл WHILE. Оператор дозволяє організовувати цикли з конструкцією:

while (вираз)
{
// код тіла циклу
}

Цикл виконується до тих пір, поки вираз в дужках істинно. Приклад циклу на 10 ітерацій.

x \u003d 0;
while (x< 10)
{
// код тіла циклу
x ++;
}

DO WHILE - цикл з умовою на виході.

do
{
// код тіла циклу
) While (вираз);

Цикл виконується поки вираз істинний.
BREAK - оператор виходу з циклу. Використовується для того, щоб перервати виконання циклів for, while, do while.

x \u003d 0;
while (x< 10)
{
if (z\u003e 20) break; // якщо z\u003e 20, то вийти з циклу
// код тіла циклу
x ++;
}

GOTO - оператор безумовного переходу.

goto metka1; // перехід на metka1
………………
metka1:

CONTINUE - пропуск операторів до кінця тіла циклу.

x \u003d 0;
while (x< 10)
{
// код тіла циклу
if (z\u003e 20) continue; // якщо z\u003e 20, то повернутися на початок тіла циклу
// код тіла циклу
x ++;
}

Масиви.

Масив це область пам'яті, де послідовно зберігаються кілька змінних.

Оголошується масив так.

int ages; // масив з 10 змінних типу int

float weight; // масив з 100 змінних типу float

При оголошенні масиви можна ініціалізувати:

int ages \u003d (23, 54, 34, 24, 45, 56, 23, 23, 27, 28);

Звертаються до змінних масивів так:

x \u003d ages; // x присвоюється значення з 5 елементу масиву.
ages \u003d 32; // 9 елементу масиву задається значення 32

Нумерація елементів масивів завжди з нуля.

Функції.

Функції дозволяють виконувати одні і ті ж дії з різними даними. У функції є:

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

Описується призначена для користувача функція поза функцій setup () і loop ().

void setup () (
// код виконується один раз при запуску програми
}

void loop () (
// основний код, виконується в циклі
}

// оголошення користувальницької функції з ім'ям functionName
type functionName (type argument1, type argument1, ..., type argument)
{
// тіло функції
return ();
}

Приклад функції, що обчислює суму квадратів двох аргументів.

int sumQwadr (int x, int y)
{
return (x * x + y * y);
}

Виклик функції відбувається так:

d \u003d 2; b \u003d 3;
z \u003d sumQwadr (d, b); // в z буде сума квадратів змінних d і b

Функції бувають вбудовані, призначені для користувача, що підключаються.

Дуже коротко, але цих даних повинно вистачити для того, щоб почати писати програми на C для систем Ардуіно.

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

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

Імена в мові C.

Імена, що представляють типи даних, повинні бути написані в змішаному регістрі. Перша літера імені повинна бути велика (верхній регістр).

Signal, TimeCount

Змінні повинні бути записані іменами в змішаному регістрі, перша буква рядкова (нижній регістр).

Рубрика:. Ви можете додати в закладки.

Після ознайомлення з основними елементами Arduino, а також написання програми «Hello World!» прийшов час для знайомства з мовою програмування.

Структура мови заснована головним чином на C / C ++, тому ті, хто раніше програмував на цій мові, не будуть відчувати труднощів при освоєнні програмування Arduino. Решта повинні освоїти основну інформацію про командах управління, типи даних і функції.

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

основи основ

Кілька формальних речей, тобто таких, про які всі знають, але іноді забувають ...

В Arduino IDE, як в C / C ++, необхідно пам'ятати про регістрах символів. Ключові слова, такі як if, for завжди записуються в нижньому регістрі. Кожна інструкція закінчується на «;». Крапка з комою повідомляє компілятору, яку частину інтерпретувати як інструкцію.

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

Доброю практикою є додавання коментарів до вмісту програми, це допомагає легко зрозуміти код. Однорядкові коментарі починаються з // (Подвійна коса риска). Багаторядкові коментарі починаються з /* і закінчуються на */

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

#include // стандартна бібліотека #include «svoya_biblioteka.h» // бібліотека в каталозі проекту

Функції в Arduino

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

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

оголошення функції

Схема оголошення функції виглядає наступним чином:

Тип імя_функциі (параметр) (// інструкції для виконання (тіло функції) return (/ * повернення значення * /);)

тип - це ім'я будь-якого доступного типу даних на цією мовою програмування. Список типів, доступних при програмуванні Arduino наведемо в окремій статті.

Після виконання, функція поверне значення оголошеного типу. У разі, якщо функція не приймає ніякого значення, що повертається, то тип даних буде «void».

імя_функциі дозволяє її однозначно ідентифікувати. Для того щоб викликати (запустити) функцію, ми даємо їй ім'я.

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

Усередині дужок «(...)» міститься власне тіло функції або інструкція, які ми хочемо виконати. Опис конкретних інструкцій вкажемо в окремій статті.

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

Нижче наведені деякі приклади декларацій функцій.

Void f1 () (// тіло функції) -------------- int minus () (// тіло функції return (0);) ----------- --- int plus (int a, int b) (return (a + b);)

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

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

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

Виклик функції

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

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

F1 (); plus (2,2); y \u003d plus (1,5);

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

Якщо функція f1 () оголошена без параметрів, то при її виклику можна вказувати ніякі параметри, тобто виклик функції f1 (0) буде невірним.

Функція plus (int a, int b) вимагає рівно двох параметрів, тому виклик з одним або трьома параметрами неможливо.

Виклик y \u003d plus (1,5) призведе до виконання функції «plus» з параметрами «1» і «5» і зберегти значення, що повертається в змінну «y».

Функції setup () і loop ().

Володіючи знаннями про оголошення і виклику функцій, ми можемо перейти до системних функцій Arduino: setup () і loop (). Arduino IDE в обов'язковому порядку необхідно оголошувати ці дві функції.

setup () - це функція, яка викликається автоматично при включенні харчування або натисканні кнопки RESET.

Відповідно до її ім'ям вона використовується для установки початкових значень змінних, декларацій входів і виходів системи, які зазвичай задаються в початкових параметрах. Завдяки своїй специфіці ця функція не повертає значення і не викликається з параметрами. Правильна декларація функції setup () представлена \u200b\u200bнижче:

Void setup () (// тіло функції - ініціалізація системи)

loop () - це функція, яка викликається в нескінченному циклі. Ця функція також не повертає значення і не викликається з параметрами. Нижче показано правильне оголошення функції loop ():

Void loop () (// тіло функції - програмний код)

Як ви бачите, оголошення функції loop () ідентично оголошенню функції setup (). Різниця полягає у виконанні цих функцій мікро контролером.

Тепер ми проаналізуємо наступний псевдокод:

Void setup () (on_led1 (); // включаємо світлодіод led1 off_led1 (); // вимикаємо світлодіод led1) void loop () (on_led2 (); // включаємо світлодіод led2 off_led2 (); // вимикаємо світлодіод led2)

У функції setup () є дві інструкції: перша включає світлодіод led1, підключений до плати (наприклад, контакт 13), а друга вимикає світлодіод led1.

Функція loop () має ідентичні інструкції для включення і виключення світлодіода led2, підключеного до плати (наприклад, контакт 12).

В результаті запуску програми світлодіод led1 блимне один раз, в той час як led2 буде загорятися і гаснути до тих пір, поки включено харчування Arduino.

Натискання кнопки RESET призведе до того, що led1 знову блимне один раз, а led2 знову почне постійно блимати.

Підведемо підсумок:

  • Функції setup () і loop () - це системні функції, які повинні бути визначені в кожному проекті. Навіть в ситуації, коли в одному з них ми не пропишемо якийсь код, ми все одно повинні оголосити ці дві функції;
  • Функція setup () виконується один раз, loop () виконується безперервно;
  • ми створюємо власні функції в одному файлі;
  • Ми можемо викликати свої функції як з setup () і loop (), так і з інших функцій;
  • Наші власні функції можна викликати з параметрами і повертати значення;
  • Виклик функції повинен бути здійснений відповідно до її декларацією.

Основа мови програмування модуля Arduino - це мова Сі (швидше за Сі ++). Ще точніше, цей діалект мови називається Processing / Wiring. Гарне огляд мови ви знайдете в додатку. А мені хочеться більше розповісти не про мову, а про програмування.

Програма - це якийсь набір команд, які розуміє процесор, процесор вашого комп'ютера або процесор мікроконтролера модуля Arduino, не має значення. Процесор читає команди і виконує їх. Будь-які команди, які розуміє процесор - це двійкові числа. Це тільки двійкові числа і ніщо інше. Виконуючи арифметичні операції, для яких процесор колись і призначався, процесор оперує з числами. Двійковими числами. І виходить, що і команди, і те, до чого вони відносяться, це тільки двійкові числа. Ось так. Але як же процесор розбирається в цій «купі» двійкових чисел?

По-перше, всі ці двійкові числа записуються в послідовні комірки оперативної пам'яті, мають адреси. Коли ви завантажуєте програму, і вона починає працювати, процесор отримує першу адресу програми, де обов'язково повинна бути записана команда. Ті команди, які вимагають від процесора операцій з числами, мають «розпізнавальні знаки», наприклад, що в наступних двох осередках пам'яті два числа, які потрібно скласти. А лічильник, назвемо його лічильником команд, де записана адреса наступної команди, в даному випадку збільшує адресу так, що в програмі за цією адресою буде наступна команда. При неправильної роботи програми або збої процесор може помилитися, і тоді, прочитавши замість команди число, процесор робить зовсім не те, що повинен робити, а програма «зависає».

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

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

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

Найближче до запису програми за допомогою двійкових чисел, мова асемблер. Для нього характерно відповідність команд мови двійковим командам, зрозумілим процесору. Але кодування програм на асемблері вимагає великих зусиль і ближче до мистецтва, ніж до формальних операцій. Більш універсальні і легше в застосуванні мови високого рівня, як Бейсік або Сі. І давно для запису програм в загальному вигляді використовують графічний мову, а останнім часом з'явилися і «перекладачі» з цієї мови на мову процесорів.

Крім мов програмування загального застосування, завжди існувала певна спеціалізація мов програмування, і існували спеціалізовані мови. До останніх я б відніс і мову програмування модуля Arduino.

Все, що потрібно сказати модулю, щоб він зробив щось потрібне нам, організовано в зручний набір команд. Але спочатку про те, що нам потрібно від Arduino?

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

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

Давайте подивимося, що ж нам може розповісти сама проста програма «Моргнути светодиодом».

int ledPin \u003d 13;

pinMode (ledPin, OUTPUT);

digitalWrite (ledPin, HIGH);

digitalWrite (ledPin, LOW);

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

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

Як ми кліпаємо светодиодом:

Включити вихідний висновок порту. Вимкнути висновок порту.

Але процесор працює дуже швидко. Ми не встигнемо помітити миготіння. Щоб помітити це миготіння, нам потрібно додати паузи. Тобто:

Включити вихідний висновок порту. Пауза 1 секунда.

Вимкнути висновок порту.

Пауза 1 секунда.

Це наша програма. Процесор прочитає першу команду і включить висновок, світлодіод загориться. Потім процесор зробить паузу в роботі і вимкнути висновок, світлодіод згасне. Але він тільки один раз мигнув.

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

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

Саме про це говорить функція void loop (), loop - це петля, замкнутий цикл. Умови припинення роботи циклу немає, а, отже, немає умови його завершення.

Крім того, ми повинні повідомити модулю Arduino, який висновок порту і як ми хочемо використовувати, для виходу (OUTPUT) або для входу (INPUT). Цій меті служить функція void setup (), яка для мови Arduino є обов'язковою, навіть якщо вона не використовується, і команда pinMode (), для завдання режиму роботи виведення.

pinMode (ledPin, OUTPUT);

І ще, мовна конструкція використовує змінні для визначення номера виводу:

int ledPin \u003d 13;

Використання змінних зручно. Вирішивши, що ви будете використовувати не висновок 13, а 12, ви внесете зміни тільки в одному рядку. Особливо сильно це позначається у великих програмах. Ім'я змінної можна вибирати на свій розсуд, але, як правило, воно повинно бути тільки символьних, і часто кількість символів обмежується. Якщо ви невірно поставите ім'я змінної, думаю, компілятор вас поправить.

Функція digitalWrite (ledPin, HIGH) встановлює заданий висновок в стан з високим рівнем, тобто включає висновок.

А delay (1000), як ви вже зрозуміли, означає паузу в 1000 мілісекунд або 1 секунду.

Залишилося зрозуміти, що означають такі приставки, як int, void. Будь-які значення, будь-які змінні розміщуються в пам'яті, як і команди програми. В осередку пам'яті записуються числа найчастіше з 8 бітів. Це байт. Але байт - це числа від 0 до 255. Для запису великих чисел потрібно два байта або більше, тобто, дві або більше елементів пам'яті. Щоб процесору було ясно, як відшукати число, різні типи чисел мають різні назви. Так число на ім'я byte, займе одну клітинку, int (integer, ціле) більше. Крім того, функції, використовувані в мовах програмування, теж повертають числа. Щоб визначити, який тип числа повинна повернути функція, перед функцією записують цей тип повертається числа. Але деякі функції можуть не повертати числа, такі функції передують записом void (див. Додаток А, змінні).

Ось, скільки цікавого може розповісти навіть найпростіша програма.

Про все це ви, сподіваюся, прочитаєте в додатку. А зараз виконаємо прості експерименти, використовуючи тільки те, що ми вже знаємо з можливостей мови. Перше, замінимо змінну типу int, яка займає багато місця в пам'яті, на byte - одне місце, одна комірка пам'яті. Подивимося, що у нас вийде.

byte ledPin \u003d 13;

pinMode (ledPin, OUTPUT);

digitalWrite (ledPin, HIGH);

digitalWrite (ledPin, LOW);

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

Для цього ми замінимо число в функції delay (1000) змінної, назвавши її my_del. Ця змінна повинна бути цілим числом, тобто, int.

int my_del \u003d 5000;

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

byte my_del \u003d 5000;

Різниця, впевнений, вийде відчутна.

Проробимо ще один експеримент зі зміною тривалості пауз. Зменшення тривалості пауз виконаємо, скажімо, п'ять разів. Зробимо паузу в 2 секунди, а потім будемо збільшувати теж п'ять разів. І знову зробимо паузу в 2 секунди. Цикл, що виконується задану кількість разів, називається циклом for і записується він так:

for (int i \u003d 0; i<5; i++)

щось, що виконується в циклі for

Для виконання циклу йому потрібна змінна, у нас це i, змінної потрібно задати початкове значення, яке ми їй і привласнили. Потім слід умова завершення роботи циклу, у нас i менше 5. А запис i ++ - це характерна для мови Сі запис збільшення змінної на одиницю. Фігурні дужки обмежують набір команд, що підлягають виконанню в циклі for. В інших мовах програмування можуть бути інші обмежувачі для виділення блоку коду функції.

Всередині циклу ми виконуємо те ж, що і раніше, з невеликими змінами:

for (int i \u003d 0; i<5; i++)

digitalWrite (ledPin, HIGH);

digitalWrite (ledPin, LOW);

my_del \u003d my_del - 100;

Про зміну записи паузи ми говорили вище, а зміна самої паузи досягається зменшенням змінної на 100.

Для другого циклу ми запишемо цей же блок коду, але змінну тривалості паузи будемо збільшувати на 100.

for (int i \u003d 0; i<5; i++)

digitalWrite (ledPin, HIGH);

digitalWrite (ledPin, LOW);

Ви помітили, що запис зменшення паузи і її збільшення виглядають по-різному. Це теж особливість мови Сі. Хоча для ясності слід повторити цей запис, змінивши тільки знак мінус на плюс. Отже, ми отримуємо таку програму:

int ledPin \u003d 13;

int my_del \u003d 1000;

pinMode (ledPin, OUTPUT);

for (int i \u003d 0; i<5; i++)

digitalWrite (ledPin, HIGH);

digitalWrite (ledPin, LOW);

for (int i \u003d 0; i<5; i++)

digitalWrite (ledPin, HIGH);

digitalWrite (ledPin, LOW);

Скопіюємо код нашої програми в програму Arduin, скомпілюємо її і завантажимо в модуль. Зміна тривалості пауз помітно. І буде ще помітніше, спробуйте, якщо цикл for виконати, скажімо, раз 8.

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

Що ми упустили в своєму експерименті? Ми не прокоментували нашу роботу. Для додавання коментарів використовується або подвійна «пряма» коса риска, або одиночна, але із зірочками (див. Додаток А). Я раджу вам це зробити самостійно, оскільки повернувшись до програми через деякий час, ви легше в ній розберетеся, якщо будуть пояснення, що ви робите в тому чи іншому місці програми. І ще раджу в папці з кожною програмою зберігати її опис на звичайній мові, виконане в будь-якому текстовому редакторі.

Найпростіша програма «моргнути светодиодом» може послужити ще для десятка експериментів (навіть з одним світлодіодом). Мені здається ця частина роботи, придумувати, що ще можна зробити цікавого, найцікавіша. Якщо ви звернетеся до додатка, де описаний мову програмування, до розділу «управління програмою», то можна замінити цикл for на інший вид циклу. І спробувати, як працюють інші види циклу.

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

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

Найпростіший приклад - на вході кнопка. Коли кнопка не було натиснуто, вхід в високому стані. Якщо натиснути кнопку, то вхід переходить в низький стан, а ми можемо «запалити» світлодіод на виході. При наступному натисканні на кнопку світлодіод можна погасити.

Це знову приклад простої програми. Навіть починаючому вона може здатися нецікавою. Однак і ця проста програма може знайти цілком корисне застосування. Наведу тільки один приклад: ми будемо після натискання на кнопку не запалювати світлодіод, а моргнути (певним чином). І світлодіод візьмемо з інфрачервоним випромінюванням. В результаті ми отримаємо пульт управління. Ось така проста програма.

У різних версіях програми є відмінності в списку прикладів. Але можна звернутися до керівництва по мові в додатку, де є приклад і схема програми (в розділі прикладів, названому «додаток») для роботи з введенням. Я скопіюють програму:

int ledPin \u003d 13;

pinMode (ledPin, OUTPUT);

pinMode (inPin, INPUT);

if (digitalRead (inPin) \u003d\u003d HIGH)

digitalWrite (ledPin, HIGH);

digitalWrite (ledPin, LOW);

І, як ви бачите, абсолютно нову програму ми отримуємо, модифікуючи стару. Тепер світлодіод буде блимати тільки тоді, коли натиснута кнопка, яка приєднана до висновку 2. Висновок 2 через резистор 10 кОм приєднаний до загального проводу (землі, GND). Кнопка одним кінцем приєднана до живлячої напруги + 5В, а іншим кінцем до висновку 2.

У програмі ми зустрічаємо нову мовну конструкцію if з розділу управління програмою. Читається вона так: якщо виконується умова (укладену в дужках), то виконується блок програми, укладений у фігурні дужки. Зверніть увагу, що в умови (digitalRead (inPin) \u003d\u003d HIGH) рівність входу високому станом виконано за допомогою двох знаків рівності! Дуже часто в поспіху про це забувається, і умова виходить невірним.

Програму можна скопіювати і завантажити в модуль Arduino. Однак, щоб перевірити роботу програми, знадобитися внести деякі зміни в конструкцію модуля. Втім, це залежить від різновиду модуля. Оригінальний модуль має розетки для з'єднання з платами розширення. В цьому випадку можна вставити відповідні одножильні в потрібні місця роз'єму. Мій модуль має ножові контакти для з'єднання з платами розширення. Я можу або пошукати відповідний роз'єм, або, що дешевше, використовувати відповідну панельку для мікросхеми в корпусі DIP.

Друге питання - як знайти у модуля ті висновки, які використовуються в програмі?

З цим питанням допоможе розібратися картинка, яку я взяв з сайту: http://robocraft.ru/.

Мал. 4.1. Розташування та призначення висновків контролера і модуля Arduino

Всі висновки мого модуля CraftDuino промарковані, так що знайти потрібний висновок не складе труднощів. Можна підключати кнопку і резистор і перевіряти роботу програми. До речі, на вищезазначеному сайті RoboCraft весь процес відображений на картинках (але програма використовує не зовсім такі висновки!). Раджу подивитись.

Багато мікроконтролери в своєму складі мають додаткові апаратні пристрої. Так Atmega168, на основі якого зібраний модуль Arduino має UART, вбудований блок для зв'язку з іншими пристроями за допомогою послідовного обміну даними. Наприклад, з комп'ютером через COM-порт. Або з іншим мікро контролером за допомогою його вбудованого блоку UART. Є ще й аналого-цифровий перетворювач. І формувач широтно- імпульсної модуляції.

Використання останнього ілюструє програма, яку я теж скопіюють з сайту RoboCraft. Але програму можна взяти і з програми. І, можливо, вона є в прикладах програми Arduino.

// Fading LED by BARRAGAN

int value \u003d 0; // змінна для зберігання потрібного значення

int ledpin \u003d 9; // світлодіод підключений до digital pin 9

// Не треба викликати функцію pinMode

for (value \u003d 0; value<= 255; value+=5) // постепенно зажигаем светодиод

analogWrite (ledpin, value); // значення виведення (від 0 до 255)

delay (30); // ждѐм 🙂

for (value \u003d 255; value\u003e \u003d 0; value- \u003d 5) // поступово гасимо світлодіод

analogWrite (ledpin, value);

Якщо в попередній програмі нової для нас була функція digitalRead (inPin), читання цифрового введення, то в цій програмі нова для нас функція analogWrite (ledpin, value), хоча параметри цієї функції - вже знайомі нам змінні. Про використання аналогового входу, використанні АЦП (аналого-цифрового перетворювача), ми поговоримо пізніше. А зараз повернемося до загальних питань програмування.

Програмування це те, що доступно всім, але потрібен час, щоб освоїти і програмування, і будь-якої мова програмування. Сьогодні є ряд програм, які допомагають освоїти саме програмування. І одна з них має безпосереднє відношення до модуля Arduino. Називається вона Scratch for Arduino або скорочено S4A. Знайти і завантажити цю програму можна за адресою: http://seaside.citilab.eu/scratch/arduino. Я не знаю, як точно перекладається назва програми, але «to begin from scratch» перекладається, як «почати з нуля».

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

Після установки програми звичайним чином можна налаштувати інтерфейс на російську мову, використовуючи перемикач мов.

Мал. 4.2. Перемикач мов інтерфейсу програми

Перший значок інструментальної панелі, якщо його натиснути, відображає всі можливі мови інтерфейсу програми. Російську мову можна знайти в розділі ...

Мал. 4.3. Список мов для використання в інтерфейсі програми

... зазначеному, як «більше ...».

Якщо нічого не робити, то напис в правому вікні «Searching board ...» залишається, але модуль не виявляється. Щоб модуль Arduino підключити до програми S4A, слід завантажити з сайту проекту ще дещо.

Мал. 4.4. Файл для завантаження в модуль Arduino для S4A

Цей файл не що інше, як програма для Arduino (Sketch). Тобто, текстовий файл, який можна скопіювати в редактор Arduino, відкомпілювати і завантажити в модуль. Після виходу з програми Arduino можна запустити програму S4A і тепер модуль знаходиться.

Мал. 4.5. Підключення модуля до програми

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