231a-ac Final Presentation

From CSclasswiki
Jump to: navigation, search

Project Goal

The goal of this project is to create an interactive LED box that displays artistic patterns based on the motion it is applied. To accompany with the assembly concentration of this class, I have changed my focus from data visualization (commonly done via arduino sketch alone) to memory manipulations and communication bewteen PC and arduino using an assembly program. The revised goal is to temporarily recording user interactions and replay these interaction later on. Although the prototype has achieved little on the artistic aspect of the original goal, this can be implemented easily to the prototyping sketch later on.


hardware description

The hardware used in this project besides the PC and the Arduino are 2 one-axis tilt switches and 1 8x8 LED matrix.

  • Tilt Switch

Each tilt switch is made of a plastic box with 4 wires attached and a metal ball inside as illustrated below. As the tilt switch being tilted, the metal ball touches the side wire and close the circuit of one side. Therefore, each tilt switch can be treated as 2 separated switches that indicates tilt in positive or negative direction along 1 axis. Together they have 3 combinations of status.


In this project, two tilt switches are attached together perpendicularly to create a 2-axis tilt switch. It can represent 9 different combinations.


  • LED Matrix

The LED Matrix used in this project is a 8x8 dual-color LED matrix. For this prototype, I treat this LED matrix as 4*4 single color (only 16 green LEDs at the 4 corners of the matrix are used).





  1. SW1 and SW2 are associated with tilt switch A; SW3 and SW4 are associated with tilt switch B.
  2. The pin numbers of the LED matrix are shown in black circles. Column and row numbers are also displayed in the schematics.
  3. Resistors used in this schematics are chosen to be 1kOhms based on approximation.

Steps taken

Testing hardware

The following sketch is used for hardware testing:

int row[4]={9,10,12,11};
int col[4]={5,6,7,8};
int sw[4]={4,3,2,1};
int val[4]={0,0,0,0};

