Introduction: Persistence of Vision Globe
Described in this Instructable is the tale of two high school seniors, Grace and Fiona, attempting to build GreatScott's POV (persistence of vision) globe. After a great deal of trial and error, they finally succeeded on a rainy California afternoon and celebrated the flashing of light emitting diodes as a hall effect sensor passed a magnet. Today, they recount their experience, from the very beginning to the very end.
Persistence of vision is the optical illusion where light leaves a glowing trail as it moves. Our POV globe takes advantage of that illusion by rapidly rotating a semicircle of LEDs that flashes in a specific pattern dictated by the Arduino to display various messages.
Much appreciation to Ms. Berbawy and Berbawy Makers for all the help throughout the project!
Supplies
Electronics
- Arduino Nano (1)
- SK9822 LED Strip (144 LED/m density)
- APA102 works as well
- U18 Hall Effect Sensor (1)
- LiPo Battery (1)
- TP4056 Protect/Charge Circuit (1)
- 5V Boost Converter (1)
- DC Motor w/ high RPM (1)
- 10k Ohm Resistor (1)
Mechanical
- 8mm Ball Bearing (1)
- Radial Magnets
- Wood
- Corner Braces (2)
- 8mm Steel Rod (1)
- 8mm/5mm Shaft Collar (1)
- Vex Steel Bar
- M3-0.5 x 12mm Screws and Nuts (3)
- M4-0.7 x 20.5mm Screws and Nuts
- M4-0.7 x 100mm Screws (2)
Tools used
- Prusa MK3 3D Printer
- Electric saw
- Orbital sander
- Drill press
- Soldering iron
- Hacksaw
- Power supply
- 12" Metal Pan and Box Brake
- Hot glue
Step 1: Planning
The first thing we started on was a CAD model of the POV globe on Autodesk Fusion 360. This served as our reference for what we wanted the end result to look similar to. We utilized premade CAD files of parts that we would use for our globe (e.g. screws, shaft collars, motors, etc.), and then adjusted some of the sizes as necessary.
Step 2: Printing the Frame and Holder
We remade our version of GreatScott's frame and cuboid CAD models on Autodesk Fusion 360, making sure we adjusted the screw holes to accommodate M3 screws and nuts. GreatScott's models can be found in his Instructable. The attached .3mf files are the models we made and printed.
Print settings we used:
This took about 6 hours to print.
This is what the print looked with supports still attached:
This is the complete cuboid.
Step 3: Cutting the Wood
We opted for wood instead of steel (which is what GreatScott used) due to greater accessibility and forgivibility for mistakes.
- Base/bottom plate: 20cm x 20cm x 2cm thick
- Side piece: 2 in. wide x 15 in. height x 0.3 in. thick
- Top piece: 2 in. wide x 5.5 in. long x 0.5 in. thick
The dimensions of all pieces can be adjusted slightly, as long as they are accurately tracked throughout the process. However, we recommend sticking with the listed dimensions for the bottom plate and side piece as it best accommodates the size of the 3D-printed circle frame.
Step 4: Drilling the Wood
Marking:
- To find the center point of the bottom plate and side piece, we marked the midpoints of each side to draw a line connecting one side to the other. Then, once the midpoints from one side to another are connected, the intersection created by the two lines indicates the center of the wood piece.
- Then, we marked two dots from the center point to indicate where the position of the screws for the motor. For us, each screw was 20.5mm away from the center.
- We placed the side piece vertically against the side of the base plate and lined up the center line of the side piece with the center line of the bottom plate.
- Then, we placed the corner bracket at the intersection and marked the screw holes on both the bottom plate and side piece.
- We repeated steps 3-4 with the top piece and side piece.
Drilling:
- We used a 4mm drill bit to drill through all the marked spots.
- We made sure to accommodate the screw head at the bottom of the base plate and drill into the wood according to the head type of the screw used for the motor. To do this, we created a counterbore hole by drilling as deep as the height of the screw head and used a drill bit a little bit wider than the screw head. (TIP: use progressively larger drill bits to avoid splintering the wood when drilling larger holes.) (Note: Now would be the best time to paint the wood, which we did later in the process, which ended up more troublesome than if we had done it after cutting and drilling the holes.)
- Then, we screwed the corner bracket into the base and side wood piece.
Ball bearing:
- We projected the shaft of the motor to a location on the top piece so that the shaft stays upright at a 90° angle.
- Then, we traced the ball bearing around the marked location.
- We drilled the hole and then used a Dremel rotary sander to smooth the inside of the hole.
- Once a hole matching the size of the ball bearing was achieved, we put the ball bearing in.
Note: We did not screw in the top piece to the side piece yet.
Step 5: Install Motor
We removed the two screws at the bottom of the motor, making sure to keep the bottom part of the motor intact (it will be difficult to reassemble the motor once it is pulled apart).
Aligning the screw holes of the motor with the two center screw holes of the bottom plate, we used M4 x 100mm screws to screw the motor with the bottom plate.
Then, we screwed the shaft collar onto the motor shaft, leaving half the space for the steel rod.
Step 6: Cutting and Drilling Into the Steel Rod
Balancing the steel rod on the motor's shaft, we marked the rod a few centimeters above where the top wood piece meets the rod. Using a hacksaw, we cut the 8mm diameter steel rod (can also be aluminum) at the mark.
Next, we put the rod through the 3D printed frame and center holder in its designated hole. (Remembering to leave enough room above the LED frame so it can go through the top wood piece.) Then, we marked the pole where the screw holes of the prints go. Using a drill press, we carefully drilled 3mm holes where marked. It is of utmost importance that the screw holes are aligned, otherwise the prints cannot be secured into the pole.
Step 7: Putting It All Together
Now that we have everything prepared, the rest of the supplies can be screwed in. At this point, the POV globe looked like an "L" with a motor screwed into the base.
- We slid the LED frame and the cuboid into the steel pole. Ensuring the screw holes are lined up, we screwed it in. We tightened it with nuts so the vibration does not loosen items off.
- Then, we slid the steel pole into the ball-bearing hole of the top wood piece. Balancing the edge of the top piece with the top of the side piece, we screwed the corner bracket into the top and side piece.
We connected the motor to the power supply, and the afterimage of a sphere showed up. Pretty neat!
Step 8: Boost Converter + Charge Circuit
For this step, we needed the LiPo battery, the protect/charge circuit, and the boost converter. We soldered the wires according to the diagram provided (since TinkerCAD doesn't have these circuits, we had to improvise using our drawing skills). It was best to keep wires color-coded: red for power and white for ground.
5V Boost Converter: In addition to soldering the boost converter to the protect/charge circuit, two wires (one red, one white) were soldered to the end of the converter, labeled VOUT+ and VOUT-. The red wire is soldered to the VOUT+; the white wire is soldered to the VOUT-.
There is an alternative to this step, using GreatScott's PCB. However, we decided to use the other option, which was the bulkier boost converter and charge circuit. It worked out in the end, though.
Step 9: Hall Effect Sensor
The Hall effect sensor was integral to this build and it was of utmost importance that the Hall effect sensor worked as expected for any of the Arduino code to work. Fortunately, it was relatively simple.
The first thing we did was solder three wires onto the Hall effect sensor to extend its prongs. They are color-coded in the picture: blue is power; white is ground; yellow is data.
We decided to use a breadboard to minimize mistakes before soldering anything together.
- We put the Hall effect sensor somewhere on the breadboard.
- Connected a 10k Ohm resistor to the power wire and the data wire of the sensor. They were placed on different rows.
- The sensor's ground wire was on the other side of the breadboard.
- We connected the circuit to power. Power should go into the power wire of the sensor and out of the ground wire.
- Now we tested it. Using a multimeter, we measured the voltage across the data and power wires of the sensor as a magnet closely passed by the tapered side of the sensor. The multimeter read 5V as the magnet passed, then immediately reset to 0V once the magnet was no longer nearby the sensor.
Note: TinkerCAD has no Hall effect sensor available for use, so the provided TinkerCAD screenshot is simply a visual guide to accompany the breadboard picture. In the screenshot, power is red, data is yellow, and ground is black.
Now that the circuit was tested to work properly, we soldered it together and glued it on!
To do this, we took a ruler or long straight edge, aligned it horizontally through the center of the cuboid holder and LED frame, and marked a dot on one side of the LED frame at that horizontal. This was the point where the LED frame was closest to the side piece.
We resoldered a long enough wire to the ground (center pin) of the hall effect sensor so it can reach from the aforementioned dot up to the top of the LED frame, and reach down the steel rod to the center cuboid holder. The data and power wires were only long enough to reach from the dot to the top of the LED frame where the steel rod is.
At the end of the data wire, we soldered one side of the 10k ohm resistor and another piece of shorter wire that reaches down the steel rod to the center cuboid center, doing the same for the power wire.
Note: we added heat shrink to the ground and power wires before soldering to shrink later to protect the connection.
Following the circuit schematic provided in GreatScott's Instructable, we soldered the data wire to D3 of the Arduino Nano. The ground and power wire will be soldered to the rest of the ground and power wires later.
We used hot glue to attach the hall effect sensor and wires to the LED frame, making sure to avoid applying glue on the hall effect sensor itself as it may disrupt its function.
Step 10: LED Strip
Cutting to size:
The first thing we did with the LED strip was cut out a segment of the strip to fit one-half of the LED frame. Fitting the LED segment into the frame was quite tight, but because of how quickly the motor needed to rotate, it was essential we glued it down once the build was complete.
Soldering:
Next, we soldered wires onto the contact points of the end of the LED segment where it reaches the top of the frame (unless it already has wires soldered on). A good idea is to keep the wires color-coded: red for power, white for ground.
The final step regarding LEDs was to solder the data wires to pins on the Arduino: the wire at the contact point labeled 'C' is soldered to pin D13 on the Arduino, and the wire at the contact point labeled 'D' is soldered to pin D11. This left us the two power wires.
Step 11: Soldering the Power Wires
Before we soldered all the power wires together, the Arduino Nano also needed to be soldered. At the 5V and GND pins, we soldered a red and white wire respectively.
Now, we had a bunch of power wires of two colors hanging about. We soldered the red wires and white wires into their color groups. Thus, we were left with two groups of soldered wires: one red and one white. To prevent shorting, we heat-shrinked the wires.
Step 12: Checking Output Voltage of the Circuit
We needed to ensure our boost converter circuit was putting out 5V for the system. Using a multimeter, we measured the voltage from the input to the boost converter's output (making sure the LiPo battery was charged first). If 5V was not being put out, we turned the potentiometer clockwise until 5V was reached.
Note: At first, it took a while and many rotations of the potentiometer until any change was seen.
Step 13: Coding the Arduino
The code for the Arduino is pretty simple. The library FastLED.h must be downloaded, otherwise the code will not compile.
It starts off with initializing variables and other Arduino things, including an array of LEDs.
Next, Boolean 2D arrays are initialized. Each element is either a 0 for false or 1 for true. A 0 indicates the LED is not lit up, a 1 indicates the LED is lit up. Each 2D array represents a character.
The setup() method is the interruption method integral to how the LEDs can achieve a persistence of vision effect.
The loop() method is what we see on the LED strip. If the sensor detects a magnet, then the 2D arrays are lit up in the order they go. This allows us to write words on the globe.
Customizability:
- Variable wait is the initial delay between the sensor detecting the magnet and the LEDs lighting up.
- Variable wait2 is the width of each array.
- Each 2D array can be adjusted to liking.
- The loops in the loop() method can be adjusted to liking.
Once uploaded to the Arduino (and the LiPo battery is charged), the LEDs should flash with every passing of the magnet against the Hall effect sensor. With the successful test, we glued the number of radial magnets needed for the sensor to detect its fields to the wooden side piece. Magnets should be glued where the sensor is closest to the piece, but a larger magnet can compensate for inaccuracy.
Attachments
Step 14: Creating an Interactive Server
We wanted to add an interactive factor to the POV globe, so we created a local web server using Visual Studio Code (VSC) that took character inputs and generated a code we could copy-paste into the Arduino IDE. Furthermore, this increased our efficiency in creating new messages to display since we did not have to manually type the code each time we wanted to create a new message.
We designed the server to allow the user to input a message and select a color using the color picker to customize their message.
In VSC, we created three text files within one folder. Each file will be written in a different language: Javascript, CSS, and HTML. The Javascript file was used for backend development and the CSS and HTML files were used for frontend development.
The files attached are text files containing the code for each file.
Javascript:
The file, titled "app-javascript," contains the script that will be generated in the bottom text box once the "Generate Code" button is pressed. Within this code, the part that allows the message to be customizable is the IF function (code lines 744-767) that plugs the message written in the first text box into the generated code. However, when we wrote this code, it was important for us to keep in mind of constants and symbols that were invalid in the boolean code.
For example, since the exclamation mark symbol "!" is an invalid character within the boolean code, we assigned it by "ExcM." Therefore, once the user inputs an exclamation mark in the first text box, the javascript code will replace it with "ExcM" within the generated code.
CSS:
The file, titled "style-css," is used to customize and style elements (e.g. color and font of the title, size of text boxes, size of margins, etc.).
HTML:
The image below is the code we wrote, which connects the backend information from the Javascript file and the styling of the frontend in the CSS file. It is used to organize the different elements within the server. Furthermore, it can be used to style elements similar to the CSS file, however, we found it easier to do most of our styling within the CSS file as it was easier to keep track of each element.
Additionally, this file allowed us to change the color of the message displayed as it pulled the RGB code selected in the color picker and updated the color value within the generated code.
Step 15: Final Touches
Gluing:
Using hot glue, we glued the boost converter & charge circuit to one side of the center cuboid holder, and the Arduino to the other side. We also used hot glue to glue down the LED strip as well.
Vibration Adjustments:
- A lot of vibration is caused because the globe was not equal in weight on both sides. Because the Hall effect sensor weighs less than the LED strip, we measured the difference in weight, and then used fan balancing weights to compensate for the difference in weight.
- There was still quite a bit of vibration in the base, so we cut and bent two VEX steel bars to form a triangle at the corner brackets.
- However, it still shook a little, so we plan to add a large weight to the wooden base in the future.
- We recut a new top piece for we opted to use a thicker cut of wood.
- If you do the same, try to use one ball bearing despite its ugliness; we found it became extremely difficult to avoid friction on the steel pole and it slowed the motor down with more ball bearings.
Step 16: Complete!
Viewing the video:
- To properly see the message ("HI PERIOD6!") displayed on the POV Globe, set the video settings to the highest possible framerate. This should be 720p60.
Optional add-on:
- As of right now, we're working on adding a drawing application to the website so we can take drawn input and output both a 2D array and loop() code for the Arduino IDE.
- Efficiency: right now our only option with this website is to constantly reset the Arduino and then upload the new code to it.
- If we added a shield or used a different Arduino, we would be able to send the code directly to the Arduino. However, that's not our priority right now.
Ta-da! The Persistence of Vision Globe is finished!