Instructables
Persistence of Vision (POV) Wands are a fun way to create interesting long exposure photographs and light displays.  The wand consists of a single row of LEDs controlled by an Arduino Uno.  When the wand is turned on it appears to be flickering in a random pattern, but if you move it quickly back and forth, you will see text or an image appear.  This wand project is incredibly customizable, I've included all CAD files, firmware, build documentation, and schematics.  Feel free to choose your own color LEDs, write personalized messages, and maybe even add something new to the project!



Parts list:

(1x) Arduino Uno REV 3 Radioshack #276-128
(20x) Amber Super-bright LED Indicator Radioshack #55050630
(1x) Arduino Proto Shield Radioshack #276-140
(1x) 9V Alkaline Battery Radioshack #23-866
(1x) Heavy-Duty 9V Snap Connectors Radioshack #270-324
(20x) 1/4 watt resistors (sample calculation below)

      from the specs of the LEDs I used:
      "Continuous forward current: 25mA"
      "Forward voltage: 3V"

      using the following relationship:
      V(volts) = I(amps) * R(ohms)
      rearranged to:
      R = V / I

      we can calculate the resistance as follows:
      voltage across resistor = 5V - 3V = 2V
      2V / 0.025A = 80ohms

      I used 100 ohm resistors so that the LEDs wouldn't be operating at their maximum ratings.  Check the datasheet of the LEDs you use to calculate these values.

I've attaching a fritzing document with a breadboard and schematic view of the circuit (and included them above) for reference.
 
Remove these adsRemove these ads by Signing Up
1-40 of 148Next »
Andrew Cleveland made it!yesterday

Worked like a charm. Thanks. I saw a similar thing spinning but it was using rgb LEDs and could stream video. It was obviously bought but still pretty impressive.

IMG_7832.jpg
jeet5552 months ago

hello dear sir i'm make this project on ceiling fan but fan is rotating anti clockwise so

characters are not show properly so please help me how can do

jmacutong3 months ago

hi. I'm currently working with this project. But my professor wants some modifications..He wants to have 3 switches/push buttons wherein pressing each button will display different messages. Can you please help me do it? Thanks. :)

you can use other atmega328p-pu chip with other message when you push other button then the other chip should be on and first one should be down you can also use atiny85!

amandaghassaei (author)  jmacutong3 months ago
that's a little tricky bc I'm using all the i/o pins on the Arduino to control the leds. The easiest solution would be to remove a few leds from the wand and use those free pins to control the buttons. Alternatively, you could use something like the 74hc595 to control the leds and free up some pins for inputs.
TANYUNSHENG2 months ago

Hai, i reduce the number of LED to 16. And i change the source code but its doesn't work. Can u please help me check and see ? and i also written using ARDUINO library commands. Below is the source code.


#include <avr/pgmspace.h>

String povtext = "LIKE";//PUT YOUR MESSAGE HERE!!- must be in all caps, spaces are fine, no punctuation

byte refreshrate = 1;//delay time for pixels to refresh in milliseconds- experiment with different values

//get length of string povtext

int dimtext = povtext.length();

//letterArray to make sure firmare is loaded correctly- each led should light up in order upon turning on

boolean load[]= {

1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,

};

//variables

byte n; //variable for loops

byte t; //variable for loops

byte l; //variable for loops

//The letters of the alphabet- edit the look of these if you want, just make sure the letters m and w are 15 pixels wide and the rest are 12 pixels

boolean letterA[] PROGMEM = {

0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0,

0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,

0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,

1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1,

1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,

1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,

1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,

1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,

1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,

1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,

1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,

1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,

1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,

1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,

1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,

1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,

};

boolean letterB[] PROGMEM = {

1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,

1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,

1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1,

1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,

1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,

1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1,

1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,

1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,

1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,

1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,

1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1,

1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,

1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,

1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1,

1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,

1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,

};

.....C to Y( too long to paste here)

boolean letterZ[] PROGMEM = {

1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,

1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,

1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,

0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0,

0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0,

0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0,

0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0,

0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0,

0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0,

0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0,

0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,

0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,

0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,

1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,

1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,

1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,

};

