Програмиране на оператори Arduino за начинаещи. Arduino - основи на програмирането. Общо описание на езиците за програмиране

Ardublock е графичен програмен език за Arduino, предназначен за начинаещи. Тази среда е доста лесна за използване, лесна за инсталиране и почти напълно преведена на руски език. Визуално проектирана програма, която наподобява блокове...

Прекъсванията са много важен механизъм в Arduino, който позволява на външните устройства да взаимодействат с контролера, когато възникнат различни събития. Чрез инсталиране на хардуерен манипулатор на прекъсвания в скицата, можем да реагираме на включване или изключване на бутон, натискане на клавиатура,...

Serial.print() и Serial.println() са основните функции на Arduino за прехвърляне на информация от платката Arduino към компютъра през серийния порт. Най-популярните Arduino Uno, Mega, Nano платки нямат вграден дисплей, така че...

Възможно ли е да се правят проекти на Arduino без самата платка на Arduino? Оказва се, доста. Благодарение на множество онлайн услуги и програми, които имат собствено име: емулатор или Arduino симулатор. Най-популярните представители на такива програми са...

Серийното начало е изключително важна инструкция на Arduino; тя позволява на контролера да установи връзка с външни устройства. Най-често това „външно устройство“ е компютърът, към който свързваме Arduino. Ето защо серийното начало е по-интензивно...

Глобалната променлива в Arduino е променлива, чийто обхват обхваща цялата програма, тя се вижда във всички модули и функции. В тази статия ще разгледаме няколко примера за използване на глобални променливи...

Arduino масивите са езиков елемент, който се използва активно от програмистите за работа с набори от данни от същия тип. Масивите се срещат в почти всички езици за програмиране, Arduino не е изключение, чийто синтаксис е много подобен...

Ще имаш нужда

  • - платка Arduino UNO,
  • - USB кабел (USB A - USB B),
  • - Персонален компютър,
  • - Светодиод,
  • - резистор 220 ома,
  • - чифт проводници 5-10 см,
  • - при наличие - макет.

Инструкции

Изтеглете средата за разработка Arduino за вашата операционна система (поддържат се Windows, Mac OS X, Linux) на страницата http://arduino.cc/en/Main/Software, можете да я инсталирате, можете. Изтегленият файл съдържа и драйвери за Arduino платки.

Инсталирайте драйвера. Обмислете опцията за Windows OS. За да направите това, изчакайте, докато операционната система ви подкани да инсталирате драйвера. Откажи. Натиснете Win + Pause, стартирайте Device Manager. Намерете секцията „Портове (COM и LPT)“. Там ще видите порт, наречен "Arduino UNO (COMxx)". Щракнете с десния бутон върху него и изберете „Актуализиране на драйвера“. След това изберете местоположението на драйвера, който току-що сте изтеглили.

Средата за разработка вече съдържа много примери за изучаване на работата на платката. Отворете примера "Blink": File > Examples > 01.Basics > Blink.

Насочете вашата среда за разработка към вашата дъска. За да направите това, в менюто Tools > Board изберете „Arduino UNO“.

Изберете порта, към който е присвоена платката Arduino. За да разберете към кой порт е свързана платката, стартирайте Device Manager и потърсете секцията Ports (COM & LPT). Портът ще бъде посочен в скоби след името на платката. Ако платката не е в списъка, опитайте я от вашия компютър и след няколко секунди я свържете отново.

Изключете платката от компютъра. Сглобете веригата, както е показано на фигурата. Моля, имайте предвид, че късият крак на светодиода трябва да бъде свързан към щифта GND, а дългият крак през резистор към цифровия щифт 13 на платката Arduino. По-удобно е да използвате макет, но ако нямате такъв, можете да свържете проводниците, като ги завъртите заедно.
Важна забележка! Цифровият пин 13 вече има собствен резистор на платката. Следователно, когато свързвате светодиод към платката, не е необходимо да използвате външен резистор. Когато свързвате светодиод към други щифтове на Arduino, използването на токоограничаващ резистор е задължително!

Сега можете да заредите програмата в паметта на платката. Свържете платката към компютъра, изчакайте няколко секунди, докато платката се инициализира. Щракнете върху бутона "Качване" и вашата скица ще бъде записана в паметта на платката Arduino. Програмирането с Arduino е много интуитивно и не е никак трудно. Вижте изображението - има малки пояснения в коментарите към програмата. Това е достатъчно, за да започнете с първия си експеримент.

Въведение

Freeduino/Arduino е програмиран на специален език за програмиране - базиран е на C/C++ и ви позволява да използвате всяка негова функция. Строго погледнато, няма отделен език на Arduino, както няма компилатор на Arduino - написаните програми се конвертират (с минимални промени) в програма на C/C++ и след това се компилират от AVR-GCC компилатора. Така че всъщност се използва вариант на C/C++, специализиран за AVR микроконтролери.

Разликата е, че получавате проста среда за разработка и набор от основни библиотеки, които опростяват достъпа до периферните устройства, разположени „на борда“ на микроконтролера.

Съгласете се, много е удобно да започнете да работите със сериен порт със скорост от 9600 бита в секунда, извършвайки повикване в един ред:

Serial.begin(9600);

