Extremely low FPS with Pyserial

I wrote a Blender script that rotates a monkey head based on this serial output. I’m using have a cheap Arduino Nano with a Gyro module. It outputs Yaw, Pitch and Roll in text via serial interface. I capture and parse that text to extract values and use them to control the head. Everything works but I’m getting just 2 FPS with nothing other in the scene then Suzanne.

import bge
import sys
sys.path.append("/usr/local/lib/python3.7/dist-packages/") 
import serial



from bge import logic
from bge import events
controller = logic.getCurrentController()
head = controller.owner


# HMD Arduino with gyro + magnetometer module 
gyro_tty = "/dev/ttyUSB0" 
gyro_baud = 115200

gyroInputScale = 5000 #Adjust this value if head rotation is too slow or fast

#below funcion is used for splicing strings. 
#Pasted from: http://www.dotnetperls.com/between-before-after-python
def between(value, a, b):
    # Find and validate before-part.
    pos_a = value.find(a)
    if pos_a == -1: return ""
    # Find and validate after part.
    pos_b = value.rfind(b)
    if pos_b == -1: return ""
    # Return middle part.
    adjusted_pos_a = pos_a + len(a)
    if adjusted_pos_a >= pos_b: return ""
    return value[adjusted_pos_a:pos_b]


def main():
    flopIterator = 0
    
    global oldYaw
    global newYaw
    global relativeYaw
    
    cont = bge.logic.getCurrentController()
    ser = serial.Serial(gyro_tty, gyro_baud)

    #The format of the GYRO output is "GY0.75GP-4.48GR8.29GEND" for every new line where: GY - Yaw, GP - Pitch, GR - Roll
 
    #Load line into a string variable
    data = str(ser.readline()) #stores:  b'GY-0.05GP-4.15GR61.50GEND

    
    if data.find("GEND") == -1: #Check data from serial port makes sense before running with it
        print("No gyro data found in serial output. Not connected? Wrong tty? Wrong baud rate?")
    else:
        # Split string and assign values to vairables

        Yaw = float(between(data, "GY", "GP")) / gyroInputScale 
        Pitch = float(between(data, "GP", "GR")) / gyroInputScale 
        Roll = float(between(data, "GR", "GEND"))  / gyroInputScale 
           
        
        print("Yaw: ", Yaw, "Pitch: ", Pitch, "Roll: ", Roll)
        
        #                   x      y     z
        head.applyRotation((Pitch, Yaw, -Roll),1) #1 for local, 0 for global coord 
        
        
main()

I’m a GNU/Linux user with a GTX970. CUDA is installed and in use. My other games run in at least 30 fps.

Am I missing something?

You’re creating one serial instance peer frame and reading the date in non asynchronously mode, there you have it.

You should create the serial instance outside your main loop and in order to read asynchronously you can either use threads or check if there is an asynchronous mode on the serial library.

Thanks for pointing me in the right direction.

I solved the problem by implementing threading and using ‘pickle’ to communicate with the thread.