Arduino порты ввода вывода

Arduino порты ввода вывода

Помимо монитора последовательного порта, в Arduino IDE есть плоттер – построитель графиков в реальном времени по данным из последовательного порта. Достаточно отправить значение при помощи команды Serial.println(значение) и открыть плоттер по последовательному соединению, например построим график значения с аналогового пина A0:

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

Вывод значений происходит каждые 10 миллисекунд, а каждые 300 миллисекунд значения обновляются. Получаем вот такой график:

Подписи графиков

В Arduino IDE с версии 1.8.10 добавили возможность подписать графики, для этого перед выводом нужно отправить названия в виде “название 1, название 2, название n” с переносом строки, и дальше просто выводить данные:

Использование пинов

Как я писал выше, аппаратный Serial имеет выводы на ноги микроконтроллера, для Nano/Uno/Mini это выводы D0 и D1. Можно ли работать с этими пинами, как с обычными цифровыми пинами? При отключенном Serial – можно, при включенном – нет. После вызова Serial.begin() ноги перестают функционировать как цифровые пины в ручном режиме, но после вызова Serial.end() можно снова ими пользоваться!

Отправка и парсинг

Рассмотрим самый классический пример для всех языков программирования: Hello World!

Отправка данных в порт не должна вызывать трудностей и вопросов, потому что всё понятно/очевидно, да и чуть выше в описании метода print мы рассмотрели все варианты вывода. Отправка в порт позволяет узнать значение переменной в нужном месте программы, этот процесс называется отладка. Когда код работает не так, как нужно, начинаем смотреть, где какие переменные какие значения принимают. Или выводим текст из разных мест программы, чтобы наблюдать за правильностью (порядком) её работы. Давайте вспомним урок циклы и массивы и выведем в порт массив:

Вывод: 0 50 68 85 15 214 63 254 – элементы массива, разделённые пробелами!

Проблемы возникают при попытке принять данные в порт. Дело в том, что метод read() читает один символ, даже если вы отправите длинное число – программа получит его по одной цифре, и составлять число из цифр придётся вручную. Проблема усугубляется тем, что read() читает именно символ, то есть код символа в таблице ASCII.

Посмотрим вот такой пример, в котором в порт отправляются принятые в него данные (так называемое эхо):

Так как же принять именно цифру? Есть хитрость – вычитать из полученного кода символа код цифры 0, либо сам 0 в виде символа: ‘0’

Также для принятия одиночных чисел у нас есть готовый метод – parseInt/parseFloat – для целочисленных и рациональных чисел соответственно. Процесс приёма и расшифровки данных называется парсинг (parsing). Давайте примем в порт число 1234, используя готовый метод парсинга.

Итак, мы используем конструкцию if (Serial.available()) <> чтобы опрашивать порт только в том случае, если в него что-то пришло. Отправив в порт число 1234 мы получим ответ ОК, отправив любое другое – error. Также вы заметите, что после отправки проходит секунда, прежде чем плата ответит. Эта секунда спрятана внутри метода parseInt, программа ждёт секунду после принятия данных, чтобы все данные успели прийти. Секунда это очень много, достаточно было ждать, скажем, 50 миллисекунд. Это можно сделать при помощи метода setTimeout.

Теперь после отправки цифры программа будет ждать всего 50 мс, и сразу же вам ответит.

В реальном устройстве часто требуется передавать несколько параметров, например у нас Bluetooth танк. Мы ему должны отправить например скорость правой гусеницы, скорость левой гусеницы, положение башни, состояние подсветки, команду на выстрел… Да что угодно. Как быть в таком случае? Тут начинается настоящий парсинг, и появляются варианты, нам придётся придумывать собственный протокол связи.

Есть два базовых варианта: отправка пакета всех-всех данных и его парсинг, или отправка отдельно каждого параметра с уникальным “ключом” у каждого. Как это понимать: суть первого варианта состоит в принятии пакета данных, которые разделены разделителем. Также правильно будет выделить начало и конец посылки. Пример: $120 80 180 1; – начальный символ $, разделитель ” ” (пробел) и завершающий символ ; . Наличие начального и завершающего символа повышает скорость работы и помехозащищённость связи. Второй вариант – посылки вида MOT1_120, содержащие ключ и значение, соответствующее этому ключу.

Как реализовать данные способы парсинга я очень подробно разбирал в примерах в сборнике полезных алгоритмов Arduino, раздел “Работа с Serial”. Но давайте я оставлю их также и здесь, пользуйтесь!

