In this project, I will show you how to build a simple POV Display using Arduino Nano. This POV Display Project can be modified to display any text on a rotating LED Display. There are few Spinning LED Display modules available in the market but I thought why not make one myself.
Introduction
We have already seen a project based on the concept of Persistence of Vision or simple called as POV. That project was the 8x8x8 LED Cube. In that project, there are 512 LEDs in the cube but as it is difficult to control all of them at once, I was controlling 64 LEDs at a time and POV does the rest of the magic.
Coming to this project, here the concept remains the same i.e. tricking our brain to believe that an object is present while it is actually not. A POV Display or a Rotating LED Display is a simple concept where we light LEDs at a variety of sequences in order to get an illusion of a Text being displayed.
Output Video
Circuit Diagram of POV Display
The following image shows the circuit diagram of the POV Display using Arduino Nano.

Components Required
I will list out the circuit related components here. There are other tools and stuff you might require in order to construct this POV Display. I will mention those while I explain the construction.
- Arduino Nano
- LEDs x 8
- 100Ω Resistors x 8
- 3.7V LiPo Batteries x 2
- IR Sensor Module
- Slide Switch
- Perf Board
- 12V DC Motor
- Power Supply for Motor

Constructing the POV Display
Now, let me take you through a step-by-step construction of the POV Display.
Getting the Base Board Ready
First, take a perf board as the one shown in the image and make a hole at the center to insert the motor’s shaft. In order to fix the motor to the board, I have used a pair of rubber holders on either side of the board.

Mounting Arduino Nano
Solder two female header strips to insert the Arduino Nano. Position these headers with the hole for motor as center.

Solder LEDs and Resistors
Take 8 LEDs and place them in a row. Solder them to the perf board. Position these LEDs approximately at the center point between the edge of the board and hole drilled for inserting the motor.
After soldering all the LEDs, solder individual current limiting resistors to the anode terminals of the LEDs.

Connecting LEDs to Arduino
The other end of the resistor must be connected to Arduino. So, take a bunch of single gauge wire and connected the resistors to corresponding pin of the Arduino Nano.
Also, all the Cathode terminals the LEDs can be shorted with a long wire and connect this wire to the GND terminal of Arduino Nano.

Terminals for Battery
I have taken a pair of two-pin female headers and soldered it near the Arduino Nano. These headers are connected to individual batteries. The Positive terminal of first battery and Negative Terminal of second battery (through the headers) are connected to VIN and GND of Arduino Nano.
Additionally, a slide switch is connected between these two headers. Out of the three pins of the switch, the first one is left open, the middle pin is connected to negative of First Battery and the last pin is connected to Positive terminal of the second battery.

When the switch is in left position i.e. open, batteries are not connected and the power to the Arduino Nano is terminated. During this position, you can charge the batteries using a TP4056 Battery Charger with the help of those 2-pin headers.
Once the switch is move to the other position, the batteries are connected in series and 7.4V is supplied to Arduino Nano to power on the circuit.
Placing the Batteries
Two 3.7V LiPo Batteries are used in this project and both these batteries are placed on either side of the Nano board. Make the connections as mentioned in the above section.

IR Sensor
A Transmissive Type IR Sensor is placed at the other end of the perf board but on the opposite side. It has three pins namely VCC, OUT and GND. VCC and GND are connected to +5V and GND of Arduino Nano while the OUT pin is connected to Pin 10.

Mounting Base
This completes the board part of the design. Next, lets make the stand or the base. Take a piece of wood and make a hole to insert the motor. Fix the perf board to the motor using holders.

Next, take a small piece of plastic and fix is on the base such that it passes through the IR Sensor. The obstacle shouldn’t touch the IR Sensor or the perf board.

