python serial doesn't work properly arduino blender

I’m trying to scale some bones and my future project I want to scale my bones in real time with my information provided by a flex sensor. My problem is that when I try next code, when it’s time to receive data from serial, my Blender 2.7 goes to Not Responding mode and it takes a few seconds to rececive data, then it changes my bone scale, and again Not Responding. I don’t know what’s wrong. The code is just something I try. If I remove the part with “ser = serial.Serial…” everything works fine. Also if I try just “ser = serial…” in another script I can receive informations from Arduino.


This is my arduino and blender code. Please help asap.

Attachments



The python script has to execute within a single frame. So you’ll have to set the serial module to be non-blocking or run it in a thread.

Another unnecessary encrypted code snippet. Why do people think that translating good understandable words into one or two letter ambiguous abbreviation is a sign of professionalism? Especially when there is absolutely no limitation to do so.

Please is something means a scale, call it scale and not s. Your code will not run faster with shorter names. It just gets harder to understand.

Sleeping
I suggest you remove “time.sleep” completely. Do not even try it.

Closing connections
I can’t tell about Serial() as I never used it. So I can only assume what it does.

Obviously it opens a sort of communication channel. This means you need to close it as you do with close(). Keep in mind, you always need to close an open connection. You need a 1:1 with opening:


connection = serial.Serial(...)
...
connection.close()

Never ever skip close. It should not belong into an if, or else if the opening does not follow the same condition.

Timing
It looks like you are not aware, that your code runs once per frame.

So you open, read and close the connection in each single frame.
Typically you open it once, read it at every frame and close it when you do not need it anymore (before game ends).

Due to the different timing you better perform that in different Python controllers.


...

#--- bge callable
def open():
    connection = serial.Serial(...)
    storeConnection(connection)

def close():
    connection = retrieveConnection()
    connection.close()
    storeConnection(None) # to ensure nobody can use it anymore

def processInput():
    connection = retrieveConnection()
    data = connection.read(....)
    processData(data)

Example of connection handling:


import bge

#--- bge internal business
INTERNAL_PROPERTY_CONNECTION = "internal.connection"

def storeConnection(connection):
     getOwner()[INTERNAL_PROPERTY_CONNECTION] = connection

def retrieveConnection():
    return getOwner()[INTERNAL_PROPERTY_CONNECTION]

#--- internal utilites
def getOwner():
    return bge.logic.getCurrentController().owner    

You can store the connection where ever you want (object, scene, module …).

Protocol
Your code opens the connection, reads exactly one byte and forgets to close the connection (see “Closing connections”).

You convert the byte and do not do anything with it. I suggest you print it to console, so you can confirm the communication works.

Typically you do not just read one byte. You need to define a protocol that enables you to apply a syntax on the bytes you receive. With the protocol you can interpret what the data mean. This enables you to apply the according changes to your business.

Naive example:


def processData(data):
   type = data[0]
   if type=="s":
      processScale(data)
   elif type == "p":
      processProcessPostion(data)
   ...

def processScale(data):
    value = data[1:5]
    scale = float(value)
    ...

def processPosition(data):
    axis = data[1]
    value = data[2:6]
    axisValue = float(axis)


This is not meant as working example. It should demonstrate an idea.

I hope it helps