Домой / Видео / Ардуино программирование справочник. Программирование 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=I*R
Где V -напряжение на резистор
I - ток через резистор
R - сопротивление, которое надо найти.
Во-первых, мы должны узнать напряжение на резистор. Большинство светодиодов 3мм или 5мм, которые вы будете использовать, имеют рабочее напряжение 3в. Значит, на резисторе нам надо погасить 5-3=2в.

Затем мы вычислим ток, проходящий через резистор.
Большинство 3 и 5мм светодиодов светятся полной яркостью при токе 20мА. Ток больше этого может вывести их из строя, а ток меньшей силы снизит их яркость, не причинив никакого вреда.

Итак, мы хотим включить светодиод в цепь 5в,чтобы на нем был ток 20мА. Так как все детали включены в одну цепь на резистор тоже будет ток 20мА.
Мы получаем
2В = 20 мА * R
2В = 0.02A * R
R = 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 = 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 = 4; int led2Pin = 5; int led3Pin = 6; int led4Pin = 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);
полный код скетча во вложении (скачиваний: 1187)

Регулировка яркости светодиодов

Иногда вам надо будет менять яркость светодиодов в программе. Это можно сделать с помощью команды analogWrite() . Эта команда так быстро включает и выключает светодиод, что глаз не видит это мерцание. Если светодиод половину времени будет включён, а половину выключен, то визуально будет казаться, что он светится в половину своей яркости. Это называется широтно-импульсная модуляция (ШИМ или PWM по-английски). Шим применяется довольно часто, так как с ее помощью можно управлять "аналоговым" компонентом с помощью цифрового кода. Не все выводы Arduino подходят для этих целей. Только те выводы, около которых нарисовано такое обозначение "~ ". Вы увидите его рядом с выводами 3,5,6,9,10,11.
Соедините один из ваших светодиодов с одним из выводов ШИМ(у автора это вывод 9). Теперь запуститьскетч мигания светодиода, но прежде измените команду digitalWrite() на analogWrite() . analogWrite() имеет два аргумента: первый это номер вывода, а второй- значение ШИМ (0-255), применительно к светодиодам это будет их яркость свечения, а для электродвигателей скорость вращения. Ниже представлен код примера для разной яркости светодиода.
//Меняем яркость светодиода int ledPin = 9;//к этому выводу подсоединен светодиод void setup() { pinMode(ledPin, OUTPUT);// инициализация пина на вывод } void loop() { analogWrite(ledPin, 255);//полная яркость (255/255 = 1) delay(1000);// пауза 1 сек digitalWrite(ledPin, LOW);//выключить светодиод delay(1000);//пауза 1 сек analogWrite(ledPin, 191);//яркость на 3/4 (191/255 ~= 0.75) delay(1000);//пауза 1 сек digitalWrite(ledPin, LOW);//выключить светодиод delay(1000);//пауза 1 сек analogWrite(ledPin, 127);//половина яркости (127/255 ~= 0.5) delay(1000);// пауза 1 сек digitalWrite(ledPin, LOW);//выключить светодиод delay(1000);//пауза 1 сек analogWrite(ledPin, 63);//четверть яркости (63/255 ~= 0.25) delay(1000);// пауза 1 сек digitalWrite(ledPin, LOW);//выключить светодиод delay(1000);//пауза 1 сек }

Попробуйте поменять значение ШИМ в команде analogWrite () ,чтобы увидеть, как это влияет на яркость.
Далее вы узнаете, как регулировать яркость плавно от полной до нулевой. Можно,конечно, скопировать кусок кода 255 раз
analogWrite(ledPin, brightness); delay(5);//short delay brightness = brightness + 1;
Но, сами понимаете - это будет не практично. Для этого лучше всего использовать цикл FOR, который использовали ранее.
В следующем примере используются два цикла, один для уменьшения яркости от 255 до 0
for (int brightness=0;brightness=0;brightness--){ analogWrite(ledPin,brightness); delay(5); }
delay(5) используется, чтобы замедлить скорость нарастания и уменьшения яркости 5*256=1280 мсек= 1.28 сек.)
В первой строке используется "brightness- " ,для того чтобы значение яркости уменьшалось на 1, каждый раз, когда цикл повторяется. Обратите внимание, что цикл будет работать до тех пор, пока brightness >=0 .Заменив знак > на знак >= мы включили 0 в диапазон яркости. Ниже смоделирован этот скетч. //плавно меняем яркость int ledPin = 9;//к этому пину подключен светодиод void setup() { pinMode(ledPin, OUTPUT);// инициализация пина на выход } void loop() { //плавно увеличиваем яркость (0 to 255) for (int brightness=0;brightness=0;brightness--){ analogWrite(ledPin,brightness); delay(5); } delay(1000);//ждем 1 сек //плавно уменьшаем яркость (255 to 0) for (int brightness=255;brightness>=0;brightness--){ analogWrite(ledPin,brightness); delay(5); } delay(1000);//ждем 1 сек } }
Это видно не очень хорошо, но идея понятна.

