The digital Etch-a-sketch demo and guts

I talked about the high-level stuff behind the digital etch-a-sketch earlier this week. Here’s a demo and then a breakdown to look at the guts of the thing.

First of all, here’s the very simple one-minute demo. It is… exciting.

Holding the camera with one hand meant that I couldn’t demonstrate the way that the program mirrors a real etch-a-sketch’s diagonal lines as pixelated. That part was cool.

Anyway, let’s break this down. Step one was mounting my two control potentiometers to a fixed surface so that they could be turned without needing to be held down. I snagged some crappy stuff out of the scrap box and drilled some holes. Then, using some nuts and washers, secured my potentiometers through the holes.

Mounted potentiometers

Mounted potentiometers

I had previously attached headers to these potentiometers, so it was pretty easy to simply plug them into the bread-board. Ditto for my accelerometer. The vast majority of this project was in software, so the circuit is super-simple.

Basic circuit

Basic circuit

With that done, all that was left on the hardware side was to wire it to my Arduino. Since I wanted the etch-a-sketch controller to be relatively free-standing, I got some lone wires for this. (Note that I’m only drawing data off one pin of the three-axis accelerometer.)

With wires!

With wires!

I had to decide what data I wanted to process on the micro-processor, and what data I wanted to process in the applet. I decided to simply send the raw potentiometer data to the applet so that t was easier to resize the applet window and still keep maximum resolution on input data. I also decided to simplify the shaking/not-shaking decision enough to allow it to be calculated on the micro-processor and then simply forward a boolean value.

I also needed to calibrate the accelerometer to account for gravity. I wanted it to calculate from a value of 0 while at rest, and different people might hold it at different angles. Here’s the exciting Arduino code:

int baseZ;

void setup()
{
baseZ = analogRead(2);
Serial.begin(9600);
}

void loop()
{
int leftPos = 1024 - analogRead(0);
int rightPos = 1024 - analogRead(1);
int zDiff = analogRead(2) - baseZ;
Serial.print(leftPos,DEC);
Serial.print(',');
Serial.print(rightPos,DEC);
Serial.print(',');
if(zDiff > 150) Serial.println(1,DEC);
else Serial.println(0,DEC);
}

Note the if-else at the very end of loop(). This handled sending the correct value to the applet about shaking.

I had planned to have a variably-sized window in the applet with coordinate values scaled at start-up, but I got lazy. I decided that since I had a resolution of 1024×1024 on the potentiometers, I would have a drawing resolution of half that: 512×512. I defined my blank-state for the applet and wrote a function to generate this state. The function was called once during setup() (instead of duplicating the data in setup() itself) and then was called any time the shake boolean from the Arduino was true. Here’s that code:

import processing.serial.*;

Serial serialInputPort;
int xPos = 5000;
int yPos = 5000;
int[] inputValues;

void setup()
{
serialInputPort = new Serial(this, Serial.list()[0], 9600);
size(544,544);
clearBackground();
}
void draw()
{
}

void clearBackground()
{
background(250,0,0);
fill(250,250,250);
rect(15,15,514,514);
// background(250,250,250);
}

void serialEvent(Serial serialInputPort)
{
String inputString = serialInputPort.readStringUntil('\n');
if(inputString != null)
{
inputString = trim(inputString);
inputValues = int(split(inputString,','));
println(inputValues[0] + "," + inputValues[1] + "," + inputValues[2]);
int inputX = (inputValues[0] / 2) + 16;
int inputY = ((1023 - inputValues[1]) / 2) + 16;
if(inputValues[2] == 1) clearBackground();
else
{
if(xPos == 5000 || yPos == 5000)
{
xPos = inputX;
yPos = inputY;
}
else
{
stroke(10,10,10);
strokeWeight(2);
line(xPos,yPos,inputX,inputY);
xPos = inputX;
yPos = inputY;
}
}
}
}

And that’s that!

Thomas

Tags:

Leave a Reply