perjantai 15. toukokuuta 2009

Blender and Physical Computing


During a Physical Computing class here at the University of Jyväskylä, I made a small experiment with Blender and Arduino. I build a very simple prototype called CHEEX (Cheap Exhibition Expander).

The idea is that instead of traditional exhibition posters or information kiosks, one could use any part of the exhibition room as a display by using data projector and servo-controlled mirror. By using sensors it is possible to react visitors and show them more information when they get near objects.

The Blender part


Blender has a virtual camera which is pointing to a target object. This target object is then animated and the camera naturally follows it. The rotations of the camera are then sent to Arduino, which controls two axis servo system which has a mirror attached to it.

Inside Blender I have a normal scene with camera, the target object and some other objects. Blender scene can be modelled according the exhibition room so that virtual camera and mirror points to same spot. Then it is possible to combine physical space with virtual space.

Technicalities


Technically system is very simple. I used very simple protocol between Blender and Arduino. By sending sequences of three bytes, I could quite easily send rotations to Arduino. First Blender sends "255" and then angle for root servo and then angle for head servo. Arduino is reading serial port and when it receives 255, it knows that following two bytes are the angles for the servos.

System also has one ultrasonic sensor and value from that sensor is send back to Blender every time Blender sends the angle values for servos. This way everything stays in sync and there is no problems with serial port buffer overflows.

System has still one major problem. Servos are connected directly to Arduino and they are using too much power. This makes the readings from the ultrasonic sensor unreliable when servos are moving (at least I *think* that is causing this). I sort of resolved the problem by taking an average of several values but that can be considered a hack. I'll order a motorshield for Arduino and test if using it will resolve the problem.

maanantai 20. huhtikuuta 2009

/dev/Arduino

I noticed that if I unplugged Arduino from my Ubuntu-box and then plugged it back, the /dev name for Arduino changed from /dev/ttyUSB0 to /dev/ttyUSB1. Fortunately this was easy to fix. The problem was solved by adding a file 97-arduino.rules in /etc/udev/rules.d/ and adding the following rule (all in one line):

kernel=="ttyUSB*", SYSFS{idVendor}=="0403",
SYSFS{idProduct}=="6001",
SYMLINK="Arduino"


So now I can always trust that Arduino is in /dev/Arduino. If you have two Arduinos,you can use serial numbers in order to recognize them (see link below).

Original source:
http://www.arduino.cc/playground/Linux/Udev

perjantai 17. huhtikuuta 2009

Bouncing virtual ball with Arduino (and Blender)

UPDATED 20.4.2009






I'm quite new on this Arduino stuff and I may have misunderstood something. But anyway, here are some observations of using Arduino and Blender's game engine.

It's easy!

It is really easy to get values from Arduino to Blender. Here is a simple setup for reading photo-resistor's values from Blender:
from Blender.Mathutils import Vector import serial 
port = '/dev/ttyUSB0' 
pin = 0 
try: 
    GameLogic.SerialPort 
except: 
    GameLogic.SerialPort = serial.Serial(port,9600) 

# read data 
valo = GameLogic.SerialPort.readline() 
val = float(valo)/200 

# BLENDER stuff 

objs = GameLogic.getCurrentScene().getObjectList() 
cube = objs["OBbox"] 
cube.setPosition([1.0,1.0,val])


Here I'm reading photoresistor values and then tell Blender's game-engine to change "box" object's position according that value. The arduino code looks like this:

/* Arduino reading photo resistor to serial * * */ 
int analogPin=0; 
int analogVal=0; 
void setup() { Serial.begin(9600); } 
void loop() { 
    // get the value from photoresistor 
    analogVal = analogRead(analogPin); 
    Serial.println(analogVal); 
    //delay(100);
}


Not so fast!



There is a one catch when reading data from Arduino to Blender. And that's the fact that python scripts are executed on every frame and that mean that you'll read data from serial port approx. 60 times per second.

However, Arduino is sending data much faster. As a result, you'll see a horrible delay in Blender. That's because the data arduino sent is buffered and you are actually reading from buffer. So you'll get "historical" values from serial port, not the current values. And for interactive application that is not wanted.

There are couple of ways to fix this:

The simplest way is to program Arduino to send data more rarely. You could use delay function if there is nothing else that Arduino should do (delay halts everything in Arduino).

Request/response model


Better and more predictable way is to tell Arduino when we want to get a value. So when we want a value, we send a signal to arduino to send data and then we read the value. This way we'll always get the current values no matter of how high or low our frame rates are.

(I *think* that it would be also possible to run a separate python thread for Arduino input and just read values from that thread)


port = '/dev/Arduino' 
pin = 0 
 
try: 
    GameLogic.SerialPort 
except: 
    try: 
        GameLogic.SerialPort = serial.Serial(port,9600,timeout=1)  
        print 'Port ' + port + 'found!' 
         
        #ok, we have a port. Let's test if we can write to it 
        try: 
            GameLogic.SerialPort.write('x') 
            GameLogic.serialRead = False 
            GameLogic.serialOk = True 
              
        except: 
            GameLogic.serialOk = False 
            print 'could not write to port ' + port + '!' 
         
         
    except: 
        GameLogic.serialOk = False 
        print 'no port ' + port + ' found!' 
     
 
 
# do stuff if serial port is OK 
if GameLogic.serialOk: 
    if GameLogic.serialRead: 
        valo = GameLogic.SerialPort.readline() 
        val = float(valo)/100 
        GameLogic.serialRead = False     
    else: 
        GameLogic.SerialPort.write('a') 
        GameLogic.serialRead = True     
     
 
    # BLENDER stuff 
    if GameLogic.serialRead == False: 
        objs = GameLogic.getCurrentScene().getObjectList() 
        cube = objs["OBbox"] 
        cube.setPosition([1.0,1.0,val])


When Blender is ready to receive a value from Arduino, it send character "a" to the Arduino. Arduino sent one value and that is read next round. Arduino code is very simple:
int analogPin=0;
int analogVal=0;

void setup() {
  Serial.begin(9600);
}

void loop() {
  if ( Serial.available()) {
    char ch = Serial.read();
    if ('a'==ch) {
      analogVal = analogRead(analogPin);
      Serial.println(analogVal);
    }
  }
}

Here is a very simple demo using photoresistor to control a box's position. A top of box there is a ball so you can bounce the ball with adjusting the amount of light.





That's it!

sunnuntai 5. huhtikuuta 2009

Arduino and schematic views



Want to make a nice shematic diagram from your Arduino-based system? Interaction Design Lab at the University of Applied Sciences Potsdam have developed a really nice tool called Fritzing that can do that and even more. It can also make PCB (Printed Circuit Board) diagram for you.

You make your connections via drag-drop and then you can just switch between different kind of views (breadboard, schematic and PCB).




Fritzing is Free Softaware and there are version for Linux, Mac and Windows. You can find downloads and more info here:

http://fritzing.org/welcome/

lauantai 4. huhtikuuta 2009

Blog

This is a blog for opendimension.org.

This blog will serve a) as a extension memory for myself by storing short notes about different kind of things (I have lousy memory) and b) as place for publishing small tutorials I think could be useful for other persons too.

What are the main topics?


If it runs on Linux, if it's free software and if it somehow could be used in the field of cultural heritage, then I'm surely interested!