Introduction: Wooden Disc Player

About: Projects in light, music, and electronics. Find them all on my site:

I wanted to demonstrate how information storing devices work by building a large scale disc playing machine. Instead of being based on light interference like CD players, the device I built plays wooden discs with holes and "non-holes" (as I refer to them in this instructable) that either pass or block a laser beam. These holes and non-holes correspond to 1's and 0's in binary data that code a text message, like song lyrics or a quote. The binary information is read off the disc, stored on an Arduino, and decoded to display the text message on an LED matrix on the front of the device. As the data is being read, the LED matrix is populated to visualize the binary information. When a high bit is read, a MIDI note is also played. The music produced may sound random, but it symbolizes a series of 1's and 0's that actually holds meaningful information.

The wooden disc player I created can only hold about 700bits (<0.1kB) because of how large the holes are in the disc. Therefore, the messages that can be stored are short. For reference, a CD can hold around 700MB of information, which is about 10 million times more information than the wooden discs I made. The whole project helps imagine the scale of information storage on CDs (an already dated storage device) and how the digital information is read and decoded into something meaningful to humans.

In this instructable, I will go over the system design and construction, how the message was converted to binary information on a wooden disc, and the many challenges along the way.

The project was inspired by many sources, including:

  • 8-bit Show and Tell's channel had an awesome video about a secret message stored on a record that could be read on a Commodore 64
  • Mechanical music playing devices called polyphons, developed in the mid 1800's
  • Techmoan's video on the CED Videodisc developed by RCA


10X 10”x15”x1/8” plywood sheet

White acrylic sheet

1X 50RPM DC motor

1X Arduino Nano

1X H-bridge L9110

1X stepper motors Nema 17 Bipolar step motor (3.5V 1A)

1X 2mm lead screws

2X pillow blocks 21. Two lead screw nuts 22. Two bearing slide bushing and 200mm linear shafts:

1X DOT matrix display MAX 7219

1X 5V power supply

1X Mini USB cable

2X photodiodes -


1X IR photodiode

2X 650nm laser module

1X 5.5 x 2.5 mm Panel Mounting DC Power Jack

1X power switch -

1X MIDI jack -

3X LM358 op amp

2X NPN transistors

1X TIP120 transistor

2X diodes

3X 10k trim pots

Resistors as shown on system schematic

Prototype board

8mm diameter magnets -

Metric hardware kit

Step 1: System Overview

The purpose of the device is to decode a message stored on a wooden disc. In this step, I'll provide a quick overview of the entire process.

1. Pick a message. I chose messages from some of my favorite writers and musicians to store on the disc. In the example drawing above, I have the classic "don't panic!" from Hitchhiker's Guide to the Galaxy.

2. Create a binary conversion table. If you are unfamiliar with binary information, there are loads of useful books, courses, and videos for learning all about the process. The basic idea is to come up with unique combinations of 1's and 0's that correspond to some action, value, letter, or other entity. For my disc player, I focused on decoding messages. Therefore I created a table that connected 5-bit binary numbers to a character (e.g. 00100 corresponds to the letter "d"), which is attached in this step. The table I created is a truncated version of the 8-bit ASCII table.

3. Convert the message to binary. Using the table I created, each character in the message is converted to binary and saved to create one binary sequence.

4. Arrange the binary on a disc. Now that I had a binary message, I needed to consider how to to store the information on a wooden disc in a way that could be read out by a device. I decided to store the 1's and 0's as non-holes and holes arranged in a circle (just like a CD). Once a full revolution was filled with information, the next data would be stored in another row moving radially outward. I chose to read one bit at a time, so only one detector for data is required. As the disc spins, the holes and non-holes pass over the detector.

But how does the detector know when to read the data? How could I be sure the data detector was reading at the right moment when the hole in the disc was over the detector? I solved this problem by adding a "clock" detector that remains stationary on the device. The most inner ring on the disc has evenly placed holes. When the clock detector registers a falling or rising edge, the data detector reads in one bit of information. The processes listed from 2-4 were all done using Matlab and are discussed in Step 18.

