Serial begin 9600 что это
Функция Arduino Serial begin
Serial begin – крайне важная инструкция Arduino, она позволяет установить контроллеру соединение с внешними устройствами. Чаще всего таким «внешним устройством» оказывается компьютер, к которому мы подключаем Arduino. Поэтому Serial begin интенсивней всего используется в скетчах, выводящих какую-то информацию на экран монитора порта, например, для отладки программы. С помощью последовательного порта плата ардуино соединяется с Bluetooth, GSM, GPS и многими другими модулями, поэтому и Serial begin – частый гость в скетчах ардуинщиков. О том, как его можно использовать и пойдет речь в этой статье.
Краткое описание
Функция begin() является методом класса Serial. Для работы с этим классом не нужно подключать внешних библиотек, т.к. он встроен в среду разработки ардуино. Использовать Serial.begin() целесообразно один раз, в самом начале работы скетча, в функции void setup(). В качестве аргументов нужно указать скорость обмена данными через последовательный порт. Самым распространенным значением является 9600 – именно такая скорость обмена данными в мониторе порта Arduino IDE стоит по умолчанию. После выполнения функции ардуино будет способна как отправлять данные на внешние устройства, так и получать их.
Пример использования функции:
Другие популярные методы класса Serial:
На платах с несколькими «железными» последовательными портами, например, Arduino Mega, для каждого из них создается свой объект Serial, поэтому вместе с Serial могут встречаться вызовы объектов Serial1, Serial2, Serial3.
Синтаксис функции
Команда Serial.begin () состоит из двух частей. Первая часть, Serial, является названием класса библиотеки для работы с монитором порта. Вторая часть, begin() обозначает название метода, которому мы должны передать один аргумент – скорость обмена данными. Функция не возвращает значений.
Синтаксис функции, два варианта:
Скорость для последовательного порта в Serial.begin()
Стандартное значение скорости в аргументе функции begin() – 9600. Эта цифра означает, что плата ардуино будет посылать по последовательному порту данные со скоростью 9600 бит в секунду (нужно учитывать, что для каждых 8 бит еще высылаются служебный стоповый бит). Естественно, приемно-передающее устройства на другом конце провода тоже должно быть настроено на эту же скорость, иначе оно будет пропускать некоторые биты или излишне торопиться, что приведет к рассинхронизации – информация будет как бы рваться на кусочки. Поэтому без лишней надобности не меняйте параметр по умолчанию – 9600.
Кроме стандартного значения можно устанавливать и другие: 300, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600, 115200. Чем выше цифра, тем выше скорость обмена, но нужно следить, чтобы эту скорость поддерживало и внешнее устройство. В некоторых ситуациях слишком высокая скорость обмена может привести к ошибкам, нужно учитывать и это. Так, например, значение 115200 устанавливаются обычно специальными высокоскоростными устройствами, например, полетными контроллерами. Значения ниже 9600 используются крайне редко.
Второй параметр для последовательного порта
Параметр config в функции begin обычно не указывается, т.к. крайне редко надо менять значения по умолчанию. Но на всякий случай приведем здесь возможные варианты параметров, которые можно найти в HardwareSerial.h:
В этих константах обозначаются разные варианты структуры пакета данных. Например, SERIAL_8N2 означает, что по последовательному порту ардуино передаст пакет длиной 8 бит без бита контроля четности (указано N) и с одним стоповым битом, который будет добавлен после байта данных.
Вопросы и ответы
Serial begin 9600 – что это значит?
Эти три слова похожи на какую-то мантру. И действуют они так же: каким-то волшебным образом наша плата ардуино организовывает канал связи и начинает информационный обмен. Конечно, на самом деле никакой мистики во всем этом нет, но заклинание мы запомнить должны:
Эта строчка говорит контроллеру ардуино, что нужно обратиться к последовательному порту по UART интерфейсу, открыть его для записи и подписаться на любые события с его стороны (для получения данных). Она обязательно должна использоваться перед выводом информации в монитор порта или считыванием данных.
На каких платах работает функция?
Эта функция работает на любых платах Arduino: Uno, Mega, Nano, Leonardo и т.д. Особенностью плат с несколькими «железными» последовательными портами является возможность вызывать объект Serial для каждого из этих портов.
Что будет, если не использовать функцию в скетче?
Все последующие команды для работы с последовательным портом не будут работать. Вы не сможете ни отправлять данные с помощью функций print() или println(), ни получать данные с помощью read() или readBytes().
Можно ли сократить функцию Serial.begin()?
Для многих начинающих программистов написание непривычных конструкций вызывает дискомфорт. Вы можете «сократить» Serial.begin() до синонима и использовать его, если так будет удобно. Для этого нужно воспользоваться #define. Вот пример:
Но следует сразу отметить, что данный способ использовать не рекомендуется, т.к. это усложняет и запутывает программу, а пользы и экономии места очень мало.
Монитор порта, отладка
Как мы с вами знаем из урока “О платформе“, на платах Ардуино стоит USB-TTL конвертер, позволяющий микроконтроллеру в текстовом режиме “консоли” общаться с компьютером по последовательному интерфейсу, Serial. На компьютере создаётся виртуальный COM порт, к которому можно подключиться при помощи программ-терминалов порта, и принимать-отправлять текстовые данные. Через этот же порт загружается прошивка, т.к. поддержка Serial является встроенной в микроконтроллер на “железном” уровне, и USB-TTL преобразователь подключен именно к этим выводам микроконтроллера. На плате Arduino Nano это кстати пины D0 и D1.
К этим же пинам можно подключаться при помощи отдельных плат “программаторов”, например на чипах CP2102 или том же CH340 с целью загрузки прошивки или просто общения с платой. В самой Arduino IDE тоже есть встроенная “консоль” – монитор порта, кнопка с иконкой лупы в правом верхнем углу программы. Нажав на эту кнопку мы откроем сам монитор порта, в котором будут настройки:
Если с отправкой, автопрокруткой, отметками времени и кнопкой “очистить вывод” всё понятно, то конец строки и скорость мы рассмотрим подробнее:
Объект Serial
Запустить связь по Serial на скорости speed (baud rate, бит в секунду). Скорость можно поставить любую, но есть несколько “стандартных”. Список скоростей для монитора порта Arduino IDE:
Отправляет в порт значение val – число или строку. В отличие от write выводит именно символы, т.е. отправив 88 вы получите 88: Serial.print(88); выведет 88. Также метод print/println имеет несколько настроек для разных данных, что делает его очень удобным инструментом отладки:
format позволяет настраивать вывод данных: BIN, OCT, DEC, HEX выведут число в соответствующей системе исчисления, а цифра после вывода float позволяет настраивать выводимое количество знаков после точки
Читает данные из буфера и ищет набор символов target (тип char), опционально можно указать длину length. Возвращает true, если находит указанные символы. Ожидает передачу по таймауту
Плоттер
Помимо монитора последовательного порта, в Arduino IDE есть плоттер – построитель графиков в реальном времени по данным из последовательного порта. Достаточно отправить значение при помощи команды Serial.println(значение) и открыть плоттер по последовательному соединению, например построим график значения с аналогового пина A0:
Плоттер поддерживает несколько линий графиков одновременно, для их отображения нужно соблюдать следующий протокол отправки данных: значение1 пробел_или_запятая значение2 пробел_или_запятая значение3 пробел_или_запятая значениеN перенос_строки, то есть значения выводятся в одну строку, одно за другим по порядку, разделяются пробелом или запятой, и в конце обязательно перенос строки. Давайте выведем несколько случайных величин:
Вывод значений происходит каждые 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, используя готовый метод парсинга.
Теперь после отправки цифры программа будет ждать всего 50 мс, и сразу же вам ответит. Остальные алгоритмы отправки и парсинга, в том числе обмена разнотипными данными между Ардуинами и другими платами смотри в уроке общение по Serial.
Управляющие символы
Существуют так называемые управляющие символы, позволяющие форматировать вывод. Их около десятка, но вот самые полезные из них
Также если для вывода вы захотите использовать одинарные ‘ или двойные кавычки, “ или обратный слэш \ – нужно выводить их при помощи соответствующего спецсимвола, иначе ваш вывод “поломается”, я думаю, не нужно объяснять, почему:
Как использовать? Просто писать в вывод. Например комбинация \r\n переведёт строку и вернёт курсор в левое положение:
Результат скопируем и вставим в excel Удобно!
Видео
Arduino библиотека Serial
Библиотека Serial — это стандартная библиотека, которая подключается в скетчи автоматически. Она используется для передачи данных через последовательный порт Arduino. В большинстве плат ардуино доступен 1 интерфейс Serial. Последовательный порт работает с двумя цифровыми пинами Ардуино 0-ой (RX) и 1-ый (TX). В Arduino Mega таких интерфейсов 3. Для доступа к интерфейсу связи необходимо использовать ключевой слово Serial (Serial1 и Serial2 для Arduino Mega).
Теперь рассмотрим доступные функции библиотеки Serial:
if(Serial)
Условие с проверкой готовности порта к работе. Используется такая конструкция довольно редко, потому что обычно интерфейс доступен.
available()
Проверяет число байтов доступных для считывания. Данная функция показывает какое количество данных уже пришло и хранится в буфере обмена. Размер буфера последовательного порта 64 байта.
Синтаксис
Параметры
Возвращаемые значения
Число байт доступных для чтения
availableForWrite()
Проверяет число байтов доступных для записи в буфер обмена, без блокировки функции записи.
Синтаксис
Параметры
Возвращаемые значения
Число байт доступных для записи
begin()
Данная функция устанавливает соединение на определенной скорости.
Синтаксис
Параметры
speed — Обязательный параметр. Скорость бит в секунду (бод). Доступные значения: 300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600 или 115200
config — Необязательный параметр. Задает биты данных, биты четности и стоп-биты. Доступные значения: SERIAL_5N1, SERIAL_6N1, SERIAL_7N1, SERIAL_8N1 (это значение задано по умолчанию), SERIAL_5N2, SERIAL_6N2, SERIAL_7N2, SERIAL_8N2, SERIAL_5E1, SERIAL_6E1, SERIAL_7E1, SERIAL_8E1, SERIAL_5E2, SERIAL_6E2, SERIAL_7E2, SERIAL_8E2, SERIAL_5O1, SERIAL_6O1, SERIAL_7O1, SERIAL_8O1, SERIAL_5O2, SERIAL_6O2, SERIAL_7O2, SERIAL_8O2
Возвращаемые значения
Отключает соединение через последовательный порт и освобождает пины RX и TX.
Синтаксис
Параметры
Возвращаемые значения
Считывает данные из буфера обмена до тех пор пока не найдет заданную строку.
Синтаксис
Параметры
needle — Обязательный параметр. Строка которую нужно найти
Возвращаемые значения
true — Если строка найдена.
false — Если строка не найдена.
findUntil()
Считывает данные из буфера обмена до тех пор пока не найдет заданную строку или терминальную строку.
Синтаксис
Параметры
needle — Обязательный параметр. Строка которую нужно найти
terminal — Обязательный параметр. Терминальная строка которую нужно найти
Возвращаемые значения
true — Если строка найдена.
false — Если строка не найдена.
flush()
Очищает буфер обмена последовательного порта
Синтаксис
Параметры
Возвращаемые значения
parseFloat()
Возвращает первое найденное в буфере обмена число с плавающей точкой. Все остальные символы игнорируются.
Синтаксис
Параметры
Возвращаемые значения
Число с плавающей точкой (float)
parseInt()
Возвращает первое найденное в буфере обмена целое число. Все остальные символы игнорируются.
Синтаксис
Параметры
skipChar — необязательный параметр. Символ который будет пропускаться при поиске
Возвращаемые значения
Целое число (long) или 0, если не найдено цифр.
Возвращает первый байт данных из буфера.
Синтаксис
Параметры
Возвращаемые значения
Первый байт входящих последовательных данных (int). Если данных нет то вернет «-1»
print()
Функция отправляет данные в последовательный порт в виде ASCII-текста.
Синтаксис
Параметры
val — обязательный параметр. Данные, которые необходимо отправить.
format — Необязательный параметр. Форматирует отправляемые данные. Может принимать следующие значения: BIN — Двоичный формат. OCT — Восьмеричный формат. DEC — Десятичный формат HEX — Шестнадцатиричный формат. 0 — Округление числа до целых. 2 — Округление число до сотых.
Возвращаемые значения
Количество записанных байтов (long)
println()
Отправляет данные в виде ASCII-текста в последовательный порт с символом конца строки (\r) и символом новой строки (\n)
Синтаксис
Параметры
val — обязательный параметр. Данные, которые необходимо отправить.
format — Необязательный параметр. Форматирует отправляемые данные. Может принимать следующие значения: BIN — Двоичный формат. OCT — Восьмеричный формат. DEC — Десятичный формат HEX — Шестнадцатиричный формат. 0 — Округление числа до целых. 2 — Округление число до сотых.
Возвращаемые значения
Количество записанных байтов (long)
Считывает данные из последовательного порта.
Синтаксис
Параметры
Возвращаемые значения
Первый доступный байт (int).
readBytes()
Считывает символы из последовательного порта в буфер. Завершает свою работу, если сосчитает данные заданной длины или если выйдет время. Время указывается при помощи функции serial.setTimeout().
Возвращаемое значение — количество символов, помещенных в буфер. Если функция вернет значение «0», это значит, что нужных данных найдено не было.
Синтаксис
Параметры
buffer — буфер, в который будут сохраняться входящие байты (char[] или byte[])
length — количество считанных байтов (int)
Возвращаемые значения
readBytesUntil()
Считывает символы из буфера последовательного порта в массив. Завершает свою работу, если обнаружит терминальный символ, если сосчитает данные заданной длины или если выйдет время. Время указывается с помощью функции Serial.setTimeout().
Синтаксис
Параметры
character — символ, который нужно найти (char)
buffer — буфер, в который будут сохранены входящие байты (char[] или byte[])
length — количество байтов, которые нужно сосчитать (int)
Возвращаемые значения
readString()
Считывает данные из буфера последовательного порта в строку. Завершает свою работу, если выйдет время. Время указывается в функции Serial.setTimeout().
Синтаксис
Параметры
Возвращаемые значения
Строка с данными, считанными из буфера последовательного порта.
readStringUntil()
Считывает символы из буфера последовательного порта в строку. Завершает свою работу, если наткнется на терминальный символ или если выйдет время. Время указывается в функции Serial.setTimeout().
Синтаксис
Параметры
terminalChar— искомый символ (char)
Возвращаемые значения
Строка, считанная из буфера последовательного порта (до символа, завершающего работу функции).
setTimeout()
Устанавливает время (в миллисекундах), в течение которого функции Serial.readBytesUntil(), Serial.readBytes(), Serial.parseInt() и Serial.parseFloat() должны будут ждать данных, входящих через последовательный порт.
Синтаксис
Параметры
time — время ожидания в миллисекундах (long).
Возвращаемые значения
write()
Передает через последовательный порт данные в двоичном виде. Данные передаются как байт или как серия байтов. Если вам нужно отправить символы, представляющие цифры какого-либо числа, используйте функцию print().
Синтаксис
Параметры
val — значение, строка или буфер для отправки.
len — размер буфера
Возвращаемые значения
Байт или количество отправленных байтов
serialEvent
Автоматически вызывается, когда есть доступные данные. Для захвата этих данных нужно воспользоваться функцией Serial.read().
Синтаксис
Параметры
statements — любые корректные функции, позволяющие делать что-то с поступившими данными.
Последовательный порт. Урок 5. Ардуино
Привет! Мы уже начали писать довольно объемные программы на ардуино. А когда программа сложнее чем «hello world» в ней могут появляться ошибки. И, наверняка, вы уже думали, что было бы неплохо следить за состоянием переменных, счетчиков и массивов в процессе выполнения программы. В этом нам поможет запись данных в последовательный порт.
В прошлый раз мы говорили про широтно-импульсную модуляцию или шим. Это довольно важная тема для ардуино. Поэтому, если вы уже забыли или пропустили предыдущий урок, пожалуйста, посмотрите его.
Во всех программах, которые мы уже написали, мы использовали массивы и переменные, которые изменяли свои значения в ходе выполнения программы. В процессе отладки такой программы очень важно иметь возможность проверить состояние переменных, счетчиков или значений элементов массива.
Поэтому сегодня посмотрим каким образом программа на ардуино может записывать данные в последовательный порт, и как использовать эти данные.
Для того, чтобы выполнить этот урок нам понадобиться.
Мы уже использовали все эти детали в предыдущем уроке, и сегодня будем использовать ту же схему подключения деталей, но изменим код программы. В уроке про написание собственной функции мы подключали кнопку к нескольким светодиодам. Тот урок можно посмотреть здесь.
Соберем схему еще раз и откроем скетч с программой.
Принципиальная схема подключения светодиодов и кнопки
Serial.begin и Serial.print()
Функция serial.begin() открывает последовательное соединение и принимает на вход скорость передачи данных в бит/c (бод). Чтобы использовать последовательный порт, добавим эту функцию в блок setup()
Теперь мы сможем вывести необходимую информацию в последовательный порт с помощью команды serial.print() или serial.println()
Добавим вывод счетчика i в нашей функции LedON(). Это значит, что при нажатии на кнопку мы будем видеть значение переменной i.
Загрузим программу в ардуино, откроем монитор последовательного порта и попробуем нажимать на кнопку. Открыть монитор можно кликом по его иконке в правом верхнем углу или комбинацией клавиш Ctrl+Shift+M.
Вывод в последовательный порт
Мы видим, что при каждом нажатии, переменная i увеличивается и выводится в монитор порта. Когда i равно 4, все светодиоды выключены, а когда 5, счетчик сбрасывается на 0.
Таким образом мы можем следить за любой переменной в программе, просто выводя ее значения в последовательный порт.
Это было довольно просто, правда? Давайте немного изменим программу и рассмотрим еще одну полезную управляющую конструкцию.
Switch Case
Эта конструкция похожа на if else. Но, использовать ее намного удобнее, когда у вас есть много вариантов выполнения программы. Работает это так. Переменная, которая приходит на вход switch() сравнивается с вариантами в case и выполняется тот кусок кода, который отвечает условию.
Заменим условные операторы в нашей функции на switch case таким образом.
Теперь переменная i сравнивается с каждым вариантом case и срабатывает та часть кода, которая подходит под условие.
Также мы немного изменили логику функции, и теперь зажигается столько светодиодов, сколько раз была нажата кнопка, попробуйте.
Программа нажатия на кнопку switch case
Полный текст программы
Заключение
В этом уроке мы рассмотрели как мы можем использовать последовательный порт для вывода отладочной информации нашей программы. И познакомились с новой управляющей конструкцией switch case. Теперь мы готовы писать по-настоящему сложные программы и создавать настоящие проекты на ардуино. В следующий раз поговорим про получение данных с внешних датчиков на ардуино.