Skip navigation

Category Archives: Exercise 2

dsc_00021

Above is a short video of my Exercise 2 and the physical interface that I made to control it.

==============================================================

Description:

This interactive driving applet consists of a Processing applet that simulates a road and a physical interface that controls it.  The physical interface was created by rewiring an optical mouse to switches and mounting them in a foam core enclosure that I made to resemble a car interior.

==============================================================

Controls:

Steering Wheel/Mouse Wheel: Turn left or right.

Gas Pedal/Left Click: Accelerate.

Shifter/Right Click: Reverse On/Off.

Brake Pedal/Middle Click: Brake.

==============================================================

Code:

PImage road;
float y = -1200;
boolean inDrive;
boolean inReverse;
boolean brake;
boolean turnLeft;
boolean turnRight;
void setup(){
addMouseWheelListener(new java.awt.event.MouseWheelListener() {
public void mouseWheelMoved(java.awt.event.MouseWheelEvent evt) {
mouseWheel(evt.getWheelRotation());
}
}
);
road = loadImage (“Road.jpg”);
size(800,600);
background(0);
}
void mousePressed() {
if ( (mouseEvent.getModifiers() & InputEvent.BUTTON2_MASK) != 0) {
inDrive=false;
inReverse=false;
brake=true;
}
else if (mouseButton==LEFT){
inReverse=false;
brake=false;
inDrive=true;
}
else if (mouseButton==RIGHT) {
inDrive=false;
brake=false;
inReverse=true;
}
else if(mouseButton!=RIGHT){
inReverse=false;
}
}
void draw(){
if(y>0){
y=-1600;
}
if(y<-1600){
y=0;
}
if(inDrive){
y+=20;
}
if(inReverse){
y-=10;
}
if(turnLeft){
rotate(PI/10);
}
if(turnRight){
rotate(-PI/10);
}
image(road,-200,y);
}
void mouseWheel(int delta) {
println(delta);
if(delta<0){
turnLeft=false;
turnRight=true;
}
if(delta>0){
turnRight=false;
turnLeft=true;
}
}

PImage road;

float y = -1200;

boolean inDrive;

boolean inReverse;

boolean brake;

boolean turnLeft;

boolean turnRight;

void setup(){

addMouseWheelListener(new java.awt.event.MouseWheelListener() {

public void mouseWheelMoved(java.awt.event.MouseWheelEvent evt) {

mouseWheel(evt.getWheelRotation());

}

}

);

road = loadImage (“Road.jpg”);

size(800,600);

background(0);

}

void mousePressed() {

if ( (mouseEvent.getModifiers() & InputEvent.BUTTON2_MASK) != 0) {

inDrive=false;

inReverse=false;

brake=true;

}

else if (mouseButton==LEFT){

inReverse=false;

brake=false;

inDrive=true;

}

else if (mouseButton==RIGHT) {

inDrive=false;

brake=false;

inReverse=true;

}

else if(mouseButton!=RIGHT){

inReverse=false;

}

}

void draw(){

if(y>0){

y=-1600;

}

if(y<-1600){

y=0;

}

if(inDrive){

y+=20;

}

if(inReverse){

y-=10;

}

if(turnLeft){

rotate(PI/10);

}

if(turnRight){

rotate(-PI/10);

}

image(road,-200,y);

}

void mouseWheel(int delta) {

println(delta);

if(delta<0){

turnLeft=false;

turnRight=true;

}

if(delta>0){

turnRight=false;

turnLeft=true;

}

}

This project is about using interesting inputs to control an interactive application. I coded a simple moving kaleidoscope that can response to input :

– V to reshuffle the shapes,

– B to cycle to the value space for the shapes color,

– N to make the shapes spin,

– , (comma) to change the direction of animation (zoom in vs zoom out)

kalei

Then, in order to control the Kaleidoscope, I build a stick reader who has 4 connectors placed on the 4 edges like in the following picture :

stickreader

system

Then I used a stick with electric contact only on 2 consecutive edges at a time, so as i slide the stick in the reader, it activates different keypress so by designing different sticks the whole system act like a barrel organ.

Example of a stick:

stick

François

Code

http://paulshen.name/sketches/2

paul shen

Each pipe is connected to a row wire of the keyboard and each nut is connected to a column wire (actually just 2 different ones). So each time a nut and a pipe touch and make a sound, it also generates a keyboard input that generates a unique set of objects on the screen, and the objects then float around. I wanted the visualization to reflect the windy nature of the input by having objects blowing away in the wind (it doesn’t quite look like that, but yeah).

Here is a picture of the windchime and the keyboard. Let’s just say that improvements can be made aesthetically:

windchime2

And a screenshot of the visualization:

screenshot

The code can be found here.

And the applet here (play using keyboard).

I’ve been thinking about kiosks a lot lately, and I experimented with a control panel that uses different sized tokens to activate switches.

(I forgot to take a photo…)  I made four pairs of switches using wire stretched over the top of a box.   The switches were in pairs about the size of a quarter, it was possible to read all switches at once using an Arduino, then a byte was sent to Processing for visualization.   If smaller or larger change was used, different numbers of switches could be activated.

arduino code