void sendToWand(boolean letterArray[]){//function to get array data

for (byte t=0; t<12; t++){ //for each time step

for (int pin= 13; pin>=0; pin--){

if (letterArray[(13-pin)*12+t]) {//if matrix element == 1 then turn led on

digitalWrite(pin, HIGH);

}

else {//if matrix element == 0 then turn led off

digitalWrite(pin, LOW);

}

}

//the following lines address the analog pins indivially and set them either high or low depending on matrix element

if (letterArray[14*12+t]) {//if matrix element == 1 then turn led on

digitalWrite(A5, HIGH);

}

else {//if matrix element == 0 then turn led off

digitalWrite(A5, LOW);

}

if (letterArray[15*12+t]) {

digitalWrite(A4, HIGH);

}

else {

digitalWrite(A4, LOW);

}

if (letterArray[16*12+t]) {

digitalWrite(A3, HIGH);

}

else {

digitalWrite(A3, LOW);

}

}

}

void sendToWandMW(boolean letterArray[]){//function to get array data

for (byte t=0; t<15; t++){ //for each time step

for (int pin= 13; pin>=0; pin--){

if (letterArray[(13-pin)*12+t]) {//if matrix element == 1 then turn led on

digitalWrite(pin, HIGH);

}

else {//if matrix element == 0 then turn led off

digitalWrite(pin, LOW);

}

}

//the following lines address the analog pins indivially and set them either high or low depending on matrix element

if (letterArray[14*12+t]) {//if matrix element == 1 then turn led on

digitalWrite(A5, HIGH);

}

else {//if matrix element == 0 then turn led off

digitalWrite(A5, LOW);

}

if (letterArray[15*12+t]) {

digitalWrite(A4, HIGH);

}

else {

digitalWrite(A4, LOW);

}

if (letterArray[16*12+t]) {

digitalWrite(A3, HIGH);

}

else {

digitalWrite(A3, LOW);

}

}

}

void setup() {

pinMode(A3, OUTPUT);

pinMode(A4, OUTPUT);

pinMode(A5, OUTPUT);

for (int pin=1; pin<14; pin++){

pinMode(pin, OUTPUT);

}

for (int pin= 13; pin>=0; pin--){//turn on each digital pin sequentially for 100ms

digitalWrite(pin, HIGH);

delay(100);

digitalWrite(pin,LOW);

}

//the following lines turn on each analog pin individually

digitalWrite(A5, HIGH);

delay(100);

digitalWrite(A5,LOW);

digitalWrite(A4, HIGH);

delay(100);

digitalWrite(A4,LOW);

digitalWrite(A3, HIGH);

delay(100);

digitalWrite(A3,LOW);

}

void loop() {

//space at beginning of text

PORTB = 0;

PORTD = 0;

digitalWrite(A5,LOW);

digitalWrite(A4,LOW);

digitalWrite(A3,LOW);

delay(refreshrate*3);

for (n=0; n<dimtext; n++) {//go through each character of povtext and call function sendToWand to display letter

if (povtext.charAt(n)=='A') {

sendToWand(letterA);

}

else if (povtext.charAt(n)=='B') {

sendToWand(letterB);

}

else if (povtext.charAt(n)=='C') {

sendToWand(letterC);

}

else if (povtext.charAt(n)=='D') {

sendToWand(letterD);

}

else if (povtext.charAt(n)=='E') {

sendToWand(letterE);

}

else if (povtext.charAt(n)=='F') {

sendToWand(letterF);

}

else if (povtext.charAt(n)=='G') {

sendToWand(letterG);

}

else if (povtext.charAt(n)=='H') {

sendToWand(letterH);

}

else if (povtext.charAt(n)=='I') {

sendToWand(letterI);

}

else if (povtext.charAt(n)=='J') {

sendToWand(letterJ);

}

else if (povtext.charAt(n)=='K') {

sendToWand(letterK);

}

else if (povtext.charAt(n)=='L') {

sendToWand(letterL);

}

else if (povtext.charAt(n)=='M') {

sendToWandMW(letterM);

}

else if (povtext.charAt(n)=='N') {

sendToWand(letterN);

}

else if (povtext.charAt(n)=='O') {

sendToWand(letterO);

}

else if (povtext.charAt(n)=='P') {

sendToWand(letterP);

}

else if (povtext.charAt(n)=='Q') {

sendToWand(letterQ);

}

else if (povtext.charAt(n)=='R') {

sendToWand(letterR);

}

else if (povtext.charAt(n)=='S') {

sendToWand(letterS);

}

else if (povtext.charAt(n)=='T') {

sendToWand(letterT);

}

else if (povtext.charAt(n)=='U') {

sendToWand(letterU);

}

else if (povtext.charAt(n)=='V') {

sendToWand(letterV);

}

else if (povtext.charAt(n)=='W') {

sendToWandMW(letterW);

}

else if (povtext.charAt(n)=='X') {

sendToWand(letterX);

}

else if (povtext.charAt(n)=='Y') {

sendToWand(letterY);

}

else if (povtext.charAt(n)=='Z') {

sendToWand(letterZ);

}

else if (povtext.charAt(n)==' ') {

PORTB = 0;

PORTD = 0;

PORTC = 0;

delay(refreshrate*3);//off for 3 pixels

}

//space between each character

PORTB = 0;

PORTD = 0;

PORTC = 0;

delay(refreshrate);

}

//space at end of text

PORTB = 0;

PORTD = 0;

PORTC = 0;

delay(refreshrate*3);

}

