0
$\begingroup$

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.

$\endgroup$
  • $\begingroup$ related: blender.stackexchange.com/questions/56453/… $\endgroup$ – lemon Mar 15 '17 at 18:45
  • $\begingroup$ Thank you for your answer. Even though I've read that thread several times before, reading it again made me discover the solution. Adding while self.ser.in_waiting !=0: in front of the try, solved the issue for me. Using if instead of while however doesn't work. Can someone maybe explain why? And this also doesn't work if I want to use multiple serial connections, because the while blocks the one connection as long as there is data available and never lets the second connection transfer its data. Would it be possible to do this with threads? $\endgroup$ – Thyra Mar 25 '17 at 17:40
  • $\begingroup$ Just reading your last comment, it is difficult to visualize what is your code with several serial inputs. Could you add this code to your question or in a link in the comments? Also, by the way, what is the need to have a timer here? $\endgroup$ – lemon Mar 25 '17 at 17:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.