5. Read in binary with the disc player. The clock and data detectors each consist of a laser and photodiode. When there is no hole, the laser reflects off the disc and hits the photodiode and registers a 1. The output of the photodiode is amplified, binarized with a Schmitt trigger, and read digitally with an Arduino Nano. After completing one row of the disc, a stepper motor (Nema 17 Bipolar step motor 3.5V 1A) translates the data detector down to the next row on the disc. The initial position of the rail holding the data detector is determined using a photointerrupt at the top position of the rail. The player consists of a MIDI output, which produces a note each time a 1 is read. Details of the circuit will be described in later steps.

6. Decode the binary and display a message. After the entire disc is read, the Arduino decodes the binary into the message and saves it as a string. The message is displayed onto the Dot Matrix display (MAX 7219).

Step 2: CAD Model, Laser Cutting, and 3D Printing

After lots of prototyping, I began the final design using Autodesk Fusion 360. A central mount holds the motors, clock detector, lead screw, rails, and LED matrix. The data detector sits on a bed that then translates along the rails. A power jack, MIDI jack, power switch, and USB access to the Arduino are all mounted on the back. The front and rear faces are attached with magnets so they can be removed and the electronics accessed. All the parts are mounted on a main chassis and then a smooth wooden exterior conceals the chassis.

I wanted the device's exterior to have rounded edges, which are difficult to achieve using laser cutting. To construct the lofted edge, I sliced the smooth part horizontally in Fusion and then lasercut each slice. One of the major challenges with this approach was making sure the stack of slices ended up being the correct height to line up with all the parts. For how challenging this was, I do not recommend this approach. The lasercutting files are attached.

The detectors for reading holes in the wooden disc, DC motor shaft mount, stepper motor mount, pillow block riser, and lead screw mount were all 3D printed. The STL files are attached in this step.

Step 3: Assembling the Exterior Top Layers

The top of the exterior case for the device consists of 14 layers. I aligned these layers so the front surfaces were flush. Between each layer wood glue was brushed on. After all the layers were added, I used several clamps to hold them together and dry overnight.

Step 4: Assembling the Back Layers

The back consists of 92 layers, which I labeled by etching the wood with the lasercutter. I used the CAD file to guide the alignment of these parts. On the third layer from the bottom, I hammered two M5 nuts into the wood. There are several joints that jut out of the layers that attach to the main chassis. The major problem was the variability in the wood thickness. I had to stack around 20 layers, check the height, and then sand to make sure the stacked layers matched the expected height in the CAD model.

Step 5: Sanding the Back and Top Shells

After I glued all the layers for the top and back, I used a power sander to smooth out the "steps" from the discontinuity between glued layers. I printed out a sketch of the front layer as a guide so my sanding matched the CAD file. I also had to use a Dremel to remove some of the material in tight spots.

Step 6: Clock Detector Assembly

To make sure the laser was focused on the disc, I had to unscrew the lens to move it as far away from the laser diode as possible. Usually, the lens is adjusted so the beam is collimated out of the module, but to increase the light reflected back onto the photodiode, the beam needs to be focused on the disc.

I pushed one photodiode and the adjusted laser module into the 3D printed clock detector mount. I soldered cables onto the leads so they could be connected to the circuit later. I then attached the clock detector module to the main chassis using four M3 bolts.

Step 7: Data Detector Stage Assembly

Before mounting the laser, the focus must be adjusted like described in Step 6. Then, the photodiode and laser are mounted in the 3D printed data detector mount. The module is then connected to the module carrier, which translates radially outward from the disc center so each row of data can be read.

The module carrier is the "stage part" of the linear stage actuator that translates using the stepper motor. To set up the stage, the lead screw nut needs to be attached to the 3D printed lead screw mount with four M3 bolts and nuts. The lead screw mount is then bolted onto the stage.

Step 8: Stepper Homing Photointerrupt Assembly

With the data and clock detectors aside, I assembled the photointerrupt used to home the stepper motor. The photointerrupt consists of a photodiode and IR emitter. When an object falls between the IR emitter and the photodiode, current can no longer flow through the photodiode and the voltage read decreases. The data detector carrier has a "flag" that blocks the IR emission when the data detector is in the correct position.

There are five parts in the mount. The IR emitter and photodiode slide into the long joints and hold in place with no glue. Cables were then soldered to the leads and heatshrink tubing was added to consolidate the cables.

Step 9: Main Chassis Assembly