И когато използвате „гол“ C/C++, ще трябва да се справите с документацията за микроконтролера и да извикате нещо подобно:

UBRR0H = ((F_CPU / 16 + 9600 / 2) / 9600 - 1) >> 8;
UBRR0L = ((F_CPU / 16 + 9600 / 2) / 9600 - 1);
sbi(UCSR0B, RXEN0);
sbi(UCSR0B, TXEN0);
sbi(UCSR0B, RXCIE0);

Ето кратък преглед на основните функции и характеристики на програмирането на Arduino. Ако не сте запознати със синтаксиса на езиците C/C++, препоръчваме ви да се обърнете към всяка литература по този въпрос или интернет източници.

От друга страна, всички представени примери са много прости и най-вероятно няма да имате никакви затруднения да разберете изходните текстове и да напишете свои собствени програми дори без да четете допълнителна литература.

По-пълна документация (на английски) е представена на официалния сайт на проекта - http://www.arduino.cc. Има и форум, връзки към допълнителни библиотеки и техните описания.

По аналогия с описанието на официалния уебсайт на проекта Arduino, „порт“ се отнася до контакт на микроконтролер, свързан към конектор под съответния номер. Освен това има сериен комуникационен порт (COM порт).

Структура на програмата

Във вашата програма трябва да декларирате две основни функции: setup() и loop().

Функцията setup() се извиква веднъж, след всяко включване или нулиране на платката Freeduino. Използвайте го за инициализиране на променливи, задаване на режими на работа на цифрови портове и др.

Функцията loop() последователно изпълнява командите, описани в нейното тяло, отново и отново. Тези. След като функцията приключи, тя ще бъде извикана отново.

Нека да разгледаме един прост пример:

void setup() // първоначални настройки
{
beginSerial(9600); // настройка на скоростта на серийния порт на 9600 bps
pinMode(3, INPUT); // настройка на 3-ти порт за въвеждане на данни
}

// Програмата проверява 3-ти порт за наличие на сигнал на него и изпраща отговор на
// като текстово съобщение до серийния порт на компютъра
void loop() // тяло на програмата
{
if (digitalRead(3) == HIGH) // условие за запитване на 3-ти порт
serialWrite("H"); // изпращане на съобщение под формата на буквата "H" до COM порта
друго
serialWrite("L"); // изпращане на съобщение под формата на буквата "L" до COM порта
забавяне (1000); // забавяне 1 сек.
}

pinMode(порт, режим);

Описание:

Конфигурира посочения порт за въвеждане или извеждане на сигнал.

Настроики:

port – номерът на порта, чийто режим искате да зададете (цяло число от 0 до 13).

режим - или INPUT (вход), или OUTPUT (изход).

pinMode(13, ИЗХОД); //13-ият щифт ще бъде изходът
pinMode(12, INPUT); //и 12-тото е входът

Забележка:

Аналоговите входове могат да се използват като цифрови входове/изходи чрез достъп до тях чрез номера 14 (аналогов вход 0) до 19 (аналогов вход 5)

digitalWrite(порт, стойност);

Описание:

Задава нивото на напрежение на високо (HIGH) или ниско (LOW) на посочения порт.

Настроики:

порт: номер на порт

стойност: ВИСОКА или НИСКА

digitalWrite(13, HIGH); // задайте щифт 13 на „високо“ състояние

стойност = digitalRead(порт);

Описание:

Прочита стойността на посочения порт

Настроики:

порт: номер на запитван порт

Върната стойност: връща текущата стойност на порта (HIGH или LOW) от тип int

int val;
val = digitalRead(12); // проучване на 12-ия щифт

Забележка:

Ако няма нищо свързано с порта, който се чете, тогава функцията digitalRead() може да върне ВИСОКИ или НИСКИ стойности хаотично.

Вход/изход за аналогов сигнал

стойност = analogRead(порт);

Описание:

Чете стойност от посочения аналогов порт. Freeduino съдържа 6 канала, аналогово-цифров преобразувател от 10 бита всеки. Това означава, че входното напрежение от 0 до 5V се преобразува в цяло число от 0 до 1023. Разделителната способност на отчитане е: 5V/1024 стойности = 0,004883 V/стойност (4,883 mV). Необходими са приблизително 100 ns (0,0001 C), за да се прочете аналогова входна стойност, така че максималната скорост на четене е приблизително 10 000 пъти в секунда.

Настроики:

Върната стойност: Връща int число в диапазона от 0 до 1023, прочетено от посочения порт.

int val;
val = analogRead(0); // прочете стойността на 0-тия аналогов вход

Забележка:

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

analogWrite(порт, стойност);

Описание:

Извежда аналогова стойност към порта. Тази функция работи на: 3, 5, 6, 9, 10 и 11 Freeduino цифрови портове.

Може да се използва за промяна на яркостта на светодиод, управление на мотор и др. След извикване на функцията analogWrite, съответният порт започва да работи в режим на широчинно-импулсна модулация на напрежението, докато има друго извикване на функцията analogWrite (или функции digitalRead / digitalWrite на същия порт).

Настроики:

порт: номер на запитвания аналогов вход

стойност: цяло число между 0 и 255. Стойност 0 генерира 0 V на посочения порт; стойност от 255 генерира +5V на посочения порт. За стойности между 0 и 255, портът започва бързо да се редува между 0 и +5 V нива на напрежение - колкото по-висока е стойността, толкова по-често портът генерира HIGH (5 V) ниво.

analogWrite(9, 128); // задаване на пин 9 на стойност, еквивалентна на 2,5 V

Забележка:

Няма нужда да извиквате pinMode, за да настроите порта да извежда сигнали, преди да извикате analogWrite.

Честотата на генериране на сигнала е приблизително 490 Hz.

време = millis();

Описание:

Връща броя милисекунди, откакто Freeduino е изпълнил текущата програма. Броячът ще препълни и ще се нулира след приблизително 9 часа.

Върната стойност: връща дълга стойност без знак

неподписан дълго време; // декларация на времева променлива от тип unsigned long
време = millis(); // прехвърляне на броя милисекунди

забавяне (време_ms);

Описание:

Поставя на пауза програмата за определения брой милисекунди.

Настроики:

time_ms – време на забавяне на програмата в милисекунди

забавяне (1000); //пауза 1 секунда

забавяне Микросекунди

забавяне Микросекунди(време_μs);

Описание:

Поставя на пауза програмата за определения брой микросекунди.

Настроики:

time_μs – време за забавяне на програмата в микросекунди

забавяне Микросекунди (500); //пауза 500 микросекунди

pulseIn(порт, стойност);

Описание:

Чете импулс (висок или нисък) от цифров порт и връща продължителността на импулса в микросекунди.

Например, ако параметърът "value" е зададен на HIGH при извикване на функцията, тогава pulseIn() изчаква високо ниво на сигнала да пристигне на порта. От момента, в който пристигне, започва обратното броене, докато на порта се получи ниско ниво на сигнала. Функцията връща дължината на импулса (високо ниво) в микросекунди. Работи с импулси от 10 микросекунди до 3 минути. Имайте предвид, че тази функция няма да върне резултат, докато не бъде открит импулс.

Настроики:

порт: номер на порт, от който четем импулса

стойност: импулсен тип HIGH или LOW

Върната стойност: връща продължителността на импулса в микросекунди (тип int)

int продължителност; // декларация на променлива за продължителност от тип int
продължителност = pulseIn(pin, HIGH); // измерване на продължителността на импулса

Серийно предаване на данни

Freeduino има вграден контролер за серийно предаване на данни, който може да се използва както за комуникация между Freeduino/Arduino устройства, така и за комуникация с компютър. На компютър съответната връзка е представена от USB COM порт.

Комуникацията се осъществява през цифрови портове 0 и 1 и следователно няма да можете да ги използвате за цифров вход/изход, ако използвате серийни функции.

Serial.begin(скорост_на_скорост);

Описание:

Задава скоростта на трансфер на информация на COM порта в битове в секунда за серийно предаване на данни. За да комуникирате с компютър, използвайте една от тези стандартизирани скорости: 300, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600 или 115200. Можете също така да дефинирате други скорости, когато комуникирате с друг микроконтролер чрез портове 0 и 1.

Настроики:

baud_rate: Скорост на потока на данни в битове в секунда.

Serial.begin(9600); //задайте скоростта на 9600 bps

Сериен.наличен

брой = Serial.available();

Описание:

Байтовете, получени през серийния порт, завършват в буфера на микроконтролера, откъдето вашата програма може да ги прочете. Функцията връща броя байтове, натрупани в буфера. Серийният буфер може да съхранява до 128 байта.

Върната стойност:

Връща int стойност - броят байтове, налични за четене в серийния буфер, или 0, ако нищо не е налично.

if (Serial.available() > 0) ( // Ако има данни в буфера
// тук трябва да има приемане и обработка на данни
}

char = Serial.read();

Описание:

Чете следващия байт от буфера на серийния порт.

Върната стойност:

Първият наличен байт входящи данни от серийния порт или -1, ако няма входящи данни.

incomingByte = Serial.read(); // четене на байт

Описание:

Изчиства входния буфер на серийния порт. Данните в буфера се губят и по-нататъшните извиквания към Serial.read() или Serial.available() ще имат смисъл за данните, получени след извикването Serial.flush().

Serial.flush(); // Изчистете буфера - започнете да получавате данни „от нулата“

Описание:

Изходни данни към сериен порт.

Настроики:

Функцията има няколко форми за извикване в зависимост от типа и формата на изходните данни.

Serial.print(b, DEC) отпечатва ASCII низ - десетичното представяне на числото b.

int b = 79;

Serial.print(b, HEX) отпечатва ASCII низ - шестнадесетичното представяне на числото b.

int b = 79;

Serial.print(b, OCT) отпечатва ASCII низ - осмичното представяне на числото b.

int b = 79;
Serial.print(b, OCT); //ще изведе низа “117” към порта

Serial.print(b, BIN) отпечатва ASCII низ - двоичното представяне на числото b.

int b = 79;
Serial.print(b, BIN); //ще изведе низа “1001111” към порта

Serial.print(b, BYTE) отпечатва малкия байт на b.

