Arduino
Serial
Библиотека Serial содержит набор функции для работы с последовательным портом Arduino.
Любая плата Arduino содержит один или несколько последовательных портов, служащих для связи с компьютером или с другими устройствами, которые также поддерживают последовательный интерфейс обмена данными.
В таблице ниже представлены данные по последовательным портам основных плат Arduino:
Плата | Пины сериального порта 1 | Пины сериального порта 2 | Пины сериального порта 3 | Пины сериального порта 4 |
---|---|---|---|---|
Uno | 0(RX), 1(TX) | |||
Nano | 0(RX), 1(TX) | |||
Mini | 0(RX), 1(TX) | |||
Mega | 0(RX), 1(TX) | 19(RX), 18(TX) | 17(RX), 16(TX) | 15(RX), 14(TX) |
Due | 0(RX), 1(TX) | 19(RX), 18(TX) | 17(RX), 16(TX) | 15(RX), 14(TX) |
TX — пин передачи данных, RX — пин получения данных.
Для соединения двух устройств, необходимо подключить пин TX первого устройство к пину RX второго, а пин RX первого — к пину TX второго соответственно.
Для связи с компьютером используется USB порт на Arduino, однако нужно помнить, что и в этом случае при использовании функций Serial нельзя задействовать пины RX и TX для каких-либо других целей.
Среду разработки Arduino IDE и PlatformIO имеют встроенный монитор порта Serial , главное — не забыть выставить одинаковую скорость на Arduino через функцию begin() и в IDE.
Функции библиотеки Serial
Функция Serial.begin()
Описание
Инициирует последовательное соединение, а также задает скорость передачи данных. Скорость измеряется в бит/с (бод). Для обмена данных с компьютером через USB используются значения из следующего списка: 300, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600 и 115200. При подключении двух устройств через пины RX и TX, могут использоваться любые другие значения.
Синтаксис
Serial.begin(speed)
Serial.begin(speed, config)
Параметры
speed — скорость передачи данных
config — необязательный параметр, устанавливает данные, четность и стоповые биты
Возвращаемое значение
Пример
Функция Serial.end()
Описание
Закрывает последовательное соединение, позволяя использовать пины RX и TX для обычного использования.
Чтобы снова включить последовательное соединение, используйте функцию begin() .
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 — любые корректные функции, позволяющие делать что-то с поступившими данными.
Железо
Это расширенный стартовый набор. В комплект входит Arduino Mega R3, макетные платы, множество датчиков, управляемые механизмы и необходимые радиоэлектронные компоненты. Полный список.
Arduino Uno — плата на базе микроконтроллера ATmega328P с частотой 16 МГц. На плате есть все необходимое для удобной и быстрой работы.
Макетная плата на 830 точек и ничего лишнего.
Монитор порта, отладка
Как мы с вами знаем из урока “Что умеет микроконтроллер“, у многих микроконтроллеров есть интерфейс UART, позволяющий передавать и принимать различные данные. У интерфейса есть два вывода на плате – пины TX и RX. На большинстве Arduino-плат к этим пинам подключен USB-UART преобразователь (расположен на плате), при помощи которого плата может определяться компьютером при подключении USB кабеля и обмениваться с ним информацией. На компьютере создаётся виртуальный COM порт (последовательный порт), к которому можно подключиться при помощи программ-терминалов и принимать-отправлять текстовые данные. Таким же образом кстати работают некоторые принтеры и большинство станков с ЧПУ.
В самой Arduino IDE есть встроенная “консоль” – монитор порта, кнопка с иконкой лупы в правом верхнем углу программы. Нажав на эту кнопку мы откроем сам монитор порта, в котором будут настройки:
Если с отправкой, автопрокруткой, отметками времени и кнопкой очистить вывод всё и так понятно, то конец строки и скорость мы рассмотрим подробнее:
- Конец строки: тут есть несколько вариантов на выбор, чуть позже вы поймёте, на что они влияют. Лучше поставить нет конца строки, так как это позволит избежать непонятных ошибок на первых этапах знакомства с платформой.
- Нет конца строки – никаких дополнительных символов в конце введённых символов после нажатия на кнопку отправка или клавишу Enter.
- NL – символ переноса строки в конце отправленных данных.
- CR – символ возврата каретки в конце отправленных данных.
- NL+CR – и то и то.
- Скорость – тут на выбор нам даётся целый список скоростей, т.к. общение по Serial может осуществляться на разных скоростях, измеряемых в бод (baud), и если скорости приёма и отправки не совпадают – данные будут получены некорректно. По умолчанию скорость стоит 9600, её и оставим.
Объект Serial
Начнём знакомство с одним из самых полезных инструментов Arduino-разработчика – Serial, который идёт в комплекте со стандартными библиотеками. Serial позволяет как просто принимать и отправлять данные через последовательный порт, так и наследует из класса Stream кучу интересных возможностей и фишек, давайте сразу их все рассмотрим, а потом перейдём к конкретным примерам.
Запустить связь по Serial на скорости speed (измеряется в baud, бит в секунду). Скорость можно поставить любую, но есть несколько “стандартных” значений. Список скоростей для монитора порта Arduino IDE:
- 300
- 1200
- 2400
- 4800
- 9600 чаще всего используется, можно назвать стандартной
- 19200
- 38400
- 57600
- 115200 тоже часто встречается
- 230400
- 250000
- 500000
- 1000000
- 2000000 – максимальная скорость, не работает на некоторых китайских платах
How does serial communications work on the Arduino?
With reference to the Arduino Uno, Mega2560, Leonardo and similar boards:
- How does serial communications work?
- How fast is serial?
- How do I connect between a sender and receiver?
Please note: This is intended as a reference question.
1 Answer 1
Asynchronous serial (usually referred to as serial) communications is used to send bytes from one device to another. A device could be one or more of the following:
Clock rate and sampling of data
Unlike SPI / USB / I2C serial communications does not have a clock signal. The sampling clock is an agreed-upon sample rate (known as the baud rate). Both sender and receiver must be configured to be using the same rate or the receiver will receive meaningless data (due to the bits not being sampled at the same rate that they were sent).
The transmission is asynchronous which basically means that bytes can be sent at any time, with varying gaps between them. This graphic illustrates a single byte being sent:
The graphic above shows the letter ‘F’ being transmitted. In ASCII this is 0x46 (in hex) or 0b01000110 (in binary). The least significant (low-order) bit is transmitted first, thus in the above graphic you see the bits arriving in the order: 01100010 .
The «idle» time between bytes is transmitted as continuous «1» bits (effectively, the transmit line is held high continuously).
To indicate the start of a byte, the Start Bit is always indicated by pulling the line low as shown on the graphic. Once the receiver sees the start bit, it waits for 1.5 times the sample time, and then samples the data bits. It waits 1.5 times so that it:
- Skips the start bit
- Samples half-way through the next bit
If the baud rate is 9600 baud, for example, then the sample rate will be 1/9600 = 0.00010416 seconds (104.16 µs).
Thus, at 9600 baud, after receiving a start bit the receiver waits for 156.25 µs, and then samples every 104.16 µs.
The purpose of the Stop Bit is to ensure that there definitely is a 1-bit between each byte. Without the stop bit, if a byte ended in a zero, then it would be impossible for the hardware to tell the difference between that and the start bit of the next byte.
To produce the above output on an Uno you could write this code:
Number of data bits
In order to save transmission time (in the olden days, heh) you were allowed to specify different numbers of data bits. The AtMega hardware supports data bits numbering from 5 to 9. Clearly the less data bits the less information you can send, but the faster it will be.
Parity bits
You can optionally have a parity bit. This is calculated, if required, by counting the number of 1’s in the character, and then making sure that this number is odd or even by setting the parity bit to 0 or 1 as required.
For example, for the letter «F» (or 0x46 or 0b01000110) you can see that there are 3 ones there (in 01000110). Thus we already have odd parity. So, the parity bit would be as follows:
- No parity: omitted
- Even parity: a 1 (3 + 1 is even)
- Odd parity: a 0 (3 + 0 is odd)
The parity bit, if present, appears after the last data bit but before the stop bit.
If the receiver does not get the correct parity bit, that is called a «parity error». It indicates that there is some problem. Possibly the sender and receiver are configured to use different baud (bit) rates, or there was noise on the line which turned a zero to a one or vice-versa.
Some early systems also used «mark» parity (where the parity bit was always 1 regardless of the data), or «space» parity (where the parity bit was always 0 regardless of the data).
9-bit transmission
Some communication equipment uses 9-bit data, so in these cases the parity bit is turned into the 9th bit. There are special techniques for sending this 9th bit (the registers are 8-bit registers so the 9th bit has to be put somewhere else).
Number of stop bits
Early equipment tended to be somewhat slower electronically, so to give the receiver time to process the incoming byte, it was sometimes specified that the sender would send two stop bits. This basically adds more time where the data line is held high (one more bit time) before the next start bit can appear. This extra bit time gives the receiver time to process the last incoming byte.
If the receiver does not get a logical 1 when the stop bit is supposed to be, that is called a «framing error». It indicates that there is some problem. Quite possibly the sender and receiver are configured to use different baud (bit) rates.
Notation
Commonly, serial communication is indicated by telling you the speed, number of data bits, type of parity, and number of stop bits, like this:
This is telling us:
- 9600 bits per second
- 8 data bits
- No parity (you might see instead: E=even, O=odd)
- 1 stop bit
It is important that the sender and receiver agree on the above, otherwise communication is unlikely to be successful.
Pin-outs
The Arduino Uno has digital pins 0 and 1 available for hardware serial:
To connect two Arduinos you swap Tx and Rx like this:
Speed
A wide range of speeds is supported (see graphic below). «Standard» speeds are usually a multiple of 300 baud (eg. 300/600/1200/2400 etc.).
Other «non-standard» speeds can be handled by setting the appropriate registers. The HardwareSerial class does this for you. eg.
As a rule-of-thumb, assuming you are using 8-bit data, then you can estimate the number of bytes you can transmit per second by dividing the baud rate by 10 (because of the start bit and stop bit).
Thus, at 9600 baud you can transmit 960 bytes ( 9600 / 10 = 960 ) per second.
Baud rate errors
The baud rate on the Atmega is generated by dividing down the system clock, and then counting up to a pre-set number. This table from the datasheet shows the register values, and error percentages, for a 16 MHz clock (such as the one on the Arduino Uno).
The U2Xn bit affects the clock rate divisor (0 = divide by 16, 1 = divide by 8). The UBRRn register contains the number the processor counts up to.
So from the table above, we see that we get 9600 baud from a 16 MHz clock as follows:
We divide by 104 and not 103 because the counter is zero-relative. Thus the error here is 15 / 9600 = 0.0016 which is close to what the table above says (0.02%).
You will notice that some baud rates have a higher error amount than others.
According to the datasheet the maximum error percentage for 8 data bits is in the range of 1.5% to 2.0% (see the datasheet for more details).
Arduino Leonardo
The Arduino Leonardo and Micro have a different approach to serial communications, as they connect directly via USB to the host computer, not via the serial port.
Because of this, you must wait for Serial to become «ready» (as the software establishes an USB connection), with an extra couple of lines, like this:
However, if you want to actually communicate via pins D0 and D1, (rather than by the USB cable) then you need to use Serial1 rather than Serial. You do so like this:
Voltage levels
Note that the Arduino uses TTL levels for serial communications. This means that it expects:
- A «zero» bit is 0V
- A «one» bit is +5V
Older serial equipment designed to plug into a PC’s serial port probably uses RS232 voltage levels, namely:
- A «zero» bit is +3 to +15 volts
- A «one» bit is −3 to −15 volts
Not only is this «inverted» with respect to TTL levels (a «one» is more negative than a «zero»), the Arduino cannot handle negative voltages on its input pins (nor positive ones greater than 5V).
Thus you need an interface circuit for communicating with such devices. For input (to the Arduino) only, a simple transistor, diode, and a couple of resistors will do it:
For two-way communication you need to be able to generate negative voltages, so a more complex circuit is required. For example the MAX232 chip will do that, in conjunction with four 1 µF capacitors to act as charge-pump circuits.
Software Serial
There is a library called SoftwareSerial that lets you do serial communications (up to a point) in software rather than hardware. This has the advantage that you can use different pin configurations for serial communications. The disadvantage is that doing serial in software is more processor-intensive and more prone to error. See Software Serial for more details.
Mega2560
The Arduino «Mega» has 3 additional hardware serial ports. They are marked on the board as Tx1/Rx1, Tx2/Rx2, Tx3/Rx3. They should be used in preference to SoftwareSerial if possible. To open those other ports you use the names Serial1, Serial2, Serial3, like this:
Interrupts
Both sending and receiving, using the HardwareSerial library, use interrupts.
Sending
When you do a Serial.print , the data you are trying to print is placed in an internal «transmit» buffer. If you have 1024 bytes or more of RAM (such as on the Uno) you get a 64-byte buffer, otherwise you get a 16-byte buffer. If the buffer has room, then the Serial.print returns immediately, thus not delaying your code. If there is no room, then it «blocks» waiting for the buffer to be emptied enough for there to be room.
Then, as each byte is transmitted by the hardware an interrupt is called (the «USART, Data Register Empty» interrupt) and the interrupt routine sends the next byte from the buffer out of the serial port.
Receiving
As incoming data is received an interrupt routine is called (the «USART Rx Complete» interrupt) and the incoming byte is placed into a «receive» buffer (the same size as the transmit buffer mentioned above).
When you call Serial.available you find out how many bytes are available in that «receive» buffer. When you call Serial.read a byte is removed from the receive buffer and returned to your code.
On Arduinos with 1000 bytes or more of RAM, there is no rush to remove data from the receive buffer, provided you don’t let it fill up. If it fills up then any further incoming data is discarded.
Note that because of the size of this buffer there is no point in waiting for a very large number of bytes to arrive, for example:
This will never work because the buffer cannot hold that much.
Before reading, always make sure data is available. For example, this is wrong:
The Serial.available test only ensures you have one byte available, however the code tries to read two. It may work, if there are two bytes in the buffer, if not you will get -1 returned which will look like ‘ÿ’ if printed.
Be aware of how long it takes to send data. As mentioned above, at 9600 baud you an only transmit 960 bytes per second, so trying to send 1000 readings from an analog port, at 9600 baud, won’t be very successful.