3
$\begingroup$

I have a potentiometer and I want this to change the location of my cube. My script run is on the cube, connected to an "Always" actuator with True Toggle.

My problem is this line:

ser = serial.Serial('COM6',9600, timeout=1)

The script throws an error: ser is not defined

This line is read every Time, so my arduino must connect every Time. I need to perform a new connect every second, but I want float move.

So I try this, because the serial line is only executed once:

import serial
import time
import bge
import bpy

cont = bge.logic.getCurrentController()
ob = bpy.data.objects["Cube"]
scene = bge.logic.getCurrentScene().objects["Cube"]
own = cont.owner
PSerial=own['SerialVerbunden']

print (PSerial)
if (PSerial==False):
    ser = serial.Serial('COM6',9600, timeout=1)
    time.sleep(1)
    count = 0
    own['SerialVerbunden']=True




a = int(ser.readline().strip())
print (a)
count = count + 1
scene.worldPosition = [a, 0, 0]
ob.location = scene.worldPosition
ob.keyframe_insert(data_path="location", frame=count)

The script throws the error mentioned above: ser is not defined.

Yes this is true, because it is loading and at the end it forgets. The variable count have the same problem. It can't count. But how I can solve it? If I write a while loop, so I cant see my cube is moving, Blender freezes.

$\endgroup$
3
  • $\begingroup$ I suspect your if block may not be getting executed, as it doesn't look like PSerial is ever False. If you put a print statement inside the if, does it print? $\endgroup$
    – gandalf3
    Commented Sep 18, 2016 at 19:11
  • $\begingroup$ I've edited your question in an attempt to make it easier to understand. If I've misinterpreted anything, please don't hesitate to edit it yourself or roll back my edits. Thanks :) That said, are you trying re-establish the serial connection once a second? Or just once? The latter seems more likely, but I'm afraid I can't quite tell what you meant. $\endgroup$
    – gandalf3
    Commented Sep 18, 2016 at 19:25
  • $\begingroup$ this is correct, my english is only bad ^^ with the PSerial Variable i would like to solve my problem, but i get more problems(ser is not defined). If this script is re-played, then probably all are variable away. Therefore my script does not work, but I want to show with what I plan. By putting the "ser variable", pyserial connects with my Arduino. This requires 1 second. That's why I had to use time.sleep (1). but I want to bypass that and would like to see at least 25 frames per second. If I use a While Loop, then Blender unresponsive and I can not finish the script. $\endgroup$
    – Dj EKI
    Commented Sep 18, 2016 at 19:50

3 Answers 3

2
$\begingroup$

I strongly suggest you separate connecting from communication. Do not forget you should execute a closing when the connection is not needed anymore.

Basically you need this three operations in this order over multiple frames:

  • establish a connection
  • communicate (receive/send) via connection
  • close connection [which seams not to apply at serial)

I suggest to implement it that way:

import serial
import bge

INTERNAL_PROPERTY_CONNECTION = "_connection"

listener = bge.logic.getCurrentController().owner

connection = listener.get(INTERNAL_PROPERTY_CONNECTION)
if not connection:
    connection = serial.Serial('COM6',9600, timeout=0)
    listener[INTERNAL_PROPERTY_CONNECTION] = connection

# your communciation
a = int(connection.readline().strip())
cube = bge.logic.getCurrentScene().objects["Cube"]
cube.worldPosition.x = a
$\endgroup$
6
  • $\begingroup$ Your script works, but has very strong deceleration and the Cube trembles. But with Errors dj-eki.de/Dateien/StackExchange/blendergamefehler2.jpg $\endgroup$
    – Dj EKI
    Commented Sep 19, 2016 at 19:45
  • $\begingroup$ It looks like a conversion problem coming from int(..) which is something you need to solve by yourself. It is just a copy from your original code. I can't tell what serial is providing to you at that stage. $\endgroup$
    – Monster
    Commented Sep 20, 2016 at 9:16
  • $\begingroup$ I note that the data are read faster than output. I have tried several scripts in my arduino. 1. Serial.println without delay. 2. Serial.println with delay (1000). So 1 second. at 1 second of delay it writes about 10 seconds, the same number. It reads a lot more than it can Output. $\endgroup$
    – Dj EKI
    Commented Sep 20, 2016 at 20:17
  • $\begingroup$ I have this Output dj-eki.de/Dateien/StackExchange/blendergamefehler3.jpg I marked some red. Is this blank line my problem? $\endgroup$
    – Dj EKI
    Commented Sep 20, 2016 at 20:46
  • $\begingroup$ This Output is coming from a = connection.readline().decode() $\endgroup$
    – Dj EKI
    Commented Sep 20, 2016 at 21:00
0
$\begingroup$

Unfortunately I have no arduino to test with at the moment, but I did something quite similar in the past.

As you've discovered, time.sleep() will freeze the execution of the entire game engine, rather than just the script. Instead of sleeping or running in a loop (don't forget that the game engine is calling our script repeatedly anyway, so in a sense we're already in a loop), try something like this:

import serial

# the bge passes the current controller in as the first argument for us, we'll call it "cont"
def receive(cont): 
    # get current gameobject
    own = cont.owner

    # check for our "reminder property":
    if "ser_init" not in own: 
        # code in here is only run once
        ser = serial.Serial('/dev/ttyUSB0')
        # store a property to remind us later if we've already run the above code
        own["ser_init"] = True 

    # everything else will be executed every logic tic like normal:

    # get data (this is how I was reading in data for my project, you might do it differently)
    data = ser.readline().decode()
    # do something with data
    print(data)

I've put it in a function receive() so that it can be called by a module execution controller:

enter image description here Note the .py extension on the script name. The script won't be executed without it!

$\endgroup$
7
  • $\begingroup$ @DjEKI Hm.. I suspect there might be an error earlier on. Do you get output when running without true level triggering enabled? $\endgroup$
    – gandalf3
    Commented Sep 19, 2016 at 19:41
  • $\begingroup$ I can see a Number as Output, without error $\endgroup$
    – Dj EKI
    Commented Sep 19, 2016 at 20:12
  • $\begingroup$ I Get a number and a empty line, how like the post from Monster $\endgroup$
    – Dj EKI
    Commented Sep 20, 2016 at 20:56
  • $\begingroup$ Is that number coming from the serial output? If you remove the print statement, is it still there? $\endgroup$
    – gandalf3
    Commented Sep 20, 2016 at 21:15
  • $\begingroup$ I get the same Error. Monster has a good answere, but have only a decode problem, i think. $\endgroup$
    – Dj EKI
    Commented Sep 21, 2016 at 19:33
0
$\begingroup$

I have solved the problem by "gandalf3" Help. His script was not working, but showed me the function of modules, so that I could be solved it myself thank you! Monster Script also works, but the fault lay with me. Nevertheless, I did not understand his script. My mistake was in Monster script: The output was a huge delay. The Arduino had a too short delay "delay (1)". My Arduino was faster than Blender :) I changed it to "delay (25)". Now I can turn the potentiometer and without delay.

My Script works: This script runs in Module.

import serial


ser = serial.Serial('COM6',9600)

def funktion():
    print (ser.readline().decode())
$\endgroup$

You must log in to answer this question.

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