• I






      
           

Научно-популярный образовательный ресурс для юных и начинающих радиолюбителей - Popular science educational resource for young and novice hams

Основы электричества, учебные материалы и опыт профессионалов - Basics of electricity, educational materials and professional experience

КОНКУРС
language
 
Поиск junradio

Радиодетали
ОК
Сервисы

Stock Images
Покупка - продажа
Фото и изображений


 
Выгодный обмен
электронных валют

Друзья JR



JUNIOR RADIO

 

Установка рабочей среды и разработка простейшей программы на Arduino




Купить радиодетали для ремонта

 

 

Arduino – это простота. Давайте убедимся в этом на практике. Что нам понадобится:

 

 


1.    Персональный компьютер с операционной системой Windows и доступом в интернет.
2.    Контроллер Arduino.
3.    USB кабель для подключения контроллера к ПК.

 Персональный компьютер сейчас есть в любом доме и на этом я останавливаться не буду. Что до операционной системы, то Arduino IDE будет работать и под Windows, и под Linux, и под MacOS. И выглядеть она везде будет одинаково. Windows я взял как наиболее распространенную и доступную. Все-таки на большинстве домашних и школьных компьютеров стоит именно она.

 

USB кабель можно найти в любом ларьке с мышками, флэшками и прочей электронной мелочевкой. Стоит он копейки…

Итак. Компьютер есть, контроллер купили, шнур нашли… Что дальше? – Выполним следующий порядок действий:
1.    Открываем Arduino.ru
2.    В разделе «Среда разработки» находим «скачать последнюю версию» и нажимаем ссылку, соответствующую Вашей операционной системе. В нашем случае Windows.
3.    Браузер начинает загружать нам на компьютер файл. Сохраняем его куда-нибудь на диск. Куда – не важно. Главное, чтоб Вы потом смогли его найти.
4.    Файл скачан. На самом деле это zip-архив. Современная Windows умеет работать с такими архивами без каких-либо специализированных средств. Открываем его проводником.
5.    Во втором окне проводника открываем удобное место на диске ПК и создаем новую папку. Имя выберете сами. Главное, чтоб Вам было понятно, что в этой папке размещается Arduino IDE.
6.    Копируем файлы и папки из архива [4] в созданную папку [5].
7.    Запускаем arduino.exe
8.    Среда установлена!
Для удобства можно еще создать ярлык на рабочем столе к файлу arduino.exe.
  Теперь можно начинать разрабатывать программу. Традиционно начнем с «Hello world». В данном случае – помигаем светодиодом.
Во-первых, микроконтроллер позволяет нам управлять своими выводами (контактами). Практически все они выведены на внешние разъемы Arduino и имеют свои номера. Контакты (или пины) могут выступать как в роли входов, так и в роли выходов. Определяется это программно.
  На большинстве контроллеров Arduino распаяно 4 светодиода: индикатор питания, прием данных, передача данных, и тестовый светодиод на пине 13. Нас пока будет интересовать последний. Заставим его мигать раз в секунду. Для этого напишем в редакторе следующий код:

int led = 13;

void setup() {               
  pinMode(led, OUTPUT);    
}

void loop() {
  digitalWrite(led, HIGH);
  delay(1000);         
  digitalWrite(led, LOW);
  delay(1000);
}

Внимание: Язык чувствителен к регистру символов. При написании программ необходимо правильно соблюдать следование строчных и заглавных букв.

Давайте сначала загрузим нашу программу в контроллер и посмотрим на результат, а потом разберем, что все это значит.
Для загрузки программы в контроллер из среды Arduino IDE необходимо выполнить следующие действия:

1.    Надо выбрать тип нашего контроллера.
В дальнейшем я буду использовать разные типы контроллеров. И по сути не важно, какой именно контроллер у Вас. Там, где это будет принципиально, я буду обращать на это внимание. Но в большинстве случаев пока будет достаточно просто выбрать тип Вашей платы из списка.

 

 

