Instructables

Arduino BlinkyBall Project

Featured
Picture of Arduino BlinkyBall Project
2012-04-25 08.28.33.jpg
2012-03-26 14.38.03.jpg
2012-03-26 14.39.14.jpg
2012-03-26 14.39.24.jpg
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
domdomgin1 year ago
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...
punx7772 years ago
I remember seeing something similar as a kickstarter project.... All i remember is the 'Slices' were so expensive that i lost interest.....
davidhend (author) 2 years ago
I will try to upload to this site but for the now it is on youtube.

http://www.youtube.com/watch?v=r2yADpGnyyc
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.
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.
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.
davidhend (author) 2 years ago
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.
jensenr302 years ago
This instructable is MAGNIFICENT!
Instructables didn't make this featured, and that makes me sad.
They would probably feature you if you did this step by step instead of assuming people know how all this stuff works.
But step by step is overrated! You made this instructable for the people who are knowledgeable about electronics. not the noobies (sorry noobies)

I would like to again commend you on your awesome instructable. Your code looks very elegant.

One question: Did you use the daisy-chain method for this project? I see you mentioned it in a comment below, but you didn't explicitly state that you are using it.

Also: It looks like you are using a function called "map". Is this built into the Arduino IDE or is it user-defined?Because It doesn't look like it is defined.


Thanks! Awaiting you response(s).

Ryan
nice
I'm not very wordy
davidhend (author) 2 years ago
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.
sasha21052 years ago
Excuse here the reference http://radiokot.ru/circuit/light/run/45/
sasha21052 years ago
Original development on a site radiokot.ru. Made such sphere, very amusing thing, my nephew from it is very glad.
randofo2 years ago
Do you have a video of it in action?
I also think a video would really benefit this instructable as it is such a cool looking creation
Pro

Get More Out of Instructables

Already have an Account?

close

PDF Downloads
As a Pro member, you will gain access to download any Instructable in the PDF format. You also have the ability to customize your PDF download.

Upgrade to Pro today!