Arduino Uno

  • Обзор
  • Программирование и связь с ПК
  • Система питания
  • Порты ввода/вывода
  • Память
  • Подведение итогов
  • Часто Задаваемые вопросы

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

Arduino UNO была разработана итальянскими инженерами как одна из основных плат, имеющих открытую архитектуру. По мере увеличения популярности, у платы появилось множество «клонов», полностью совместимых по программной и аппаратной части. На рисунке №1 показан внешний вид платы Arduino UNO с обеих сторон.

Рисунок №1 – плата Arduino Uno

Как видно из рисунка, подключение к пинам микроконтроллера выполняется через штыревые линейки, распаянные по обе стороны платы. Таким образом разработчик может связать ATMega328 с внешними устройствами при помощи макетных проводов. Также под топологию Arduino Uno создано огромное количество шилдов, обеспечивающих дополнительный функционал путём их каскадного включения. Пример такого включения показан на рисунке №2.

Рисунок №2 – Arduino Uno и шилд для ЧПУ

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

Удобно организованный доступ к портам микроконтроллера – это хорошо, но что ещё содержит Arduino Uno на своём борту? Разобраться в дополнительных деталях поможет рисунок №3, на котором обведены и подписаны все основные элементы платы и дана общая характеристика для штыревых контактов.

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

Рисунок №3 – распиновка платы Arduino Uno

Программирование и связь с ПК

В левом верхнем углу (рисунок №3) расположен USB-разъём. Он выполняет две функции. Первая – организация канала обмена данными между микроконтроллером и ПК и вторая – запись прошивки в ATMega328.

На аппаратном уровне за связь с компьютером отвечает модуль последовательного интерфейса передачи данных (UART), который встроен в ATMega328 и выведен на контактах 0(RX) и 1(TX) платы Arduino Uno. Однако просто передавать данные на компьютер не получиться. Посредником между ATmega328 и компьютером выступает отдельно установленный микроконтроллер ATMega16. Его специальная прошивка позволяет определять плату Arduino Uno как виртуальный СОМ-порт, когда та подключается к ПК. Обмен данными будет сопровождаться миганием соответствующих светодиодов RX и TX, расположенных справа от ATMega16.

Что касается записи прошивки, то этот процесс максимально упрощён и сводится к нажатию всего одной кнопки в среде Arduino IDE. Такая простота обусловлена тем, что Arduino Uno выпускается со встроенным прошитым загрузчиком, работающем по протоколу STK500. Следовательно, во внешнем программаторе нет никакой необходимости. Тем не менее, для любителей прошить контроллер напрямую, на плате предусмотрена колодка ICSP (справа посередине) для внутрисхемного программирования в обход загрузчика. Сам DFU-загрузчик находиться в ATMega16 и также может быть переписан путём внутрисхемного программирования через аналогичную колодку в верхней левой части платы.

Система питания

Для того, чтобы плата Arduino Uno могла функционировать, на неё необходимо подать питание. Сделать это можно несколькими способами, а именно:

Запитать непосредственно через USB-разъём с помощью шнура для программирования или связи с ПК;

Запитать от AC/DC адаптера с выходным напряжением 7-12В, подключившись через специальный разъём внешнего питания.

Подать напряжение 7-12В напрямую на вход Vin, который расположен на штыревой колодке питающей группы. При этом минусовой контакт источника питания следует соединить с одним из контактов GND платы.

Также, плата Arduino Uno, предоставляет пользователю два контакта, на которых присутствуют напряжения 5В и 3,3В. Эти напряжения формируются встроенными линейными стабилизаторами при любом из вышеперечисленных способов питания. Максимальный ток, который способен обеспечить вывод 3,3В равен 50мА. Некоторые «умельцы» питают плату через один из этих выводов, однако это чревато выходом последней из строя, так как входное напряжение идёт в обход стабилизатора и любой скачок просто-напросто спалит микроконтроллер.

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

Читать еще:  Maunfeld mpa 60 нержавейка

Вывод IOREF, служит для информирования подключаемых к Arduino Uno модулей или шилдов об уровне бортового напряжения. Если подключаемый модуль имеет возможность работать как с 5В, так и с 3,3В, то прочитав значение на выводе IOREF, он может выбрать для себя соответствующий режим работы.

Порты ввода/вывода

