Source Code. Projects. Nerd Stuff. Art Stuff.

Accelerometer + LED Matrix


Posted on October 9th, by amoeboar in classes, pcomp. No Comments

Following the lab tutorial, I used Processing to draw a circle based on an accelerometer’s x- and y-axis data. The result is a simple controller similar to a Wii remote.

(Note that the y-axis is inverted)

 

[gn_media url="http://www.youtube.com/watch?v=40_RyYqFvYA&feature=youtu.be" width="600" height="400"]

Setup:


[gn_spoiler title="accelerometerTest" open="0" style="1"]
[gn_tabs style="3"]
[gn_tab title="Arduino code"]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
 // accelerometer Test
// load this onto Arduino

const int switchPin = 2;

void setup() {
   // open serial communications at 9600 bps
   Serial.begin(9600);
   pinMode(switchPin, INPUT);
 }

void loop() {
   // read the sensor:
   int sensorValue = analogRead(A0);
   // print the results:
   Serial.print(sensorValue);
   Serial.print(",");

   // read the sensor:
   sensorValue = analogRead(A1);
   // print the results:
   Serial.print(sensorValue);
   Serial.print(",");

   // read the sensor:
   sensorValue = digitalRead(switchPin);
   // print the last reading with a println() so that
   // each set of three readings prints on a line by itself:
   Serial.println(sensorValue);
 }
[/gn_tab] [gn_tab title="Processing sketch"]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import processing.serial.*;     // import the Processing serial library
Serial myPort;                  // The serial port
float bgcolor;                  // Background color
float fgcolor;                  // Fill color
float xpos, ypos;               // Starting position of the ball

void setup() {
  size(800, 600);
  // List all the available serial ports
  // println(Serial.list());
  // Arduino is attached to port [0]
  // Open Serial.list()[0] corresponding to the first serial port
  String portName = Serial.list()[0];
  myPort = new Serial(this, portName, 9600);
  myPort.bufferUntil('\n');
}

void draw() {
  background(bgcolor);
  fill(fgcolor);
  // Draw the shape
  ellipse(xpos, ypos, 20, 20);
}

void serialEvent(Serial myPort) {
  // read the serial buffer
  String myString = myPort.readStringUntil('\n');
  if (myString != null) {
    myString = trim(myString);
    // split the string at the commas
    // and convert the sections into integers:
    int sensors[] = int(split(myString, ','));
    // print out the values you got:
    for (int sensorNum = 0; sensorNum < sensors.length; sensorNum++) {
      print("Sensor " + sensorNum + ": " + sensors[sensorNum] + "\t");
    }
      // make sure there are three values before you use them:
   if (sensors.length > 1) {
      xpos = map(sensors[0], 250, 450, 0, width);
      ypos = map(sensors[1], 250, 450, 0, height);
      // the switch values are 0 and 1.  This makes them 0 and 255:
      fgcolor = sensors[2] * 255;
    }
    // add a linefeed after all the sensor values are printed:
    println();
  }
}
[/gn_tab] [/gn_tabs] [/gn_spoiler]

 

LED matrix:

I wanted to experiment more with the accelerometer. Awhile back I made an LED cube which made use of an LED matrix and row-column scanning. However, this project had automatically set up animations and very little in the way of interactivity. I wanted to take the LED matrix and use the accelerometer, so I scaled it down and combined that project with this week’s lab.

This is how an LED matrix works:

For this project, the LEDs have a common anode per each row, and a common cathode per each column. The rows are set to their own pins, as are the columns. The software sends a signal to a row, holding one leg of an LED high. While this pin is being held HIGH, the Arduino sends a LOW signal to the appropriate column to complete the circuit and turn the LED on. This cycling through rows and columns is called row-column scanning, and it happens quickly enough that your eyes see a continuously lit LED, a phenomenon called persistance of vision (POV).

The code is adopted from Tom Igoe’s Tilty Ball program, but because I didn’t have an LED matrix available I had to make my own.

[gn_media url="http://www.youtube.com/watch?v=PSH9NIb_V1Q" width="600" height="400"]

[gn_spoiler title="Accelerometer + LED Matrix" open="0" style="1"]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
 // max and min values from the accelerometer,
// found by experiment:
const int sensorMin = 380;
const int sensorMax = 620;
// 2-dimensional array of row pin numbers (for two matrices):
const int col[4] = {2, 3, 4, 5};
// 2-dimensional array of row pin numbers (for two matrices):
const int row[4] = {6, 7, 8, 9};
// 2-dimensional array of pixels:
int pixels[4][4];
// cursor position
int x = 0;
int y = 0;

void setup() {
  // initialize the I/O pins as outputs:

  // iterate over the pins:
  for (int i = 0; i < 4; i++) {
    // initialize the output pins:
    pinMode(col[i], OUTPUT);
    pinMode(row[i], OUTPUT);
    // take the col pins (i.e. the cathodes) high to ensure that
    // the LEDS are off:
    digitalWrite(col[i], HIGH);
  }
  // initialize the pixel matrix:
  for (int x = 0; x < 4; x++) {
    for (int y = 0; y < 4; y++) {
      pixels[x][y] = HIGH;
    }
  }
}

void loop() {
  // read input:
  readSensors();

  // draw the screen:
  refreshScreen();
}

void readSensors() {
  // turn off the last position:
  pixels[x][y] = HIGH;
  // read the sensors for X and Y values:
  x = map(analogRead(0), sensorMin, sensorMax, 0, 4);
  y = map(analogRead(1), sensorMin, sensorMax, 0, 4);
  pixels[x][y] = LOW;
}

void refreshScreen() {
  // iterate over the rows (anodes):
  for (int thisRow = 0; thisRow < 4; thisRow++) {
    // take the row pin (anode) high:
    digitalWrite(row[thisRow], HIGH);
    // iterate over the cols (cathodes):
    for (int thisCol = 0; thisCol < 4; thisCol++) {
      // get the state of the current pixel;
      int thisPixel = pixels[thisRow][thisCol];
      // when the row is HIGH and the col is LOW,
      // the LED where they meet turns on:
      digitalWrite(col[thisCol], thisPixel);
      // turn the pixel off:
      if (thisPixel == LOW) {
        digitalWrite(col[thisCol], HIGH);
      }

    }
    // take the row pin low to turn off the whole row:
    digitalWrite(row[thisRow], LOW);
  }
}
[/gn_spoiler]




Leave a Reply