Introduction: Digilog_Bike POV Display

  • Digilog

Digital + Analog

Digital meets analog

  • POV

Persistance Of Visual

Also known as afterimage display, if shaken at high speed, afterimage remains.

People think they are watching video when they watch TV. But in fact, he is looking at several consecutive pictures. This is mistaken for an image because of the effect of afterimages remaining on our retinas when viewing successive pictures. This kind of illusion is called a POV.

Step 1: Idea Concept

POV is implemented by attaching an LED strap to the wheel of a bike.

Step 2: Materials List

Step 3: Tools

Not too many tools needed however you will need :

1. Soldering Machine

2. A Soldering iron

3. Glue gun

4. Nipper

Step 4: Making Frame

Cutting the Bike and Attaching the Base

The grinder was used to cut the bike wheels off the bike and welded steel plates to secure the wheels.

Step 5: Sketching Final Images and Concepts

We picked a dragon as the final image. Because the wave of the dragon seemed to be best represented by the afterimage effect.

Step 6: Make Moving Image Cut

Divide the image into three parts that will fit on each bike and divide the total of 12 images by color and motion.

Step 7: Software Prepare

  • Sub part 1. Install Arduino

Arduino Download:

(Install to fit your OS version and system.)


  • Sub part 2. Install library
*( If you would like to install through Github, please visit the link above Github Arduino Library: )

1. Run Arduino program

2. Allow the link Top menu – sketch – include library – add .Zip library

3. You should choice the .Zip file that already installed github library4


*( If you want using the Arduino program services )

1. Run Arduino programs

2. Allow the link Top menu – sketch – include library – management library – searching ‘Adafruit neopixel’ – you can see ‘Adafruit Neopixel by Adafruit’

3. Install and update library


  • Sub part 3. Install converter program

1. Install Rotation Circle Program (R.C.P):

2. You need to reading a README file

Step 8: Making Hardware Power Supply

*This is how to supply Arduino 5V voltage through the battery.
Please follow the steps below.

1. Connect Lithium battery and JBATT charging module. (For reference, JBATT module has a built-in power switch.)

2. Connect the output terminal of JBATT to Vin terminal of Arduino and Ground terminal.

3. Connect the Micro 5pin usb port to the charging port to check if the product has been working properly.

4. Next, turn the built-in switch to ON.

5. If the red led lights up and the green led lights up in Arduino, the product power stage configuration is completed normally.

Step 9: Making Hardware I/O & Checking OUTPUT(NeoPixel Working)

*This part consists of sensor and output stage.

1. Connect the Arduino and Hall sensors. The data pin connects to Arduino pin 2.

2. When the Arduino is powered up and the magnet is in close contact with the Hall sensor, the red led will light up.

3. Connect Arduino and Neopixel. Only 30 Neopixels are used.

4. Connect the data pin with Arduino pin 6.

5. Connect the Arduino and download cable to your computer's usb port and run Arduino on your computer.

6. Select Tool – board – “Arduino / Genuino Mega or Mega 2560” from the top menu bar of Arduino program.

7. Check if there is a list of products that can be directly connected to the port. If it is not checked, click to select it.

8. Paste the code below and click Upload at the top left. (Afterwards, all program uploads follow steps 5-8.)

9. Configuration is complete when all 30 neoled pixels turn on.


#1. including header file and preprocessing

First we need to bring the library Adafruit_NeoPixel that is able to act Neopixels.

Library can be used by declaring objects.

Adafruit_NeoPixel class can input 3 parameter's in public.

The first parameter is the number of LEDs.

seconds parameter is the pin number connected to the Neopixel digital input.

Third parameter is to input options according to the product characteristics. three-color WS2812b product uses the 'NEO_GRB' input

#include <Adafruit_NeoPixel.h>
#define PIN 6
Adafruit_NeoPixel strip = Adafruit_Neopixel(30,PIN,NEO_GRB+NEO_KHZ800);

#2. setup

In the setup part, initialize the object and prepare it for use.

'Adafruit_Neopixle_Object.begin()' sets all LEDs to turn off.

'' outputs with the brightness set in the LED.