Here is the step all the parts come together. I mounted the stepper motor to the 3D printed mount and attached it to the chassis using M5 bolts. The data detector stage is screwed into the stepper motor's lead screw. The coupler and lead screw support blocks are all connected together and attached to the main chassis. At this point, rotating the lead screw will translate the data detector stage. Before adding the rail, the stage flag needs to be attached onto the stage. The small "stick" on this part will eventually fall within the photointerrupt during stage homing.

The two 3D printed pillow risers and the two pillow blocks are bolted onto the data detector stage with M3 bolts. I then slid the rail into the pillow blocks and mounted the rail onto the chassis. There is some play in the mounts for the rail, lead screw, and stepper motor, so they should be adjusted to make the translation of the stage as smooth as possible.

Step 10: Mounting the Dot LED Display

Before mounting the MAX7912 LED matrix, I made sure to test it with an Arduino. I then connected four standoffs with M3 nuts to the mount. The LED matrix mount connects to the main chassis using two friction-based contacts. The first and third LED panels are removed from the LED matrix to expose the through holes for mounting. I secured the LED matrix to the standoffs with four M3 bolts.

Step 11: DC Motor and Rear Chassis Mounting

The motor is mounted onto the main chassis with six M3 bolts. After checking all the connections and adding heat shrink tubing, it is time to add the rear chassis. The 3D printed disc mount is attached to the DC motor shaft. I pressed in two magnets and an M3 nut. After sliding the mount onto the shaft, it is tightened with an M3 bolt.

First, two magnets are pressed into the front arms. These magnets will hold down the front panel later. Several "arms" and the photointerrupt connect the rear chassis to the front chassis. I had to use a hammer to push these arms all the way into the chassis. For looser connections, I added a little glue.

Step 12: Soldering Electronics

Finally, it is time to test the system modules! I connect female Dupont connectors at the end of the detector module, clock module, photointerrupt, DC motor, and LED matrix. I built up all the circuits on a breadboard first and checked that everything was working. Above I have a picture of a test disk and the data signal after amplification and Schmitt trigger. Once I was confident in my circuit, I soldered all the components on a prototype board according to the schematic above.

Step 13: Mounting Rear Panel Electronics

I painted the front and rear panels with black acrylic paint and then prepared the electronics to mount to the rear panel. I slid the Arduino Nano into the 3D printed mount and then soldered male header pins to it. The power jack, power switch, MIDI jack, and Arduino mount were all fastened to the rear panel. I then made the appropriate connections to all these components on the prototype board. At this point, I made one final check of all the modules' electronics to make sure everything was working. Finally, I attached the prototype board to the rear chassis with four screws.

Step 14: Connect the Rear Case

Before adding the rear case, I cut out several sections (marked with red boxes in the pictures above) using a jigsaw. The top hole is not shown in the picture because I made this cut later after switching to a larger motor. I had to adjust this rear shell to fit into the proper mounts in the chassis. The alignment wasn't perfect and I had to cut some joints and use glue instead. The important part was to align the top and bottom joints as shown in the pictures. The holes are later covered by panels.

Step 15: Assemble and Mount the Laser Dump

The laser dump blocks the laser going through the disc. Without it, the laser would pass through when the disc had a hole. The dump also provides a visualization of the 1's and 0's on the disc being serially read.

The assembly consists of four laser-cut wooden parts and one plexiglass part. I glued each of the parts together using superglue. Just as the rounded edges on the case, the laser dump has "steps" that need to be sanded so the assembly is smooth.

After smoothing out the part, I slid the assembly into the top part of the electronics part. One more "arm" stabilizes the laser dump. I pointed out this "arm" with a red arrow in the pictures attached in the step.

Step 16: Build the Electronics Box

To help show all the parts required for building the box, I have an exploded CAD screenshot. First, I pushed the side panels into place. These panels on the left and right side help secure the main chassis and the LED matrix mount. The front panel is designed to fit into the ridges on the left and right side panels.

I then pressed M5 nuts into small parts used for attaching a panel to the bottom of the device. The other nuts used to hold the bottom panel were mounted in Step 4. I then screwed in four M5 bolts to hold the bottom panel, which is easy to remove in case I needed to adjust anything on the main chassis.

To complete the box, I glued wooden sheets with no holes on the sides and front of the device.

Step 17: Build the Back, Front, and Bottom Panels