2.    Теперь код надо откомпилировать. Процесс компиляции преобразует текст программы в машинный код, который выполняется микроконтроллером. Так же при компиляции среда Arduino выведет в нижней части окна (консоле) все имеющиеся в коде синтаксические ошибки. Для запуска компиляции необходимо нажать кнопку на тулбаре:



При успешном завершении компиляции среда сообщит Вам об этом в консоли и укажет итоговый размер прошивки.

 

 

3.    Подключаем Arduino к компьютеру через USB. Windows при этом обнаружит новое устройство и установит к нему драйверы. Если операционка не сможет подобрать нужный драйвер, не беда. Установите его в ручном режиме. Все необходимые драйверы есть в папке <Arduino path>\drivers. (Здесь и далее <Arduino path> будет обозначать путь к папке Arduino IDE на Вашем компьютере.) Вам необходимо открыть диспетчер устройств Windows, найти там наше "неизвестное устройство" и переустановить драйвер вручную с указанием пути к выше означенной папке. В итоге в Windows появится новый COM-порт. Этот порт надо будет выбрать в среде Arduino в меню Сервис->Последовательный порт.

3.    Загрузка прошивки в контроллер. Нажимаем на тулбаре соседнюю кнопку:



Среда при этом заново откомпилирует Ваш код и попытается загрузить его в Arduino. Плата при этом будет весело моргать светодиодами. По окончании загрузки в среде появится надпись "Загрузка выполнена". Если на консоли нет сообщений об ошибках, то все прошло удачно. Контроллер перезагрузится и начнет выполнять свеже загруженную программу. В нашем случае каждую секунду будет включать и выключать светодиод.

 

Основы языка Arduino

Начать надо с того, что в основе языка Arduino лежит более древний язык Си. Вообще, если быть точным, то Arduino является потомком языка Processing. Но это не так важно. Не будем разбираться в родственных и наследственных связях языков. Просто примите на веру, что в основе этой цепочки находится Си. А потому тут будут действовать практически все правила, которые существуют в Си. Ну и добавятся некоторые специфические....

Вернемся к нашей программе:

int led = 13;

void setup() {
  pinMode(led, OUTPUT);
}

void loop() {
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);                  // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);                  // wait for a second
}


Любая программа на языке Си состоит из функций. Под функцией понимается блок команд, который выполняет некоторые действия, принимает на вход некоторые параметры и возвращает единственное значение. В нашей программе таких функций две: setup и loop. Перед именем функции всегда указывается тип возвращаемого ею значения. Сразу за именем в круглых скобках указывается набор входных параметров. В нашем случае параметров нет, поэтому в скобках пусто. Но скобки должны быть всегда. Код, составляющий исполняемую часть функции, всегда размещается в фигурных скобках. Эти скобки еще называются "операторными", а сами исполняемые команды - операторами. Надо отметить, что переход к новой строке не воспринимается языком Си как конец оператора. Для этого служит символ ";". Таким образом всю программу можно написать хоть в одну строку. Но для облегчения читаемости есть несколько простых правил:

  1. На одной строке размещается один оператор
  2. Код внутри операторных скобок имеет смещение вправо на пару пробелов

Таким образом общий вид функции на языке Си будет выглядеть так:

<тип возвращаемого значения> <уникальное имя функции>([<список входных параметров>])

{

  <тело функции>

}

Если функция не возвращает никакого значения, то вместо <типа возвращаемого значения> указывается ключевое слово void - бестиповый. Имя функции служит для того, чтобы мы могли к ней обратиться из любой точки кода. Если имена были бы не уникальны, то микроконтроллер просто бы нас не понял - какой код мы хотим выполнить. Список входных параметров - это перечисление через запятую имен переменных с указанием их типа данных. Тело функции, как уже говорилось выше, представляет собой набор исполняемых операторов.

Вернемся к нашей программе и Arduino.

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

В нашем случае для того чтобы включать и выключать светодиод мы должны на соответствующий выход микроконтроллера подавать попеременно высокое и низкое напряжение. Но прежде чем это делать, надо указать микроконтроллеру, что используемый нами контакт будет являться выходом. Для этого в языке Arduino существует функция pinMode(). На вход она принимает два значения:

1. int pin - целое число, указывающее на номер контакта

2. const Mode - константа, указывающая на режим работы контакта. Для этого параметра определены два значения: INPUT - вход; OUTPUT - выход.

Эта функция должна выполняться всего один раз при старте программы. Поэтому вызов pinMode(led, OUTPUT); мы поместили в тело функции setup(). Здесь led - переменная, принимающая целочисленные значения (int). Мы ее объявили в самом начале нашей программы и сразу присвоили ей значение нужного нам контакта - 13.

Далее, чтобы обеспечить мигание светодиода, нам необходимо циклически переключать напряжение на этом контакте с низкого уровня на высокий и обратно. Делающий это код разумно поместить в функцию loop(). Поскольку она выполняется микроконтроллером циклически, нам необходимо описать всего один проход (итерацию) этого цикла. Для установки уровня сигнала на выходе мы использовали функцию digitalWrite(). Она так же принимает на вход два значения - номер контакта и константу, указывающую на уровень сигнала( LOW - низкий; HIGH - высокий). Таким образом digitalWrite(led, HIGH) включает светодиод, а digitalWrite(led, LOW) - выключает его. Мы так же использовали функцию delay(). Зачем? Все дело в том, что наш микроконтроллер работает на частоте 16 мегагерц. Т.е. он выполняет 16 миллионов действий в секунду. Несколько утрируя примем, что функция digitalWrite() содержит до 10 действий. Поскольку вызываем мы ее дважды за итерацию примем, что одна итерация нашего цикла будет 20 действий. Далее несложно посчитать, что светодиод будет включаться и выключаться примерно 80000 раз в секунду. Человеческий глаз не в состоянии заметить столь быстрые действия и нам будет казаться, что он просто тускло горит. Функция delay() как раз существует для того, чтобы приостановить дальнейшее выполнение программы на заданное время. Причем это время передается ей в виде единственного параметра и указывается в милисекундах. И в нашей программе мы указываем, что после каждого изменения состояния выхода микроконтроллера мы на секунду приостанавливаем дальнейшее выполнение программы. Вот так еще толком ничего не зная о электричестве, электронике и программировании мы смогли уже управлять светом! Конечно, дальше нам предстоит разобраться детальнее в электрических цепях и изучить язык Си.

Цифровой ввод


Ранее мы научились мигать светодиодом с заданной частотой. Теперь сделаем следующий шаг - научимся получать команды извне и в зависимости от них выполнять действия. Простейшим устройством ввода информации является кнопка или переключатель. Суть устройства в механическом замыкании и размыкании пары контактов. Подключить кнопку к Arduino достаточно легко:

На схеме представлено два варианта подключения. В чем разница? - в нажатом состоянии кнопка S1 подает на вход микроконтроллера сигнал низкого уровня (логический "0"), а S2 - высокий (логическую "1"). В обоих случаях схема дополнена так называемыми подтягивающими сопротивлениями(резисторами). Зачем? - Если его не будет, в ненажатом состоянии кнопки вход микроконтроллера окажется ни к чему не подключенным и сигнал на нем будет "никаким". С другой стороны, если вместо резистора будет прямое соединение с GND или +5В, то при нажатии кнопки получим короткое замыкание и выход из строя источника питания. Чтобы этого не произошло в схему и включен резистор. Его номинал можно рассчитать по закону Ома. Обычно он составляет 10-100кОм. Теперь разберем программную часть. Подключим кнопку к микроконтроллеру по левой схеме и заставим наш светодиод на 13 контакте гореть когда кнопка нажата и гаснуть при ее отпускании. Для этого напишем следующий код:

int led = 13;
int button = 2;

void setup() {               
  pinMode(led, OUTPUT);    
  pinMode(button, INPUT);
}

int val;

void loop() {
  val = digitalRead(button);
  digitalWrite(led, !val);
}