RGB-светодиод и Arduino

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

Включая разные светодиоды с различной яркостью можно комбинировать и получать разные цвета. Для Arduino, где количество градаций яркости равно 256 вы получите 256^3=16581375 возможных цветов. Реально их, конечно, будет меньше.
Светодиод, который мы будем использоваться общим катодом. Т.е. все три светодиода конструктивно соединены катодами к одному выводу. Этот вывод мы подсоединим к выводу GND. Остальные выводы, через ограничительные резисторы, надо подсоединить к выводам ШИМ. Автор использовал выводы 9-11.Таким образом можно будет управлять каждым светодиодом отдельно. В первом скетче показано, как включить каждый светодиод отдельно.



//RGB LED - test //pin connections int red = 9; int green = 10; int blue = 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 = 9; int green = 10; int blue = 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.
В прикрепленном файле скетч, который продемонстрирует плавные переходы цветов от красного к зеленому, затем к синему, красному, зеленому и т.д. (скачиваний: 326)
Пример скетча работает, но есть много повторяющегося кода. Можно упростить код, написав собственную вспомогательную функцию, которая будет плавно менять один цвет на другой.
Вот как она будет выглядеть: (скачиваний: 365)
Давайте рассмотрим определение функции по частям. Функция называется fader и имеет два аргумента. Каждый аргумент отделяется запятой и имеет тип объявленный в первой строке определения функции: void fader (int color1, int color2) . Вы видите, что оба аргумента объявлены как int , и им присвоены имена color1 и color2 в качестве условных переменных для определения функции. Void означает, что функция не возвращает никаких значений, она просто выполняет команды. Если надо было бы написать функцию, которая возвращала результат умножения это выглядело бы так:
int multiplier(int number1, int number2){ int product = number1*number2; return product; }
Обратите внимание, как мы объявили Тип int в качестве типа возвращаемого значения вместо
void .
Внутри функции идут команды, которые вы уже использовали в предыдущем скетче, только номера выводов заменили на color1 и color2 . Вызывается функция fader , ее аргументы вычисляются как color1 = red и color2 = green . В архиве полный скетч с использованием функций (скачиваний: 272)

Кнопка

В следующем скетче будет использоваться кнопка с нормально разомкнутыми контактами, без фиксации.


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


//определяем нажатие кнопки int buttonPin = 7; void setup(){ pinMode(buttonPin, INPUT);//инициализируем пин на вход Serial.begin(9600);//инициализируем последовательный порт } void loop(){ if (digitalRead(buttonPin)==HIGH){//если кнопка нажата Serial.println("pressed"); // выводим надпись "pressed" } else { Serial.println("unpressed");// иначе "unpressed" } }
В этом скетче несколько новых команд.
-эта команда принимает значение High (высокий уровень) и low (низкий уровень), того вывода, который мы проверяем. Предварительно в setup() этот вывод надо настроить на вход.
; //где buttonPin это номер вывода, куда подсоединяется кнопка.
Последовательный порт позволяет отправлять Arduino сообщения на компьютер, в то время, как сам контроллер выполняет программу. Это полезно для отладки программы, отправки сообщений на другие устройства или приложения. Чтобы включить передачу данных через последовательный порт (другое название UART или USART), надо инициализировать его в setup()

Serial.begin() имеет всего один аргумент-это скорость передачи данных между Arduino и компьютером.
скетче используется команда для вывода сообщения на экран в Arduino IDE (Tools >> Serial Monitor).
- конструкция позволяют контролировать ход выполнения программы, объеденив несколько проверок в одном месте.
If(если) digitalRead возвращает значение HIGH, то на мониторе выводится слово "нажата". Else(иначе) на мониторе выводится слово " отжата" . Теперь можно попробовать включать и выключать светодиод по нажатию кнопки.
//button press detection with LED output int buttonPin = 7; int ledPin = 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)==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 = 512
analogRead имеет только один аргумент- Это номер аналогового входа (А0-А5). В следующем скетче приводится код считывания напряжения с потенциометра. Для этого подключите переменный резистор, крайними выводами на пины 5V и GND, а средний вывод на вход А0.