int b = 79;
Serial.print(b, BYTE); // ще покаже числото 79 (един байт). В монитора
//от серийния порт получаваме символа “O” - негов
//кодът е 79

Serial.print(str) ако str е низ или масив от символи, прехвърля str към байт байт на COM порта.

char байтове = (79, 80, 81); //масив от 3 байта със стойности 79,80,81
Serial.print("Ето нашите байтове:"); // извежда реда „Ето нашите байтове:“
Serial.print(байтове); //извежда 3 символа с кодове 79,80,81 –
//това са знаците "OPQ"

Serial.print(b) ако b е от тип byte или char, отпечатва самото число b на порта.

char b = 79;
Serial.print(b); //ще изведе знака “O” към порта

Serial.print(b) ако b е от тип цяло число, отпечатва десетичното представяне на b към порта.

int b = 79;
Serial.print(b); //ще изведе низа “79” към порта

Описание:

Функцията Serial.println е подобна на функцията Serial.print и има същите опции за извикване. Единствената разлика е, че два допълнителни знака се извеждат след данните - знак за връщане на каретка (ASCII 13 или "\r") и знак за нов ред (ASCII 10 или "\n").

Пример 1 и пример 2 ще изведат едно и също нещо към порта:

int b = 79;
Serial.print(b, DEC); //ще изведе низа “79” към порта
Serial.print("\r\n"); // ще покаже знаците "\r\n" – преместване на ред
Serial.print(b, HEX); //ще изведе низа “4F” към порта
Serial.print("\r\n");//ще отпечата знаците "\r\n" – подаване на ред

int b = 79;
Serial.println(b, DEC); //ще изведе низа “79\r\n” към порта
Serial.println(b, HEX); //ще изведе низа “4F\r\n” към порта

В монитора на серийния порт получаваме.

Основата на езика за програмиране на модула Arduino е езикът C (най-вероятно C++). По-точно този диалект на езика се нарича Processing/Wiring. Ще намерите добър преглед на езика в приложението. Но искам да говоря повече не за езика, а за програмирането.

Програмата е определен набор от команди, който се разбира от процесора, процесора на вашия компютър или процесора на микроконтролера на модула Arduino, няма значение. Процесорът чете инструкциите и ги изпълнява. Всички команди, които процесорът разбира, са двоични числа. Това са само двоични числа и нищо друго. Чрез извършване на аритметичните операции, за които процесорът някога е бил проектиран, процесорът оперира с числа. Двоични числа. И се оказва, че както командите, така и това, за което се отнасят, са само двоични числа. Като този. Но как процесорът сортира тази „купчина“ от двоични числа?

Първо, всички тези двоични числа се записват в последователни RAM клетки, които имат адреси. Когато заредите програма и тя започне да работи, процесорът получава първия адрес на програмата, където трябва да се напише командата. Тези инструкции, които изискват процесорът да работи с числа, имат „идентификационни знаци“, например, че в следващите две клетки на паметта има две числа, които трябва да бъдат добавени. И броячът, нека го наречем програмен брояч, където е написан адресът на следващата команда, в този случай увеличава адреса, така че програмата да съдържа следващата команда на този адрес. Ако програмата не работи правилно или има повреди, процесорът може да направи грешка и след това, след като прочете число вместо команда, процесорът прави нещо съвсем различно от това, което трябва да прави, и програмата „замръзва“.

Така всяка програма е поредица от двоични числа. А програмирането е способността да се записват правилно правилните последователности от двоични числа. Преди доста време за писане на програми започнаха да се използват специални инструменти, наречени езици за програмиране.

Всяка програма обаче първо изисква да имате ясно разбиране какво трябва да прави програмата и защо е необходима. Колкото по-ясно разбирате това, толкова по-лесно е да създадете програма. Малките програми, въпреки че е трудно да се каже кои програми са малки и кои не, могат да се разглеждат като цяло. По-сложните програми е най-добре да се разделят на части, които могат да се третират като независими програми. Това ги прави по-добри за създаване, по-лесни за отстраняване на грешки и тестване.

Не съм готов да споря, но мисля, че е по-удобно да стартирате програма с описание на обикновен език. И в този смисъл смятам, че програмирането не трябва да се бърка с писането на програмен код. Когато една програма е описана с обикновени думи, за вас е по-лесно да определите например кой език за програмиране да изберете, за да създадете програмния код.

Най-близкото нещо до писането на програма, използваща двоични числа, е асемблерният език. Характеризира се със съответствието на езиковите команди с бинарните команди, разбираеми от процесора. Но кодирането на програми на асемблер изисква много усилия и е по-близо до изкуство, отколкото до формални операции. Езиците на високо ниво като BASIC или C са по-универсални и по-лесни за използване. И от дълго време графичният език се използва за писане на програми в обща форма, а наскоро се появиха „преводачи“ от този език на езика на процесорите.

В допълнение към общите езици за програмиране винаги е имало известна специализация на езиците за програмиране и е имало специализирани езици. Сред последните бих включил и езика за програмиране на модула Arduino.

Всичко, от което се нуждаем, за да кажем на модула да направи нещо, от което се нуждаем, е организирано в удобен набор от команди. Но първо, какво ни трябва от Arduino?

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

