Introduction: Arduino BlinkyBall Project
I frequent a blog called hackaday.com which featured a project by "Nikolai", it was a 10cm LED ball that used shift registers. It seems like a really fun project to attempt but the cost of having the boards made & not having any experience sending eagle drawings to fab shops initially kept me from starting. After some planning I decided to make my own boards by hand although because of that choice I would have to scale up the design dimension wise & reduce the number of "slices".
I started off with rectangular 2200 hole PCB's from RadioShack and using cutting dykes I made half circle boards with a cutout in the center to to fit the processing module, lipo battery & charger. Each slice is comprised of 2 - 8-bit shift registers, 16 LED's & 16 resistors. There are 8 slices in total so there are 128 LED's, I use and Arduino nano 3.1 from makershed.com along with a lipo batter & charger available at sparkfun.com. In order to fit these slices together to form a sphere I used circular PCB's that I found at radioshack. I used a dremel to cut slits every 45-degrees for each of the slices to slide into, the package comes with 3 sizes & 2 of each, I used the middle size. I added a parallax mesmic 2125 accelerometer to the main board in the center to provide orientation to the sphere. You charge the LiPo batter through a USB mini port located in the center, charging takes 1 Hour approximately and lasts for 45 minutes.
I wanted to thank Nikolai for the insperation & Null Space Labs HackerSpace for their take on the project. I also wrote Charlie over there to get his input on the spiral animation & he was very nice & helpfull. I am going to post all of the code that I used in case anyone is interested. I wouldn't say that I am the most proficient programmer & am still learning so be kind.
Links: www.hackaday.com/2011/10/16/we-want-this-led-ball/ //Original
http://charliex2.wordpress.com/2012/02/11/the-blinky-ball-nullspacelabs/ //Null Space Labs In LA made a really cool version
Code:
int clockPin = 13; //IC Pin 11, Yellow Jumper
int dataPin = 11; //IC Pin 14, Blue Jumper
int latchPin = 8; //IC Pin 12, Green Jumper
const int xPin = 2; // X output of the accelerometer
const int yPin = 3; // Y output of the accelerometer
word patterns[176] = {
0b1100000000000000,
0b0110000000000000,
0b0011000000000000,
0b0001100000000000,
0b0000110000000000,
0b0000011000000000,
0b0000001100000000,
0b0000000110000000,
0b0000000011000000,
0b0000000001100000,
0b0000000000110000,
0b0000000000011000,
0b0000000000001100,
0b0000000000000110,
0b0000000000000011,
0b0000000000000001,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b1010111010001101,
0b0110101010011010,
0b0101010010011100,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b1010111010001101,
0b0110101010011010,
0b0101010010011100,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b1100000000000000,
0b0110000000000000,
0b0011000000000000,
0b0001100000000000,
0b0000110000000000,
0b0000011000000000,
0b0000001100000000,
0b0000000110000000,
0b0000000011000000,
0b0000000001100000,
0b0000000000110000,
0b0000000000011000,
0b0000000000001100,
0b0000000000000110,
0b0000000000000011,
0b0000000000000001,
0b0000000000000001,
0b0000000000000011,
0b0000000000000110,
0b0000000000001100,
0b0000000000011000,
0b0000000000110000,
0b0000000001100000,
0b0000000011000000,
0b0000000110000000,
0b0000001100000000,
0b0000011000000000,
0b0000110000000000,
0b0001100000000000,
0b0011000000000000,
0b0110000000000000,
0b1100000000000000,
0b1100000000000000,
0b0110000000000000,
0b0011000000000000,
0b0001100000000000,
0b0000110000000000,
0b0000011000000000,
0b0000001100000000,
0b0000000110000000,
0b0000000011000000,
0b0000000001100000,
0b0000000000110000,
0b0000000000011000,
0b0000000000001100,
0b0000000000000110,
0b0000000000000011,
0b0000000000000001,
0b0000000000000001,
0b0000000000000011,
0b0000000000000110,
0b0000000000001100,
0b0000000000011000,
0b0000000000110000,
0b0000000001100000,
0b0000000011000000,
0b0000000110000000,
0b0000001100000000,
0b0000011000000000,
0b0000110000000000,
0b0001100000000000,
0b0011000000000000,
0b0110000000000000,
0b1100000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b1010100100111110,
0b1010110100100101,
0b1010101001101111,
0b1100101111010101,
0b1111011010101010,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000
};
int index = 17;
int count = sizeof(patterns)/2;
unsigned int oldy = 0;
void setup()
{
// initialize serial communications:
Serial.begin(9600);
// initialize the pins connected to the accelerometer
// as inputs:
pinMode(xPin, INPUT);
pinMode(yPin, INPUT);
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
}
void loop()
{
accelorometer();
}
void accelorometer()
{
// variables to read the pulse widths:
int pulseX, pulseY;
// variables to contain the resulting accelerations
int accelerationX, accelerationY;
// read pulse from x- and y-axes:
pulseX = pulseIn(xPin,HIGH);
pulseY = pulseIn(yPin,HIGH);
// convert the pulse width into acceleration
// accelerationX and accelerationY are in milli-g's:
// earth's gravity is 1000 milli-g's, or 1g.
accelerationX = ((pulseX / 10) - 500) * 8;
accelerationY = ((pulseY / 10) - 500) * 8;
// print the acceleration
Serial.print("X: ");
Serial.print(accelerationX);
// print a tab character:
Serial.print("\t");
Serial.print("Y: ");
Serial.print(accelerationY);
Serial.println();
if(accelerationY == oldy){
count = count + 1;
if(count >= 500){
for(int times = 0; times <= 160; times++){
idleTime();
}
count = count - 50;
}
}else{
count = count - 1;
if(count <= 0){
count = 0;
}
}
int ywordPos = map(accelerationY, -1023, 1023, 0, 16);
byte registerOne = highByte(patterns[ywordPos]);
byte registerTwo = lowByte(patterns[ywordPos]);
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, registerOne);
shiftOut(dataPin, clockPin, MSBFIRST, registerTwo);
digitalWrite(latchPin, HIGH);
oldy = accelerationY;
}
void idleTime()
{
byte registerOne = highByte(patterns[index]);
byte registerTwo = lowByte(patterns[index]);
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, registerOne);
shiftOut(dataPin, clockPin, MSBFIRST, registerTwo);
digitalWrite(latchPin, HIGH);
delay(65);
index++;
if (index >= count){
index = 17;
}
}
http://www.youtube.com/watch?v=r2yADpGnyyc
12 Comments
10 years ago on Introduction
can some tell me if this can work on arduino duemilanova atmega 168.can anyone help with the code for this without using accelerometer...Also any chance of scematic please..thanks...
11 years ago on Introduction
I remember seeing something similar as a kickstarter project.... All i remember is the 'Slices' were so expensive that i lost interest.....
11 years ago on Introduction
I will try to upload to this site but for the now it is on youtube.
http://www.youtube.com/watch?v=r2yADpGnyyc
Reply 11 years ago on Introduction
charlieplexing might get this down to as few pins as are on an arduino with out the need of the registers and condensing the words down to a small equation would speed up your code. i am looking at the latter right now i know the first word is:
n = 0
n + 1
n + 2
n * 2
so a small loop like
while(n < 98304)
{
if(n = 0)
{
n = n + 1;
}
if(n = 1)
{
n = n + 2;
}
for(n = 3; n < 98304; n * 2)
{
return n;
}
}
or something like that.
Reply 11 years ago on Introduction
I don't think you can have all the LEDs on at the same time with charlieplexing, which is something I would want to do with a project like this.
Reply 11 years ago on Introduction
technically no you cant but of course you can pulse them fast enough to seem to be all on but in reality they are not. much like the florescent lights they just flicker faster than the eye can see it.
11 years ago on Introduction
Thank you for the kind words. instructables actually did feature the project the very first day I uploaded if I remember correctly. I did daisy chain the shift registers so that the output of one slice feeds the next slice as it works its way around. The map function is actually built into the Arduino IDE, it allows you to scale values to the range you specify. It is a really usefull here is an example:
const int potPin = 0; //select the input pin for the potentiometer
int ledPin = 13; //select the pin for the LED
void setup()
{
Serial.begin(9600);
pinMode(ledPin, OUTPUT); //declare the ledPin as an OUTPUT
}
void loop()
{
int val; //the value coming from the sensor
int percent; //the mapped value
val = analogRead(potPin); //read the voltage on the pot (val range 0 to 1023)
percent = map(val, 0, 1023, 0,100); //percent range from 0 to 100
Serial.println(percent);
digitalWrite(ledPin, HIGH); //turn the LedPin on
delay(percent); //on time given by percent value
digitalWrite(ledPin, LOW); //tun the ledPin off
}
You could use this command to map a potentiometer to an Electronic Speed Control in order to regulate the speed of a Brushless DC motor. Brushless motors are in everything and the ESC handles the complicated signaling. RC planes/cars/quadrocopters all use ESC to control their motors also in case your ever interested.
11 years ago on Introduction
I have used the charlieplexing method for LED control in the past. You would be able to turn on all the LED's at once but the problem is it would be very complicated to wire something like this in that way. Using 74HC595 shift-registers makes things easy because you can daisy chain them together connecting the output of one to the input of the next "slice". You would need 16 pins plus another pin for every "layer" you have if you charlieplexed the leds, using shift registers only requires using 3 pins on your micro-controller. Also you would have to run all 16+ wires to each slice adding a good deal of complexity to your wiring. As far as the speed of the code above it is so fast you have to add the delay otherwise, in the stored animations, it all pretty much happens in an instant. I imagine you could run the accelerometer function without delay but I did not test that. I appreciate you'lls interest in this project & have fun.
11 years ago on Introduction
Excuse here the reference http://radiokot.ru/circuit/light/run/45/
11 years ago on Introduction
Original development on a site radiokot.ru. Made such sphere, very amusing thing, my nephew from it is very glad.
11 years ago on Introduction
Do you have a video of it in action?
Reply 11 years ago on Introduction
I also think a video would really benefit this instructable as it is such a cool looking creation