# Custom arduino controller in blender

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:
wait(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

b'493\r\n'
b'493\r\n'
b'493\r\n'

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() {
Serial.begin(9600);
}

void loop() {
}

574
576
578

• look this, maybe is what you need. https://blender.stackexchange.com/questions/80971/blender-game-controller-using-arduino-not-working-properly – Strapicarus Sep 16 '17 at 6:47
• That should solve the looping problem, but what about the outputs not matching? – CalculatedRisk Sep 16 '17 at 6:54
• Did you try it already and check if that the outputs match? – Strapicarus Sep 16 '17 at 6:56
• 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. – CalculatedRisk Sep 16 '17 at 7:39

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

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

return {'FINISHED'}

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

return {'RUNNING_MODAL'}

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

def _finish(self):
context.window_manager.event_timer_remove(self.timer)


• 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. – dr. Sybren Sep 17 '17 at 8:21
• I would suggest sprinkling print() statements through the code, to see what gets executed and what doesn't. – dr. Sybren Sep 17 '17 at 9:02