pyControl / code

pyControl GUI and framework code
https://pycontrol.readthedocs.io
GNU General Public License v3.0
23 stars 20 forks source link

Enable larger serial messages #98

Closed alustig3 closed 1 year ago

alustig3 commented 1 year ago

Previously if you were to send large messages to the pyboard, it would error out. For example if you run the following task that has a dictionary with many characters as one of its variables.

# A simple state machine which flashes the blue LED on the pyboard on and off.
# Does not require any hardware except micropython board.

from pyControl.utility import *
from devices import *

# Define hardware (normally done in seperate hardware definition file).

blue_LED = Digital_output("B4")

# States and events.

states = [
    "LED_on",
    "LED_off",
]

events = []

v.big_var = {"valA":(1,2,34,34534532,34,2,335234,235,89),"valB":"this is some long text making the variable longer"}

initial_state = "LED_off"

# State behaviour functions

def LED_on(event):
    if event == "entry":
        timed_goto_state("LED_off", 0.5 * second)
        blue_LED.on()
    elif event == "exit":
        blue_LED.off()

def LED_off(event):
    if event == "entry":
        timed_goto_state("LED_on", 0.5 * second)

# Run end behaviour

def run_end():  # Turn off hardware at end of run.
    blue_LED.off()

If you run the above task and press the set button in the controls dialog set the big_var variable, you will git a TypeError from the frameork:

Traceback (most recent call last):||  File "<stdin>", line 1, in <module>||  File "pyControl/framework.py", line 174, in run||  File "pyControl/framework.py", line 104, in receive_data||TypeError: object with buffer protocol required|

What happens is that the framework reads the first couple of bytes of the serial message, including the data_len, then immediately tries to read the data_len amount of bytes. The problem for longer messages is that there hasn't been enough time for the serial buffer to receive all of the bytes, so the framework throws an error trying to read bytes that are not there.

This commit fixes the problem and allows large data to be passed to the pyboard.

@ThomasAkam, there may be a better way to implement this. Let me know what you think.

ThomasAkam commented 1 year ago

Thanks for spotting this issue. A simple fix is to use usb_serial.recv() rather than usb_serial.read() as recv waits till the specified number of bytes have been read. I've made this change in a commit I just pushed to the dev branch.