Авторизоваться
Дмитрий Цирульников 29.10.2021 Опубликована

Последовательное соединение между Raspberry Pi и Raspberry Pico 

В начале 2021 года я начал свой проект роботов. Одним из его подпроектов было знакомство с Arduino и C-программированием. Arduino не имеет себе равных с точки зрения библиотек датчиков и исполнительных механизмов и не имеет себе равных по принципу «подключи и работай». Однако в середине года я принял решение перейти на использование Raspberry Pico и MicroPython для реализации моего робота. Этот выбор мотивирован использованием одного и только одного языка программирования для промежуточного программного обеспечения Robotics, SBD и микроконтроллера, а также использования мощных библиотек Python для распознавания изображений, которые предлагает камера RealSense D435.

Для начала мне нужно заново изучить основы последовательных подключений между Raspberry Pico с MicroPython и Raspberry Pi с Python. В этой статье объясняются основы успешного подключения.

Варианты подключения оборудования

Чтобы подключиться от Pi к Pico, есть три варианта:

  • Прямой USB-USB
  • Прямые контакты Tx / Rx
  • USB-TTL для Rx / Rx

Поскольку Raspberry Pico еще относительно молод, техническая зрелость стека MicroPython влияет на то, какие из этих подключений можно использовать.

Когда вы используете вариант A или C, вы можете сразу перейти к примерам. Если вы хотите использовать вариант B, вам необходимо включить контакты Tx / Rx, выполнив действия, описанные в следующем разделе.

Как включить контакты Tx / Rx на Raspberry Pi

После этой замечательной статьи вам необходимо сделать следующее:

  • Инициализировать последовательный порт через Raspi-Config
  $> sudo raspi-config

  => 3. Interface Option
  => P6. Serial Port
    =>  Would you like a login shell to be accessible over serial?
        Answer with 'No'
    =>  Would you like the serial port hardware to be enabled?
        Answer with 'Yes'
  • Отключить службу /dev/ttyS0
  $> sudo systemctl stop serial-getty@ttyS0.service
  $> sudo systemctl disable serial-getty@ttyS0.service
  • Снимаем консоль с загрузки
  $> sudo nano /boot/cmdline.txt
    => Remove or comment out a line that says 'console=serial0,115200'

Интересно, что Pi по-прежнему будет отправлять системные сообщения через контакты Tx / Rx - это может быть конкретный вариант использования, который вы искали. Вот пример вывода, когда я выключаю Pi.

>> [  OK  ] Stopped LSB: automatic crash report generation.
>> [  OK  ] Stopped User Manager for UID 1000.
>> [  OK  ] Stopped Login Service.
>> RPI 4 Model B (0xc03111)

Отправка данных из Pi в Pico

Отправка данных с Raspberry Pi на Pico - это один и тот же код во всех примерах с небольшими изменениями: порт, к которому подключен Pico.

Используйте этот шаблонный код:

# sender.py
import time
import serial

ser = serial.Serial(
  port='/dev/ttyS0', # Change this according to connection methods, e.g. /dev/ttyUSB0
  baudrate = 115200,
  parity=serial.PARITY_NONE,
  stopbits=serial.STOPBITS_ONE,
  bytesize=serial.EIGHTBITS,
  timeout=1
)

msg = ""
i = 0

while True:
    i+=1
    print("Counter {} - Hello from Raspberry Pi".format(i))
    ser.write('hello'.encode('utf-8'))
    time.sleep(2)

Объяснение:

  • Строка 2: Импортируйте библиотеку serial, которая обеспечивает последовательное соединение.
  • Строка 4: Создайте последовательный объект, который настроен точно так же, как конфигурация Pico UART по умолчанию (скорость передачи 115200, размер байта 8 бит и т.д.). Параметр port должн быть настроен в соответствии с методами подключения - см ниже подробного описание
  • Строка 19: Чтобы отправить данные, сначала вы должны обработать с помощью encode строковые данные, а затем отправить их с помощью write в последовательный объект.

Теперь рассмотрим приемную сторону.

Получение данных: подключение USB к USB

На момент написания этой статьи самой последней версией MicroPython, работающей на Pico, была MicroPython v1.16 on 2021-06-18. В этой версии нет встроенной библиотеки для последовательной связи через USB.

Однако в этом потоке Pico Forum пользователь предоставляет чистую реализацию MicroPython, которая порождает поток на втором ядре процессора Pico, который активно прослушивает входящие байты через USB. Я пробовал этот код в своем раннем прототипе робота и мог использовать его для получения сообщений через USB на Pico, которые приказывали моему роботу двигаться.

Вот мой рабочий пример:

# receiver.py / USB => USB
import sys
sys.path.append('/radu')