void setup() {
  pinMode(2, INPUT);
  pinMode(3, INPUT);
  pinMode(4, INPUT);
  pinMode(5, INPUT);
  pinMode(6, INPUT);
  pinMode(7, INPUT);
  pinMode(8, INPUT);
  pinMode(9, INPUT);
  pinMode(10, INPUT);

  Serial.begin(9600);
}

void loop(){
  int i = 0;
  byte b = 0;

  for(i=0; i< 8; i++) {

    if (digitalRead(i+2) == HIGH) {
      b = (b | (1<<i));
      //      Serial.println(i, HEX);
    }
    Serial.println(b, BYTE);
  }
}

&#91;/sourcecode&#93;

processing code (displays a different sized box)

&#91;sourcecode language='java'&#93;

//-*-Java-*-
// exercise 2 -- display, loosely based on
// Graph
// by David A. Mellis
//

import processing.serial.*;

Serial port;
String buff = "";
int NEWLINE = 10;

void setup()
{
    size(500,500);

    println("Available serial ports:");
    println(Serial.list());

  // Uses the first port in this list (number 0).  Change this to
  // select the port corresponding to your Arduino board.  The last
  // parameter (e.g. 9600) is the speed of the communication.  It
  // has to correspond to the value passed to Serial.begin() in your
  // Arduino sketch.
  port = new Serial(this, Serial.list()&#91;0&#93;, 9600);

  // If you know the name of the port used by the Arduino board, you
  // can specify it directly like this.
  //port = new Serial(this, "COM1", 9600);

}

void draw()
{
    int b = 0;
    background(0);
    stroke(255);

    while (port.available() > 0) {
    b = port.read();
    if ((b == 10) || (b == 13) || ( b == 48)) {
        continue;
    }
    else if (b > 0) {
        //        println(b);
        rect(20,20,b*1.5,b*2);
    }
    }
}

IMG_6303

This is my soda can button. The program detects when a soda can is placed on the coaster-like button and simulates fizzing by trapping the bubbles at the top of the screen. Once the can is lifted, the bubbles move upwards freely to give the effect of drinking the soda.

Here’s a close up of the button. I basically just soldered two wires to the mouse left button and made it so when the can was placed, it would complete the circuit and thus press the button.

IMG_6305

Here’s the code. I modified this Processing tutorial.

int numBalls = 700;
float spring = 0.005;
float gravity = 0.03;
float friction = -0.5;
Ball[] balls = new Ball[numBalls];

void setup()
{
size(500, 800);
noStroke();
smooth();
for (int i = 0; i < numBalls; i++) {
balls[i] = new Ball(random(width), random(height), random(5, 15), i, balls);
}
}

void draw()
{
background(85,52,19);
for (int i = 0; i < numBalls; i++) {
if (keyPressed) {
balls[i].collide();
balls[i].collect();
balls[i].display();
} else {
balls[i].collide();
balls[i].move();
balls[i].display();
}
}
}

class Ball {
float x, y;
float diameter;
float vx = 0;
float vy = 0;
int id;
Ball[] others;

Ball(float xin, float yin, float din, int idin, Ball[] oin) {
x = xin;
y = yin;
diameter = din;
id = idin;
others = oin;
}

void collide() {
for (int i = id + 1; i < numBalls; i++) {
float dx = others[i].x – x;
float dy = others[i].y – y;
float distance = sqrt(dx*dx + dy*dy);
float minDist = others[i].diameter/2 + diameter/2;
if (distance < minDist) {
float angle = atan2(dy, dx);
float targetX = x + cos(angle) * minDist;
float targetY = y + sin(angle) * minDist;
float ax = (targetX – others[i].x) * spring;
float ay = (targetY – others[i].y) * spring;
vx -= ax;
vy -= ay;
others[i].vx += ax;
others[i].vy += ay;
}
}
}

void move() {
vy -= gravity;
y = y – .25;
if (y width) {
x = width – diameter;
vx *= friction;
}
else if (x – diameter height) {
y = height – diameter/2;
vy *= friction;
}
else if (y – diameter/2 < 0) {
y = diameter/2;
vy *= friction;
}
}

void display() {
fill(255, 204);
ellipse(x, y, diameter, diameter);
}
}

Cube, coveredCube Output

I had a bluetooth keyboard around that I didn’t like, so I created a new kind of wireless input device. I made a cube that could sense which side was up — my original plan being to use this information to roll around a virtual cube. However, making the cube took so much time I ended up having to go with a simpler idea — displaying a color similar to the currently-up color of he cube.

Source code posted here.

My instructable for the orientation sensors here.

A bit more detail. The five-cent orientation sensors (two of these are used):

orientation sensor, no top

With the cap on:

orientation sensor, assembled

The keyboard interface. There were conveniently placed “test points” — essentially hacking-ready solder pads — for each contact:
Keyboard interface

Everything fit into the box (a floppy disk box that I’ve had for something like six years and have never used for anything):

Cube, put together

Overall, I’m pleased with the feel of the resulting cube. I think more could be done with the visualization. I’d also like it if the tilt sensors worked better (the nickles sometimes bind a bit on the perfboard). Finally, even though I do like the current feel, the whole cube isn’t as solid as it could be — a purpose-built (and painted) enclousure would be a nice addition to this project.