jmacutong made it!3 months ago

I made it!. I presented this project to my professor and I've got a good grade. But he is insisting what he wants - the three push buttons with three different messages. He said that he can increase my grade if i am able to do it. My plan is to reduce the LEDs to free some pins but i'm afraid i can't edit the codes. Also i dont know the codes for the push buttons and where i will put it. Can you please help me?? I really want to have a high grade on that subject.

HAHA.jpg.png
m0sama made it!3 months ago

Thanks a lot for this extremely useful instructable. I made it and added a Bluetooth module to it (Bluetooth Gold Mate) to allow controlling the message shown on the POV Wand through an Andriod device (instead of having it hard coded). I made a brief video that describes my project here. Thanks again!

http://youtu.be/8MPuFQb0CjY

IMG_1166.JPGIMG_1136.JPG10171665_10202341466002513_7392959235502717194_n.jpgIMG_1154.JPG
amandaghassaei (author)  m0sama3 months ago

wow! great project, that's a great idea!

iivanovskis made it!3 months ago

Thanks, cool :)

IMG_1196.JPGIMG_1175.JPG
Macs935 months ago
(removed by author or community request)
amandaghassaei (author)  Macs935 months ago

start by wiring up 16 leds and running the same code, you'll see that all of the letters are cut off, you can go in and change the bit array (still leaving them 12x20) so that they form the letters nicely at less than 20 px. That's the easiest solution.

(removed by author or community request)
amandaghassaei (author)  Macs934 months ago

do a 1sec+ exposure with the refresh rate I've got in my code.

amandaghassaei (author)  Macs935 months ago

yes a few seconds exposure is good. the refresh rate changes the amount that the letters are stretched for a given velocity. The default settings should be fine.

(removed by author or community request)
amandaghassaei (author)  Macs934 months ago

the arrays that look like this:

boolean letterA[] PROGMEM = {
0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0,
0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0,
0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1,
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
};

zvizvi4 months ago

Wow! fr***in' wonderful! beautiful code, too. Kudos!

rrace001 made it!6 months ago

Thank You! Love the programming. It taught me a lot! I just built one on a solder-less breadboard and it worked great (Only 16 LEDs but it is a start). I wanted to do one of these because I found an old Realistic Electronic Kaleidoscope at a thrift store and wanted to convert it to a POV. Unfortunately you cannot directly address the LEDs because it uses LM3914N chips which is just for meters I think. I am new to this stuff. I am not going to give up though. If anything the rotary contacts will come in very handy but I will give it one more shot and see if I can solder in an arduino nano or something similar. Only one channel for communications so not sure how I am going to do it unless i just solder it to the blade. Fun Stuff!

DSC_7822.JPG
amandaghassaei (author)  rrace0015 months ago

nice job!

ram123manohar11 months ago
sister i have this wand..and it works like a charm..now i want to upgrade this..i want to add this wand a small keyboard of small push buttons..so that i can change thye TEXT manually whenever i want..can you give your valueable suggestions..if u really make it..thats a gift for us

Hey there!! I was digging around in some chips that I have and I found this mm74c922n chip that I bought a while back so I looked up using a keypad with it and when I found :http://www.instructables.com/id/16-key-Keypad-Deco... I thought of this post and your question... Hope this helps!!