Запустите следующий код и посмотрите в serial monitor, как меняются значения в зависимости от поворота ручки резистора.
//analog input int potPin = A0;//к этому пину подсоединяется центральный вывод потенциометра void setup(){ //аналоговый пин по умолчанию включен на вход, поэтому инициализация не нужна Serial.begin(9600); } void loop(){ int potVal = analogRead(potPin);//potVal is a number between 0 and 1023 Serial.println(potVal); }
Следующий скетч объединяет скетч нажатия кнопки и скетч управления яркостью светодиода. Светодиод будет включаться от кнопки, и управлять яркостью свечения будет потенциометр.
//button press detection with LED output and variable intensity int buttonPin = 7; int ledPin = 9; int potPin = A0; void setup(){ pinMode(buttonPin, INPUT); pinMode(ledPin, OUTPUT); Serial.begin(9600); } void loop(){ if (digitalRead(buttonPin)==HIGH){//if button pressed int analogVal = analogRead(potPin); int scaledVal = map(analogVal, 0, 1023, 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 – это приобрести отладочную плату (хорошо бы сразу приобрести монтажную плату и т.п.). Уже описывал, какие виды плат Arduino представлены на рынке. Кто еще не читал статью советую ознакомиться. Для изучения основ выбираем стандартную плату Arduino Uno (оригинал или хорошую китайскую копию — решать вам). При первом подключении оригинальной платы проблем возникнуть не должно, а вот с «китайцем» нужно будет немного поковыряться (не переживайте – всё покажу и расскажу).