Arduino Uno предоставляет пользователю 14 цифровых и 6 аналоговых выводов. Цифровые выводы имеют нумерацию от 0 до 13 и способны работать в двух направлениях, т.е. каждый из них может быть как входом, так и выходом. Направление определяется функцией pinMode(). Помимо этого, для каждого цифрового пина имеется возможность программно включить подтягивающий резистор, соединённый с плюсом питания микроконтроллера. Номинал подтягивающего резистора лежит в диапазоне 20-50кОм. Следует учитывать, что максимальное выходное напряжение одного вывода составляет 5В, а максимальный ток — 40мА. Превышение допустимой нагрузки способно вывести микроконтроллер из строя.

Аналоговые выводы имеют обозначения А0-А5. Каждый из них соединён со встроенным 10-битным АЦП микроконтроллера ATMega328. Это означает, что мы можем одновременно измерять 6 напряжений и получать по 1024 значения для каждого канала. По умолчанию диапазон измеряемого напряжения равен 0-5В, т.е. при 0В значение АЦП будет равно 0, а при 5В значение АЦП станет равным 1023. Этот диапазон можно изменить подачей на вывод AREF своего опорного напряжения, которое станет верхней границей измерения. Если в аналоговых выводах нет необходимости, они без проблем могут использоваться как цифровые.

Помимо первичных функций, некоторые выводы Arduino Uno имеют дополнительные. Например:

выводы 3, 5, 6, 9, 10 и 11 способны формировать широтно-импульсную модуляцию (ШИМ) с помощью функции analogWrite().

выводы A4(SDA) и A5(SCL) представляют интерфейс связи по протоколу I2C.

выводы 10(SS), 11(MOSI), 12(MISO), 13(SCK) обеспечивают связь по SPI-интерфейсу.

выводы 0(RX) и 1(TX) — обеспечивают последовательный интерфейс передачи данных.

к выводу 13 подключен smd-светодиод, расположенный на плате.

RESET – подача низкого уровня на этот вывод приведёт к сбросу микроконтроллера.

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

Способы чтения и управления портами ввода-вывода Arduino

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

Способ первый – стандартный язык для Arduino IDE

Всем известно, что Ардуино программируется на C++ с некоторой адаптацией и упрощениями для новичков. Он называется Wiring. Изначально все порты ардуино определяются как входы, и нет нужды задавать это в коде.

Порты обычно прописываются в функции инициализации переменных:

Для этого используется команда pinMode, у неё достаточно простой синтаксис, сначала указывается номер порта, затем его роль через запятую.

pinMode (nomer_porta, naznachenie)

С помощью этой команды внутренняя схема микроконтроллера конфигурируется определенным образом.

Есть три режима в которых может работать порт: INPUT – вход, в этом режиме происходит считывание данных с датчиков, состояния кнопок, аналогового и цифрового сигнала. Порт находится в т.н. высокоимпедансном состоянии, простыми словами – у входа высокое сопротивление. Устанавливается это значение, на примере 13 пина платы, при необходимости так:

pinMode (13, INPUT);

OUTPUT – выход, в зависимости от команды прописанной в коде порт принимает значение единицы или нуля. Выход становится своего рода управляемым источником питания и выдаёт максимальный ток (в нашем случае 20 мА и 40 мА в пике) в нагрузку к нему подключенную. Чтобы назначить порт как выход на Arduino нужно ввести:

pinMode (13, OUTPUT);

INPUT_PULLUP – порт работает как вход, но к нему подключается т.н. подтягивающий резистор в 20 кОм.

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

pinMode (13, INPUT_PULLUP);

Данные принимаются с портов и передают на них командами:

digitalWrite(пин, значение) – переводит выходной пин в логическую 1 или 0, соответственно на выходе появляется или исчезает напряжение 5В, например digitalWrite (13, HIGH) – подаёт 5 вольт (логическую единицу) на 13 пин, а digitalWrite (13, low) – переводит 13 пин в состояние логического ноля (0 вольт);

digitalRead(пин) – считывает значение со входа, пример digitalRead (10), считывает сигнал с 10 пина;

analogRead(пин) – считывает аналоговый сигнал с аналогового порта, вы получаете значение в диапазоне от 0 до 1023 (в пределах 10-битного АЦП), пример analogRead (3).

Способ два – управление портами через регистры Atmega и ускорение работы кода

Такое управление конечно простое, но в этом случае есть два недостатка – большее потребление памяти и низкое быстродействие при работе с портами. Но вспомните что такое Arduino независимо от варианта платы (uno, micro, nano)? В первую очередь, это микроконтроллер AVR семейства ATMEGA, в последнее время используется МК atmega328.

