I want to turn on an LED for a while when my Raspberry Pi Pico receives some data from USB. Here is the code I'm using for the Raspberry Pi Pico:
import select
import sys
import machine
poll_obj = select.poll()
poll_obj.register(sys.stdin, select.POLLIN)
counter = 0
pin = machine.Pin(25, machine.Pin.OUT)
pin.value(0)
while True:
poll_results = poll_obj.poll(1)
if poll_results:
# Read the data from stdin (read data coming from PC)
data = sys.stdin.read().strip()
pin.value(1)
# Write the data to the input file
print("receivedL " + str(data))
else:
counter = counter + 1
if(counter >= 1000):
pin.value(0)
counter = 0
print("test")
pc code:
import serial
s = serial.Serial(port="COM3", parity=serial.PARITY_EVEN, timeout=1)
s.flush()
data = s.read()
while True:
print(data)
data = s.read()
s.write("1".encode())
s.flush()
I run this setup as follows:
Plug in the Raspberry Pi Pico and run the code (not using Thonny or another editor). Verify the code is running by connecting to the USB port with PuTTY. Disconnect from PuTTY and run my code on the PC. The PC usually shows one output from the Raspberry Pi Pico, then nothing more. Also, the LED does not blink. I'm not 100% sure if the issue is with the write function on my PC, but since the read seems to work fine, I'm suspecting something else might be wrong.
Aslo, when i'm not using putty to verify connection, problem still happening.
Can anyone help me figure out what might be going wrong?
This is happening because in the line data = sys.stdin.read().strip()
you are not supplying a parameter for the number of characters to wait for (so it waits for the filestream to end, as would happen if the file was closed). In addition your pyserial code is sending an endless stream of characters which, if the Pico code was working as intended, would mean that the LED would stay on.
So change the Pico line to data = sys.stdin.read(1).strip()
so that you are just waiting for one byte to arrive before you turn on the LED.
Ideally also modify the pyserial code so that it just sends a byte every couple of seconds for the purposes of the test. I have done this here, and also used s.readline()
to retrieve the print statements sent by the Pico through the serial port, and display them as whole words rather than each character on a separate line:
import serial
import time
s = serial.Serial(port="COM3", parity=serial.PARITY_EVEN, timeout=1)
s.flush()
while True:
data = s.readline()
print(data)
s.write("1".encode())
print("write")
s.flush()
time.sleep(2)
Here is a part of the output from the pyserial program:
b'test\r\n'
write
b'received 1\r\n'
write
b'test\r\n'
One final point: It is very useful to know when the Pico has rebooted correctly and is ready to receive serial comms from the PC. To help with this, put the following just before the start of the while loop on the Pico. This gives a single flash after you reboot the Pico, telling you that it is ready to receive.
pin.value(1)
utime.sleep(.5)
pin.value(0)
Simpler version of the Pico code
As you are not having any luck with the revised Pico code, try this. It is something I used a while ago. It causes the LED to flash each time it receives a byte.
"""
Flash LED when anything received at serial port
"""
import select
import sys
from machine import Pin
import utime
# gpio_no = 'LED' # For Pico W
gpio_no = 25 # For non Pico W
led = Pin(gpio_no, Pin.OUT)
# setup poll to read USB port
poll_object = select.poll()
poll_object.register(sys.stdin,1)
led.value(0)
led.toggle()
utime.sleep(.2)
led.toggle()
print("Started looking")
while True:
# check usb input
if poll_object.poll(0):
#read as character
ch = sys.stdin.read(1)
print (ch,"hello from the pico")
led.value(1)
utime.sleep(.2)
led.value(0)
utime.sleep(.2)
Try running this with the pyserial code above. For me it gives:
b''
write
b'1 hello from the pico\r\n'
write
b'1 hello from the pico\r\n'
write
etc.