import os

from bot import Bot
from rusb import USB

from _thread import start_new_thread
from time import sleep_ms

radu = Bot('Radu MK1')
usb = USB()

input_msg = None
bufferSTDINthread = start_new_thread(usb.bufferSTDIN, ())

while True:
  input_msg = usb.getLineBuffer()
  if input_msg and 'ros_msg' in input_msg:
    obj = eval(input_msg)
    radu.notify(obj)

  sleep_ms(10)

Получение данных: соединение контактов Tx / Rx

Прямое соединение между выводами Tx / Rx означает:

  • Подключите землю: Pi PIN 6 к Pico Pin 3
  • Подключите Tx к Rx: Pi PIN 8 (GPIO 14) к Pico Pin 1 (GPIO 0)
  • Подключите Tx к Rx: Pi PIN 10 (GPIO 15) к Pico Pin 2 (GPIO 1)

Как объяснялось выше, вам также необходимо настроить Raspberry Pi для включения этих контактов. По завершении используйте следующий код:

# receiver.py / Tx/Rx => Tx/Rx
import os
import machine
from time import sleep

uart = machine.UART(0, 115200)
print(uart)

b = None
msg = ""

while True:
    sleep(1)
    if uart.any():
        b = uart.readline()
        print(type(b))
        print(b)
        try:
            msg = b.decode('utf-8')
            print(type(msg))
            print(">> " + msg)
        except:
            pass

В этой программе:

  • Строка 5: Создайте экземпляр uart, обратившись к внутреннему экземпляру Pico machine.UART. Он определяется с теми же значениями, с которыми настроен код отправителя. Обратите внимание, что документация MicroPython также позволяет вам создать инстанс UART с другой конфигурацией, например, с более медленной скоростью передачи.
  • Строка 12: условие uart.any() возвращает положительное целое число, если в соединении UART доступен хотя бы один символ.
  • Строка 13: для чтения данных используйте read(i), где i- количество символов, или readline() чтобы прочитать все символы, пока не будет достигнута новая строка. Работа с отдельными символами эффективнее и быстрее, работа с полными строками более надежна, если вам нужно обмениваться сложной информацией.
  • Строка 16: try - except начинается блок, в котором ...
  • Строка 17: ... полученное сообщение декодируется и затем печатается. Если есть какая-либо ошибка, программа продолжает работу, не вызывая ошибки.

Получение данных: соединение USB-TTL с контактом Tx / Rx

Во-первых, вам нужно приобрести адаптер USB-TTL, который поставляется как минимум с двумя разными чипсетами: FT232RL и CH340g.

Вставьте адаптер в USB-порты Picos, а затем используйте его dmesg, чтобы увидеть, как настроено это устройство.

[326612.390873] usb 1-2: new full-speed USB device number 54 using xhci_hcd
[326612.543888] usb 1-2: New USB device found, idVendor=1a86, idProduct=7523, bcdDevice= 2.64
[326612.543893] usb 1-2: New USB device strings: Mfr=0, Product=2, SerialNumber=0
[326612.543895] usb 1-2: Product: USB Serial
[326612.546221] ch341 1-2:1.0: ch341-uart converter detected
[326612.549000] usb 1-2: ch341-uart converter now attached to ttyUSB0

В последней строке говорится ttyUSB0, что код отправителя необходимо изменить следующим образом:

# sender.py / USB-TTL => Tx/Rx
# ...
ser = serial.Serial(
  port='/dev/USB0'
  # ...
)

Код для приема данных остается таким же, как и при прямом соединении Tx / Rx.

Пример вывода

Теперь давайте посмотрим на наш код в действии.

Выполнение sender.py на Raspberry Pi выводит эту информацию:

>>>
Counter 1 - Hello from Pi4
Counter 2 - Hello from Pi4
Counter 3 - Hello from Pi4
Counter 4 - Hello from Pi4

И запуск receinver.py на Raspberry Pico покажет это:

%Run -c $EDITOR_CONTENT
(sysname='rp2', nodename='rp2', release='1.16.0', version='v1.16 on 2021-06-18 (GNU 10.2.0 MinSizeRel)', machine='Raspberry Pi Pico with RP2040')
UART(0, baudrate=115200, bits=8, parity=None, stop=1, tx=0, rx=1, txbuf=256, rxbuf=256, timeout=0, timeout_char=1, invert=None)
<class 'bytes'>
b'hello\n'
<class 'str'>
>> hello

Источник

Forem logo
Коментарии
Авторизоваться что-бы оставить комментарий
Присоединяйся в тусовку
Наш сайт использует файлы cookie для вашего максимального удобства. Пользуясь сайтом, вы даете свое согласие с условиями пользования cookie