В Arduino IDE вы можете программировать на родном для этого семейства языке C AVR, так, как если бы вы работали с отдельным микроконтроллером. Но обо всем по порядку. Чтобы управлять портами Ардуино таким образом вам нужно сначала внимательно рассмотреть следующую иллюстрацию.

Возможно кому-то будет нагляднее изучать порты в таком виде (на рисунке тоже самое, но в другом оформлении):

Здесь вы видите соответствие выводов Ардуино и названий портов атмеги. Итак, у нас есть 3 порта:

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

У Atmega есть три регистра длиной в 8 бит, которые управляют состоянием портов, например, порта B разберемся в их назначении проведя аналогии со стандартными средствами wiring описанными в начале статьи:

PORTB – Управление состоянием вывода. Если пин находится в режиме «Выхода», то 1 и 0 определяют наличие этих же сигналов на выходе. Если же пин находится в режиме «Входа», то 1 подключает подтягивающий резистор (тоже что и INPUT_PULLUP рассмотренный выше), если 0 – высокоимпедансное состояние (аналог INPUT);

PINB – регистр чтения. Соответственно в нём находится информация о текущем состоянии выводов порта (логическая единица или ноль).

DDRB – регистр направления порта. С его помощью вы указываете микроконтроллеру чем является порт – входом или выходом, при этом «1» — выход, а «0» — вход.

Вместо буквы «В» может быть любая другая согласно названиям портов, например, PORTD или PORTC аналогично работают и другие команды.

Помигаем светодиодом, заменим стандартную функцию digitalWrite(). Для начала вспомним как выглядит исходный пример из библиотеки Arduino IDE.

Это код всем известного «blink», который демонстрирует мигание светодиодом, встроенным в плату.

В комментариях даны пояснения к коду. Логика такой работы заключается в следующем.

Команда PORTB B00100000 переводит PB5 в состояние логической единицы, смотрим, а те картинки и таблицу что расположены ниже и видим, что PB5 соответствует 13 пину Ардуины.

Буква «В» перед цифрами говорит о том, что мы в записываем значения в двоичном виде. Нумерация в двоичном коде идёт справа налево, т.е. здесь единица стоит в шестом с правого края бите, что говорит микроконтроллеру о взаимодействии с состоянием шестого бита регистра порта B (PB5). В таблице ниже изображена структура порта D, она аналогична и приведена для примера.

Вы можете задавать значение не в двоичном, а в шестнадцатеричном виде, например, для этого открываем калькулятор windows и в режиме «ВИД», выбираем вариант «Программист».

Вводим желаемое число:

И нажимаем на HEX:

В таком случае переносим это всё в Arduino IDE, но уже вместо приставки «В» будет «0х».

Но при таком вводе возникает проблема. Если у вас к другим пинам подключено что-либо, то внося команду типа B00010000 – вы все выводы кроме 13 (PB5) обнулите. Вы можете вносить данные на каждый пин по отдельности. Это будет выглядеть следующим образом:

Такая запись может показаться непонятной, давайте разберемся.

Это операция логического сложения, |= значит прибавить к содержимому порту что-либо.

А это значит, что нужно сложить слово из 8 бит в регистре с единицей, смещенной на 5 бит – в результате, если было 11000010 получается 11010010. На этом примере видно, что изменился только PB5, остальные биты этого регистра остались без изменений, как и остались неизменными состояния выводов микроконтроллера.

Но при логическом сложении возникает проблема – вы не можете превратить единицу в ноль, потому что:

Нам на помощь придёт логическое умножение и инвертирование:

&= значит умножить содержимое порта на определенное число.

А это число, на которое мы умножает. Знак «

» обозначает инвертирование. В нашем случае проинвертированная единица является нулем. То есть мы умножаем содержимое порта на ноль, сдвинутый на 5 бит. Например, было 10110001, стало 10100001. Остальные биты остались без изменений.

Тоже самое можно сделать с помощью операции инвертирования (^):

Чтение с портов, аналог digitalRead() выполняют с помощью регистра PIN, на практике это выглядит так:

Здесь мы проверяем равно ли выражение в скобках реальному состоянию портов, т.е. аналогично тому, если бы мы написали if (digitalRead(12) == 1).

Заключение