void setup()                    
  for (int i=0;i<4;i++){
  pinMode(sw[i], INPUT);          //set all switch pins to input
  pinMode(row[i], OUTPUT);     //set all LED pins to output
  pinMode(col[i], OUTPUT);    
  digitalWrite(row[i], LOW);       //turn on all LEDs
  digitalWrite(col[i], HIGH);

//turn a column on/off based on the status of a corresponding switch 
void writeLED(int colNum,int val){
  if (val==HIGH){

void loop()                   
  for (int i=0;i<4;i++){
    val[i] = digitalRead(sw[i]);  // get switch status from input pin  
    writeLED(col[i],val[i]);  //turn on/off LEDs

In the setup, pin numbers referring to various switches, LED column and rows are stored in arrays for easier access. All the LED row pins are set low and are never changed when this sketch runs. Therefore, changing the value of each column pin can turn on or off a column of 4 LEDs.

In the loop section, the sketch reads 4 integers of 0 or 1 from the 4 switch pins and stores them into an array. It then writes the invert of these value to 4 LED column pins, thus the 4 columns of LEDs reflect the status of 4 switches.

When the tilt switches are tilted, one or two columns of LEDs are lighted.

Programing Techniques

Software description

The final software adds another feature to the original sketch used in hardware testing: replaying past actions when the kit is inactive for some interval of time.


The arduino sketch, loop.pde, still controls the interaction between the switches and the LED matrix, while responding to calls from the PC. The assembly program on the PC constantly reads switch status and stores it into a buffer in memory every tenth of a second or so (depends on the speed of the PC processor and the USB connection). When the assembly program notices the switch status has not changed for a while, it stops arduino from interacting with motion, and sends status data in the PC memory back to the arduino one after another. The arduino receives these data and turns on/off LEDs in the same scheme as it is interacting with motion. After a certain amount of past actions are 'replayed', the arduino restores its user interaction abilities.


Programing Details

  • data structure

Arduino-serial.c receives and sends data in ASCII characters, so each pin status is represented by a byte, '0' or '1'. 4 consecutive bytes that represents the status of 4 pins can also be accessed together as double word. For example, '0001' means that PIN 1, 2 and 3 are LOW; PIN 4 is HIGH.

Such characters are stacked into a reserved array in memory, under the label Memory.

  • switching between interacting mode and playback mode

To prevent LED from responding to motion when arduino is in the playback mode, I add one more operation "p" to the sketch. This command toggles playback on and off by altering the value of a boolean variable, playback. The code for reading from the 4 input pins is executed only if playback is false.

  • impose status to input pins

In order to make arduino replay past actions, I need to overwrite the status of the 4 input pins with imposed values. However, it's a bad idea to switch pins between input/output mode. To work around this, the arduino sketch writes to or reads from the variables that contain the pin status without utilizing any hardware.

  • preventing overflow

The reason for choosing to store pin status in memory instead of external files is that I want to simulate the product having a short term memory. Further more, this also leads into an interesting topic about preventing overflow.

Since this program is expected to run continuously as people stops by and play with it, no matter how big the available memory is, it is likely to run out and get a segmentation fault at some point. My approach to this problem is making newer status overwrite the oldest status when maximum size is reached. This creates an interesting effect that the arduino will eventually 'forget' the actions that are replayed for a certain number of times.

To illustrated this effect, I set the maximum size of the part of memory that stores past status to 1024 bytes. Past actions can be played twice or three times before being overwrote by newer ones, if no motion applied after the first playback. Also, the number of bytes being replayed and the time between each playback can also affect how many of times the same action can be replayed.

  • text interface

Lastly, I create some useful text output that is readable to common users using ANSI Characters. I find that moving the cursor around makes the program noticeably slower. For instance, I can observe a small lag between the change of LEDs and the updating of status on the screen. (For debugging purposes, I prefer the simple command line output. )


  • Although the tilt switches only generate binary outputs, they work very accurately and has minimal fluctuation during change of status.
  • The LED responds to motion accurately in real time, probably due to the simple visualization scheme used in the sketch.
  • The speed at which the status being updated and at playback are partly controlled by calls to a delay() function inside the main loop and inside the playback loop. For a 2G processor, the following function, modified from Lab7, creates a 10ms delay.
;;; ----------------------------------------------------------------
;;; delay 10 ms, or 0.01 sec
;;; ----------------------------------------------------------------
	mov	ecx,10000000	
.for	add	eax, 1		
	loop	.for		

Nevertheless, the memory operations and printing to screen slows the program down so that the loop counter decrements less than 10 times per second. If the delay time is further decreased, it's hard for human eyes to keep track of the outputs on the screen. At current setting, some fast vibration may be filtered by the time gap, but the replay performance is satisfactory.

Playback runs faster than the main loop. This is partly due to the fact that playback loop is simpler, and also because that reading from pins has 2 steps: sending the command and waiting for the response, while writing to pins only requires 1 step. I called delay() three times in the playback loop to make the LED display alters at similar pace as they were handled interactively.

Overall, the speed also depends on the speed of the PC processor.

  • 3 global constants are defined in the assembly program to specify the number of cycles during each playback, the number of cycles between last action and next playback, and the size of status storage in the memory. For prototyping purposes, I keep them small so that the features of this program can be observed easily.
;;;---------------- Global Constants-----------------------------
%assign replayStepN	50	;# of steps during each playback
%assign alarmMax	100	;# of steps between last action and playback	
%assign MAXBUF     1024		;size of buffer in bytes


Main programs:

Other programs needed for compiling:

To compile and run:

   nasm -f elf final.asm
   gcc -o arduino-serial arduino-serial.c asm_io.o final.o
   ./arduino-serial -b 9600 -p /dev/ttyUSB0

Sample Output:

*       Interactive LED Matrix (v1)    *
*    CSC231 Fall 2008 Final Project    *
*             231a-ac Yang Li          *
Current Switch Status:1101
Time before next playback: 51
Playback? OFF