Кнопку подключим к контакту 2 микроконтроллера. Назначим его как вход - pinMode(button, INPUT).
В основном цикле читаем состояние входа button. Для этого используется функция digitalRead(pin). Полученное значение мы используем для включения светодиода. Надо только помнить, что по нашей схеме нажатому состоянию кнопки соответствует логический "0" на входе МК. При этом для включения светодиода на выход надо подать логическую "1". Язык Си является математическим языком и легко может вычислять значения логических выражений. Для этого есть ряд простых правил и операторов. Логические выражения оперируют понятиями "истина" и "ложь". В языке Си для этого используются числа 1 и 0 соответственно. В Arduino IDE даже предусмотрен специальный тип данных для хранения логических значений boolean. Переменные этого типа могут принимать одно из двух значений: true (истина), false(ложь). Так же стоит иметь ввиду, что любое число можно привести к логическому типу. При этом будет работать правило: если число равно нулю, то значением будет ложь; в противном случае будет истина. Т.е. любое число отличное от нуля будет истиной.

Для вычисления логических выражений нам понадобятся следующие логические операторы:

  1. оператор сравнения "равно" - "=="
  2. оператор сравнения "не равно" - "!="
  3. оператор сравнения "больше" - ">"
  4. оператор сравнения "меньше" - "<"
  5. оператор сравнения "больше или равно" - ">="
  6. оператор сравнения "меньше или равно" - "<="
  7. оператор "логическое И" - "&&"
  8. оператор "логическое ИЛИ" - "||"
  9. оператор "логическое НЕ" - "!"

Как упоминалось выше, в нашей программе должна работать следующая логика:

  • если на входе "0", то на выходе "1"
  • если на входе "1", то на выходе "0"

Это соответствует логическому "НЕ". И для выполнения этой операции в вызове digitalWrite перед передаваемым значением стоит оператор "!".

На самом деле в записи digitalWrite(led, !val); скрыто выполнение двух действий:

  1. вычисление значения "НЕ val"
  2. запись полученного значения на выход МК

Язык Си позволяет делать и более сложные конструкции. Например, основной цикл нашей программы можно было бы записать в одну строку и обойтись без использования переменной val. Выглядело бы это так: 

void loop() {
  digitalWrite(led, !digitalRead(button));
}

Можно попробовать собрать на макетной плате обе схемы и увидеть отличия в их работе. Так же не сложно будет модифицировать нашу программу так, чтоб отличий в итоге не было.

Машинная азбука


Так уж повелось, что люди по всему миру используют арабскую или десятичную систему исчисления. В ее основе лежат цифры от 0 до 9. Все числа при этом получаются как комбинации этих десяти цифр путем увеличения их количества в итоговом числе - разрядности. И чем выше разряд цифры, тем она более значима. Ну да не будем останавливаться на прописных истинах. Зададимся лучше другим вопросом: а удобно ли использовать арабские цифры в электронике? - Мягко говоря, не очень. Как говорилось ранее, в цифровой технике есть понятие логического нуля и логической единицы - сигнал либо есть, либо нет. Фактически это означает, что машинная система исчисления должна базироваться на этих двух цифрах - 0 и 1. А это есть ни что иное как двоичная система исчисления. В ней действуют все те же правила, что и в привычной нам десятичной. Ведь от формы записи суть числа не меняется. Выглядит это примерно так: 0 и 1 так и останутся неизменными. Для числа 2 же в двоичной системе подходящей цифры нет. Значит она будет записана путем увеличения разрядности - 10. Аналогично число 3 будет выглядеть как 11. Число 4 будет иметь уже три разряда - 100. Число 5 будет выглядеть как 101, 6 - 110, 7 - 111, 8 - 1000. И так далее...Итак, двоичная система исчисления базируется на цифрах 0 и 1. В цифровой электронике один разряд двоичного числа называется битом. В битах же измеряют и разрядность двоичных чисел. Кстати, наши микроконтроллеры имеют разрядность 8 бит. Что это значит? Дело в том, что числа внутри микроконтроллера передаются и обрабатываются по специальным шинам данных. Число проводов в этой шине определяет количество параллельно передаваемых сигналов. Каждый такой провод представляется разрядом битом. Таким образом наш микроконтроллер может работать с числами длинна которых равна восьми разрядам. Но у нас далеко не все числа имеют разрядность 8. Как быть с числами, чья разрядность меньше 8 понятно - просто дополним эти числа нулями слева до получения нужной разрядности. Но это даст нам диапазон исчисления от 0 до 255. Как-то мало. На самом деле люди уже давно решили эту проблему. И решена она была до гениальности просто: Если нет возможности передать требуемое число разрядов параллельно, значит надо это сделать последовательно. Так 8 бит объединили в один байт, а передача 16-ти разрядного числа свелась к передаче двух байтов один за другим последовательно. Но это не решает проблемы отрицательных чисел... А вот тут ситуация повернулась еще интереснее: оказалось, что отрицательные числа (равно как и дробные) на уровне микропроцессора просто не нужны - последнему достаточно целых положительных чисел. Ну процессору они то может и не нужны, а нам еще как нужны! Для этого в языках программирования и существует типизация данных.
 

