I want to apply data send by an Arduino to a blender object to rotate it. Now I use this script, which works, but blocks blender so I can not see the rotation:
obj = bpy.data.objects['cube']
obj.rotation_mode = 'QUATERNION'
ser = serial.Serial(SerialConnectionPath,57600, timeout=1)
time.sleep(2)
ser.write('x'.encode('ascii'))
while 1:
try :
x = ser.readline().decode().strip('\r\n')
print(x)
# apply rotation here....
except ValueError:
error = "Error"
ser.close()
The next way I tried is to use a timed modal operator from the templates which I only changed slightly. The one I use looks the following:
class cl(bpy.types.Operator):
"""Operator which runs its self from a timer"""
bl_idname = "object.op"
bl_label = "Modal Timer Operator"
_timer = None
ser = None
obj = None
def __init__(self):
self.ser = serial.Serial(SerialConnectionPath,57600, timeout=1)
time.sleep(2)
self.ser.write('x'.encode('ascii')) #tell the arduino to begin sending data
self.obj = bpy.data.objects['cube']
def modal(self, context, event):
if event.type in {'RIGHTMOUSE', 'ESC'}:
self.cancel(context)
self.ser.close()
return {'CANCELLED'}
if event.type == 'TIMER':
try :
x = self.ser.readline().decode().strip('\r\n')
print(x)
# apply rotation here
except ValueError:
error = "SomeError"
return {'PASS_THROUGH'}
def execute(self, context):
wm = context.window_manager
self._timer = wm.event_timer_add(0.1, context.window)
wm.modal_handler_add(self)
return {'RUNNING_MODAL'}
def cancel(self, context):
wm = context.window_manager
wm.event_timer_remove(self._timer)
return {'CANCELLED'}
def register():
bpy.utils.register_class(cl)
def unregister():
bpy.utils.unregister_class(cl)
if __name__ == "__main__":
register()
bpy.ops.object.op()
The problem is, that it works, it prints out the received values, but there is a massive delay in the data (about a few seconds). Does anyone know what could cause this? Another strange thing, is that it works maybe one out of ten times when I run the script.