void setup(){

#3. main loop

The action of main loop uses a for loop to sequentially output (0.1 seconds) the LEDs in white

void loop(){
	for(uint16_t i=0;i<strip.numPixels();i++){

Step 10: Assembling and Attach to the Wheel

1. Connect Neopixels. (Pay attention to pin number check)

2. Connect the Hall Sensor. (Refer to Step.9)

3. Attach the frame to the Arduino between the bikes.(Attach the Arduino case parallel to the bicycle frame).

4. Insert the Arduino connected to Neopixel. (Be careful because the glue gun is hot).

5. Insert the connected Hall sensor into Arduino, (Secure the cable tie so that the Hall sensor does not fall off).

6. Solder to connect battery. (Be careful when you solder).

7. Fix it with a glue gun. (Attach the charging module on the battery to secure space).

8. Plug in each line before connecting to Arduino,

9. Plug in according to each pin number. (Connect the jump lines for the charging module without confusing them).

10. Finish with a glue gun once, (Please be careful not to fall).

Step 11: Checking INPUT(HALL Sensor Data)

*Check the software code to see if the sensor is working.

1. Paste and upload the code below.

2. Click the Serial Monitor button on the top right of the Arduino.

3. When the magnet is in contact with the Hall sensor for more than 1 second, the configuration is completed when the word “contact magnetic” appears on the serial monitor.

#1. Define pin number and setup

The first configuration pin number to use the Hall sensor and set the pin number as an Input-only port.

Set the communication to check the data of Hall sensor on the serial monitor.

#define HALL 2
void setup(){
	pinMode(HALL, INPUT);

#2. main loop

Check the Hall sensor data at 0.1 seconds intervals.

If the magnet is sensed and the data is changed, "contact magnetic" is output to the serial monitor.

void loop(){
		Serial.println("contact magnetic");

Step 12: Coding Algorithm

*Create logic and coding to control Neopixels based on sensor values.

1. Paste and upload the code below.

2. It is normal for the image not to be displayed properly because no frame is produced. But you can see it works roughly.

3. Quickly touch and release the Hall sensor and magnet within 1 second. Repeat this operation about 10 times.

4. The configuration is complete when the colors of the Neopixels change regularly.


#1. Including header files and preprocessing

First, we must understand that the Arduino Mega's memory is not large enough to hold an image file.

Therefore, the 'avr/pgmspace' header file is used to utilize different memory space.

To use Neopixels, you declare an object and configuration an I/O pin number.

The image array is too large to coding, so download and paste the attached files.

#include <avr/pgmspace.h>
#include <Adafruit_NeoPixel.h>

#define PIN 6
#define NUMPIXELS 30
#define HALL 2

Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_RGB + NEO_KHZ800);

// paste array in 'image_array_1.txt'
// " 'image_array_2.txt'
// " 'image_array_3.txt'
// " 'image_array_4.txt'

#2. Global variable & setup

Set a global variable.

The main thing is to set the brightness, it was determines the life-cycle of the product.

int count = 0;
double v = 0;
double last_v = 0;
double timer = micros();
double ex_timer = micros();
double last_timer = micros();
int deg = 36;
int pix = 35;
int rgb = 3;
double q_arr[2] = {0, 0};
int HALL_COUNT = 0;
double VELO;
double processing_timer = micros();

void setup(){

#3. main loop - image expression output part

This code is a conditional statement about how to output the time the wheel spins by resolution.

This part uses the cycle of turning the bicycle wheel once as a very important parameter.

Also, it is important to reading image array data from memory.

void loop() {

  if ((count < 120) && ((micros() - timer) > (ex_timer / 120.0) - (micros() - processing_timer))) {

    timer = micros();
    if (VELO > 360000) {
      for (int i = 0 + 5; i < pix; i++) {
        strip.setPixelColor(i - 5, strip.Color(pgm_read_byte(&(image_1[count][i][1])), pgm_read_byte(&(image_1[count][i][2])), pgm_read_byte(&(image_1[count][i][0]))));
    else if (VELO <= 360000 and VELO > 264000) {
      for (int i = 0 + 5; i < pix; i++) {
        strip.setPixelColor(i - 5, strip.Color(pgm_read_byte(&(image_2[count][i][1])), pgm_read_byte(&(image_2[count][i][2])), pgm_read_byte(&(image_2[count][i][0]))));
    else if (VELO <= 264000 and VELO > 204000) {
      for (int i = 0 + 5; i < pix; i++) {
        strip.setPixelColor(i - 5, strip.Color(pgm_read_byte(&(image_3[count][i][1])), pgm_read_byte(&(image_3[count][i][2])), pgm_read_byte(&(image_3[count][i][0]))));
    else if (VELO <= 204000) {
      for (int i = 0 + 5; i < pix; i++) {
        strip.setPixelColor(i - 5, strip.Color(pgm_read_byte(&(image_4[count][i][1])), pgm_read_byte(&(image_4[count][i][2])), pgm_read_byte(&(image_4[count][i][0]))));
  else if ((count >= 120)) {
    for (int i = 0 + 5; i < pix; i++) {
      strip.setPixelColor(i - 5, strip.Color(0, 0, 0));

#4. main loop - processing and cycle time check & sensing

This is the most important part of the whole system.

First, check the time taken to execute the entire code and adjust the LED output time per cycle.

The time sensed each time the wheel is spinning predicts the time of the next cycle.

Acceleration can be estimated by subtracting the last measured cycle time from the on-time measured cycle time.

The system calculates the processing time and acceleration to calculate how long the LEDs turn on continuously.

  processing_timer = micros();

  if ((digitalRead(HALL) == HIGH) && (HALL_COUNT == 1)) {
    VELO = v;
    v = micros() - last_timer;
    ex_timer = q_arr[0] - q_arr[1] + v;
    last_timer = micros();
    q_arr[0] = q_arr[1];
    q_arr[1] = v;
    count = 0;
    HALL_COUNT = 0;
  else if (digitalRead(HALL) == LOW) {
    HALL_COUNT = 1;

Step 13: Using Software

*Use software to transform the image and insert procession data into the code.

1. Insert the image from the above step into the image folder in the R.C.P folder installed in the preparation step.

- How to put image is as follows.
- Rename 4 animated images of product # 1 in order of 1.png, 2.png, 3.png, and 4.png.
- Rename 4 animated images of product # 2 in order of 5.png, 6.png, 7.png, 8.png.
- Rename 4 animated images of Product # 3 in order of 9.png, 10.png, 11.png, 12.png.

2. Run the Ver.5.exe file.

3. Verify that 12 files pro_1_code_1.txt to pro_3_code_4.txt are created in the R.C.P folder.

4. If it is not created, change the contents of config.txt as the following configuration file.

5. Once the file is created, copy the entire content from the file pro_1_code_1.txt and paste it into the part shown in the code below.

6. Add the pro_1_code_2.txt, pro_1_code_3.txt, and pro_1_code_4.txt contents to the marked part in the 5th order.

7. Referring to 5 and 6, the pro_2_code... , pro_3_code completes the code the same way.

Step 14: Complete

Completed the production of a POV that creates one image with three wheels.