Для чего такие сложности с управлением портами, если можно использовать стандартные удобные функции? Всё дело в быстродействии и размерах кода. При использовании второго способа, рассмотренного в статье размер кода, значительно снижается, а быстродействие увеличивается на несколько порядков. Стандартный digitalWrite() выполнялся за 1800 мкс, а запись прямо в порт за 0,2 мкс, а digitalRead() за 1900 мкс, а стал также за 0,2 мкс. Этот способ управления был найден на просторах сети и часто встречается в коде готовых проектов.

Читать еще:  Alcatel one touch go watch

Порты ввода-вывода Arduino

В данной статье рассказывается о портах ввода-вывода микроконтроллера Arduino. Всё написанное также верно и для клонов Arduino, например Freeduino.

Различные устройства и приборы подключаются к микроконтроллеру через порты ввода-вывода. Микроконтроллер, являющийся ядром Arduino — это 8-битный микроконтроллер, и поэтому его порты ввода-вывода также являются 8-битными. Это общий принцип, и хотя теоретически порт ввода-вывода 8-битного микроконтроллера может быть и 16-ти, и 32-х, и 64-битным, но практического смысла оснащать 8-битный микроконтроллер не-8-битным портом ввода-вывода нет, поскольку для чтения или записи данных в такой порт пришлось бы использовать несколько команд ассемблера, то есть операция обмена данными с таким портом производилась бы только за несколько тактов.

Порт ввода-вывода обычного назначения (GPIO — General Purpose Input/Output) представляет собой несколько выводов (пинов) микроконтроллера по числу бит, то есть в данном случае это 8 выводов. Если посмотреть на плату Arduino, то с одной стороны находятся две группы по 8 контактов, обозначенные как цифровые (Digital), а с другой стороны две группы по 6 контактов, одна из которых — это контакты напряжений питания и пин сброса (Reset), а вторая — это 6 контактов, обозначенных как входы для аналоговых сигналов (Analog In).

С точки зрения программы для микроконтроллера каждый порт — это несколько специальных регистров (переменных), производя чтение или запись данных в которые можно менять состояние или режим работы выводов микроконтроллера. Поскольку каждому выводу порта обычного назначения соответствует 1 бит, то напряжение на соответствующем выводе может меняться, принимая логическое значение либо высокий уровень (HIGH), либо низкий уровень (LOW).

Как правило высокому уровню напряжения соответствуют напряжение, равное или чуть меньше, чем напряжение питания микроконтроллера (для Arduino это +5 вольт), а низкому уровню соответствует либо уровень земли (0 вольт), либо небольшое напряжение (например, +0.2 или +0.6 вольт). Половина напряжения высокого уровня называется высоким нулём (Hi-Z).

Для логических микросхем существует ряд электрических стандартов напряжений, основанных на технологии, по которой данная микросхема выполнена. Например, TTL, CMOS и т.п. Если две микросхемы с одинаковым напряжением питания выполнены по разным технологиям (например, одна из их CMOS, а другая TTL), то они как правило логически совместимы между собой, если речь идёт только о сигналах 1 или 0. Но уровень сигнала Hi-Z у них может отличаться, что может потребовать их электрического согласования.

Например, уровень Hi-Z микросхемы, которая получает сигнал равен +2В, а уровень Hi-Z микросхемы, которая сигнал то принимает, то передаёт +2,4В). Таким образом вторая микросхема передаёт сигнал первой, и затем переводит порт в состояние ввода данных, то есть у неё на выводе уровень Hi-Z +2.4В. А первая читает порт, а там логическая единица.

Но на практике с подобными проблемами можно столкнуться, разве что пытаясь передать сигнал с выхода микросхемы с напряжением питания +3,3В на вход микросхемы с напряжением питания +5В. Если у второй уровень Hi-Z составляет 2В, то электрического согласования не потребуется, а если 2,4В, то потребуется поставить между этими выводами схему согласования уровней на полевом транзисторе.

Тем не менее, при подключении микросхем друг к другу это следует учитывать, поскольку мне приходилось сталкиваться например с тем, что микросхема питается от напряжения +5В, а логическая единица у неё +3,2В, и хотя она при этом работает, но нагревается во время работы градусов до 60 по Цельсию. То есть напряжение питания +5В, а порты ввода-вывода, хоть и совместимые с 5-вольтовой логикой, но трёхвольтовые, то есть для работы с такой микросхемой лучше использовать микроконтроллер с напряжением питания +3,3В (прим. Это так называемый электрический стандарт интерфейса PCI).

Микроконтроллер Arduino, кстати, вполне может работать на частоте 8МГц и с напряжением питания +3,3В, но в конструктиве Arduino такая возможность не предусмотрена, поэтому к Arduino лучше подключать микросхемы 5-вольтовой логики.