По-горе вече използвахме прости програми, за да проверим връзката на модула с компютъра. За някои те може да изглеждат твърде прости и следователно неинтересни, но всяка сложна програма се състои от по-прости фрагменти, подобни на тези, с които вече сме се запознали.

Нека видим какво може да ни каже най-простата програма „Мигане на светодиод“.

int ledPin = 13;

pinMode(ledPin, ИЗХОД);

digitalWrite(ledPin, HIGH);

digitalWrite(ledPin, LOW);

Първо, нека си припомним какво е светодиод. По същество това е обикновен диод, в който поради конструкцията си, когато токът тече в права посока, преходът започва да свети. Тоест, за да свети един светодиод, през него трябва да тече ток, което означава, че трябва да се приложи напрежение към светодиода. И така, че токът да не надвишава допустимата стойност, резисторът трябва да бъде свързан последователно със светодиода, който се нарича резистор за ограничаване на тока (вижте Приложение А, цифров изход). Напрежението се прилага към светодиода от микроконтролера, който формира основата на модула Arduino. Микроконтролерът, в допълнение към процесора, който изпълнява нашите команди, има един или повече I/O портове. Без да разглеждаме конкретното устройство на порта, да кажем следното - когато щифтът на порта работи като изход, той може да се представи като изход на цифрова микросхема с две състояния, включено и изключено (на изхода има напрежение , няма напрежение на изхода).

Но същият щифт на порта може да работи и като вход. В този случай той може да бъде представен например като вход на цифрова микросхема - към входа се прилага логическо ниво, високо или ниско (вижте Приложение А, цифров вход).

Как мигаме светодиода:

Активиране на изходния щифт на порта. Изключете изхода на порта.

Но процесорът е много бърз. Няма да имаме време да забележим мигането. За да забележим това мигане, трябва да добавим паузи. Това е:

Активиране на изходния щифт на порта. Пауза 1 секунда.

Изключете изхода на порта.

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

Това е нашата програма. Процесорът ще прочете първата команда и ще включи изхода, светодиодът ще светне. След това процесорът ще спре и ще изключи изхода, светодиодът ще изгасне. Но той премигна само веднъж.

Повтарянето на процес или набор от команди се нарича цикъл в програмирането. Използват се различни видове цикли. Има цикъл, който се изпълнява определен брой пъти. Това е for цикъл. Има цикли, които се изпълняват, докато не бъде изпълнено условие, което е част от конструкцията на цикъла в езика. И ако условието никога не е изпълнено, тогава цикълът се изпълнява безкраен брой пъти. Това е безкраен цикъл.

Не мисля, че микроконтролерите се използват с програми от вида, показан по-горе. Тоест няколко команди се изпълняват веднъж и контролерът вече не работи. По правило той работи непрекъснато, веднага щом към него се приложи захранващо напрежение. Това означава, че микроконтролерът трябва да работи в безкраен цикъл.

Точно това казва функцията void loop(), цикълът си е цикъл, затворен цикъл. Няма условие за спиране на цикъла и следователно няма условие за неговото завършване.

Освен това трябва да кажем на модула Arduino кой щифт на порта искаме да използваме и как искаме да се използва, за изход (OUTPUT) или за вход (INPUT). Тази цел се обслужва от функцията void setup(), която е задължителна за езика Arduino, дори и да не се използва, и командата pinMode() за задаване на работния режим на изхода.

pinMode(ledPin, ИЗХОД);

И все пак езиковата конструкция използва променливи, за да определи изходния номер:

int ledPin = 13;

Използването на променливи е удобно. Ако решите, че ще използвате изход 12, а не 13, ще направите промяна само на един ред. Това е особено вярно при големи програми. Името на променливата може да бъде избрано по ваше желание, но по принцип то трябва да бъде само със знаци, а броят на знаците често е ограничен. Ако зададете името на променливата неправилно, мисля, че компилаторът ще ви коригира.

Функцията digitalWrite(ledPin, HIGH) настройва посочения пин на високо състояние, т.е. включва щифта.

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

Остава да разберем какво означават префикси като int и void. Всички стойности, всякакви променливи се намират в паметта, както и програмните команди. Числата, често състоящи се от 8 бита, се записват в клетките на паметта. Това е байт. Но байтът е число от 0 до 255. За да запишете големи числа, имате нужда от два байта или повече, тоест две или повече клетки от паметта. За да стане ясно на процесора как да намери число, различните видове числа имат различни имена. Така че число, наречено байт, ще заема една клетка, int (цяло число, цяло число) ще заема повече. В допълнение, функциите, използвани в езиците за програмиране, също връщат числа. За да определите какъв тип число трябва да върне дадена функция, добавете префикс към функцията с този тип върнато число. Но някои функции може да не връщат числа; такива функции се предшестват от нотацията void (вижте Приложение A, променливи).

Ето колко интересно може да разкаже дори най-простата програма.

Надявам се, че можете да прочетете за всичко това в приложението. Сега нека направим прости експерименти, използвайки само това, което вече знаем от възможностите на езика. Първо, нека заменим променлива от тип int, която заема много място в паметта, с байт - едно място, една клетка от паметта. Да видим какво можем да направим.

байт ledPin = 13;