thank you...i will sure get back to this..:)

amandaghassaei (author)  ram123manohar10 months ago
that sounds like a cool project. if you want to use an existing keyboard, I think you'll have to use your computer as an intermediate. If you make your own keyboard, you can listen for keypressed with digitalWrite and then get those to change the value of "povtext"
AlfredNobel6 months ago

How could I change the code so that it only uses 8 LEDs instead of 20? Like pins 6-13. I'm having trouble with the data1 and data2 for loops for a 8 row, 5 column character set I made. I can't seem to get anything from data2 to display out to the LEDs, either in the initialization or in the actual character blinking.

john marvin6 months ago

Good day! can i attached a motor on your project, is it possible? thanks

amandaghassaei (author)  john marvin6 months ago
yes, definitely
roeyb16 months ago

I made the wand but It is just turning on all the lights and not changing. I am also getting this: avrdude: stk500_getsync(): not in sync: resp=0x00

amandaghassaei (author)  roeyb16 months ago

Sounds like the Arduino software is having trouble talking to your Arduino. Try these solutions:

  1. unplug the usb connection and plug it back in, then try to upload again
  2. make sure you have the Arduino Uno (or whatever model Arduino you are using) selected under Tools>>Board
  3. sometimes the Arduino doesn't like it when you have things connected to digital pins 0 and 1 during the upload process (these pins are connected to the Serial port as well), try disconnecting any wires from those pins and re-uploading.

let me know if that solves it! Also what kind of computer are you using? MAC/PC?

Thanks so much! It works now.

amandaghassaei (author)  roeyb16 months ago

great!

PC and I will try it ASAP

unigamer7 months ago

Great instructable! I used this as the basis for my version which uses a Pro Mini. I changed a few things:

- removed arduino equivalent commands (they're slower and I couldn't be bothered re-writing them for my setup)
- reduced the number of LEDS from 20 to 18 (consequently had to change the bit shifting code a little bit)
- added the ability to change the message using a serial connection (I use a bluetooth serial adapter)
-
changed the way the letters are called so different functions are not
needed for M and W (they're longer than the other characters)
- added punctuation marks: ? ! / : + = -

My code is available from this page: http://jonathanjamieson.com/projects/electronics/p...

Or if you want a direct link: http://jonathanjamieson.com/POV%20Wand%20Mini%20-%20Files.zip

unigamer unigamer7 months ago

Also, I wrote a little program that converts at bitmap monochrome into 1's and 0's to make it easier to draw pictures for the wand. It will work with the code in this instructable as well as mine (just be sure to make the image height the correct number of pixels to the number of LEDs you have!

amandaghassaei (author)  unigamer7 months ago

nice!

hammondsenior7 months ago

hi there, firstly I love this! I made one of my own and it worked like a dream! It was my first arduino project and I learnt loads from it. I like to make various devices to use for light painting photography which is why this appealed to me so much. However, I got ahead of myself and decided to make a bigger version. Basically I made the same thing but instead of all the LEDs being individually wired to the shield, I put four times the amount of LEDs in and soldered them into fours. Now my wand is 80 LEDs long, with there being four for every wire from the shield if that makes sense. It works the same as the 20 LED wand, only I didn't consider the dimensions of the letters, so now they come out the same width as they do with the small wand, but are four times the height! Can anybody help me with what I can do to make them four times wider to match the height? Any help or advice would be greatly appreciated.
One other thing, I soldered a 26 way socket onto the shield and ran the ribbon cable from the corresponding plug to the LEDs. It works the same, but now it allows me to easily unplug the arduino from the wand and move it to a different sized or coloured wand. This was to save me having to buy multiple boards and shields, and to allow me to chop and change if I'm out taking light painting.
Cheers,

Craig.

amandaghassaei (author)  hammondsenior7 months ago

very cool, increase the value of "refreshrate"

hneira7 months ago

Hi, beautiful Project, but I try change the text ("POV" for "HELLO") and the text not change. Do you know why?

pov.png
hneira hneira7 months ago

Solution: I disconnect the pin 0 and 1, and I discharge the proyect.

amandaghassaei (author)  hneira7 months ago

yes!

1-40 of 148Next »