This finishes the complete construction of the POV Display using Arduino Nano.
Code
The code for the project is given below.
#include <TimeLib.h> | |
int LED_PINS[] = {9,8,7,6,5,4,3,2}; | |
int INPUT_PIN = 10; | |
int DEFAULT_LED =13; | |
int CUSTOM_CHAR_LENGTH = 5; | |
int LED_COUNT = 8; | |
int k; | |
const unsigned char CUSTOM_CHAR[95][5] = { | |
{0x00,0x00,0x00,0x00,0x00}, // 0x20 32 | |
{0x00,0x00,0x6f,0x00,0x00}, // ! 0x21 33 | |
{0x00,0x07,0x00,0x07,0x00}, // ” 0x22 34 | |
{0x14,0x7f,0x14,0x7f,0x14}, // # 0x23 35 | |
{0x00,0x07,0x04,0x1e,0x00}, // $ 0x24 36 | |
{0x23,0x13,0x08,0x64,0x62}, // % 0x25 37 | |
{0x36,0x49,0x56,0x20,0x50}, // & 0x26 38 | |
{0x00,0x00,0x07,0x00,0x00}, // ‘ 0x27 39 | |
{0x00,0x1c,0x22,0x41,0x00}, // ( 0x28 40 | |
{0x00,0x41,0x22,0x1c,0x00}, // ) 0x29 41 | |
{0x14,0x08,0x3e,0x08,0x14}, // * 0x2a 42 | |
{0x08,0x08,0x3e,0x08,0x08}, // + 0x2b 43 | |
{0x00,0x50,0x30,0x00,0x00}, // , 0x2c 44 | |
{0x08,0x08,0x08,0x08,0x08}, // – 0x2d 45 | |
{0x00,0x60,0x60,0x00,0x00}, // . 0x2e 46 | |
{0x20,0x10,0x08,0x04,0x02}, // / 0x2f 47 | |
{0x3e,0x51,0x49,0x45,0x3e}, // 0 0x30 48 | |
{0x00,0x42,0x7f,0x40,0x00}, // 1 0x31 49 | |
{0x42,0x61,0x51,0x49,0x46}, // 2 0x32 50 | |
{0x21,0x41,0x45,0x4b,0x31}, // 3 0x33 51 | |
{0x18,0x14,0x12,0x7f,0x10}, // 4 0x34 52 | |
{0x27,0x45,0x45,0x45,0x39}, // 5 0x35 53 | |
{0x3c,0x4a,0x49,0x49,0x30}, // 6 0x36 54 | |
{0x01,0x71,0x09,0x05,0x03}, // 7 0x37 55 | |
{0x36,0x49,0x49,0x49,0x36}, // 8 0x38 56 | |
{0x06,0x49,0x49,0x29,0x1e}, // 9 0x39 57 | |
{0x00,0x36,0x36,0x00,0x00}, // : 0x3a 58 | |
{0x00,0x56,0x36,0x00,0x00}, // ; 0x3b 59 | |
{0x08,0x14,0x22,0x41,0x00}, // < 0x3c 60 | |
{0x14,0x14,0x14,0x14,0x14}, // = 0x3d 61 | |
{0x00,0x41,0x22,0x14,0x08}, // > 0x3e 62 | |
{0x02,0x01,0x51,0x09,0x06}, // ? 0x3f 63 | |
{0x3e,0x41,0x5d,0x49,0x4e}, // @ 0x40 64 | |
{0x7e,0x09,0x09,0x09,0x7e}, // A 0x41 65 | |
{0x7f,0x49,0x49,0x49,0x36}, // B 0x42 66 | |
{0x3e,0x41,0x41,0x41,0x22}, // C 0x43 67 | |
{0x7f,0x41,0x41,0x41,0x3e}, // D 0x44 68 | |
{0x7f,0x49,0x49,0x49,0x41}, // E 0x45 69 | |
{0x7f,0x09,0x09,0x09,0x01}, // F 0x46 70 | |
{0x3e,0x41,0x49,0x49,0x7a}, // G 0x47 71 | |
{0x7f,0x08,0x08,0x08,0x7f}, // H 0x48 72 | |
{0x00,0x41,0x7f,0x41,0x00}, // I 0x49 73 | |
{0x20,0x40,0x41,0x3f,0x01}, // J 0x4a 74 | |
{0x7f,0x08,0x14,0x22,0x41}, // K 0x4b 75 | |
{0x7f,0x40,0x40,0x40,0x40}, // L 0x4c 76 | |
{0x7f,0x02,0x0c,0x02,0x7f}, // M 0x4d 77 | |
{0x7f,0x04,0x08,0x10,0x7f}, // N 0x4e 78 | |
{0x3e,0x41,0x41,0x41,0x3e}, // O 0x4f 79 | |
{0x7f,0x09,0x09,0x09,0x06}, // P 0x50 80 | |
{0x3e,0x41,0x51,0x21,0x5e}, // Q 0x51 81 | |
{0x7f,0x09,0x19,0x29,0x46}, // R 0x52 82 | |
{0x46,0x49,0x49,0x49,0x31}, // S 0x53 83 | |
{0x01,0x01,0x7f,0x01,0x01}, // T 0x54 84 | |
{0x3f,0x40,0x40,0x40,0x3f}, // U 0x55 85 | |
{0x0f,0x30,0x40,0x30,0x0f}, // V 0x56 86 | |
{0x3f,0x40,0x30,0x40,0x3f}, // W 0x57 87 | |
{0x63,0x14,0x08,0x14,0x63}, // X 0x58 88 | |
{0x07,0x08,0x70,0x08,0x07}, // Y 0x59 89 | |
{0x61,0x51,0x49,0x45,0x43}, // Z 0x5a 90 | |
{0x3c,0x4a,0x49,0x29,0x1e}, // [ 0x5b 91 | |
{0x02,0x04,0x08,0x10,0x20}, // \ 0x5c 92 | |
{0x00,0x41,0x7f,0x00,0x00}, // ] 0x5d 93 | |
{0x04,0x02,0x01,0x02,0x04}, // ^ 0x5e 94 | |
{0x40,0x40,0x40,0x40,0x40}, // _ 0x5f 95 | |
{0x00,0x00,0x03,0x04,0x00}, // ` 0x60 96 | |
{0x20,0x54,0x54,0x54,0x78}, // a 0x61 97 | |
{0x7f,0x48,0x44,0x44,0x38}, // b 0x62 98 | |
{0x38,0x44,0x44,0x44,0x20}, // c 0x63 99 | |
{0x38,0x44,0x44,0x48,0x7f}, // d 0x64 100 | |
{0x38,0x54,0x54,0x54,0x18}, // e 0x65 101 | |
{0x08,0x7e,0x09,0x01,0x02}, // f 0x66 102 | |
{0x0c,0x52,0x52,0x52,0x3e}, // g 0x67 103 | |
{0x7f,0x08,0x04,0x04,0x78}, // h 0x68 104 | |
{0x00,0x44,0x7d,0x40,0x00}, // i 0x69 105 | |
{0x20,0x40,0x44,0x3d,0x00}, // j 0x6a 106 | |
{0x00,0x7f,0x10,0x28,0x44}, // k 0x6b 107 | |
{0x00,0x41,0x7f,0x40,0x00}, // l 0x6c 108 | |
{0x7c,0x04,0x18,0x04,0x78}, // m 0x6d 109 | |
{0x7c,0x08,0x04,0x04,0x78}, // n 0x6e 110 | |
{0x38,0x44,0x44,0x44,0x38}, // o 0x6f 111 | |
{0x7c,0x14,0x14,0x14,0x08}, // p 0x70 112 | |
{0x08,0x14,0x14,0x18,0x7c}, // q 0x71 113 | |
{0x7c,0x08,0x04,0x04,0x08}, // r 0x72 114 | |
{0x48,0x54,0x54,0x54,0x20}, // s 0x73 115 | |
{0x04,0x3f,0x44,0x40,0x20}, // t 0x74 116 | |
{0x3c,0x40,0x40,0x20,0x7c}, // u 0x75 117 | |
{0x1c,0x20,0x40,0x20,0x1c}, // v 0x76 118 | |
{0x3c,0x40,0x30,0x40,0x3c}, // w 0x77 119 | |
{0x44,0x28,0x10,0x28,0x44}, // x 0x78 120 | |
{0x0c,0x50,0x50,0x50,0x3c}, // y 0x79 121 | |
{0x44,0x64,0x54,0x4c,0x44}, // z 0x7a 122 | |
{0x00,0x08,0x36,0x41,0x41}, // { 0x7b 123 | |
{0x00,0x00,0x7f,0x00,0x00}, // | 0x7c 124 | |
{0x41,0x41,0x36,0x08,0x00}, // } 0x7d 125 | |
{0x04,0x02,0x04,0x08,0x04}, // ~ 0x7e 126 | |
}; | |
char Display_String[] = “Electronics Hub“; | |
void setup() | |
{ | |
pinMode(DEFAULT_LED, OUTPUT); | |
pinMode(INPUT_PIN, INPUT); | |
for (int i = 0; i < LED_COUNT; i++) | |
{ | |
pinMode(LED_PINS[i], OUTPUT); | |
} | |
} | |
void loop() | |
{ | |
while(digitalRead(INPUT_PIN) != 0) | |
{ | |
digitalWrite(DEFAULT_LED, LOW); | |
} | |
digitalWrite(DEFAULT_LED, HIGH); | |
for (int a=sizeof(Display_String)-1; a>-1; a–) | |
{ | |
PRINT_STRING(Display_String[a]); | |
} | |
} | |
void PRINT_STRING(char data) | |
{ | |
if (data < 32 || data > 126) | |
{ | |
data = 32; | |
} | |
data -= 32; | |
for (int x=CUSTOM_CHAR_LENGTH-1; x>-1; x–) | |
{ | |
byte temp_data = CUSTOM_CHAR[data][x]; | |
for (int y=0; y<LED_COUNT; y++) | |
{ | |
digitalWrite(LED_PINS[y], bitRead(temp_data,y)); | |
} | |
delayMicroseconds(500); | |
} | |
for ( k = 0; k < LED_COUNT; k++) | |
{ | |
digitalWrite(LED_PINS[k] , LOW); | |
} | |
delayMicroseconds(250); | |
} | |
How POV Display Works?
Let me explain the working of the POV Display project with the help of a simple example. Consider you want to display the alphabet ‘B’. In order to display this character, the LEDs get turned on and off in a pattern over 5 steps. Each step is associated with a column of the LEDs and shown in the following image.

The delay between the switching of the columns is very less usually in the order of hundreds of microseconds (as you can see in the code).
In order to fix a starting point, the Arduino uses the IR Sensor as a reference i.e. when ever a signal from the IR Sensor is received, it starts displaying the text.