Всего микроконтроллер ATmega328p (как и ATmega168) в корпусе PDIP имеет три порта ввода-вывода. Они обозначены, как порты B, С и D:

  • Порт D — это группа выводов Digital с номерами от 0 до 7.
  • Порт B — это 5 выводов Digital с номерами от 8 до 13. Им соответствуют 5 младших бит порта B (старшие 2 вывода используются для подключения кварцевого резонатора 16 МГц).
  • Порт С — это группа выводов Analog In. Им соответствуют 6 младших бит порта C (7-й бит используется как сигнал Reset, 8-й бит не используется).

Таким образом всего Arduino имеет 20 контактов ввода-вывода обычного назначения (GPIO).

Помимо портов GPIO к микроконтроллеру можно подключать устройства через специальные интерфейсы. Например, микроконтроллер Arduino оснащён следующими интерфейсами:

  • USART — универсальный синхронный и асинхронный последовательный приёмник и передатчик (Universal Synchronous and Asynchronous serial Receiver and Transmitter). Выводы Digital с номерами 0 (приёмник) и 1 (передатчик). Он используется, например, для подключения Arduino к компьютеру через USB, но не напрямую, а посредством микрохемы переходника USB-to-serial.
  • Master/Slave SPI — последовательный периферийный интерфейс (Serial Peripheral Interface). Выводы Digital с номерами от 10 до 13. В режиме slave (подчинённый) он позволяет программировать Arduino через ICSP с помощью программатора. В режиме master (мастер) он позволяет подключать к Arduino различные устройства с интерфейсом SPI — например использовать Arduino как программатор или подключить к Arduino флешку формата SD Card или MMC.
  • TWI — двухпроводной интерфейс (Two-Wire Interface), совместимый с интерфейсом I2C. Выводы Analog In с номерами 4 и 5. Он позволяет подключать к Arduino, например LCD-дисплеи или микросхемы памяти EEPROM.
  • ADC — аналого-цифровой преобразователь или АЦП (Analog-to-Digital Converter). Он позволяет подключать к Arduino аналоговые приборы. Например, потенциометры, датчики (сенсоры), микрофон и т.п. Всего у микроконтроллера Arduino шесть 10-битных аналоговых входов — группа контактов Analog In .
  • Аналоговый компаратор (AIN). Выводы Digital с номерами 6 (позитивный вход) и 7 (негативный вход). Если напряжение на позитивном входе компаратора превышает напряжение на негативном входе, то микроконтроллер может генерировать специальное прерывание, либо использовать этот сигнал для детектора фронтов на 16-битном таймере . В качестве негативного входа вместо вывода Digital 7 может быть использован любой из выводов группы Analog In . Позволяет Arduino измерять частоту и уровень аналогового сигнала.
  • PWM — широтно-импульный модулятор или ШИМ (Pulse Width Modulation). Выводы Digital c номерами 3, 5, 6, 9, 10, 11. Позволяет микроконтроллеру Arduino генерировать аналоговые сигналы с разрядностью от 2 бит с частотой 250 кГц до 8 бит с частотой 15625 кГц. Всего микроконтроллер Arduino имеет 6 ШИМ-модуляторов, по 2 на каждый из 3 таймеров.
  • ICP — модуль захвата ввода (Input Capture Unit). Вывод Digital с номером 8. Позволяет Arduino измерять частоту и цикл заполнения цифрового сигнала.
  • T0 и T1 — Источники внешнего тактового сигнала для таймеров-счётчиков 0 и 1. Выводы Digital с номерами 4 и 5. Позволяют подключать к Arduino, например, микросхемы часов реального времени или синхронизировать Arduino с устройствами, работающими на частотах, которые не кратны системной частоте Arduino 16 Мгц (например, 5 МГц или 1.8432 МГц).

Таким образом, каждый пин Arduino может использоваться либо как вывод обычного назначения (GPIO), либо как один из выводов специального назначения. После нажатия на кнопку сброс либо сразу после включения, все специальные функции выводов отключены, а сами выводы находятся в состоянии Hi-Z, то есть при сбросе они становятся электрически и логически нейтральными. То есть для того, чтобы задействовать для того или иного вывода микроконтроллера его специальную функцию, его следует соответствующим образом программно инициализировать. Это делается записью нужных значений в соответствующие регистры.

Цифровые выводы

