我正在尝试通过 USB(COM 端口)在 Raspberry Pi Pico 和 Windows PC(Python)之间实现双向通信。 关键是,我无法将任何内容从我的 PC 发送到树莓派,也无法返回。 不会影响面包板上的 LED,也不会在终端中打印消息。
这是PC端的代码:
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 中使用序列调试器?
致以诚挚的问候!
我已经尝试了串行或标准库库中的许多方法,但没有任何结果。 同样重要的是 - 对于脚本的 PC 端我使用 PyCharm,对于 Raspberry 端 - Thonny。 刷新 Raspberry Pico 后,我断开串行并开始在 PyCharm 中运行脚本,使用不同的解释器。
最简单的解决方案
串行通信是纯粹双向的。给定的串行端口上不能有超过 2 个设备。在 Thonny(和 micropython)中,这是专门用于加载代码的。当程序运行时,您不能直接从您的计算机写入串口。但是,当程序未在 pico 上运行时,您可以访问 REPL。您可以在 here 阅读更多相关信息。这允许您直接在 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 端口用作串行连接。在 raspberry pi 表单上有一个 thread,其中显示了功能性 2-way 串行代码。同样,这个 tutorial 将引导您在后台线程中完成它。
可以使用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
#comming 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 # circuolar incomming USB serial data buffer (pre fill)
bufferEcho = True # USB serial port echo incooming 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
# incomming 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()
'''