Raspberry Pi Pico 与 PC 之间的串行通信

问题描述 投票:0回答:2

我正在尝试在Raspberry Pi Pico和Windows PC(Python)之间通过USB(COM端口)实现2路通信。我无法从我的 PC 发送到 Raspberry Pi Pico,也无法返回。不会影响面包板上的 LED,也不会在终端中打印消息。

电脑端代码:

import serial
import time

# open a serial connection
s = serial.Serial("COM7", 115200)

print(s)
# blink the led
while True:
    s.write(b"on\n")
    time.sleep(1)
    s.readline().strip()
    s.write(b"off\n")
    time.sleep(1)
    s.readline().strip()

Raspberry Pi Pico 上的代码:

import time
from machine import Pin
import sys

led = Pin(0, machine.Pin.OUT)
led2 = Pin(2, machine.Pin.OUT)
led2.value(0)
led.value(0)

def led_on():
    led.value(1)

def led_off():
    led.value(0)


while True:
    # read a command from the host
    v = sys.stdin.readline().strip()

    # perform the requested action
    if v.lower() == "on":
        led_on()
        print("Turned on!")
    elif v.lower() == "off":
        led_off()
        print("Turned off!")

在 Raspberry Pi Pico 上调试代码最明智的方法是什么?获取串口连接后,标准打印调试?有没有办法在 Thonny IDE 中使用序列调试器?

我尝试了串行库和 stdlib 库中的方法,但没有结果。对于 PC,我使用 PyCharm,对于 Raspberry Pi,我使用 Pico Thonny。刷新 Raspberry Pi Pico 后,我断开串行连接并使用不同的解释器在 PyCharm 中运行脚本。

python micropython usbserial raspberry-pi-pico
2个回答
0
投票

最简单的解决方案

串行通信是纯双向的。给定串行端口上不能有超过 2 个设备。在 Thonny(和 micropython)中,它专门用于加载代码。当程序运行时,您无法直接从计算机写入串行端口。但是,当程序未在 pico 上运行时,您可以访问 REPL。您可以在这里阅读更多相关信息。这允许您直接在 pico 上调用函数。所以你可以编写这样的程序:

from machine import pin

led = Pin(0, machine.Pin.OUT)
led2 = Pin(2, machine.Pin.OUT)
led2.value(0)
led.value(0)

def led_on():
    led.value(1)

def led_off():
    led.value(0)

并通过发送从 REPL 调用它

>>> led_on()

这无疑是最简单的解决方案,并且还允许您访问 microPython 中的任何函数,这可能对调试有用,因为您可以打印任何您想要的值。

更稳健的解决方案

上面的代码没有错。由于 Thonny 已经接管了串行端口,因此它无法与 Thonny 一起使用。如果您将代码上传为 .u2f 文件,或者使用单独的调试器(例如 pi 或第二个 pico 作为 picoprobe)并使用 UART 外设之一,那么您可以使用 USB 端口作为串行连接。树莓派窗体上有一个线程,其中显示了功能性的2路串行代码。同样,这个教程将引导您在后台线程中完成此操作。


-1
投票