Подключаем Arduino к компьютеру USB кабелем. На плате должен засветиться светодиод «ON «. В диспетчере устройств появится новое устройство «Неизвестное устройство «. Необходимо установить драйвер. Тут внесу небольшую неясность (кот отвлек – я не запомнил, какой из драйверов решил «проблему неизвестного устройства ».

Предварительно скачал и распаковал программную средy Arduino (arduino-1.6.6-windows ). Затем скачал этот . Он самораспаковывающейся. Запустил файл CH341SER.EXE . Выбрал установку (INSTALL) . После установки появилось сообщение, нажал «Ок » (прочитать не успел).

После перешёл в свойства все еще «неизвестного устройства» и выбрал кнопку «Update Driver». Выбрал вариант «Установка из указанного места» – указал папку с разархивированной программной средой Arduino. И о чудо – всё удачно заработало…

Запускаем программу Arduino (в моём случае 1.6.6) и разрешаем доступ.

Все проекты (программы) для Arduino состоят из двух частей: void setup и void loop . void setup выполняется всего один раз, а void loop выполняется снова и снова.

Прежде чем продолжим, необходимо выполнить две обязательные операции:

— указать в программной среде Arduino, какую плату вы используете. Tool->board-> Arduino Uno. Если отметка уже стоит на нужной вам плате – это хорошо, если нет – ставим отметку.

— указать в программной среде какой последовательный порт вы используете для связи с платой. Tool->port-> COM3. Если отметка уже стоит на порте – это хорошо, если нет – ставим отметку. Если у вас в разделе порты представлен больше, чем один порт, как же узнать, какой именно используется для соединения с платой? Берём плату и отсоединяем от неё провод. Снова заходим в порты и смотрим, какой из них исчез. В моём случае вкладка «порты» вообще стала не активной.

Снова подключаем провод USB.

Для первой программы никаких дополнительных модулей не нужно. Будем включать светодиод, который уже смонтирован на плате (на 13 выводе микроконтроллера).

Для начала сконфигурим 13 вывод (на вход или на выход).

Для этого вводим в блок «void setup » команду pinMode , в скобках указываем параметры (13, OUTPUT ) (Какой вывод задействован, Режим работы ). Программная среда выделяет слова/команды соответствующим цветом шрифта.

Переходим в блок «void loop » и вводим команду digitalWrite с параметрами (13, HIGH) .


Первая программа готова, теперь осталось загрузить её в микроконтроллер. Нажимаем кнопку UPLOAD.

Светодиод засветился. Но не стоит так скептически относиться к простоте первой программы. Вы только, что освоили первую управляющую команду. Вместо светодиода ведь можно подключить любую нагрузку (будь-то освещение в комнате или сервопривод, перекрывающий подачу воды), но об этом всём поговорим позже…

Светодиод мы включили, он немного посветил, пора его выключать. Для этого видоизменим написанную нами программу. Вместо «HIGH » напишем «LOW ».


Нажимаем кнопку UPLOAD. Светодиод погас.

Мы уже познакомились с понятием « », пора им воспользоваться. Дальнейшие программы будут становится все объёмнее и сложнее, а работы по их изменению будут занимать все больше и больше времени, если мы оставим подобный стиль написания кода.

Смотрим на программу (снова включим светодиод). Зададим номер вывода микроконтроллера не числом 13 , а переменной, которой будет присвоено значение соответствующего вывода (в нашем случае 13). В дальнейшем будет очень удобно изменять значения переменных в начале программы, вместо того, чтобы шарится по коду в поисках тех мест, где необходимо произвести замены значений.

Создаём глобальную переменную int LED_pin = 13; (тип переменной, имя переменной, присваиваемое ей значение ).


Нажимаем кнопку UPLOAD. Светодиод светится. Все работает отлично.

В этом уроке, кроме включения/выключения светодиода, мы еще научимся мигать им.

Для этого вводим вторую команду «digitalWrite » с параметрами (LED_pin, LOW ).


Нажимаем кнопку UPLOAD. И что мы видим? Светодиод светится «в пол наказа». Причина кроется в том, что время переключения двух состояний (HIGH и LOW ) ничтожно мало и человеческий глаз не может уловить эти переключения. Необходимо увеличить время нахождения светодиода в одном из состояний. Для этого пишем команду delay с параметром (1000 ) . Задержка в миллисекундах: 1000 миллисекунд – 1 секунда. Алгоритм программы следующий: включили светодиод – ждём 1 секунду, выключили светодиод – ждём 1 секунду и т.д.


Нажимаем кнопку UPLOAD. Светодиод начал мерцать. Все работает.

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


Нажимаем кнопку UPLOAD. Светодиод мерцает, как и мерцал.

Доработаем написанную нами программу. Задачи следующие:

  • Светодиод включен 0,2 секунды и выключен 0,8 секунды;
  • Светодиод включен 0,7 секунды и выключен 0,3 секунды.

В программе созданы 2 переменные, что отвечают за временные задержки. Одна определяет время работы включенного светодиода, а вторая – время работы выключенного светодиода.

Спасибо за внимание. До скорой встречи!

Основа языка программирования модуля Arduino - это язык Си (скорее Си++). Ещё точнее, этот диалект языка называется Processing/Wiring. Хорошее обозрение языка вы найдёте в приложении. А мне хочется больше рассказать не о языке, а о программировании.

Программа - это некий набор команд, которые понимает процессор, процессор вашего компьютера или процессор микроконтроллера модуля Arduino, не суть важно. Процессор читает команды и выполняет их. Любые команды, которые понимает процессор - это двоичные числа. Это только двоичные числа и ничто иное. Выполняя арифметические операции, для которых процессор некогда и предназначался, процессор оперирует с числами. Двоичными числами. И получается, что и команды, и то, к чему они относятся, это только двоичные числа. Вот так. Но как же процессор разбирается в этой «куче» двоичных чисел?

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

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

Однако любая программа в первую очередь требует от вас ясного понимания того, что должна делать программа, и для чего она нужна. Чем яснее вы это понимаете, тем легче создать программу. Небольшие программы, хотя трудно сказать, какие программы небольшие, а какие нет, можно рассматривать целиком. Более сложные программы лучше разбить на части, которые можно рассматривать как самостоятельные программы. Так их лучше создать, легче отладить и проверить.

Я не готов спорить, но считаю, что программу удобнее начинать с описания на обычном языке. И в этом смысле я считаю, что программирование не следует путать с написанием кода программы. Когда программа описана обычными словами, вам легче определить, например, какой язык программирования выбрать для создания кода программы.

Ближе всего к записи программы с помощью двоичных чисел, язык ассемблер. Для него характерно соответствие команд языка двоичным командам, понятным процессору. Но кодирование программ на ассемблере требует больших усилий и ближе к искусству, чем к формальным операциям. Более универсальны и легче в применении языки высокого уровня, как Бэйсик или Си. И давно для записи программ в общем виде используют графический язык, а в последнее время появились и «переводчики» с этого языка на язык процессоров.

Кроме языков программирования общего применения, всегда существовала некоторая специализация языков программирования, и существовали специализированные языки. К последним я бы отнёс и язык программирования модуля Arduino.

Всё, что нужно сказать модулю, чтобы он сделал что-то нужное нам, организовано в удобный набор команд. Но вначале о том, что нам нужно от Arduino?

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

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

Давайте посмотрим, о чём нам может рассказать самая простая программа «Помигать светодиодом».

int ledPin = 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 = 13;

Использование переменных удобно. Решив, что вы будете использовать не вывод 13, а 12, вы внесёте изменение только в одной строке. Особенно сильно это сказывается в больших программах. Имя переменной можно выбирать по своему усмотрению, но, как правило, оно должно быть только символьным, и часто количество символов ограничивается. Если вы неверно зададите имя переменной, думаю, компилятор вас поправит.

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

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

Осталось понять, что означают такие приставки, как int, void. Любые значения, любые переменные размещаются в памяти, как и команды программы. В ячейки памяти записываются числа зачастую из 8 битов. Это байт. Но байт - это числа от 0 до 255. Для записи больших чисел нужно два байта или больше, то есть, две или больше ячеек памяти. Чтобы процессору было ясно, как отыскать число, разные типы чисел имеют разные названия. Так число по имени byte, займёт одну ячейку, int (integer, целое) больше. Кроме того, функции, используемые в языках программирования, тоже возвращают числа. Чтобы определить, какой тип числа должна вернуть функция, перед функцией записывают этот тип возвращаемого числа. Но некоторые функции могут не возвращать числа, такие функции предваряют записью void (см. Приложение А, переменные).

Вот, сколько интересного может рассказать даже самая простая программа.

Обо всём этом вы, надеюсь, прочитаете в приложении. А сейчас проделаем простые эксперименты, используя только то, что мы уже знаем из возможностей языка. Первое, заменим переменную типа int, которая занимает много места в памяти, на byte - одно место, одна ячейка памяти. Посмотрим, что у нас получится.

byte ledPin = 13;

pinMode (ledPin, OUTPUT);

digitalWrite (ledPin, HIGH);

digitalWrite (ledPin, LOW);

После компиляции и загрузки программы в модуль мы не заметим изменений в работе программы. Хорошо. Тогда изменим программу так, чтобы заметить изменения в её работе.

Для этого мы заменим число в функции delay (1000) переменной, назвав её my_del. Эта переменная должна быть целым числом, то есть, int.

int my_del = 5000;

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

byte my_del = 5000;

Разница, уверен, получится ощутимая.

Проделаем ещё один эксперимент с изменением длительности пауз. Уменьшение длительности пауз выполним, скажем, пять раз. Сделаем паузу в 2 секунды, а затем будем увеличивать тоже пять раз. И вновь сделаем паузу в 2 секунды. Цикл, выполняемый заданное количество раз, называется циклом for и записывается он так:

for (int i = 0; i<5; i++)

что-то, что выполняется в цикле for

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

Внутри цикла мы выполняем то же, что и раньше, с небольшими изменениями:

for (int i = 0; i<5; i++)

digitalWrite (ledPin, HIGH);

digitalWrite (ledPin, LOW);

my_del = my_del - 100;

Об изменении записи паузы мы говорили выше, а изменение самой паузы достигается уменьшением переменной на 100.

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

for (int i = 0; i<5; i++)

digitalWrite (ledPin, HIGH);

digitalWrite (ledPin, LOW);

Вы заметили, что запись уменьшения паузы и её увеличения выглядят по-разному. Это тоже особенность языка Си. Хотя для ясности следовало повторить эту запись, изменив только знак минус на плюс. Итак, мы получаем такую программу:

int ledPin = 13;

int my_del = 1000;

pinMode (ledPin, OUTPUT);

for (int i = 0; i<5; i++)

digitalWrite (ledPin, HIGH);

digitalWrite (ledPin, LOW);

for (int i = 0; i<5; i++)

digitalWrite (ledPin, HIGH);

digitalWrite (ledPin, LOW);

Скопируем код нашей программы в программу Arduin, скомпилируем её и загрузим в модуль. Изменение длительности пауз заметно. И будет ещё заметнее, попробуйте, если цикл for выполнить, скажем, раз 8.

То, что мы сейчас сделали, делают и профессиональные программисты - имея готовую программу, её легко можно модифицировать под свои нужды или желания. Поэтому все свои программы они хранят. Что я советую делать и вам.

Что мы упустили в своём эксперименте? Мы не прокомментировали нашу работу. Для добавления комментария используется либо двойная «прямая» косая черта, либо одиночная, но со звёздочками (см. Приложение А). Я советую вам это сделать самостоятельно, поскольку вернувшись к программе через некоторое время, вы легче в ней разберётесь, если будут пояснения, что вы делаете в том или ином месте программы. И ещё советую в папке с каждой программой хранить её описание на обычном языке, выполненное в любом текстовом редакторе.

Самая простая программа «помигать светодиодом» может послужить ещё для десятка экспериментов (даже с одним светодиодом). Мне кажется эта часть работы, придумывать, что ещё можно сделать интересного, самая интересная. Если вы обратитесь к приложению, где описан язык программирования, к разделу «управление программой», то можно заменить цикл for на другой вид цикла. И попробовать, как работают другие виды цикла.

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

О внешних событиях микроконтроллер узнаёт, в основном, по состоянию входов. Настроив выводы порта на цифровой вход, мы можем следить за ним. Если исходное состояние входа - высокий уровень, а событие вызывает переход входа в низкое состояние, то мы можем что-то сделать, реагируя на это событие.

Самый простой пример - на входе кнопка. Когда кнопка не нажата, вход в высоком состоянии. Если нажать кнопку, то вход переходит в низкое состояние, а мы можем «зажечь» светодиод на выходе. При следующем нажатии на кнопку светодиод можно погасить.

Это опять пример простой программы. Даже начинающему она может показаться неинтересной. Однако и эта простая программа может найти вполне полезное применение. Приведу только один пример: мы будем после нажатия на кнопку не зажигать светодиод, а помигаем (определённым образом). И светодиод возьмём с инфракрасным излучением. В результате мы получим пульт управления. Вот такая простая программа.

В разных версиях программы есть различия в списке примеров. Но можно обратиться к руководству по языку в приложении, где есть пример и схема программы (в разделе примеров, названном «приложение») для работы с вводом. Я скопирую программу:

int ledPin = 13;

pinMode (ledPin, OUTPUT);

pinMode (inPin, INPUT);

if (digitalRead(inPin) == HIGH)

digitalWrite(ledPin, HIGH);

digitalWrite (ledPin, LOW);

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

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

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

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

С этим вопросом поможет разобраться картинка, которую я взял с сайта: http://robocraft.ru/.

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

Все выводы моего модуля CraftDuino промаркированы, так что найти нужный вывод не составит труда. Можно подключать кнопку и резистор и проверять работу программы. Кстати, на вышеупомянутом сайте RoboCraft весь процесс отображён на картинках (но программа использует не совсем такие выводы!). Советую посмотреть.

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

Использование последнего иллюстрирует программа, которую я тоже скопирую с сайта RoboCraft. Но программу можно взять и из приложения. И, возможно, она есть в примерах программы Arduino.

// Fading LED by BARRAGAN

int value = 0; // переменная для хранения нужного значения

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

// Нет необходимости вызвать функцию pinMode

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

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

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

for(value = 255; value >=0; value-=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. Подключение модуля к программе

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

В жизни ардуинщика рано или поздно наступает момент, когда в штатной среде разработки становится тесно. Если скетчам перестает хватать памяти, требуется жесткий реалтайм и работа с прерываниями или просто хочется быть ближе к железу - значит пришло время переходить на C. Бывалые электронщики при упоминании Arduino презрительно поморщатся и отправят новичка в радиомагазин за паяльником. Возможно, это не самый плохой совет, но мы пока не будем ему следовать. Если отбросить Arduino IDE и язык wiring/processing, у нас в руках останется прекрасная отладочная плата, уже оснащенная всем необходимым для работы микроконтроллера. И, что немаловажно, в память контроллера уже зашит бутлоадер, позволяющий загружать прошивку без использования программатора.

Для программирования на языке C нам понадобится AVR GCC Toolchain.

Также нам потребуется установленная Arduino IDE, т.к. она содержит утилиту avrdude, которая нужна для загрузки прошивки в контроллер. CrossPack тоже содержит avrdude, но версия, идущая с ним, не умеет работать с Arduino.

После того, как все установлено, создадим наш первый проект. Для начала напишем Makefile . Он позволит нам избежать ввода длинных команд вручную при каждой компиляции и загрузке прошивки.

#Контроллер, установленный на плате. Может быть другим, например atmega328 DEVICE = atmega168 #Тактовая частота 16 МГц CLOCK = 16000000 #Команда запуска avrdude. Ее нужно скопировать из Arduino IDE. AVRDUDE = /Applications/Arduino.app/Contents/Resources/Java/hardware/tools/avr/bin/avrdude -C/Applications/Arduino.app/Contents/Resources/Java/hardware/tools/avr/etc/avrdude.conf -carduino -P/dev/tty.usbserial-A600dAAQ -b19200 -D -p atmega168 OBJECTS = main.o COMPILE = avr-gcc -Wall -Os -DF_CPU=$(CLOCK) -mmcu=$(DEVICE) all: main.hex .c.o: $(COMPILE) -c $< -o $@ .S.o: $(COMPILE) -x assembler-with-cpp -c $< -o $@ .c.s: $(COMPILE) -S $< -o $@ flash: all $(AVRDUDE) -U flash:w:main.hex:i clean: rm -f main.hex main.elf $(OBJECTS) main.elf: $(OBJECTS) $(COMPILE) -o main.elf $(OBJECTS) main.hex: main.elf rm -f main.hex avr-objcopy -j .text -j .data -O ihex main.elf main.hex avr-size --format=avr --mcu=$(DEVICE) main.elf

В этом файле нам нужно вписать свою команду для запуска avrdude. На разных системах она будет выглядеть по разному. Чтобы узнать свой вариант, запускаем Arduino IDE и в настройках ставим галочку «Show verbose output during upload».

Теперь загружаем в Arduino любой скетч и смотрим сообщения, выводимые в нижней части окна. Находим там вызов avrdude, копируем все, кроме параметра -Uflash и вставляем в Makefile после «AVRDUDE = ».


Небольшое замечание: все отступы в Makefile делаются символами табуляции (клавишей Tab). Если ваш текстовый редактор заменяет эти символы пробелами, команда make откажется собирать проект.

Теперь создадим файл main.c - собственно текст нашей программы, в которой традиционно помигаем светодиодом.

#include #include #define LED_PIN 5 int main() { DDRB |= 1 << LED_PIN; while(1) { PORTB |= 1 << LED_PIN; _delay_ms(1000); PORTB &= ~(1 << LED_PIN); _delay_ms(1000); } return 0; }

Наш проект готов. Откроем консоль в директории нашего проекта и введем команду «make»:


Как видим, размер получившейся прошивки составляет всего 180 байт. Аналогичный ардуиновский скетч занимает 1116 байт в памяти контроллера.

Теперь вернемся к консоли и введем «make flash» чтобы загрузить скомпилированный файл в контроллер:


Если загрузка прошла без ошибок, то светодиод, подключенный к 13 контакту платы, радостно замигает. Иногда avrdude не может найти плату или отваливается по таймауту - в этом случае может помочь передегивание USB кабеля. Также, во избежание конфликтов доступа к плате, не забудьте закрыть Arduino IDE перед командой «make flash».

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

Удачи в освоении микроконтроллеров!

Введение

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

Разница заключается в том, что Вы получаете простую среду разработки, и набор базовых библиотек, упрощающих доступ к находящейся «на борту» микроконтроллера периферии.

Согласитесь, очень удобно начать работу с последовательным портом на скорости 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++, советуем обратиться к любой литературе по данному вопросу, либо Internet-источникам.

С другой стороны, все представленные примеры очень просты, и скорее всего у Вас не возникнет трудностей с пониманием исходных текстов и написанием собственных программ даже без чтения дополнительной литературы.

Более полная документация (на английском языке) представлена на официальном сайте проекта – http://www.arduino.cc . Там же есть форум, ссылки на дополнительные библиотеки и их описание.

По аналогии с описанием на официальном сайте проекта Arduino, под «портом» понимается контакт микроконтроллера, выведенный на разъем под соответствующим номером. Кроме того, существует порт последовательной передачи данных (COM-порт).

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

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

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

Функция loop() последовательно раз за разом исполняет команды, которые описаны в ее теле. Т.е. после завершения функции снова произойдет ее вызов.

Разберем простой пример:

void setup() // начальные установки
{
beginSerial(9600); // установка скорости работы серийного порта на 9600 бит/сек
pinMode(3, INPUT); // установка 3-его порта на ввод данных
}

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

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

Описание:

Конфигурирует указанный порт на ввод или вывод сигнала.

Параметры:

порт – номер порта, режим которого Вы желает установить (значение целого типа от 0 до 13).

режим – либо INPUT (ввод) либо OUTPUT (вывод).

pinMode(13, OUTPUT); //13й вывод будет выходом
pinMode(12, INPUT); //а 12й – входом

Примечание:

Аналоговые входы могут использоваться как цифровые входы/выходы, при обращении к ним по номерам с 14 (аналоговый вход 0) по 19 (аналоговый вход 5)

digitalWrite(порт, значение);

Описание:

Устанавливает высокий (HIGH) или низкий (LOW) уровень напряжения на указанном порте.

Параметры:

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

значение: HIGH или LOW

digitalWrite(13, HIGH); // выставляем 13й вывод в «высокое» состояние

value = digitalRead (порт);

Описание:

Считывает значение на указанном порту

Параметры:

порт: номер опрашиваемого порта

Возвращаемое значение: возвращает текущее значение на порту (HIGH или LOW) типа int

int val;
val = digitalRead(12); // опрашиваем 12й вывод

Примечание:

Если к считываемому порту ничего не подключено, то функция digitalRead () может беспорядочно возвращать значения HIGH или LOW.

Аналоговый ввод/вывод сигнала

value = analogRead(порт);

Описание:

Считывает значение с указанного аналогового порта. Freeduino содержит 6 каналов, аналого-цифрового преобразователя на 10 битов каждый. Это означает, что входное напряжения от 0 до 5В преобразовывается в целочисленное значение от 0 до 1023. Разрешающая способность считывания составляет: 5 В/1024 значений = 0,004883 В/значение (4,883 мВ). Требуется приблизительно 100 нС (0.0001 С), чтобы считать значение аналогового ввода, так что максимальная скорость считывания - приблизительно 10000 раз в секунду.

Параметры:

Возвращаемое значение: возвращает число типа 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 В на указанном порте; значение 255 генерирует +5 В на указанном порте. Для значений между 0 и 255, порт начинает быстро чередовать уровень напряжения 0 и +5 В - чем выше значение, тем, более часто порт генерирует уровень HIGH (5 В).

analogWrite(9, 128);// устанавливаем на 9 контакте значение эквивалентное 2,5В

Примечание:

Нет необходимости вызвать функцию pinMode, чтобы установить порт на вывод сигналов перед вызовом функции analogWrite.

Частота генерирования сигнала – приблизительно 490 Гц.

time = millis();

Описание:

Возвращает число миллисекунд, с момента исполнения Freeduino текущей программы. Счетчик переполнится и обнулится приблизительно через 9 часов.

Возвращаемое значение: возвращает значение типа unsigned long

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

delay(время_мс);

Описание:

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

Параметры:

время_мс – время задержки программы в миллисекундах

delay(1000); //пауза 1 секунда

delayMicroseconds

delayMicroseconds(время_мкс);

Описание:

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

Параметры:

время_мкс – время задержки программы в микросекундах

delayMicroseconds(500); //пауза 500 микросекунд

pulseIn(порт, значение);

Описание:

Считывает импульс (высокий или низкий) c цифрового порта и возвращает продолжительность импульса в микросекундах.

Например, если параметр «значение» при вызове функции установлен в HIGH, то pulseIn() ожидает, когда на порт поступит высокий уровень сигнала. С момента его поступления начинается отсчет времени до тех пор, пока на порт не поступит низкий уровень сигнала. Функция возвращает длину импульса (высокого уровня) в микросекундах. Работает с импульсами от 10 микросекунд до 3 минут. Обратите внимание, что эта функция не будет возвращать результат, пока импульс не будет обнаружен.

Параметры:

порт: номер порта, с которого считываем импульс

значение: тип импульса HIGH или LOW

Возвращаемое значение: возвращает длительность импульса в микросекундах (тип int)

int duration; // объявление переменной duration типа int
duration = 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.

Параметры:

скорость_передачи: скорость потока данных в битах в секунду.

Serial.begin(9600); //устанавливаем скорость 9600 бит/сек

Serial.available

count = 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 bytes = {79, 80, 81}; //массив из 3 байт со значениями 79,80,81
Serial.print("Here our bytes:"); //выводит строку «Here our bytes:»
Serial.print(bytes); //выводит 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»

В мониторе последовательного порта получим.