Fidget spinners...the fast spinning toy that came out of nowhere. It's a simple design that's a lot of fun to play with. I decided that I wanted to make my own, but as with everything I make, I wanted to add some flare to it. The idea is to add LED's to it to create a Persistance of Vision (POV) display. It's basically a set of LED's that blink on and off really fast and whenever you move them back and forth really really fast, the LED's display a text or message. That's the idea, now let's see if we can do it.
The appeal of Fidget spinners is that they're small enough to fit in the palm of your hand. That being the case, we'll need to keep our parts small. If you're an expert at making circuit boards and soldering surface mount components, then you are probably already capable of making something small enough for this project. For the rest of us, however, I'm going to try and keep this as simple as possible.
For the lights, using regular LED's is out of the question, since they are so large. Each of them, as well, also require a resistor. So it makes the most sense to use surface mount (SMT) components for these items. Luckily, there are tiny components that are made for use with the "Arduino Lilypad" which is meant for e-textile, but will work great for our needs. There are tiny, easy to connect LED and resistor combo's that come in a pack of 5, which is perfect, because we need 5. I chose to go with Red LED's because they use less power. Even better, there's also a 3v coin battery holder with an on/off switch that could potentially be the perfect size. And obviously we'd need a 3v coin cell battery to go with that.
Thanks to the Lilypad components, we have our small LED's and a power source. The last component we need is a way to control the LED's. We need a microcontroller that's small enough to fit on the Fidget. The Attiny85 is the perfect size to fit the bill, so that's what I decided to go with. We'll also need a way to program the Attiny85 microcontroller. If you have an Arduino, there are some good guides online for hooking it up to an Arduino and programming it through the Arduino. Otherwise, you can get a little USB AVR programmer. It would also be handy to get a Dip Socket or two so that we don't have to solder things directly to the Attiny85:
Before we start cramming everything into a fidget, we should test everything out first to see if it works. I started out by connecting everything to a breadboard using this diagram.
I actually loaded this onto a perf-board that had the exact same layout as the breadboard above. I used a perf-board so that it could be portable enough to spin for the test. For that same reason, a drilled a hole in the middle of the perf-board and hot glued it to a small DC motor that was powered by a 9v battery. If you don't want to go the motor route, just attach it to anything that well let you spin it by hand.
The core of making this work is the ATTiny microcontroller, and it's useless until we load a program onto it telling it what to do. There are a couple of common ways to load up software: through an Arduino (as noted previously) and through a USB AVR programmer.
I'm using the AVR Programmer, which requires a little bit of software setup. You can find full instructions on this Sparkfun website, but here are the basic steps:
- Download the USB driver (for Windows)
- Extract it and update the driver for the AVR within Device Manager
- Install the Arduino IDE
- Download the ATTiny Arduino Add-on
- Extract the ATTiny Arduino Add-on to the Arduino>hardware folder in your user drive.
- In the Arduino IDE, select Tools > Board > Attiny
- Then select Tools > Processor > Attiny85
- Finally, select Tools > Programmer > USBtinyISP
Then you can paste this code to make the LED's read "HELLO",
int delayTime = 1; //sub-char delay time
int charBreak = 3; //char delay time
int LED1 = 0;
int LED2 = 1;
int LED3 = 2;
int LED4 = 3;
int LED5 = 4;
void setup()
{
pinMode(0, OUTPUT);
pinMode(1, OUTPUT);
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
}
int a[] = {1, 6, 26, 6, 1};
int b[] = {31, 21, 21, 10, 0};
int c2[] = {14, 17, 17, 10, 0};
int d[] = {31, 17, 17, 14, 0};
int e[] = {31, 21, 21, 17, 0};
int f[] = {31, 20, 20, 16, 0};
int g[] = {14, 17, 19, 10, 0};
int h[] = {31, 4, 4, 4, 31};
int i[] = {0, 17, 31, 17, 0};
int j[] = {0, 17, 30, 16, 0};
int k[] = {31, 4, 10, 17, 0};
int l[] = {31, 1, 1, 1, 0};
int m[] = {31, 12, 3, 12, 31};
int n[] = {31, 12, 3, 31, 0};
int o[] = {14, 17, 17, 14, 0};
int p[] = {31, 20, 20, 8, 0};
int q[] = {14, 17, 19, 14, 2};
int r[] = {31, 20, 22, 9, 0};
int s[] = {8, 21, 21, 2, 0};
int t[] = {16, 16, 31, 16, 16};
int u[] = {30, 1, 1, 30, 0};
int v[] = {24, 6, 1, 6, 24};
int w[] = {28, 3, 12, 3, 28};
int x[] = {17, 10, 4, 10, 17};
int y[] = {17, 10, 4, 8, 16};
int z[] = {19, 21, 21, 25, 0};
int eos[] = {0, 1, 0, 0, 0};
int excl[] = {0, 29, 0, 0, 0};
int ques[] = {8, 19, 20, 8, 0};
void displayLine(int line)
{
int myline;
myline = line;
if (myline>=16) {digitalWrite(LED1, HIGH); myline-=16;} else {digitalWrite(LED1, LOW);}
if (myline>=8) {digitalWrite(LED2, HIGH); myline-=8;} else {digitalWrite(LED2, LOW);}
if (myline>=4) {digitalWrite(LED3, HIGH); myline-=4;} else {digitalWrite(LED3, LOW);}
if (myline>=2) {digitalWrite(LED4, HIGH); myline-=2;} else {digitalWrite(LED4, LOW);}
if (myline>=1) {digitalWrite(LED5, HIGH); myline-=1;} else {digitalWrite(LED5, LOW);}
}
void displayChar(char c)
{
if (c == 'a'){for (int i = 0; i <5; i++){displayLine(a[i]);delay(delayTime);}displayLine(0);}
if (c == 'b'){for (int i = 0; i <5; i++){displayLine(b[i]);delay(delayTime);}displayLine(0);}
if (c == 'c'){for (int i = 0; i <5; i++){displayLine(c2[i]);delay(delayTime);}displayLine(0);}
if (c == 'd'){for (int i = 0; i <5; i++){displayLine(d[i]);delay(delayTime);}displayLine(0);}
if (c == 'e'){for (int i = 0; i <5; i++){displayLine(e[i]);delay(delayTime);}displayLine(0);}
if (c == 'f'){for (int i = 0; i <5; i++){displayLine(f[i]);delay(delayTime);}displayLine(0);}
if (c == 'g'){for (int i = 0; i <5; i++){displayLine(g[i]);delay(delayTime);}displayLine(0);}
if (c == 'h'){for (int i = 0; i <5; i++){displayLine(h[i]);delay(delayTime);}displayLine(0);}
if (c == 'i'){for (int it = 0; it <5; it++){displayLine(i[it]);delay(delayTime);}displayLine(0);}
if (c == 'j'){for (int i = 0; i <5; i++){displayLine(j[i]);delay(delayTime);}displayLine(0);}
if (c == 'k'){for (int i = 0; i <5; i++){displayLine(k[i]);delay(delayTime);}displayLine(0);}
if (c == 'l'){for (int i = 0; i <5; i++){displayLine(l[i]);delay(delayTime);}displayLine(0);}
if (c == 'm'){for (int i = 0; i <5; i++){displayLine(m[i]);delay(delayTime);}displayLine(0);}
if (c == 'n'){for (int i = 0; i <5; i++){displayLine(n[i]);delay(delayTime);}displayLine(0);}
if (c == 'o'){for (int i = 0; i <5; i++){displayLine(o[i]);delay(delayTime);}displayLine(0);}
if (c == 'p'){for (int i = 0; i <5; i++){displayLine(p[i]);delay(delayTime);}displayLine(0);}
if (c == 'q'){for (int i = 0; i <5; i++){displayLine(q[i]);delay(delayTime);}displayLine(0);}
if (c == 'r'){for (int i = 0; i <5; i++){displayLine(r[i]);delay(delayTime);}displayLine(0);}
if (c == 's'){for (int i = 0; i <5; i++){displayLine(s[i]);delay(delayTime);}displayLine(0);}
if (c == 't'){for (int i = 0; i <5; i++){displayLine(t[i]);delay(delayTime);}displayLine(0);}
if (c == 'u'){for (int i = 0; i <5; i++){displayLine(u[i]);delay(delayTime);}displayLine(0);}
if (c == 'v'){for (int i = 0; i <5; i++){displayLine(v[i]);delay(delayTime);}displayLine(0);}
if (c == 'w'){for (int i = 0; i <5; i++){displayLine(w[i]);delay(delayTime);}displayLine(0);}
if (c == 'x'){for (int i = 0; i <5; i++){displayLine(x[i]);delay(delayTime);}displayLine(0);}
if (c == 'y'){for (int i = 0; i <5; i++){displayLine(y[i]);delay(delayTime);}displayLine(0);}
if (c == 'z'){for (int i = 0; i <5; i++){displayLine(z[i]);delay(delayTime);}displayLine(0);}
if (c == '!'){for (int i = 0; i <5; i++){displayLine(excl[i]);delay(delayTime);}displayLine(0);}
if (c == '?'){for (int i = 0; i <5; i++){displayLine(ques[i]);delay(delayTime);}displayLine(0);}
if (c == '.'){for (int i = 0; i <5; i++){displayLine(eos[i]);delay(delayTime);}displayLine(0);}
delay(charBreak);
}
void displayString(char* s)
{
for (int i = 0; i<=strlen(s); i++)
{
displayChar(s[i]);
}
}
void loop()
{
displayString("hello");
}
Make sure the ATTiny85 is insterted into the AVR programmer, and then with it plugged in, click the "upload" button to upload the code to the ATTiny85. When it's done, you can remove the AVR programmer and put the ATTiny85 back in your breadboard.
First TestTo test it out, flip the switch on the battery pack to the "on" position. You should start seeing the LED's blinking. Dim the lights in the room and start spinning the perfboard either by hand or by powering the motor. Once the LED's reach a certain speed, they should start to spell something!
What would an LED Fidget display be without...a fidget? Before I started making a fidget, I measured out all the electronic parts on the perfboard and tried to keep the size as minimal as possible. How you make the fidget is up to you and what you have available to you. It could be wood, metal, injection molding, clay, etc. For me, I decided to go with a 3D printer.
So that I didn't have to design the fidget spinner from scratch, I downloaded a basic model from Thingiverse to use as a template. Then I headed over to Tinkercad.com to customize and edit the fidget spinner using the measurements I had taken of my electronic parts.
Finally, it was just a matter for printing it all out on my 3D printer.
We have our Fidget, and we have our LED display. Now we need to combine them. So I took the components from the perfboard and either removed them, or I left them in the perfboard, but cut them to size.
Once everything fit snugly, I began soldering new wires to make connections between the components. I used shrink tubing to cover the wires as they went in between the fidget pods. Once everything was in place, I hot glued it all down.
Finally, I added a bearing to the center of the fidget, and attached the fingerpads to the bearing. Now you can give it a spin! If any of the pods are too light, you can supplement the weight by adding a penny or so to the lightweight pod.
Now you can flip the switch on the battery pack, dim the lights, and start spinning the fidget to see if you can read the LED's! If you have trouble reading it, it may be due to the timing of the POV display and how fast you're spinning it. To tweak this, you can edit the "delaytime" variable in the code to make the timing slower (higher number) or faster (lower number). Once you get it perfected, you can impress your friends with your own LED fidget display!
Comments