В этой статье мы покажем вам, как обмениваться данными между Raspberry Pi и платой Arduino через последовательный интерфейс.
Для начала, кратко объясним, что такое последовательный интерфейс. Затем посмотрим, как настроить оборудование и программное обеспечение, а затем углубимся в код Python (Cpp для Arduino). Разберем простой пример, ведущий к более совершенному использованию Raspberry Pi, Arduino и других электронных устройств.
Это руководство подходит для плат Raspberry Pi 4 (и ранних: 3B, 3B +) и любой платы Arduino. Мы будем использовать в основном Arduino Uno, но также более подробно расскажем о различиях между платами Arduino, когда дело касается последовательной передачи данных.
При работе с электронными устройствами передача данных является ключевым моментом. Каждое устройство – помимо своей основной функции – должно четко обмениваться данными с другими устройствами. Это одна из самых важных вещей, с которыми нужно уметь работать, чтобы перейти от очень простых приложений к более сложным.
Что такое последовательный интерфейс (UART)?
Последовательная передача данных – это просто способ их передачи. Данные отправляются последовательно, по одному биту (1 байт = 8 бит), в отличие от параллельной связи, когда одновременно отправляется много битов.
Что такое протокол UART?
Говоря более конкретно, когда вы используете последовательный порт с Arduino и Raspberry Pi, вы используете протокол UART. UART означает «Универсальный асинхронный приёмопередатчик».
По сути, это асинхронный multi-master протокол, основанный на последовательном интерфейсе, который позволяет обмениваться данными между двумя платами. Будьте уверены, есть библиотеки, которые справятся со всеми низкими уровнями за вас.
Multi-master означает, что все подключенные устройства смогут отправлять данные, когда требуется. Это одно из основных отличий от протоколов «master-slaves», где только главное устройство может инициировать обмен данными.
Обычно используются другие протоколы, такие как I2C и SPI, когда вам нужны конфигурации ведущий-ведомый: например, когда у вас есть одна плата Arduino и несколько датчиков или исполнительных механизмов.
На плате Arduino Uno есть один UART, который можно использовать либо с USB-кабелем, либо с контактами RX / TX (не используйте его с обоими одновременно). Некоторые платы имеют больше доступных UART.
Например, Arduino Mega имеет разные последовательные интерфейсы (Serial, Serial1, Serial2, Serial3), а Arduino Zero имеет только порт USB (используйте SerialUSB вместо Serial).
На Raspberry Pi возможно подключить множество последовательных устройств к портам USB. У каждого устройства будет свое имя (посмотрим как их найти позже в этой статье). Вы также можете использовать GPIO (RX0 / TX0) для дополнительного UART.
Вы, наверное, уже знакомы с библиотекой Serial для Arduino
Когда вы используете монитор последовательного порта, в общем случае ваша среда разработки Arduino запускает последовательный интерфейс с вашим Arduino. Вы можете получать и отправлять данные прямо с монитора последовательного порта.
То, что мы сделаем здесь, почти то же самое, за исключением того, что вместо вашей среды разработки Arduino другой стороной последовательного интерфейса будет плата Raspberry Pi. Нам нужно будет произвести некоторые настройки и написать код, чтобы он заработал. Тогда и Raspberry Pi, и Arduino смогут отправлять сообщения друг другу.
Давайте теперь посмотрим, как физически соединить две платы вместе.
Настройка оборудования для последовательного интерфейса
Есть 2 способа подключить Raspberry Pi и Arduino для последовательного интерфейса.
1. С помощью USB
Самый простой способ – соединить обе платы кабелем USB.
Со стороны Raspberry Pi USB-разъем – это все, что вам нужно. Вы можете выбрать любой из 4 портов USB, имеющихся на плате.
Для Arduino вы будете использовать USB-порт, который вы используете для загрузки кода с вашего компьютера (со среды разработки Arduino) на вашу плату. Выбор USB-разъема зависит от того, какая у вас версия. Для таких плат, как Arduino Uno и Mega, разъем будет отличаться от Arduino Nano и от Arduino Zero.
В этом примере мы использовали плату Arduino Uno.
Как видите, это простейшее аппаратное соединение, которое вы можете установить между Raspberry Pi и Arduino.
Примечание: сначала вам нужно подключить Arduino к компьютеру, чтобы вы могли загрузить код в плату. После этого подключите USB-кабель к Raspberry Pi. Raspberry Pi будет питать Arduino через этот кабель
2. С помощью интерфейса ввода/вывода общего назначения (GPIO)
Чтобы установить последовательное соединение, вы также можете использовать простые провода между интерфейсом ввода/вывода Raspberry Pi и контактами Arduino
В зависимости от типа вашей платы Arduino вам может потребоваться переключатель уровня напряжения. Raspberry Pi работает при напряжении 3,3 В. Для плат Arduino, таких как Due, 101, это тоже подойдет, так как они также используют 3,3 В.
Но для многих Arduino, таких как Uno, Mega, Leonardo, Nano и многих других, плата работает при напряжении 5 В. Таким образом, вам понадобится переключатель напряжения 3,3 В / 5 В для защиты Raspberry Pi при подключении RX и TX.
В оставшейся части этого руководства мы будем использовать настройку с помощью кабеля USB. С ним будет проще работать, поэтому советуем использовать USB-кабель вместо GPIO для последовательного интерфейса.
Как настроить программное обеспечение Raspberry Pi?
Для Arduino не требуется никаких специальных настроек. Просто убедитесь, что вы скачали и установили среду разработки Arduino.
Однако, на вашем Raspberry Pi требуется несколько вещей, чтобы интерфейс заработал.
Подключитесь к Raspberry Pi через протокол SSH или с помощью экрана, мыши и клавиатуры, и откройте консоль. Если вы еще не установили ОС на плату, вы можете очень легко установить Raspbian или Ubuntu на SD-карту.
1. Найдите плату Arduino
При подключении к Arduino через USB, вы должны обнаружить ее по адресу /dev/ttyACM0 или /dev/ttyUSB0 (иногда цифра в адресе может отличаться, к примеру /dev/ttyACM1).
Запустите
1 |
ls /dev/tty* |
Вы должны обнаружить плату. Если вы не уверены какой девайс – плата Arduino, отключите кабель и повторите.
Таким образом, вы сможете с легкостью определить имя платы Arduino.
2. Настройка разрешения для работы последовательного интерфейса
Вы можете добавить своего пользователя в группу dialout, чтобы избежать таких ошибок, как: serial.serialutil.SerialException: [Errno 13] could not open port / dev / ttyACM0: [Errno 13] Permission denied: ‘/ dev / ttyACM0
1 |
$ sudo adduser ваше_имя_пользователя dialout |
Это даст доступ к последовательным устройствам (/ dev / ttyACMx, / dev / ttyUSBx,…).
После того, как вы добавили себя в группу dialout, вам необходимо перезагрузить Pi (или, по крайней мере, выйти из системы / войти в систему), чтобы применить изменения.
Установите библиотеку последовательного интерфейса Python на Raspberry Pi
Вам необходимо установить библиотеку, чтобы иметь возможность использовать последовательный интерфейс с Python.
В этой статье мы будем использовать библиотеку pySerial.
Чтобы установить её:
1 |
python3 -m pip install pyserial |
Эта библиотека Python хорошо известна и используется во многих приложениях.
Если при установке вы получаете сообщение об ошибке, например «/ usr / bin / python3: No module named pip», вам необходимо сначала установить pip с помощью
1 |
sudo apt install python3-pip |
3. Организация связи Arduino и Raspberry Pi
Начнем с очень простой программы.
Код Arduino
Загрузите этот код со своего компьютера в Arduino, используя среду разработки Arduino.
1 2 3 4 5 6 7 |
void setup() { Serial.begin(9600); } void loop() { Serial.println("Hello from Arduino!"); delay(1000); } |
Для начала, мы инициализируем последовательный порт и выбираем скорость передачи, в данном случае, 9600 бод. 9600 – это обычно используемая скорость передачи, к тому же довольно низкая.
В ваших будущих приложениях вы можете без проблем использовать скорость передачи 57600 или даже 115200 бод. В этом уроке мы продолжим с 9600.
Каждую секунду мы заставляем Arduino отправлять строку с помощью Serial.println (). Команда println () добавляет символ новой строки «\ n» в конец каждой строки.
Вы можете открыть монитор последовательного порта, чтобы увидеть строку на вашем компьютере.
Код Python на Raspberry Pi
1 2 3 4 5 6 7 8 9 |
#!/usr/bin/env python3 import serial if __name__ == '__main__': ser = serial.Serial('/dev/ttyACM0', 9600, timeout=1) ser.flush() while True: if ser.in_waiting > 0: line = ser.readline().decode('utf-8').rstrip() print(line) |
Итак, что делает этот код?
1 2 |
#!/usr/bin/env python3 import serial |
Сначала мы импортируем предварительно установленную библиотеку последовательного интерфейса.
1 2 |
if __name__ == '__main__': ser = serial.Serial('/dev/ttyACM0', 9600, timeout=1) |
Последовательный интерфейс инициализируется вызовом serial.Serial () вместе с несколькими параметрами:
1) Имя последовательного устройства для Arduino: обычно ‘/ dev / ttyACM0’, ‘/ dev / ttyUSB0’ или подобное.
2) Скорость передачи: этот параметр очень важен. Вам нужно использовать ту же скорость передачи данных, что и на Arduino, иначе все, что вы будете читать и писать, работать не будет. Итак, мы выбрали 9600, как и в Arduino.
3) Тайм-аут: это тайм-аут для операций чтения. Здесь мы установили 1 секунду. Это означает, что когда мы читаем из Serial, программа не зависнет, если данные не поступят. Если после 1 секунды или чтения получены не все байты, функция вернет уже полученные байты.
Итак, serial.Serial () возвращает объект, который вы можете использовать для всех своих последовательных операций. Мы сохраняем его в переменной «ser».
1 |
ser.flush () |
Затем мы используем функцию flush (). Это очистит любой буфер ввода и вывода, чтобы избежать получения или отправки неверных / неполных данных в начале связи
1 2 3 4 |
while True: if ser.in_waiting> 0: line = ser.readline (). decode ('utf-8'). rstrip () print (line) |
В бесконечном цикле (подумайте о функции loop () в скетче Arduino) мы проверяем, доступны ли некоторые данные с помощью атрибута in_waiting (не ставьте скобки, это не функция). Если да, то мы можем прочитать данные.
Функция readline () будет читать все байты, пока не будет обнаружен символ новой строки.
Если мы просто выведем то, что получили, мы увидим надпись b’Hello from Arduino!\r\n’. Вы получаете байты при чтении из последовательного интерфейса, и нужно преобразовать (декодировать) эти байты в соответствующий тип данных. Итак, мы используем декодирование («utf-8») – также можно использовать декодирование («ascii») – для декодирования полученных данных и размещения их в строке.
Наконец, функция rstrip () специфична для строк, она позволяет удалить любые завершающие символы (новую строку, возврат каретки). Таким образом мы можем удалить «\ r» и «\ n» и получить правильную строку.
Примечание: здесь каждый раз читается полная строка. Если вы хотите прочитать определенное количество байтов – один или несколько – используйте функцию read (size=1).
4. Тестирование последовательной связи
Теперь отключите плату Arduino от компьютера и подключите ее к Raspberry Pi.
Код Arduino запускается, как только плата включается.
На Raspberry Pi сделайте файл Python исполняемым и запустите его.
1 2 3 4 5 |
$ chmod +x receive_serial_data_from_arduino.py $ ./receive_serial_data_from_arduino.py Hello from Arduino! Hello from Arduino! Hello from Arduino! |
Работает! Строка, отправляемая Arduino, каждую секунду отображается в консоли Raspberry Pi.
Двунаправленная последовательная связь между Raspberry Pi и Arduino
Давайте сделаем немного интереснее. Вы видели, как отправлять данные с Arduino на Raspberry Pi. В этой части вы увидите, как отправлять сообщения от Raspberry Pi с Arduino. Таким образом, у вас будут два направления коммуникации, и вы сможете создавать программы, требующие взаимодействия друг от друга.
Код Arduino
1 2 3 4 5 6 7 8 9 10 |
void setup() { Serial.begin(9600); } void loop() { if (Serial.available() > 0) { String data = Serial.readStringUntil('\n'); Serial.print("You sent me: "); Serial.println(data); } } |
Здесь мы проверяем, получил ли Arduino данные с помощью Serial.available (). Это даст информацию о количество байтов, уже доставленных и сохраненных в буфере приема.
Если поступили какие-то данные, мы используем Serial.readStringUntil () с символом новой строки «\n», чтобы перейти на следующую строку. Это похоже на функцию readline (). Все байты, полученные до “\ n”, автоматически конвертируются и добавляются в объект Arduino String.
Затем мы просто выводим полученные данные, добавив некоторый текст.
Примечание: если вы хотите читать байты один за другим, вы можете сделать это с помощью функции Serial.read ().
Затем вам нужно будет преобразовать эти байты, если необходимо: int, string и т. д.
Код Python для Raspberry Pi
1 2 3 4 5 6 7 8 9 10 |
import serial import time if __name__ == '__main__': ser = serial.Serial('/dev/ttyACM0', 9600, timeout=1) ser.flush() while True: ser.write(b"Hello from Raspberry Pi!\n") line = ser.readline().decode('utf-8').rstrip() print(line) time.sleep(1) |
Используйте функцию pySerial write () для отправки данных в Arduino.
Здесь мы добавили символ «b» перед отправляемой строкой. Это закодирует строку в байты, потому что через последовательный интерфейс можно отправлять только байты.
Любые данные, которые не являются байтами или байтовыми массивами, должны быть преобразованы перед отправкой. Если вы просто попытаетесь отправить такую строку, вы получите эту ошибку ” TypeError: unicode strings are not supported, please encode to bytes: ‘Hello from Raspberry Pi!’ ”
Примечание: вместо
1 ser.write (b "Hello from Raspberry Pi! \ n")Вы можете написать
1 ser.write ("Hello from Raspberry Pi! \ n" .encode ('utf-8'))или
1 ser.write ("Hello from Raspberry Pi! \ n" .encode ('ascii'))Функция encode () закодирует строку для последовательного интерфейса.
Кроме того, мы добавляем символ новой строки «\n», потому что это то, что требуется от Arduino для завершения чтения с помощью Serial.readStringUntil (‘\n’).
Затем мы делаем то же самое, что и раньше: читаем строку, декодируем ее в строку и удаляем любой завершающий символ.
Мы не используем здесь ser.in_waiting, потому что для этого конкретного приложения мы знаем, что Arduino отправит обратно некоторые данные сразу после того, как получит строку. Кроме того, у нас есть тайм-аут в 1 секунду, чтобы не застрять на этой строке.
Наконец, мы выводим полученную строку и ждем 1 секунду с помощью time.sleep () перед отправкой следующей строки через последовательный интерфейс.
Проверка двунаправленной последовательной связи
На Raspberry Pi сделайте свой файл Python исполняемым и запустите его.
1 2 3 4 5 |
$ chmod + x bidirectional_serial_communication.py $ ./bidirectional_serial_communication.py You sent me: Hello from Raspberry Pi! You sent me: Hello from Raspberry Pi! You sent me: Hello from Raspberry Pi! |
Отлично! Arduino получил строку и отправил ее обратно с еще несколькими словами. Затем Raspberry Pi получил и вывел последнюю строку.
Пример последовательной связи Raspberry Pi и Arduino
Теперь, когда вы знаете, как настроить Arduino и Raspberry Pi для последовательной связи и написать программы для обмена данными между каждой платой, давайте создадим более сложное приложение.
В этом примере к плате Arduino будут подключены 4 светодиода и одна кнопка.
Raspberry Pi и Arduino будут подключены с помощью USB-кабеля и использовать последовательную связь для связи между собой.
Вот результат, который мы хотим получить:
- При нажатии кнопки Arduino отправит уведомление на Raspberry Pi (простой байт).
- Raspberry Pi затем выберет случайное целое число от 1 до 4 и отправит его на Arduino.
- Arduino включит светодиод, соответствующий этому номеру, и выключит другие светодиоды.
Это наша возможность попрактиковаться во взаимодействии и синхронизации задач между Arduino и Raspberry Pi.
Если вы дошли до этого пункта руководства, мы рекомендуем вам попробовать написать код самостоятельно прежде чем вы прочитаете код, который предоставлен ниже.
Кроме того, существует множество вариантов исполнения кода, поэтому ваш код может отличаться от данного и это совершенно нормально. Вы можете получить справку из справочника Arduino Serial и справочника pySerial API.
Схема
Что нужно, чтобы собрать эту схему?
- Подключите 4 светодиода к контактам 9-12. Добавьте резистор 220 Ом для каждого светодиода между длинной ножкой и цифровым выводом. Более короткая ножка подключается к земле.
- Добавьте кнопку с резистором 10 кОм, подключенным к земле (понижающий резистор). Одна сторона кнопки подключена к 5V, другая к цифровому выводу 5 для чтения.
- Не забудьте сделать общую землю между всеми компонентами: платой Arduino, 4 светодиодами и кнопкой. Не добавляйте источник питания, если вы неправильно подключили заземление.
- Подключите Arduino и Raspberry Pi с помощью кабеля USB для последовательной связи (кабель USB уже соединяет землю двух плат).
Код Arduino
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
#define LED_1_PIN 9 #define LED_2_PIN 10 #define LED_3_PIN 11 #define LED_4_PIN 12 #define BUTTON_PIN 5 byte lastButtonState = LOW; byte currentButtonState = LOW; unsigned long lastButtonDebounceTime = 0; unsigned long buttonDebounceDelay = 20; void powerOffAllLEDs() { digitalWrite(LED_1_PIN, LOW); digitalWrite(LED_2_PIN, LOW); digitalWrite(LED_3_PIN, LOW); digitalWrite(LED_4_PIN, LOW); } void setup() { Serial.begin(9600); pinMode(LED_1_PIN, OUTPUT); pinMode(LED_2_PIN, OUTPUT); pinMode(LED_3_PIN, OUTPUT); pinMode(LED_4_PIN, OUTPUT); pinMode(BUTTON_PIN, INPUT); powerOffAllLEDs(); } void loop() { byte readValue = digitalRead(BUTTON_PIN); if (readValue != lastButtonState) { lastButtonDebounceTime = millis(); } if (millis() - lastButtonDebounceTime > buttonDebounceDelay) { if (readValue != currentButtonState) { currentButtonState = readValue; if (currentButtonState == HIGH) { Serial.write(18); } } } lastButtonState = readValue; if (Serial.available() > 0) { int ledNumber = Serial.read() - '0'; powerOffAllLEDs(); switch (ledNumber) { case 1: digitalWrite(LED_1_PIN, HIGH); break; case 2: digitalWrite(LED_2_PIN, HIGH); break; case 3: digitalWrite(LED_3_PIN, HIGH); break; case 4: digitalWrite(LED_4_PIN, HIGH); break; default: // если неправильный пин, то ничего не делает // все светодиоды будут выключены break; } } } |
С помощью функции setup () мы задаем номера контактов для всех 4 светодиодов и кнопки.
Также убеждаемся, что все светодиоды выключены.
Затем в цикле loop () мы делаем 2 вещи: обрабатываем кнопку и управляем 4 светодиодами.
Оба действия выполняются одно за другим, но обрабатываются они очень быстро, поэтому создается впечатление, что они выполняются одновременно. Это один из примеров многозадачности программы Arduino.
Первое действие: работа с кнопкой.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
byte readValue = digitalRead(BUTTON_PIN); if (readValue != lastButtonState) { lastButtonDebounceTime = millis(); } if (millis() - lastButtonDebounceTime > buttonDebounceDelay) { if (readValue != currentButtonState) { currentButtonState = readValue; if (currentButtonState == HIGH) { Serial.write(18); } } } lastButtonState = readValue; |
Нам нужно заблокировать кнопку, чтобы проигнорировать дребезг контактов.
Когда мы узнаем, что кнопка нажата, мы можем отправить некоторые данные на Raspberry Pi через последовательный интерфейс.
Здесь использована функция Serial.write (): она отправляет байт или серию байтов. Она отличается от Serial.print (), благодаря чему вывод будет приятно видеть на мониторе последовательного порта. Поскольку мы взаимодействуем с другой машиной, а не с человеком, проблем с этим нет.
Здесь мы отправляем число 18. Это просто случайное число, которое мы будем ассоциировать с состоянием «кнопка была нажата», поэтому, когда Raspberry Pi получит номер, он проверит, равно ли оно 18.
Вы можете отправлять различные команды или сообщения через последовательный интерфейс, используя разные числа.
Примечание: в общем случае вы также можете использовать прерывания Arduino, чтобы узнать, когда была нажата кнопка. Если вы это делаете, не используйте библиотеку Serial в прерывании. Если вам необходимо использовать прерывания, установите флаг внутри прерывания используя переменную типа boolean) и используйте Serial внутри вашей функции loop ().
И второе действие: управление 4 светодиодами.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
if (Serial.available() > 0) { int ledNumber = Serial.read() - '0'; powerOffAllLEDs(); switch (ledNumber) { case 1: digitalWrite(LED_1_PIN, HIGH); break; case 2: digitalWrite(LED_2_PIN, HIGH); break; case 3: digitalWrite(LED_3_PIN, HIGH); break; case 4: digitalWrite(LED_4_PIN, HIGH); break; default: // если неправильный пин, то ничего не делает // все светодиоды будут выключены break; } } |
Сначала мы проверяем, получил ли Arduino данные от Raspberry Pi по последовательному интерфейсу.
Если да, мы читаем следующий байт с помощью Serial.read (). Здесь вы можете заметить небольшой трюк, состоящий в вычитании символа «0», что позволяет преобразовать символ в число, которое он собой представляет.
После этого все очень просто. Мы выключаем все светодиоды, а затем включаем только светодиод, связанный с номером: 1, 2, 3 или 4. В случае отправки неправильного значения ни один светодиод не будет включен.
Код Python для Raspberry Pi
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#!/usr/bin/env python3 import serial import random if __name__ == '__main__': ser = serial.Serial('/dev/ttyACM0', 9600, timeout=1) ser.flush() while True: number = ser.read() if number != b'': if int.from_bytes(number, byteorder='big') == 18: led_number = random.randint(1,4) print("Button has been pressed.") print("Sending number " + str(led_number) + " to Arduino.") ser.write(str(led_number).encode('utf-8')) |
Сначала мы добавляем одну строку импорта: библиотеку Random.
В бесконечном цикле («while True») мы сначала читаем один байт из Serial. Тайм-аут установлен на 1 секунду. Если через секунду ничего не получено, функция read () вернет b».
Поэтому мы проверяем, было ли то, что мы получили, просто пустым (b”) или что-то ещё. В последнем случае мы преобразуем полученные данные в целое число, чтобы их можно было использовать в коде. Для этого мы используем функцию int.from_bytes (), которая преобразует b’0x12′ (шестнадцатеричное представление 18 – 0x12) в 18.
Как видите, мы проверяем, что число 18, чтобы продолжить действие. Если нужно обрабатывать разные команды, рекомендуется использовать разные номера для каждой команды.
Мы выбираем случайное число от 1 до 4, чтобы определить, какой светодиод включить. Затем мы отправляем его с помощью функции pySerial write (). Чтобы отправить целое число через Serial, мы сначала преобразуем его в строку с помощью str (), а затем кодируем с помощью encode («utf-8»).
Тестирование приложения
Теперь вы можете подключить Arduino к Raspberry Pi с помощью USB-кабеля. Затем Raspberry Pi будет подавать питание как на Arduino, так и на 4 светодиода.
Если у вас есть много устройств, подключенных к вашему Arduino, вы можете добавить внешний источник питания к разъему источника питания Arduino. Например, если вы хотите использовать шаговый двигатель, Raspberry Pi однозначно не хватит тока для себя, Arduino и двигателя. В данном случае с 4 светодиодами все будет работать.
Запустите свой скрипт Python и нажмите кнопку. Вы увидите лог, и один из светодиодов на Arduino будет включен.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
$ chmod +x arduino_raspberry_pi_leds_button.py $ ./arduino_raspberry_pi_leds_button.py Button has been pressed. Sending number 3 to Arduino. Button has been pressed. Sending number 2 to Arduino. Button has been pressed. Sending number 4 to Arduino. Button has been pressed. Sending number 1 to Arduino. Button has been pressed. Sending number 3 to Arduino. Button has been pressed. Sending number 3 to Arduino. |
Каждый раз, когда вы нажимаете кнопку:
- Arduino обнаруживает нажатие и отправляет число 18 на Raspberry Pi.
- Raspberry Pi получает данные из последовательного порта и проверяет, равно ли число 18. Если да, то выбирается случайное число (от 1 до 4) на Raspberry Pi и отправляется на Arduino.
- Arduino получает этот номер и включает соответствующий светодиод.
Примечание: чтобы сделать это приложение быстрее и с меньшим количеством кода, вы также можете выбрать использование протокола Firmata, например, библиотеки pyFirmata на Raspberry и библиотеки StandardFirmata на Arduino.
Вывод
В этом руководстве вы узнали, как обмениваться данными между Raspberry Pi и платой Arduino через последовательный интерфейс.
В жизни это вам пригодится? Ответ – да, и довольно часто.
Raspberry Pi отлично подходит для того, чтобы использовать большую электрическую мощность, встроенную в ваше приложение. Вы можете запускать законченное программное обеспечение на многих языках программирования, веб-серверах, приложениях для робототехники и т.д. Raspberry Pi, безусловно, имеет несколько GPIO, которые вы можете использовать, но они не так хороши, как Arduino. Кроме того, у вас больше шансов сжечь свой Pi, если вы сделаете что-то не так с оборудованием.
Arduino больше подходит для непосредственного управления аппаратными датчиками и исполнительными механизмами: IMU, серводвигателями, шаговыми двигателями, всем, что требует большей мощности и т.д.
В целом, две платы могут отлично работать вместе: Raspberry Pi в качестве «мозга» приложения, Arduino в качестве «мускулов» и последовательная связь, для их взаимодействия.
8 комментариев. Оставить новый
Raspberry PI Zero + Arduino UNO по UART: Установил библиотеку pySerial, залил на Arduino код. На Raspberry Pi устройство определилось как /dev/ttyUSB0. При запуске проверочного кода receive_serial_data_from_arduino.py на Raspberry выходят ошибки:
Traceback (most recent call last):
File “/usr/lib/python3.7/ast.py”, line 35, in parse
return compile(source, filename, mode, PyCF_ONLY_AST)
File “/home/pi/test_arduino.py”, line 4
ser = serial.Serial(‘/dev/ttyUSB0’, 9600, timeout=1)
^
IndentationError: expected an indented block
В чем может быть проблема?
В Python очень важно соблюдение отступов – они задают границы блоков, как фигурные скобки в Си. У вас как раз связанная с этим ошибка (indentation)
первый тест
#!/usr/bin/env python3
import serial
if __name__ == ‘__main__’:
ser = serial.Serial(‘/dev/ttyS1’, 9600, timeout=1)
ser.flush()
while True:
if ser.in_waiting > 0:
line = ser.readline().decode(‘utf-8’).rstrip()
print(line)
второй тест
#!/usr/bin/env python3
import serial
import time
if __name__ == ‘__main__’:
ser = serial.Serial(‘/dev/ttyS1’, 9600, timeout=1)
ser.flush()
while True:
ser.write(b”Hello from Raspberry Pi!\n”)
line = ser.readline().decode(‘utf-8’).rstrip()
print(line)
time.sleep(1)
Хотел выложить с правильными отступами, но невозможно, пробелы удаляются из комментариев
Можно ли к usb порту raspberry подключить usb/ttl конвертер типа ft232rl для использования Arduino pro mini?
Здравствуйте! Да, вы можете использовать FT232RL для обеспечения связи между Raspberry Pi и Arduino Pro Mini через последовательный порт (UART).
Отличная статья. Читал ее для того, чтобы решить задачу получения ШИМ сигнала с фоторезистора и использовать его в HomeAssistant. Благодаря этой статье сигнал ШИМ на RaspberryPi получил от Arduino, а вот как его прокинуть в HomeAssistant, чтобы в приложении смотреть уровень освещенности?
Здравствуйте, чтобы отобразить данные датчика с UART порта на Rusberry Pi, вам нужно добавить соответствующий сенсор в HomeAssistant (в файл Configuration.yaml).
sensor:
- platform: serial
serial_port: /dev/ttyACM0
, где /dev/ttyACM0 – USB порт, к которому подключена Arduino.