我正在尝试在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 中运行脚本。
最简单的解决方案
串行通信是纯双向的。给定串行端口上不能有超过 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路串行代码。同样,这个教程将引导您在后台线程中完成此操作。
您可以使用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()
'''