pinMode(ledPin, ИЗХОД);

digitalWrite(ledPin, HIGH);

digitalWrite(ledPin, LOW);

След компилиране и зареждане на програмата в модула, няма да забележим промени в работата на програмата. Глоба. След това ще променим програмата, така че да забележим промени в нейната работа.

За да направим това, ще заменим числото във функцията за забавяне (1000) с променлива, наричайки я my_del. Тази променлива трябва да е цяло число, тоест int.

int my_del = 5000;

Не забравяйте да завършите всяка команда с точка и запетая. Направете промени в програмата, компилирайте я и я заредете в модула. След това променете променливата и прекомпилирайте и заредете отново:

байт my_del = 5000;

Сигурен съм, че разликата ще бъде забележима.

Нека направим още един експеримент с промяна на продължителността на паузите. Нека намалим продължителността на паузите, да речем, пет пъти. Нека направим пауза за 2 секунди и след това я увеличим също пет пъти. И отново правим пауза за 2 секунди. Цикъл, който се изпълнява определен брой пъти, се нарича for цикъл и се записва по следния начин:

за (int i = 0; i<5; i++)

нещо, което се изпълнява в for цикъл

За да изпълни цикъла, той се нуждае от променлива, за нас това е i, променливата трябва да получи първоначална стойност, която сме й присвоили. След това следва условието за прекратяване на цикъла, имаме i по-малко от 5. И записът i++ е типичен запис на езика C за увеличаване на променлива с единица. Къдравите скоби ограничават набора от команди, които могат да бъдат изпълнени в for цикъл. Други езици за програмиране могат да имат различни разделители за подчертаване на блок от функционален код.

Вътре в цикъла правим същото като преди, с няколко малки промени:

за (int i = 0; i<5; i++)

digitalWrite(ledPin, HIGH);

digitalWrite(ledPin, LOW);

my_del = my_del - 100;

Говорихме за промяна на записа на пауза по-горе и промяната на самата пауза се постига чрез намаляване на променливата със 100.

За втория цикъл ще напишем същия блок код, но ще увеличим променливата за продължителност на паузата със 100.

за (int i = 0; i<5; i++)

digitalWrite(ledPin, HIGH);

digitalWrite(ledPin, LOW);

Забелязахте, че записът на намаляване на паузата и нейното увеличаване изглежда различно. Това също е характеристика на езика C. Въпреки че за по-голяма яснота този запис трябваше да се повтори, като се промени само знакът минус на плюс. Така че получаваме тази програма:

int ledPin = 13;

int my_del = 1000;

pinMode(ledPin, ИЗХОД);

за (int i = 0; i<5; i++)

digitalWrite(ledPin, HIGH);

digitalWrite(ledPin, LOW);

за (int i = 0; i<5; i++)

digitalWrite(ledPin, HIGH);

digitalWrite(ledPin, LOW);

Нека копираме кода на нашата програма в програмата Arduin, да го компилираме и да го заредим в модула. Забележима е промяната в продължителността на паузите. И ще бъде още по-забележимо, опитайте, ако for цикълът се изпълни, да речем, 8 пъти.

Това, което току-що направихме, е това, което правят професионалните програмисти - разполагайки с готова програма, тя лесно може да бъде модифицирана, за да отговаря на вашите нужди или желания. Ето защо те съхраняват всичките си програми. Какво ви съветвам да направите и вие.

Какво пропуснахме в нашия експеримент? Не сме коментирали нашата работа. За да добавите коментар, използвайте двойна наклонена черта или единична наклонена черта, но със звездички (вижте Приложение A). Съветвам ви да направите това сами, защото когато се върнете към програмата след известно време, ще го разберете по-лесно, ако има обяснения за това, което правите на това или онова място в програмата. И също така ви съветвам да съхранявате описанието му на обикновен език, направено във всеки текстов редактор, в папката с всяка програма.

Най-простата програма „мигащ светодиод“ може да служи за още дузина експерименти (дори с един светодиод). Струва ми се, че тази част от работата, да измисля какво още може да се направи по интересен начин, е най-интересна. Ако се обърнете към приложението, където е описан езикът за програмиране, към раздела „контрол на програмата“, можете да замените цикъла for с друг вид цикъл. И опитайте как работят други видове цикъл.

Въпреки че процесорът на микроконтролера, както всеки друг, може да извършва изчисления (затова е изобретен) и това се използва например в устройства, най-типичната операция за микроконтролер ще бъде да настрои изхода на порта на високо или ниско състояние, тоест „мигане на светодиода“ като реакция на външни събития.

Микроконтролерът научава за външни събития главно от състоянието на входовете. Като настроим щифтовете на порта към цифров вход, можем да го наблюдаваме. Ако първоначалното състояние на входа е високо и дадено събитие кара входа да премине на ниско ниво, тогава можем да направим нещо в отговор на това събитие.

Най-простият пример е бутон на входа. Когато бутонът не е натиснат, входът е във високо състояние. Ако натиснем бутона, входът става нисък и можем да „светим“ светодиода на изхода. Следващият път, когато натиснете бутона, светодиодът може да се изключи.