The front and rear panels are attached to the case with magnets so the electronics can be easily accessed. I hammered the magnets into the laser-cut parts. In a few locations, the magnets had to be glued in place. The front panel consists of two parts so the magnets are hidden. The two side panels cannot be removed and are glued in place at this point of the assembly.

I initially designed the system with the lower part of the rear assembly glued, but later decided it would be better for the panel to be removable. Therefore, I added two long nails along the case with hot glue and two magnets on the rear jack panel. When this lower rear panel is pushed into place, the magnets are attracted to the nails to secure it.

Step 18: Using Matlab to Convert Message to Binary Disc

A huge part of this project was figuring out how to go from a text message to binary information stored on a disc (labeled as 1 through 4 in the attached workflow diagrams). I used Matlab to process the message and output a vector file that was used for lasercutting the discs. After I picked a message, my code first converted the message to binary based on a truncated ASCII table I created. Attached is the Excel table containing the truncated ASCII table. The function called "abcGetBinary.m" is the one that converted the text to 1's and 0's.

The difficult part was converting these 1's and 0's to holes positioned on a disc. The size of the holes depended on the speed of the disc rotation, the processing time for the Arduino, and the size of the laser beam on the disc. The data sensor reads whenever the clock signal changes states (either high to low OR low to high, AKA at the falling or rising edge of the signals). The holes are arc-shaped and must be added to the correct positions that correspond to 0's in the data file. I included a drawing showing how the rising and falling edges of the clock holes correspond to the middle of the data holes and non-holes.

The goal is to create a figure consisting of all these features and export it as an SVG file from Matlab. I chose the disc diameter size based on the size of the message. Holes for the magnets and mount are also added to the figure created. A ring of holes around the center is added to the figure for generating the clock signal on the disc. The arc holes are created using functions I made called tLine and arcM. To know the first value to read in the data, the first row of data consists of one hole that corresponds to the start of the read. The code then uses a for-loop to go through each value of the data and adds a hole for 0's. Attached are the Matlab functions required.

Step 19: Decoupage and Cut the Discs

I wanted the wooden discs to be decorated like CDs, so I decoupaged old magazine and atlas clippings to create unique discs. I cut out interesting images and arranged them onto thin plywood. After finalizing the arrangement, I glued one clip at a time using Mod Podge craft glue. I brushed the craft glue over the entire collage once all the clippings were glued on. After the glue dried enough, I pressed the collage with several text books to flatten out any wrinkles. The finished collage was placed in the lasercutter and cut using the SVGs generated from the Matlab code. I was happy the collage was not burnt or damaged using this technique.

Step 20: Code the Disc Player

The disc player was coded using Arduino and requires the following libraries added in the script:

Stepper.h, MD_Parola.h, MD_MAX72xx.h, SPI.h, and MIDI.h

The script begins by declaring the pins used in the system (see the table above), stepper motor properties, disc read parameters, MIDI notes to play, and variables for storing the binary information. In the setup function, the stepper motor used to shift the data detector stage is homed using a function I made called findHome(). This function reads the photointerrupt and then advances the stepper motor a few steps. The stepper motor continues to advance until the flag on the data detector stage falls within the photointerrupt detector.

The DC motor is also powered in the setup function by sending a high signal to the base of a saturated transistor. As the motor turns, the clock detector is read. When there is rising or falling edge in the clock signal, the data detector is read. In order to know the first hole to read (i.e. the first bit in the data stream), the first row has only one hole, which corresponds to the starting point in the read. The process of finding the first bit to read is contained within a function called findStart(), which is run in the setup function because it only has to be done once.

In the loop function, the code constantly checks for rising or falling edges in the clock signal. When an edge is detected, the data from the disc is read from the detector module and stored in an array on the Arduino. When a data read is high, a MIDI note is played using the MIDI library and an LED is turned on in the LED array. The position of the LED in the array is advanced in each data read. When five bits have been detected and stored, a function is called to look up the letter that corresponds to the 5-bit number. For example, 00100 would be sent to the function and the letter "d" would be returned.

The process is continued with each letter being added to the previous string until 00000 is read, which is decoded as "end of message." The full string is then displayed on the LED matrix using the example sketch provided MD_Parola library (Parola_Scrolling).

Thanks for reading my instructable!

CNC Contest 2020

Second Prize in the
CNC Contest 2020