User login

Powered by Drupal, an open source content management system

Theory and Practice of Tangible User Interfaces

Motor-driven message decoder

Submitted by nick on Wed, 10/15/2008 - 23:34

Assignment: DC Motor: Actuation Assignment 1

Collaborators:

 

Assignment: DC Motor: Actuation Assignment 1
Collaborators: ash

Description

In this project, we attempted to make a motor-driven decoder for secret messages. The concept was to create an animation with a hidden message every 4 frames, then make a tube the user could look through, capped with a motor-driven disc that would block out all but the relevant frames. We really liked the concept - you could imagine this on a billboard in a public space, offering a different message to people who viewed the billboard through a decoder.

In practice, though, this turned out to be quite difficult, and while we succeeded in getting it to work on occasion, our control of the DC motor was too limited to be able to get it decode reliably, much to our disappointment. A further version of this might use a motor with finer-grained control, like a stepper motor, to set the speed just right.

Components

  • Arduino board
  • DC motor
  • potentiometer
  • 1k resistor
  • transistor
  • battery pack with batteries
  • cardboard tube and disc
  • cork cylinder
  • electrical tape

Processing Code

/*
* Make animated text with a hidden message
*/

int frameWidth = 600;
int currentFrame = 0;
PImage[] frames = new PImage[12];
PFont fontA;
int fr = 24;
boolean start;

String[] secretMsg = { "HELLOTHERE", "ASHSOLTANI" };
int[] secretMsgRow = {};

void setup()
{
size(frameWidth, frameWidth);
background(255);
// set up text style
fontA = loadFont("DayRoman-48.vlw");
textFont(fontA, 48);
textAlign(CENTER);
// set up secret message
secretMsgRow = expand(secretMsgRow, secretMsg.length);
int row;
for (int i=0; i < secretMsg.length; i++) {
// avoid dupes
row = 0;
while (row==0) {
row = floor(random(1,9));
for (int x=0; x < secretMsgRow.length; x++) {
if (secretMsgRow[x]==row) row = 0;
}
}
// set row
secretMsgRow[i] = row;
}
secretMsgRow = sort(secretMsgRow);
println(secretMsgRow);
// draw and save letters
for (int i=0; i < frames.length; i++) {
pushMatrix();
letterLayout(i % 5 == 0);
popMatrix();
frames[i] = get();
fill(255);
rect(0, 0, frameWidth, frameWidth);
}
}

void draw() {
image(frames[frameCount % frames.length], 0, 0);
println(fr);
frameRate(fr);
}

// listen for keyboard events
void keyPressed() {
if (key == CODED) {
if (keyCode == UP) {
fr++;
}
else if (keyCode == DOWN) {
fr--;
}
else if (keyCode == ENTER) {
start = true;
}
}
}

void letterLayout(boolean includeMsg)
{
// Set the gray value of the letters
fill(0);

// Set the left and top margin
int margin = 10;
int gap = 60;
translate(margin*1.5, margin*2);

// Create a matrix of letterforms
int counter = 0;
for(int i=0; i<margin; i++) {
for(int j=0; j<margin; j++) {
char letter = ' ';

// Select the letter
if (includeMsg) {
for (int x=0; x < secretMsgRow.length; x++) {
if (secretMsgRow[x]==i  && j < secretMsg[x].length()) {
letter = secretMsg[x].charAt(j);
}
}
}
if (letter == ' ') {
// pick a random letter
counter = floor(random(0, 26));
int count = 65+(i*margin)+j;
letter = char(65+counter);
}

// color letter
if(letter == 'A' || letter == 'E' || letter == 'I' ||
letter == 'O' || letter == 'U') {
fill(190, 0, 0);
}
else {
fill(0);
}

// Draw the letter to the screen
text(letter, 15+j*gap, 25+i*gap);
}
}
}

Arduino Code

/*
* one pot fades one motor
* modified version of AnalogInput
* by DojoDave <http://www.0j0.org>
* http://www.arduino.cc/en/Tutorial/AnalogInput
*/

int potPin = 0;   // select the input pin for the potentiometer
int motorPin = 9; // select the pin for the Motor
int val = 0;      // variable to store the value coming from the sensor
void setup() {
Serial.begin(9600);
}
void loop() {
val = analogRead(potPin);    // read the value from the sensor, between 0 - 1024
Serial.println(val);
analogWrite(motorPin, val/4); // analogWrite can be between 0-255
}