Това отново е пример за проста програма. Дори на начинаещ може да му се стори безинтересно. Тази проста програма обаче може да намери и доста полезни приложения. Ще дам само един пример: след като натиснете бутона, светодиодът няма да свети, а ще мига (по определен начин). И да вземем светодиод с инфрачервено лъчение. В резултат на това ще получим контролен панел. Това е толкова проста програма.

Има разлики в списъка с примери в различните версии на програмата. Но можете да се обърнете към езиковото ръководство в приложението, което има пример и програмна диаграма (в секцията с примери, наречена „приложение“) за работа с въвеждане. Ще копирам програмата:

int ledPin = 13;

pinMode(ledPin, ИЗХОД);

pinMode(inPin, INPUT);

if (digitalRead(inPin) == HIGH)

digitalWrite(ledPin, HIGH);

digitalWrite(ledPin, LOW);

И както можете да видите, ние получаваме напълно нова програма, като модифицираме старата. Сега светодиодът ще мига само когато се натисне бутонът, който е свързан към пин 2. Пин 2 е свързан към общия проводник (земя, GND) чрез резистор 10 kOhm. Бутонът е свързан в единия край към +5V захранващо напрежение, а в другия край към пин 2.

В програмата срещаме нова езикова конструкция if от секцията за управление на програмата. Той гласи така: ако условието (оградено в скоби) е изпълнено, тогава програмният блок, ограден във фигурни скоби, се изпълнява. Обърнете внимание, че в условието (digitalRead(inPin) == HIGH) равенството на входа към високото състояние се извършва с помощта на два знака за равенство! Много често при бързане това се забравя и условието се оказва неправилно.

Програмата може да бъде копирана и заредена в модула Arduino. Въпреки това, за да проверите работата на програмата, ще трябва да направите някои промени в дизайна на модула. Това обаче зависи от вида на модула. Оригиналният модул има гнезда за свързване на разширителни карти. В този случай можете да поставите подходящи плътни проводници на необходимите места в конектора. Моят модул има блейд контакти за свързване към разширителни платки. Мога или да потърся подходящ конектор, или, което е по-евтино, да използвам подходящо гнездо за чипа в DIP корпус.

Вторият въпрос е как да намеря щифтовете на модула, които се използват в програмата?

Снимката, която направих от сайта: http://robocraft.ru/ ще ви помогне да разберете това.

Ориз. 4.1. Местоположение и предназначение на щифтовете на контролера и модула Arduino

Всички щифтове на моя модул CraftDuino са етикетирани, така че намирането на правилния щифт е лесно. Можете да свържете бутон и резистор и да проверите работата на програмата. Между другото, на гореспоменатия уебсайт RoboCraft целият процес е показан в снимки (но програмата не използва точно същите заключения!). Съветвам ви да погледнете.

Много микроконтролери включват допълнителни хардуерни устройства. Така че Atmega168, на базата на който е сглобен модулът Arduino, има UART, вграден модул за комуникация с други устройства, използващи сериен обмен на данни. Например с компютър през COM порт. Или с друг микроконтролер, използвайки неговия вграден UART блок. Има и аналогово-цифров преобразувател. И шейпер за модулация на ширината на импулса.

Използването на последния е илюстрирано с програма, която също ще копирам от сайта на RoboCraft. Но програмата може да се вземе и от приложението. И може би е в примерите за програмата Arduino.

// Избледняващ светодиод от BARRAGAN

int стойност = 0; // променлива за съхраняване на желаната стойност

int ledpin = 9; // Светодиод, свързан към цифров пин 9

// Няма нужда да извиквате функцията pinMode

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

analogWrite(ledpin, стойност); // изходна стойност (от 0 до 255)

забавяне (30); // чакам 🙂

for(value = 255; value >=0; value-=5) // постепенно изключване на светодиода

analogWrite(ledpin, стойност);

Ако в предишната програма функцията digitalRead(inPin), четене на цифров вход, беше нова за нас, тогава в тази програма функцията analogWrite(ledpin, value) е нова за нас, въпреки че параметрите на тази функция са променливи, които вече са ни познати . По-късно ще говорим за използването на аналоговия вход, използвайки ADC (аналогово-цифров преобразувател). Сега да се върнем към общите проблеми с програмирането.

Програмирането е нещо, което всеки може да прави, но ще отнеме време, за да овладеете както програмирането, така и всеки език за програмиране. Днес има редица програми, които ви помагат да овладеете програмирането. И един от тях е пряко свързан с модула Arduino. Нарича се Scratch for Arduino или накратко S4A. Можете да намерите и изтеглите тази програма на: http://seaside.citilab.eu/scratch/arduino. Не знам как точно се превежда името на програмата, но „започнете от нулата“ се превежда като „започнете от нулата“.

Уебсайтът на проекта 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. Свързване на модула към програмата

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

След като се запознаете с основните елементи на Arduino, както и напишете програма “Hello World!”. Време е да се запознаете с един език за програмиране.

Структурата на езика се основава основно на C/C++, така че тези, които преди това са програмирали на този език, няма да имат затруднения с овладяването на програмирането на Arduino. Други трябва да научат основна информация за контролните команди, типовете данни и функциите.

