I have a very basic setup with a potentiometer hooked up to my Arduino analog 0 pin with it spamming output to the serial monitor. I am attempting to get the output in blender to match the arduino output by using the following code:

from time import sleep as wait
import serial

ser = serial.Serial("COM4",9600)
    while 1==1:

This code freezes the main window and also outputs whatever the initial value for the potentiometer was despite rotating it so the output gets stuck outputting something like


I realise that these issues are mainly due to the fact that my loop is endless but I'm not really sure how to create a coroutine in python and all the tutorials I've tried either don't work or require extra modules. I'd also like to know why it is outputting differently from the arduino serial monitor and how I can solve that.

This is the arduino code/output

void setup() {

void loop() {

  • $\begingroup$ look this, maybe is what you need. https://blender.stackexchange.com/questions/80971/blender-game-controller-using-arduino-not-working-properly $\endgroup$ Commented Sep 16, 2017 at 6:47
  • $\begingroup$ That should solve the looping problem, but what about the outputs not matching? $\endgroup$ Commented Sep 16, 2017 at 6:54
  • $\begingroup$ Did you try it already and check if that the outputs match? $\endgroup$ Commented Sep 16, 2017 at 6:56
  • $\begingroup$ Yes. It still prints out the b'\r\n' bits which I could use string manipulation to get rid of but that's not really ideal. Also this method executes the script as a whole repeatedly right? What is the delay in that and how would I only re-execute parts of my script? It doesn't exactly seem ideal or scale-able to continuously import modules. $\endgroup$ Commented Sep 16, 2017 at 7:39

1 Answer 1


You're reading binary data from the serial port, so that is why you have a bytes string (indicated by the b'' style of quoting). To convert it to a string, use

as_bytes = ser.readline()
line = as_bytes.decode('utf-8')

To get a repeated call to a "loop" function, it's easiest to start a modal operator with a high-frequency timer.

import bpy

class SERIAL_OT_arduino_read(bpy.types.Operator):
    bl_idname = "serial.arduino_read"
    bl_label = "Read From Arduino"

    def execute(self, context):
        as_bytes = self.ser.readline()
        line = as_bytes.decode('utf-8').strip()
        print('Serial line:', line)

        return {'FINISHED'}

    def modal(self, context, event):
        if event.type == 'TIMER':
        elif event.type == 'LEFTMOUSE':  # Confirm
            return {'FINISHED'}
        elif event.type in ('RIGHTMOUSE', 'ESC'):  # Cancel
            return {'CANCELLED'}

        return {'RUNNING_MODAL'}

    def invoke(self, context, event):
        self.ser = serial.Serial("COM4", 9600)
        self.timer = context.window_manager.event_timer_add(0.01, context.window)
        return {'RUNNING_MODAL'}

    def _finish(self):


# test call

This will read the serial port approximately 100x per second. Blender can still be used while this operator is running.

I haven't tested this code, just copied parts of the documentation and mixed it with your code.

  • $\begingroup$ Calling operator "bpy.ops.object.modal_operator" error, could not be found $\endgroup$ Commented Sep 17, 2017 at 7:54
  • $\begingroup$ That was a copy-paste error. It should have been the actual operator being defined in the script, i.e. bpy.ops.serial.arduino_read. $\endgroup$
    – dr. Sybren
    Commented Sep 17, 2017 at 8:21
  • $\begingroup$ No errors now but also no additional output. Thanks for the speedy replies btw. $\endgroup$ Commented Sep 17, 2017 at 8:25
  • $\begingroup$ I would suggest sprinkling print() statements through the code, to see what gets executed and what doesn't. $\endgroup$
    – dr. Sybren
    Commented Sep 17, 2017 at 9:02

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .