Raspberry Pi 和 Raspberry Pico 之间的串行连接
Raspberry Pi 和 Raspberry Pico 之间的串行连接
本文作者:Sebastian 来源于medium.com

2021年初,我开始了我的机器人项目。 它的子项目之一是熟悉 Arduino 和 C 编程。 Arduino 在传感器和执行器库方面无可挑剔,在“连接并工作”体验方面无与伦比。 然而,在年中,我决定改用 Raspberry Pico 和 MicroPython 来实现我的机器人。 这种选择的动机是为机器人中间件、SBD 和微控制器使用一种且仅一种编程语言,以及利用 RealSense D435 相机提供的强大的 Python 库进行图像识别。
为此,我需要重新学习运行 MicroPython 的 Raspberry Pico 和运行 Python 的 Raspberry Pi 之间的串行连接的要点。 本文介绍了建立成功连接的基础知识。
这篇文章最初出现在我的博客 admantium.com
硬件连接选项
要从 Pi 连接到 Pico,有三个选项:
- 直接 USB 转 USB
- 直接 Tx/Rx 引脚
- USB-TTL 到 Rx/Rx
由于 Raspberry Pico 还比较年轻,MicroPython 堆栈的技术成熟度会影响这些连接中的哪些可以使用。
当您使用选项 A 或 C 时,您可以跳转到示例。 如果要使用选项 B,则需要按照下一节中描述的步骤启用 Tx/Rx 引脚。
如何在 Raspberry Pi 上启用 Tx/Rx 引脚
在这篇 很棒的文章 ,您需要执行以下操作:
- 通过 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'
有趣的是,树莓派仍会通过 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 连接的端口。
使用这个样板代码:
1 # sender.py 2 import time 3 import serial 4 ser = serial.Serial( 5 port='/dev/ttyS0', # Change this according to connection methods, e.g. /dev/ttyUSB0 6 baudrate = 115200, 7 parity=serial.PARITY_NONE, 8 stopbits=serial.STOPBITS_ONE, 9 bytesize=serial.EIGHTBITS, 10 timeout=1 11 ) 12 13 msg = "" 14 i = 0 15 16 while True: 17 i+=1 18 print("Counter {} - Hello from Raspberry Pi".format(i)) 19 ser.write('hello'.encode('utf-8')) 20 time.sleep(2)
解释:
- 第 3 行:导入
serial
启用串行连接的库 - 第 4 行:创建一个与默认 Pico UART 配置完全相同的串行对象(波特率 115200,字节大小 8 位等)。 这
port
部分需要根据连接方式定制 - 详情见下文 - 第 19 行:要发送数据,您首先
encode
字符串数据,然后write
它到串行对象
现在让我们检查接收方。
接收数据:USB 转 USB 连接
在撰写本文时,在 Pico 上运行的最新版本的 MicroPython 是 MicroPython v1.16 on 2021-06-18
. 此版本没有用于通过 USB 进行串行通信的内置库。
然而,在这个 Pico 论坛线程 中,用户提供了一个纯 MicroPython 实现,它在第二个 Pico CPU 内核上生成一个线程,该线程主动侦听通过 USB 传入的字节。 我在我早期的机器人原型中尝试了这个代码,并且可以使用它通过 Pico 上的 USB 接收命令我的机器人移动的消息。
这是我的工作示例:
# 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 以启用这些引脚。 完成后,使用以下代码:
1 # receiver.py / Tx/Rx => Tx/Rx 2 import os 3 import machine 4 from time import sleep 5 6 uart = machine.UART(0, 115200) 7 print(uart) 8 9 b = None 10 msg = "" 11 12 while True: 13 sleep(1) 14 if uart.any(): 15 b = uart.readline() 16 print(type(b)) 17 print(b) 18 try: 19 msg = b.decode('utf-8') 20 print(type(msg)) 21 print(">> " + msg) 22 except: 23 pass
在这个程序中:
- 第 6 行:创建一个
uart
实例通过访问 Pico 的内部machine.UART
实例。 这与配置发件人代码的值相同。 请注意, MicroPython 文档 还允许您创建不同配置的 UART 实例,例如使用较慢的波特率。 - 第 14 行:条件
uart.any()
当 UART 连接上至少有一个字符可用时,返回一个正整数。 - 第 13 行:要读取数据,请使用
read(i)
在哪里i
是字符数,或readline()
读取所有字符,直到到达换行符。 使用单个字符更高效、更快,如果您需要交换复杂的信息,使用完整的行更可靠。 - 第 18 行:A
try - except
块开始于... - 第 20 行:……接收到的消息被解码然后打印。 如果有任何错误,程序将继续运行而不引发错误。
接收数据:USB-TTL 到 Tx/Rx 引脚连接
首先,你需要一个 USB-TTL 适配器,它至少有两种不同的芯片组:FT232RL 和 CH340g。

将适配器插入 Picos USB 端口,然后使用 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
并运行 receiver.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
结论
本文介绍了使用 (Micro)Python 将 Raspberry Pi 与 Raspberry Pico 连接的三个选项。 第一个选项是 USB 转 USB,需要外部 MicroPython 库来接收数据。 第二种选择是直接从两台机器连接 Rx/Tx。 在对 Pi 进行一些配置后,它可以稳定运行。 第三种选择是使用 USB-FTL 转 Tx/Rx。 无需配置,开箱即用。
考虑到源代码,在 Pi 上是 pyserial
库:打开一个与 Pico 具有相同配置(波特率、停止位)的串行连接对象,并发送编码数据 serial.write()
. 在 Pico 上,它的建筑 machine.UART
访问内置 UART 或可配置的对象。 利用 uart.readline()
接收字节,然后 decode()
数据。