您可以使用Pico的双核,创建一个线程来监听COM。查看此页面为您提供解决方案(https://forums.raspberrypi.com//viewtopic.php?t=302889)。上传一个 main.py 到 Pico 并释放 COM 串口(一般为 COM3 ,也可以使用 PC python 查询)。连接Pico MicroUSB,Pico中的main.py将运行。 然后就可以使用PC python操作COM发送数据了

''' main.py in Pico
#coming from https://forums.raspberrypi.com//viewtopic.php?t=302889
from sys import stdin, exit
from _thread import start_new_thread
from utime import sleep
# 
# global variables to share between both threads/processors
# 
bufferSize = 1024                 # size of circular buffer to allocate
buffer = [' '] * bufferSize       # circular incoming USB serial data buffer (pre fill)
bufferEcho = True                 # USB serial port echo incoming characters (True/False) 
bufferNextIn, bufferNextOut = 0,0 # pointers to next in/out character in circualr buffer
terminateThread = False           # tell 'bufferSTDIN' function to terminate (True/False)
#
# bufferSTDIN() function to execute in parallel on second Pico RD2040 thread/processor
#
def bufferSTDIN():
    global buffer, bufferSize, bufferEcho, bufferNextIn, terminateThread
    
    while True:                                 # endless loop
        if terminateThread:                     # if requested by main thread ...
            break                               #    ... exit loop
        buffer[bufferNextIn] = stdin.read(1)    # wait for/store next byte from USB serial
        if bufferEcho:                          # if echo is True ...
            print(buffer[bufferNextIn], end='') #    ... output byte to USB serial
        bufferNextIn += 1                       # bump pointer
        if bufferNextIn == bufferSize:          # ... and wrap, if necessary
            bufferNextIn = 0
#
# instantiate second 'background' thread on RD2040 dual processor to monitor and buffer
# incoming data from 'stdin' over USB serial port using ‘bufferSTDIN‘ function (above)
#
bufferSTDINthread = start_new_thread(bufferSTDIN, ())

#
# function to check if a byte is available in the buffer and if so, return it
#
def getByteBuffer():
    global buffer, bufferSize, bufferNextOut, bufferNextIn
    
    if bufferNextOut == bufferNextIn:           # if no unclaimed byte in buffer ...
        return ''                               #    ... return a null string
    n = bufferNextOut                           # save current pointer
    bufferNextOut += 1                          # bump pointer
    if bufferNextOut == bufferSize:             #    ... wrap, if necessary
        bufferNextOut = 0
    return (buffer[n])                          # return byte from buffer

#
# function to check if a line is available in the buffer and if so return it
# otherwise return a null string
#
# NOTE 1: a line is one or more bytes with the last byte being LF (\x0a)
#      2: a line containing only a single LF byte will also return a null string
#
def getLineBuffer():
    global buffer, bufferSize, bufferNextOut, bufferNextIn

    if bufferNextOut == bufferNextIn:           # if no unclaimed byte in buffer ...
        return ''                               #    ... RETURN a null string

    n = bufferNextOut                           # search for a LF in unclaimed bytes
    while n != bufferNextIn:
        if buffer[n] == '\x0a':                 # if a LF found ... 
            break                               #    ... exit loop ('n' pointing to LF)
        n += 1                                  # bump pointer
        if n == bufferSize:                     #    ... wrap, if necessary
            n = 0
    if (n == bufferNextIn):                     # if no LF found ...
            return ''                           #    ... RETURN a null string

    line = ''                                   # LF found in unclaimed bytes at pointer 'n'
    n += 1                                      # bump pointer past LF
    if n == bufferSize:                         #    ... wrap, if necessary
        n = 0

    while bufferNextOut != n:                   # BUILD line to RETURN until LF pointer 'n' hit
        
        if buffer[bufferNextOut] == '\x0d':     # if byte is CR
            bufferNextOut += 1                  #    bump pointer
            if bufferNextOut == bufferSize:     #    ... wrap, if necessary
                bufferNextOut = 0
            continue                            #    ignore (strip) any CR (\x0d) bytes
        
        if buffer[bufferNextOut] == '\x0a':     # if current byte is LF ...
            bufferNextOut += 1                  #    bump pointer
            if bufferNextOut == bufferSize:     #    ... wrap, if necessary
                bufferNextOut = 0
            break                               #    and exit loop, ignoring (i.e. strip) LF byte
        line = line + buffer[bufferNextOut]     # add byte to line
        bufferNextOut += 1                      # bump pointer
        if bufferNextOut == bufferSize:         #    wrap, if necessary
            bufferNextOut = 0
    return line                                 # RETURN unclaimed line of input

#
# main program begins here ...
#
# set 'inputOption' to either  one byte ‘BYTE’  OR one line ‘LINE’ at a time. Remember, ‘bufferEcho’
# determines if the background buffering function ‘bufferSTDIN’ should automatically echo each
# byte it receives from the USB serial port or not (useful when operating in line mode when the
# host computer is running a serial terminal program)
#
# start this MicroPython code running (exit Thonny with code still running) and then start a
# serial terminal program (e.g. putty, minicom or screen) on the host computer and connect
# to the Raspberry Pi Pico ...
#
#    ... start typing text and hit return.
#
#    NOTE: use Ctrl-C, Ctrl-C, Ctrl-D then Ctrl-B on in the host computer terminal program 
#           to terminate the MicroPython code running on the Pico 
#
try:
    inputOption = 'LINE'                    # get input from buffer one BYTE or LINE at a time
    while True:

        if inputOption == 'BYTE':           # NON-BLOCKING input one byte at a time
            buffCh = getByteBuffer()        # get a byte if it is available?
            if buffCh:                      # if there is...
                print (buffCh, end='')      # ...print it out to the USB serial port

        elif inputOption == 'LINE':         # NON-BLOCKING input one line at a time (ending LF)
            buffLine = getLineBuffer()      # get a line if it is available?
            if buffLine:                    # if there is...
                print (buffLine)            # ...print it out to the USB serial port

        sleep(0.1)

except KeyboardInterrupt:                   # trap Ctrl-C input
    terminateThread = True                  # signal second 'background' thread to terminate 
    exit()
'''
© www.soinside.com 2019 - 2024. All rights reserved.