This hand-held toy "Balance" is an interactive piece that exercises the sense of balance and the cooperation between eyes and hands.
Many children and elderly have problems with their hands. Aiming to improve the control of one's body, Balance uses an accelerometer to detect body gestures, and transform physical movements into visual stimulation. The user controls the light dot (from an LED matrix display) by gently tilting the box, and the goal is to find the way out of the labyrinth without touching the walls. The subtlety that Balance required challenges the user's ability to control both his hand and mind.
Here's the latest iteration of my final project, Balance, which trains hand balancing skills for children. It uses an accelerometer to detect the tilting of the device, and reflect changes through a LED matrix display. The coding of the game (currently a pong game) is still under development...
Right now it's four arrows pointing to four different directions corresponding to device tilting. I changed the shape from a cross to a more biomorphic shape, for easier grip and turning/tilting for children. I'm exploring different shapes and sizes, to find an ideal mid point... The battery is quite big and heavy for a device like this. I'm wondering what other batteries I could use (using 9V now).
My project for the final is a further iteration of our group project for LED matrix. Since we have gone so far, I'd like to carry it to another level and make it into a product.
My design here is a game control that kids use to practice their perception of "balance". The control is shaped like a cross, with a LED matrix display in the middle. There are two speakers on each side of the control. The control has a accelerometer inside, so that it will detect tilting and acceleration. Kids use this control to play games that requires a sense of balance. There will be audio as well as visual feedback of how well you are controlling your balance. This device will finetone kids' ability to control their hands --- which will lead to higher development of their brains.
Hey everyone, my Arduino has been giving me the error message that "Serial port ' ...' already in use. Try quitting any programs that may be using it". I tried quitting Arduino, restarting computer, and updating to lastest version.. but still doesn't solve the problem. Does anyone have any ideas how to solve this?
We have been working on combining LED matrix with other sensors to create a game controller, where the matrix functions as display, sensor as data input and Arduino as internal game logics. The controller includes a battery (1.5V?), an LED matrix, an accelerometer, a 7-digit display, an Arduino board and an enclousure.
The LED matrix that we bought from Sparkfun is an 8x8 Red/Green display. The accelerometer from RadioShack is dual-axis, sensing tilt, collision, vibration, rotation, and gravity. The idea is to use accelerometer to sense tilting and shaking of the controller itself, using the data as input for the pong game that's embedded in the Arduino. The faster you shake the controler when the ball hit the "pong board", the faster the ball will fly away. The 7-digit display will show your score, and it'll be cleared every time you lose.
The making process:
(here I moved the 7-digit display to the top side so that there's space for battery.)
We have been working on the code, which is a hybrid between two sets of codes (matrix and acceleromter). The hybridization is quite complicated, as the matrix code came with lots of unfamiliar syntax... I am posting the two sets of code separately here:
LED Matrix code:
/ Simple program to test using the Arduino with the RGB Matrix
// & Backpack from Sparkfun. Code is a combination of Heather Dewey-Hagborg,
// Arduino Forum user: Little-Scale, and // Daniel Hirschmann. Enjoy!
//
// The Backpack requires 125Khz SPI, which is the slowest rate
// at which the Arduino's hardware SPI bus can communicate at.
//
// We need to send SPI to the backpack in the following steps:
// 1) Activate ChipSelect;
// 2) Wait 500microseconds;
// 3) Transfer 64bytes @ 125KHz (1 byte for each RGB LED in the matrix);
// 4) De-activate ChipSelect;
// 5) Wait 500microseconds
// Repeat however often you like!
#define CHIPSELECT 10//ss
#define SPICLOCK 13//sck
#define DATAOUT 11//MOSI / DI
#define DATAIN 12//MISO / DO
int data[] =
//{0,0,0,0,0,0,0,0,
//0,0,1,1,0,1,1,0,
//0,1,0,0,1,0,0,1,
//0,1,0,0,0,0,0,1,
//0,0,1,0,0,0,1,0,
//0,0,0,1,0,1,0,0,
//0,0,0,0,1,0,0,0,
//0,0,0,0,0,0,0,0
//};
char spi_transfer(volatile char data)
{
SPDR = data; // Start the transmission
while (!(SPSR & (1<<SPIF))) // Wait the end of the transmission
{
};
}
void setup()
{
byte clr;
pinMode(DATAOUT,OUTPUT);
pinMode(SPICLOCK,OUTPUT);
pinMode(CHIPSELECT,OUTPUT);
digitalWrite(CHIPSELECT,HIGH); //disable device
SPCR = B01010001; //SPI Registers
SPSR = SPSR & B11111110; //make sure the speed is 125KHz
/*
SPCR bits:
7: SPIEE - enables SPI interrupt when high
6: SPE - enable SPI bus when high
5: DORD - LSB first when high, MSB first when low
4: MSTR - arduino is in master mode when high, slave when low
3: CPOL - data clock idle when high if 1, idle when low if 0
2: CPHA - data on falling edge of clock when high, rising edge when low
1: SPR1 - set speed of SPI bus
0: SPR0 - set speed of SPI bus (00 is fastest @ 4MHz, 11 is slowest @ 250KHz)
*/
clr=SPSR;
clr=SPDR;
delay(10);
}
void loop()
{
delay(100);
int index = 0;
digitalWrite(CHIPSELECT,LOW); // enable the ChipSelect on the backpack
delayMicroseconds(500);
for (int i=0;i<8;i++) for (int j=0;j<8;j++)
{
spi_transfer(data[index]);
index++;
}
digitalWrite(CHIPSELECT,HIGH); // disable the ChipSelect on the backpack
delayMicroseconds(500);
}
Accelerometer code:
int pinX = 3; int pinY = 2; unsigned long serialTimer = millis(); unsigned long xAcc = 0; unsigned long yAcc = 0; boolean flipflop;
#define CHIPSELECT 10//ss#define SPICLOCK 13//sck#define DATAOUT 11//MOSI / DI#define DATAIN 12//MISO / DO int data[] ={0,0,0,0,0,0,0,0,0,0,1,1,0,1,1,0,0,1,0,0,1,0,0,1,0,1,0,0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,0,1,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0}; char spi_transfer(volatile char data){SPDR = data; // Start the transmissionwhile (!(SPSR & (1<<SPIF))) // Wait the end of the transmission{};} void setup(){byte clr;pinMode(DATAOUT,OUTPUT);pinMode(SPICLOCK,OUTPUT);pinMode(CHIPSELECT,OUTPUT);digitalWrite(CHIPSELECT,HIGH); //disable device SPCR = B01010001; //SPI RegistersSPSR = SPSR & B11111110; //make sure the speed is 125KHz /*SPCR bits: 7: SPIEE - enables SPI interrupt when high 6: SPE - enable SPI bus when high 5: DORD - LSB first when high, MSB first when low 4: MSTR - arduino is in master mode when high, slave when low 3: CPOL - data clock idle when high if 1, idle when low if 0 2: CPHA - data on falling edge of clock when high, rising edge when low 1: SPR1 - set speed of SPI bus 0: SPR0 - set speed of SPI bus (00 is fastest @ 4MHz, 11 is slowest @ 250KHz) */ clr=SPSR;clr=SPDR;delay(10);} void loop() { delay(100); int index = 0; digitalWrite(CHIPSELECT,LOW); // enable the ChipSelect on the backpack delayMicroseconds(500); for (int i=0;i<8;i++) for (int j=0;j<8;j++) { spi_transfer(data[index]); index++; } digitalWrite(CHIPSELECT,HIGH); // disable the ChipSelect on the backpack delayMicroseconds(500);}
We used the method and code that we found on the website HERE.
After tinkering for a while, we successfully made the LED matrix lit up and displaying some messages, but it's not behaving the same way as on the website. Instead of showing only the message, the whole matrix lights up --- we are not sure if it's the problem with the code or wiring. We're posting the code here so if anyone's interested or has an idea please let us know. And the pictures will be coming in an hour or so.
The code we downloaded from www.oomlout.co.uk:
/* * Example Code for an 8 x 8 LED Matrix * For More Details Visit http://www.tinyurl.com/yhwxv6h * * Scrolls a message across an 8 x 8 LED Matrix * To adjust the speed change the variable speed. * The message is held in requestString[] */
int speed = 20; //number of times to repeat each frame int pauseDelay = 500; //microseconds to leave each row on before moving to the next
char requestString[] = " THIS IS A MESSAGE "; //The string to display //to change the message in code you right yourself simply //change this data and reset index and offset to 0 //Variables used for scrolling (both start at 0 int index = 0; //this is the current charachter in the string being displayed int offset = 0; //this is how many columns it is offset by
//Pin Definitions int rowA[] = {9,8,7,6,5,4,3,2}; //An Array defining which pin each row is attached to //(rows are common anode (drive HIGH)) int colA[] = {17,16,15,14,13,12,11,10}; //An Array defining which pin each column is attached to //(columns are common cathode (drive LOW))
//Constants defining each charachters position in an array of integer arrays //Letters const int A = 0; const int B = 1; const int C = 2; const int D = 3; const int E = 4; const int F = 5; const int G = 6; const int H = 7; const int I = 8; const int J = 9; const int K = 10; const int L =11; const int M = 12; const int N = 13; const int O = 14; const int P = 15; const int Q =16; const int R = 17; const int S = 18; const int T = 19; const int U = 20; const int V =21; const int W = 22; const int X = 23; const int Y = 24; const int Z = 25;
//Punctuation const int COL =26; const int DASH = 27; const int BRA2 = 28; const int _ = 29; const int LINE = 34; const int DOT =36;
//Extra Charchters
const int SMILE =35; const int COLDOT = 36;
//The array used to hold a bitmap of the display //(if you wish to do something other than scrolling marque change the data in this //variable then display) byte data[] = {0,0,0,0,0,0,0,0};
//The alphabet //Each Charachter is an 8 x 7 bitmap where 1 is on and 0 if off const int _A[] = {B0001000, B0010100, B0100010, B1000001, B1111111, B1000001, B1000001, B0000000};
//Load the bitmap charachters into an array (each charachters position corresponds to its previously defined index (ie _A (a's bitmap) //is at index 0 and A = 0 so letters[A] will return the 'A' bitmap) const int* letters[] = {_A,_B,_C,_D,_E,_F,_G,_H,_I,_J,_K,_L,_M,_N,_O,_P,_Q,_R,_S,_T,_U,_V,_W,_X,_Y,_Z,_COL,_DASH,_BRA2,__, _FULL, _CHECK, _A3, _TEMP, _LINE, _SMILE, _DOT, _COLDOT};
//Setup runs once when power is applied void setup() { for(int i = 0; i <8; i++){ //Set the 16 pins used to control the array as OUTPUTs pinMode(rowA[i], OUTPUT); pinMode(colA[i], OUTPUT); } }
//An array holding the powers of 2 these are used as bit masks when calculating what to display const int powers[] = {1,2,4,8,16,32,64,128};
//Loads the current scroll state frame into the data[] display array void loadSprite(){ int currentChar = getChar(requestString[index]); int nextChar = getChar(requestString[index+1]);
for(int row=0; row < 8; row++){ //iterate through each row data[row] = 0; //reset the row we're working on for(int column=0; column < 8; column++){ //iterate through each column data[row] = data[row] + ((powers[column] & (letters[currentChar][row] << offset))); //loads the current charachter offset by offset pixels data[row] = data[row] + (powers[column] & (letters[nextChar][row] >> (8-offset) )); //loads the next charachter offset by offset pixels } } offset++; //increment the offset by one row if(offset==8){offset = 0; index++; if(index==sizeof(requestString)-2){index=0;}} //if offset is 8 load the next charachter pair for the next time through }
void showSprite(int speed2){ for(int iii = 0; iii < speed2; iii++){ //show the current frame speed2 times for(int column = 0; column < 8; column++){ //iterate through each column for(int i = 0; i < 8; i++){ digitalWrite(rowA[i], LOW); //turn off all row pins } for(int i = 0; i < 8; i++){ //Set only the one pin if(i == column){ digitalWrite(colA[i], LOW);} //turns the current row on else{ digitalWrite(colA[i], HIGH); }//turns the rest of the rows off }
for(int row = 0; row < 8; row++){ //iterate through each pixel in the current column int bit = (data[column] >> row) & 1; if(bit == 1){ digitalWrite(rowA[row], HIGH); //if the bit in the data array is set turn the LED on }
} delayMicroseconds(pauseDelay); //leave the column on for pauseDelay microseconds (too high a delay causes flicker) } } }
//returns the index of a given charachter //for converting from a string to a lookup in our array of charachter bitmaps int getChar(char charachter){ int returnValue = Z; switch(charachter){ case 'A': returnValue = A; break; case 'a': returnValue = A; break; case 'B': returnValue = B; break; case 'b': returnValue = B; break; case 'C': returnValue = C; break; case 'c': returnValue = C; break; case 'D': returnValue = D; break; case 'd': returnValue = D; break; case 'E': returnValue = E; break; case 'e': returnValue = E; break; case 'F': returnValue = F; break; case 'f': returnValue = F; break; case 'G': returnValue = G; break; case 'g': returnValue = G; break; case 'H': returnValue = H; break; case 'h': returnValue = H; break; case 'I': returnValue = I; break; case 'i': returnValue = I; break; case 'J': returnValue = J; break; case 'j': returnValue = J; break; case 'K': returnValue = K; break; case 'k': returnValue = K; break; case 'L': returnValue = L; break; case 'l': returnValue = L; break; case 'M': returnValue = M; break; case 'm': returnValue = M; break; case 'N': returnValue = N; break; case 'n': returnValue = N; break; case 'O': returnValue = O; break; case 'o': returnValue = O; break; case 'P': returnValue = P; break; case 'p': returnValue = P; break; case 'Q': returnValue = Q; break; case 'q': returnValue = Q; break; case 'R': returnValue = R; break; case 'r': returnValue = R; break; case 'S': returnValue = S; break; case 's': returnValue = S; break; case 'T': returnValue = T; break; case 't': returnValue = T; break; case 'U': returnValue = U; break; case 'u': returnValue = U; break; case 'V': returnValue = V; break; case 'v': returnValue = V; break; case 'W': returnValue = W; break; case 'w': returnValue = W; break; case 'X': returnValue = X; break; case 'x': returnValue = X; break; case 'Y': returnValue = Y; break; case 'y': returnValue = Y; break; case 'Z': returnValue = Z; break; case 'z': returnValue = Z; break; case ' ': returnValue = _; break; case '3': returnValue = A3; break; // case '<': returnValue = TEMP; break; // case '*': returnValue = FULL; break; case '|': returnValue = LINE; break; case '_': returnValue = _; break; case ':': returnValue = COL; break; case '-': returnValue = DASH; break; case ')': returnValue = BRA2; break; case '%': returnValue = SMILE; break; case '.': returnValue = DOT; break; case '^': returnValue = COLDOT; break; } return returnValue; }
This week our group is doing research on LED Matrix. Here are three projects that I wan to use as my precendents.
First one is TENORI-ON (2004) by Toshio Iwai, curated by MoMA. Promoted by Yamaha as “a digital musical instrument for the twenty-first century,” the TENORI-ON’s “visible music” interface is suitable for both serious musicians and beginners to electronic music.
The second project is "Duality" by ART+COM from Germany. It has a LED matrix installed under a glass floor, which difuses the LED light. Passersby trigger the installation that interplays between solid and liquid, virtual and real, light and water: Their footsteps generate virtual waves that transform to real water waves in the pond.
The third project is an interactive LED Coffee Table that's featured on SparkFun. It is a four-way multi-player pong.
Maker Faire came to Queens, New York last weekend. I had some fun with 3D printing, arduino and robots over there.
1. First project to comment on... well it's not actually a project. It's the new technology of 3D printing that virtually can make any kind of shape out of plastic and metal. I was amazed by how much this technology has widened designer's choice of ideas. From now on no matter how complex your form is, it's possible to realize it without joints welding or glue. I enjoyed it especially since most of my designs take organic forms. The technology is best for skeletony forms or anything that has layers or internal structures.
2. This is a 3D printer that prints with any kind of jelly-like material. May it be chocolate, joint compound, tooth paste, or ice (the creater said so, I've no idea how that's possible though).This design takes 3D printing into daily life. How cool it is to eat some home-made peanut butter robots?
3. This wearable technology thing grabbed my eyes instantly. It detects your heartbeat + sweat from your middle finger, which tells if you are telling "truth" or "lie". Even though the designer didn't explained it to me, I'm guessing the big red heart sewed on the T-shirt syncs with the hearbeats. What can it do? Well I think first it's very interesting to express one's feelings through live data visualization, and second, anything that glows and blinks on your shirt is simply awesome.
Recent Comments