Основные типы данных Arduino будут выглядеть так:


byte - Имя говорит само за себя. Длина - 1 байт, диапазон значений от 0 до 255.
int - целое число. Длина 2 байта, диапазон значений от -32768 до 32767. Для формирования отрицательного числа используется старший бит старшего байта. Установка его в 1 указывает на то, что число меньше нуля.
uint - беззнаковое целое. Практически тоже самое, что и int. Только старший бит старшего байта используется по прямому назначению. Таким образом достигается диапазон значений от 0 до 65535 без изменения разрядности.
float - тип предназначен для вещественных чисел в диапазоне от -3.4028235E+38 до 3.4028235E+38. Число занимает в памяти 32 бита или 4 байта. Тут надо сказать, что математические операции с дробными числами для процессора не являются естественными и потому занимают много больше времени, нежели целочисленные.

На "больших" ПК это не очень заметно, но скорость нашего МК всего 16МГц. И потому сравнительно небольшое количество операций над такими числами может существенно сказаться на быстродействии. Есть и другие типы данных, но о них будем говорить по мере необходимости. На данном этапе нам будет достаточно этих. Итого: с представлением чисел в микроконтроллере разобрались, с двоичной системой вроде бы тоже... Arduino IDE и компилятор взяли на себя пересчет чисел из одной системы в другую и обратно. Поэтому мы не задумываясь пишем в коде привычные десятичные числа. Но иногда бывает удобно записать в коде двоичное число. Тогда компилятору надо принудительно указывать, что число именно двоичное, а не десятичное из одних нулей и единиц. Для этого в начале числа ставится латинская буква "B" от слова binary - двоичный. Да и все бы хорошо, но есть "ложка дегтя". Двоичная запись чисел получается очень длинной и занимает на экране много места. Человеку ее читать неудобно. Десятичная запись короткая, но ее сложно разделять на байты. Что тоже часто создает проблему. Вот бы иметь такую систему исчисления, которая была бы лишена этих недостатков. Формально система должна обладать достаточно большим количеством чисел, а ее основание (количество чисел) должно быть равно какой-либо степени двойки. Много чего перепробовали... В итоге программисты пришли к использованию шестнадцатеричной системы исчисления. Ее основанием являются цифры от 0 до 9 и буквы латинского алфавита от a до f. Правила записи чисел в ней сходны с другими системами. Но что в ней действительно для нас будет удобным: для записи одного байта понадобится всего два символа. Такая запись будет удобно читаться с экрана и легко разделяться по байтам. Для компилятора признаком шестнадцатеричной записи числа будет служить префикс "0x".
На последок я приведу три строки кода, абсолютно идентичных между собой с точки зрения компилятора:
a = 15;
a = b1111;
a = 0xff;

По материалам rc-master,  автор Зайчиков Александр

 

В начало обзора






Необходимо добавить материалы...
Результат опроса Результаты Все опросы нашего сайта Архив опросов
Всего голосовало: 380



          

Радио для всех© 2024