Голяма част от информацията, съдържаща се тук, ще бъде съвместима с всеки курс по C/C++, като се вземат предвид разликите в типовете данни, както и няколко специфични инструкции относно програмирането на I/O портове.

Основи

Няколко формални неща, тоест онези, за които всички знаят, но понякога забравят...

В Arduino IDE, както и в C/C++, трябва да сте наясно с малките и малки букви. Ключови думи като if, for винаги се пишат с малки букви. Всяка инструкция завършва с ";". Точката и запетая казва на компилатора коя част да интерпретира като инструкция.

Скобите (..) се използват за обозначаване на програмни блокове. Използваме ги за ограничаване на функционални тела (вижте по-долу), цикли и условни оператори.

Добра практика е да добавяте коментари към съдържанието на програмата, това прави кода лесен за разбиране. Едноредовите коментари започват с // (двойна наклонена черта). Многоредовите коментари започват с /* и завършва с */

Ако искаме да включим някоя библиотека в нашата програма, използваме командата include. Ето примери за свързване на библиотеки:

#включи // стандартна библиотека #include “svoya_biblioteka.h” // библиотека в директорията на проекта

Функции в Arduino

Функция (подпрограма) е отделна част от програма, която изпълнява определени операции. Функциите се използват за опростяване на основната програма и подобряване на четимостта на кода. Полезно е да използваме функции, тъй като можем лесно да ги използваме в много от нашите проекти.

Стандартният курс по програмиране съдържа информация за функциите, които ще бъдат представени в следващите статии. В случая на Arduino функциите ще бъдат обсъдени в началото, защото дори най-простата програма трябва да има две специални функции. Това вече беше споменато в предишни статии, но тук систематизираме тази информация.

Декларация на функция

Диаграмата за деклариране на функцията изглежда така:

Тип function_name(параметър) ( // инструкции за изпълнение (тяло на функция) return (/* върната стойност*/); )

Типе името на всеки наличен тип данни в даден език за програмиране. Ще предоставим списък с видовете, налични при програмиране на Arduino, в отделна статия.

След изпълнение функцията ще върне стойността на декларирания тип. Ако функцията не приеме никаква върната стойност, тогава типът данни ще бъде „void“.

име_на_функцияпозволява уникалното му идентифициране. За да извикаме (изпълним) функция, ние й даваме име.

параметър— параметър за извикване на функция. Параметрите не са задължителни, но често са полезни. Ако напишем функция, която няма аргументи, оставяме скобите празни.

Вътре в скобите "(...)" е действителното тяло на функцията или инструкцията, която искаме да изпълним. Ще предоставим описание на конкретни инструкции в отделна статия.

Всички функции, които връщат стойност, завършват с оператор return, последван от върнатата стойност. Само функции, декларирани с нулев указател ("void"), не съдържат израз за връщане. Трябва да знаете, че операторът return прекратява функцията независимо от местоположението.

По-долу са някои примери за декларации на функции.

Void f1() ( // тяло на функция) —————————————— int minus() ( // тяло на функция връщане (0); ) ———————————— ——— int plus(int a, int b) ( return (a+b); )

Както можете да видите от примерите, декларацията на функция може да приеме много форми в зависимост от вашите нужди.

Силно ви препоръчваме да научите и използвате функциите, когато пишете свои собствени програми. С течение на времето всеки програмист натрупва своя собствена библиотека от функции „за всички случаи“, което улеснява и ускорява писането на нови програми.

След като вече знаем как да напишем собствена функция, трябва да се научим как да я използваме.

Извикване на функция

Пишем всички функции в един файл/програма. Има, разбира се, и по-елегантно решение, но ще се опитаме да го опишем следващия път.

След като декларираме функция, можем да я използваме в други функции с подходящото име и всички необходими параметри. По-долу са дадени примери за извикване на функциите, които дадохме по-горе:

F1(); плюс(2,2); y=плюс(1,5);

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

Ако функцията f1() е декларирана без параметри, тогава не могат да бъдат зададени параметри при извикването й, т.е. извикването на f1(0) ще бъде неправилно.

Функцията plus(int a, int b) изисква точно два параметъра, така че извикването с един или три параметъра не е възможно.

Извикването на y=plus(1,5) ще изпълни функцията "plus" с параметри "1" и "5" и ще съхрани върнатата стойност в променливата "y".

функции setup() и loop().

Със знания за декларирането и извикването на функции, можем да преминем към системните функции на Arduino: настройвам()И цикъл (). Arduino IDE се изисква да декларира тези две функции.

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

Както подсказва името му, той се използва за задаване на началните стойности на променливи, декларации на системни входове и изходи, които обикновено се посочват в първоначалните параметри. Поради своята специфика тази функция не връща стойност и не се извиква с параметри. Правилната декларация на функцията setup() е по-долу:

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

loop() е функция, която се извиква в безкраен цикъл. Тази функция също не връща стойност и не се извиква с параметри. Правилната декларация на функцията loop() е показана по-долу:

Void цикъл () ( // тяло на функция - програмен код )

Както можете да видите, декларацията на функцията 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(), така и от други функции;
  • Нашите собствени функции могат да бъдат извикани с параметри и да върнат стойност;
  • Извикването на функция трябва да бъде направено в съответствие с нейната декларация.