[Tutor] Serial communication problem

Alan Gauld alan.gauld at yahoo.co.uk
Tue Dec 12 13:46:31 EST 2023


On 07/12/2023 21:27, Phil wrote:
> Thank you Alan, Cameron and Rauf for your replies.
> 
> I know that the "1" and "0" are received by the pico because the LED 
> turns on and off.
> 
> I know that the "ok" ready signal is sent by the pico because the python 
> code prints "ok".
> 
> The pico seems to be ignoring the "s" sent by the python code, I'm not 
> certain of that. Debugging the running  pico code is difficult, I'm 
> relying on print statements.
> 
> The delays are sprinkled among the code just to be sure that the serial 
> transmissions aren't being overwhelmed. The delays haven't helped.
> 
> Here is the latest python code:
> 
> # synchronised write and read to and from the pico
> 
> import time
> import serial
> 
> with serial.Serial("/dev/ttyACM0", 9600) as ser:
>      while True:
>          for char in (b"1", b"0"):
>              ser.write(char)
>              time.sleep(1)
> 
> 
>              # Wait for acknowledgment
>              while True:
>                  print("in the loop")
> 
>                  ready = ser.readline().decode().strip("\r\n")
>                  print(ready)
> 
>                  if ready == "ok":
>                      print(f"after if: {ready}")
> 
>                      time.sleep(1)
>                      #ser.flush()
>                      #ser.reset_input_buffer()
>                      #ser.reset_output_buffer()
>                      break
> 
>              ser.write(b"s")
>              print("outside the loop")
>              time.sleep(2)
> 
>              data = ser.readline().decode().strip("\r\n")
>              print(f"Received: {data}")
> 
>              time.sleep(1)
>              print()
>              print()
> 
> And here is the pico code:
> 
> import uselect
> import sys
> import machine
> import utime
> 
> 
> class LEDController:
>      def __init__(self):
>          self.led = machine.Pin('LED', machine.Pin.OUT)
>          self.led_status = 'led off'
> 
>      def set_led_status(self, new_ch):
>          if new_ch == '1':
>              self.led.value(1)
>              self.led_status = 'led on'
>              #print(self.led_status)
>          elif new_ch == '0':
>              self.led.value(0)
>              self.led_status = 'led off'
> 
>      def get_led_status(self):
>          return self.led_status
>          #return "X"
> 
>      def read_char(self):
>          poll_obj = uselect.poll()
>          poll_obj.register(sys.stdin,1)
> 
>          if poll_obj.poll(0):
>              #read one character
>              ch = sys.stdin.read(1)
>          else:
>              ch = None
>          return ch
> 
>      def send_acknowledgement(self):
>          print('ok')
> 
> controller = LEDController()
> 
> while True:
>      new_ch = controller.read_char()
>      print(new_ch)
> 
>      if new_ch is not None:
>          controller.set_led_status(new_ch)
>          controller.send_acknowledgement()
> 
>          # After sending acknowledgement, get LED status
>          status_request = controller.read_char()
>          #utime.sleep(1)
>          #print(status_request)
> 
>          #status_request = 's'
>          if status_request == 's':
>              led_status = controller.get_led_status()
>              print(led_status)
>              #print("Z")
> 
> utime.sleep(.5)
> 
> I just ran this project and I see the LED is not blinking, so I've 
> stuffed something up. I've got a medical appointment so I've go to scoot.
> 
> I'm sorry to be such a pest.
> 


No easy answer here but a suggestion based on the apparent
fact that you have no way to generate debug output other
than turning the LED on/off....

Try writing a program to send the 's' to the pico and make it
flash the LED continuously. Then send another letter to turn
it off again.

See if you can get that to work. That way you will have a
positive indication that sending a Python bytestring object
to the pico can be done sucessfully. From the code above
I don't see any proof that the pico successfully received
and recognised the 's' bytestring. We know it can receive
numbers but not bytes/strings.

PS. It may be that you only need to convert the received
char to a bytes object in the pico code?


I also don't much like the fact that you do two reads inside
the while True loop. It might be better to see if you can
reduce that to a single read per iteration. Particularly
since, if the 's' did wind up being read as new_char
instead of status_request you'd have no way of knowing...

That might require a dispatch table, something
like(pseudo code):

def led_on():...
def led_off():...
def send_status():...
def read():...

dispatch = {1: led_on,
            0: led_off,
            's': send_status
            }

while True:
  ch = read()
  if ch in dispatch.keys():
     dispatch[ch]()
  else: ...  # what happens on error?



-- 
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.amazon.com/author/alan_gauld
Follow my photo-blog on Flickr at:
http://www.flickr.com/photos/alangauldphotos





More information about the Tutor mailing list