В прошлом уроке мы использовали вывод под номером 13. Познакомимся с другими портами и как можно их использовать.

У каждой платы Arduino есть свой набор выводов, которые также могут называться порты, выходы, пины (pin). В большинстве случаев рассматривается плата Arduino UNO. Набравшись опыта, вам не составит труда разобраться с другими платами.

Хорошенько осмотрите плату. По краям платы вы увидите колодки, в которые можно вставлять провода. Они все подписаны. С одной стороны идут цифровые выводы от 0 до 13 и GND, с другой стороны аналоговые выводы от A0 до A5 и GND (2 шт.), 5V, 3.3V. Запомните их расположение, оставшиеся выводы используются гораздо реже, особенно на начальном этапе. Подробнее о плате есть в отдельной статье.

Обратите внимание, что аналоговые выводы на самом деле являются цифровыми и их можно использовать в таком качестве, если вам не хватило стандартных выводов от 0 до 13. Поэтому аналоговые выводы можно представлять как 14, 15, 16, 17, 18, 19 вместо A0, A1, A2, A3, A4, A5. Может пригодиться при создании массива пинов, так проще перечислять все пины от 0 до 19. Но это происходит достаточно редко, вам должно хватить уже существующих выводов.

Аналоговые и цифровые выводы могут принимать цифровой сигнал. Цифровым сигналом называют последовательность нулей и единиц от скачков напряжения от 0 до 5 вольт. Вдобавок, аналоговые выводы могут принимать аналоговые сигналы — диапазон плавно изменяющего напряжения от 0 до 5 вольт с маленьким шагом.

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

Можно программно управлять цифровыми выводами — подавать ток и не подавать ток. А также можно считывать информацию — подаётся ли ток или нет. Чтобы проверить эти утверждения, необходимо создать замкнутую цепь. Но есть одна проблема — мы не можем увидеть проходящий ток. Поэтому для наглядности будем добавлять в цепь светодиод. Если ток в цепи есть, то светодиод будет светиться. Удобно. А также мы будем использовать Serial Monitor (о нём позже), чтобы выводить информацию на экран.

Читать еще:  Center 223 токоизмерительные клещи цена

Старайтесь не использовать выводы 0 и 1. Они используются для приёма и передачи данных по USB, если в вашем проекте появится такая необходимость, а вы уже припаяли провода, то будут лишние проблемы и трата времени. Выводы 2 и 3 используются в прерываниях. Конечно, в простых проектах это не принципиально, но лучше сразу привыкнуть к правильному порядку. Таблица приоритетов может выглядеть следующим образом: D4, D7, D8. D5, D6, D9, D10. D2, D3. D11, D12, D13, D0, D1.

Мигаем светодиодом на любом выводе

Прежде чем мы двинемся дальше, следует познакомиться ещё с одним важным инструментом — макетная плата. Для сложных схем требуется больше места. В таких случаях соединяют отдельные компоненты схемы с помощью проводов. Для лучшего соединения провода желательно использовать пайку. Но для новичка это сложно, да и муторно. Ведь если схема сложная и мы где-то сделали ошибку, то придётся все заново отпаивать и припаивать.

Специально для этих целей была придумана макетная плата Breadboard. Когда я впервые взял её в руки, то растерялся. Интуитивно-понятным интерфейсом здесь и не пахло. Множество дырочек, красные и синие полосочки, буковки, циферки. Радиолюбители на форумах говорят, что это примитивная штука, не требующая объяснений. Но, когда впервые сталкиваешься с таким предметом, то так не думаешь.

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

На моей доске доступно 830 контактов. Четыре рельсы по бокам предназначены для подключения питания и земли. Между ними — 126 групп соединённых между собой контактов. У вас могут быть платы другого размера, но общая идея остаётся прежней.

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

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

Далее необходимо соединить Breadboard с платой Arduino. Располагаем их рядышком и соединяем их с помощью перемычек. Первая перемычка вставляется так — на Breadboard ножка перемычки вставляется в свободное отверстие красной рельсы, а вторая ножка втыкается на Arduino в порт вывода с меткой 5V. Вторую перемычку ставим так — первая ножка вставляется на Breadboard в отверстие синей рельсы, а вторая ножка вставляется на Arduino в порт вывода с меткой GND (на плате несколько меток GND, подойдёт любой).

Подключаем плату к компьютеру. Если все сделано правильно, то светодиод должен загореться. Ура, получилось!

Учимся читать схему

Посмотрим, что мы сделали. Мы последовательно соединили светодиод с резистором к источнику питания на 5 Вольт. По этой схеме ток течёт из вывода с меткой 5V, далее проходит через резистор, потом через светодиод и попадает в вывод с меткой GND.

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

Каждый электронный компонент имеет свой графический символ. Например, для резистора используется следующий символ (используется в США, в России и Европе используется другой символ):

Как видите, символ резистора симметричен, как и сам компонент.

Светодиод обозначается символом:

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

Плюс (слева) и минус (справа) питания также имеют символы:

Попробуем соединить все описанные детали вместе, чтобы изобразить нашу цепь.

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

Усложняем схему

Мы создали примитивную схему, которой нельзя управлять. Ток течёт через резистор и светодиод, минуя порты ввода/вывода.

Изменим схему следующим образом. Сейчас у нас резистор соединяется с выводом 5V. Давайте соединим его теперь с выводом 13. Вытащим ножку резистора из вывода 5V и вставим его в отверстие на Breadboard таким образом, чтобы оно находилось на одной линии с другой ножкой резистора. Далее соединяем перемычкой вывод 13 на Arduino и соседнее отверстие рядом с ножкой резистора. Светодиод оставляем на месте.

На схеме это будет выглядеть следующим образом.

Откройте предыдущую программу с миганием встроенного светодиода и запустите её. У вас теперь будут мигать два светодиода одновременно — встроенный и наш, так как они оба использует выход 13.

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

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

02.Digital: BlinkWithoutDelay (Мигаем светодиодом без delay())

Рассмотрим урок BlinkWithoutDelay из меню File | Examples | 02.Digital.

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

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

Для демонстрации нужен светодиод с резистором и кнопка.

Режим INPUT

В примерах с миганием светодиодов мы устанавливали режим OUTPUT. По умолчанию, все выводы имеют режим INPUT и можно не указывать этот режим.

Но лучше контролировать данный процесс и явно прописывать, чтобы всегда видеть перед глазами код и понимать происходящее. С режимом ввода связан один интересный и важный момент. Воспроизведём следующую ситуацию. Подключим светодиод к выводу 13 (для наглядности, чтобы не всматриваться в встроенный маленький светодиод) и установим для вывода 7 режим ввода. Провод соединим между выводом 7 и 5V.

Светодиод будет светиться, если на выводе 7 есть ток, иначе светиться не будет. Мы следим за выводом 7, считывая показания через digitalRead(). Соединив второй конец провода от вывода 7 с выводом 5V, мы замыкаем цепь — ток течёт, функция получает значение логической единицы (true) и светодиод светится.

Вытаскиваем провод из вывода 5V и вставляем в вывод GND — ток не течёт, функция получает значение логического ноля и светодиод не светится.

В обоих случаях мы получаем логическую единицу или логический ноль, т.е. true или false.

Казалось, всё очевидно и понятно. Но сделаем одну вещь — вытащим провод из вывода GND и оставим его болтаться в воздухе. Теперь попробуйте взять провод в руки или просто проведите рукой над проводом — вы увидите, что иногда светодиод начинает светиться. Чудо! На самом деле всё просто — вход 7 находится в «никаком» состоянии. Он может срабатывать и не срабатывать хаотично, непредсказуемым образом, а причиной являются шумы, образующиеся вокруг: провода действуют как маленькие антенны и производят электричество из электромагнитных волн среды. На состояние могут действовать самые разные наводки — датчики, рука, другие устройства, провода и т.д.

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

В теории считается, что за логическую единицу принимается 5В, а за логический ноль — 0В. Но на самом деле это не так. Значения от 2.6В платой уже воспринимается как логическая единица. А логический ноль наступает при значении 2.1В и ниже. У нас возникает диапазон от 2.1 до 2.6, который является неопределённым и плата не может гарантированно опознать эти значения и может считать их в случайном порядке как единицу и как ноль. Именно это и произошло в нашем примере с висящим проводом. Причиной является делитель напряжение, который находится у каждого цифрового вывода

Выводы 0 и 1

Старайтесь не использовать выводы 0 и 1 в своих схемах, так как они используются самой платой для загрузки скетча через USB. Иногда применяют следующий приём: временно убирают модуль с этих выводов, загружают скетч, а потом снова устанавливают модуль. Например, такое можно наблюдать при работе с Bluetooth-модулями.

На следующих занятиях мы подключим светодиод и заставим его не только мигать, но и плавно менять своё свечение.

Ссылка на основную публикацию
Adblock
detector