Digital Electronics Lab 2018 – Final Project Report

1. Simple Explanation

Essentially, my box is a bunch of knobs that allow me to communicate with a computer in whatever way I want. I can set the knobs to control different things in different pieces of software, such as those for making music and visuals. The idea has always been to provide tangible feedback to the user in real time. With a simple USB connection, the entire device can power itself and exchange information with a computer. The layout has been kept simple so I do not have to think very much about what my hands are doing while I’m using it; this frees me up to consider other creative aspects of my projects.

2. Video

3. Detailed Explanation

Teensy Code (C++)

Let’s start with the hardware. 20 potentiometers in a 4×5 grid are directly mounted to a flat sheet of acrylic. LEDs above each row indicate which step (column) of the grid is being powered and measured. All the wires on the back of the panel are grouped by type (signal, power, LED), and connect via pin headers to the Teensy below. The Teensy rests in a custom-soldered bed of pin headers atop a PCB, for easy troubleshooting. For now, to reduce the strain on any wires, an acrylic box suspends the panel 4″ above the Teensy on the PCB.

The acrylic panel was laser-cut to the exact dimensions necessary to accommodate the potentiometers. The shafts of the pots protrude through the front of the panel, and are fastened by a washer and nut. Knurled knobs atop the shafts add aesthetic appeal.

Every pot is connected to ground through a network of wires that serve as the grounding bus. The power for each row is supplied by a digital-on signal from one of the digital output pins on the teensy. (Each column/step of the power rails are electrically connected to each pot, but are separate from the others.) This configuration requires fewer wires and used pins on the Teensy. Four ribbons of five wires each attach to the middle lugs of each potentiometer, per column. On the Teensy side, detachable male pin headers allow these ribbons to be disconnected for repairs.

As will be explained in a moment, the project has two modes: one where it responds to MIDI coming from a different source (like a daw), and another where the Teensy spits out MIDI to be used by a physical or software instrument. A SPST switch on the board next to the Teensy allows for switching between these modes (however, I suggest stopping whatever relevant activities are happening in the computer before switching modes).

Now for the software. The Teensy source code accesses the Serial and MIDI libraries. All the input and output digital pins are configured in the setup() function.

Let’s begin with declaration of variables. stepLength is set to the default time value for which a single step will hold, in milliseconds. ledPins[] is an array that holds the references for the output pins for the LEDs. currentStep holds the value for the step in the sequence, and is updated after each stepTime (for outputMode()) or when the Teensy receives an incoming MIDI signal (for inputMode()). lastStep is used for comparisons in order to properly trigger later events (like sending Serial data). switchPin holds the reference for the center pin on the SPST switch that’s used to go between modes. potMatrixPins[][] holds all the references for the analog pins. Meanwhile, potMatrix[][] holds the values read on each step. rowPowerPins[] holds the values for the digital output pins that light up the LEDs on the panel. currentMIDI[] and lastMIDI[] are used by outputMode() to send out MIDI, convert between MIDI and serial (byte) values, and compare between two adjacent steps.

I intentionally kept the loop() function pretty minimal, and broke out everything into a bunch of other functions. Depending on which way the mode switch is thrown, loop() will continuously call either inputMode() or outputMode(). These respective modes will call their own sub-functions.

First, inputMode(). It simply reads incoming MIDI and calls the event handler. The actual event handler (myNoteOn()) powers up the current step, invokes readPotValues() to read the values, and transmitSerial() to transmit bytes of Serial. Then myNoteOff() cuts the power to the pots and increments stepCount.

outputMode() is not broken out like the structure for the input mode, because the Teensy is directly in control of whatever’s happening; it’s not waiting to read incoming values from elsewhere. Its code is nearly identical to that of myNoteOn() and myNoteOff() combined. The only differences are that it calls the function txMIDI() to transmit MIDI values to a connected device and that it delays the program function for previously read-and-mapped stepLength values.

Processing Code (Java)

Now, let’s discuss the code in Processing, a visual scripting language coded in Java. Late in the project, I migrated my code from the traditional Processing IDE to Eclipse, which is much better for more complicated software development. The default IDE is what’s known as a PApplet, which extends the functionality of Java with new classes and methods, while simplifying some of the syntax. In order for Eclipse to run Processing sketches, I had to import essential libraries that are buried within the “package contents” of the Processing app. These .jar files are self-contained with the functionality I need to work with Serial and to make anything display on the screen.

One of the tradeoffs of working in Eclipse is that the syntax becomes more complicated. Java really cares about the cope of variables and methods, so I have to designate them as public or private, in addition to their return types. I also have to specify that my class inherits the functionality of the PApplet class. Inheritance is an enormously important concept in higher-level programming. Essentially, one class is able to take on the methods and variables of the “parent” class, and can even extend the functionality. This makes the “child” or subclass a subtype of the parent’s class type. Writing my class as inheriting the PApplet’s methods allows me to call some of its methods for my own uses. If you know how to do this, it’s definitely worth using Eclipse.

The main() method is analogous to the loop() function in the C++ code. It’s what runs while the program is operating, cooperating with all the other methods to make everything work. PApplet has its own overriden main method, which I use inside my class’ own main method to have the PApplet handle everything I write in my class.

One extra method I have to create is settings() at the top of the class. This is where I set the size of the canvas on which I will draw the visuals. setup() takes care of instantiating Serial communication and a PImage object called fader, which will be used to loop delayed projections of previous frames atop one another. incomingSerial, mappedSerial, lastStep, and currentStep are exactly what they sound like; they store the recorded incoming serial values. current is an array that holds all the bytes of the pot values from all steps in the cycle.

Now for the other methods. getSerial() recieves the incoming Serial that’s sent out by the Teensy. interpolate() creates smooth transisitions among the frames for the objects on screen. It calls linInt(), which compares the target and current values, and then advances the values slightly towards their goal. This is actually a recreation of the lerp() function that Processing already has. The problem with lerp(), however, is that it is not friendly to the standard double-type values that Eclipse interprets decimal numbers as (Processing likes floats). So, I figured out the logic behind lerp() and rewrote the method to take doubles, just to make my life a little easier.

All these methods serve the primary method called draw(), which is analogous to the main() method in Java and the loop() method in the Arduino C++ code. Every frame, it first clears the screen, takes in the serial values from the Teensy (via getSerial()), linearly interpolates them between the last stored value for the previous step and the current incoming serial, and then draws ellipses to the screen.

The PImage object “fader” captures what’s on the screen in the previous frame and displays it again in the following, before the new ellipses are drawn. When this is continuously repeated, the result is an echoing or trailing effect of multicolored ellipses dancing on screen, either to the timing of the Teensy (in outputMode()) or from the incoming MIDI from a DAW (in inputMode()).

In a nutshell, that’s all the code that I’ve written for this project! The Teensy’s compiled C++ sends information out, while the processing Java code receives all this and makes something appealing out of it.

4. Source Code

Arduino (Teensy) Code (C++):

#include <MIDI.h> // invoking MIDI library.
// Serial included by default, as well.

int stepLength = 250; // default, in milliseconds.
int ledPins[4] = {0, 1, 2, 3}; // not including ground.
int currentStep; // 0-3 (4 steps)
int lastStep; // for comparison purposes

int switchPin = 28; // for changing modes

// specific analog reading row pins
int potMatrixPins[4][5] =
  {A0, A1, A2, A3, A4},
  {A5, A6, A7, A8, A9},
  {A13, A14, A15, A16, A17},
  {A18, A19, A20, A21, A22},
}; // all the attachments of pots to the analog pins.

int potMatrix[4][5]; // stored values from analogRead()s

int rowPowerPins[4] = {12, 11, 10, 9}; // not including ground

int currentMIDI[5]; // outputed/read MIDI per step
int lastMIDI[5]; // for comparison purposes

void setup() // configuring the Teensy for proper functionality.

  pinMode(switchPin, INPUT); // Sets up pin that changes between inputMode() and outputMode()

  for (int i = 0; i < 4; i++) // Setting up pins for lighting up LEDs
    pinMode(ledPins[i], OUTPUT);

  for (int i = 0; i < 4; i++) // Setting up pins for powering columns (steps) of pots.
    pinMode(rowPowerPins[i], OUTPUT);

  Serial.begin(115200); // Establishing baud rate for Serial
  usbMIDI.setHandleNoteOn(myNoteOn); // Establishing which function is called (myNoteOn()) when a note-on MIDI signal is detected
  usbMIDI.setHandleNoteOff(myNoteOff); // Establishing which function is called (myNoteOff()) when a note-off MIDI signal is detected.

void loop() // continuously runs during program execution
  if (digitalRead(switchPin)) // If the switch is set to on/HIGH, go into input mode.

  else // If the switch is set to off/LOW, go into output mode.

// six values: step #, pot values 1-5.
// The first should correspond to the step (in this case, the row of the array).
// The others should correspond to the analog read values for the 5 respective pots.
void transmitSerial()
  Serial.write(currentStep); // Transmission of first value
  for (int i = 0; i < 5; i++) // it's 5, not 6!!!
    Serial.write(potMatrix[currentStep][i]); // Transmitting pot values.

// mapping range of Serial values to MIDI note values.
void calculateMIDI()
  for (int j = 0; j < 5; j++)
    lastMIDI[j] = currentMIDI[j]; // Priming for later comparisons.
    currentMIDI[j] = map(potMatrix[currentStep][j], 0, 255, 24, 108); // Conversion from Serial to MIDI.

void txMIDI()
  // We need to send out usable MIDI values to other places,
  // so we first have to "convert" from Serial values to MIDI values.

  if (lastMIDI[0] != currentMIDI[0]) // detection of change in MIDI note
    // Turn off previous note
    usbMIDI.sendNoteOff(lastMIDI[0], 0, 1);

    // Control change
    usbMIDI.sendControlChange(10, currentMIDI[2], 1);

    // Turn on next note
    usbMIDI.sendNoteOn(currentMIDI[0], 100, 1);

// Event handler for when incoming MIDI note detected
void myNoteOn(byte channel, byte note, byte velocity)
  // turn on both LED indicator and power to column of pots.
  digitalWrite(rowPowerPins[currentStep], HIGH);
  digitalWrite(ledPins[currentStep], HIGH);

  // Once pots are powered, read analog values.
  // Send them out (to processing or elsewhere).

// Event handler for when incoming MIDI off signal detected
void myNoteOff(byte channel, byte note, byte velocity)
  // Cut power to LED indicator and respective column/step of pots.
  digitalWrite(rowPowerPins[currentStep], LOW);
  digitalWrite(ledPins[currentStep], LOW);

  // increment currentStep value (remain within 0-3)
  currentStep ++;
  currentStep %= 4;

// Not yet used; for later implementation.
// Void myControlChange(byte channel, byte control, byte value)

// Use external (incoming) MIDI values for control
void inputMode()
{; // call incoming MIDI-on event handler (myNoteOn())

  // Not yet used; for later implementation.
  // usbMIDI.setHandleControlChange(myControlChange);

// Use internal pot values for MIDI control.
void outputMode()

  // Turning on power. to LEDs and pots.
  digitalWrite(rowPowerPins[currentStep], HIGH);
  digitalWrite(ledPins[currentStep], HIGH);

  // Read pot values for the row.
  // If you make this a double for-loop,
  // you will always be reading zero values on the other rows!

  //Serial data to be sent to Processing (or elsewhere).
  // Transmit MIDI to DAW or other compatible instrument.
  //******** Where the magic happens.

  stepLength = map(potMatrix[currentStep][4], 20, 255, 1, 750); // 20 seems to be as low as they go.

  // Turning off power to LEDs and step/column of pots.
  digitalWrite(rowPowerPins[currentStep], LOW);
  digitalWrite(ledPins[currentStep], LOW);

  // Iterate step (within range 0-3).
  currentStep ++;
  currentStep %= 4;

// Analog-read the pot values for the current powered-up step.
void readPotValues()
  for (int j = 0; j < 5; j++)
    potMatrix[currentStep][j] = 1023 - analogRead(potMatrixPins[currentStep][j]);
    // map them from 10-bit values to 8-bit values (bytes).
    potMatrix[currentStep][j] = map(potMatrix[currentStep][j], 0, 1023, 0, 255);

Processing (Java) Code:

import processing.core.*; // Underlying code to make the Processing PApplet run.
import processing.serial.*; // Getting Processing to communicate with the Teensy.

//Testing01 is a subclass of the type PApplet, so it inherits all of the parent's functions.
public class Testing01 extends PApplet
	// The main() method required to make a Java program run (at least in
	// Eclipse).
	public static void main(String[] args)
		// Calling the overridden main() method and passing it the argument of
		// the current class.

	// Will capture the incoming Serial data from the Teensy.
	// Create serial object from Serial library.
	Serial mySerial;

	// Required method to create canvas.
	public void settings()
		size(1080, 720); // Setting size of canvas.

	// The standard function in Processing to establish the fundamentals of the
	// program.
	// Similar to in C++ for Arduino.
	public void setup()
		background(0); // Clear frame; make completely black.

		// constructor (this, the serial port, the baud rate).
		mySerial = new Serial(this, Serial.list()[1], 115200);
		fader = get(0, 0, width, height);

	// serial-related declarations//
	int[] incomingSerial = new int[6]; // Stores incoming Serial bytes for
										// current frame.
	int[][] mappedSerial = new int[4][6]; // Stores Serial bytes that have been
											// converted to pixel values.
	int lastStep; // Same as in C++
	int currentStep; // Same as in C++

	// Contains current (mapped) values, for comparison with interpolated
	// values.
	int[][] current = new int[4][5]; // does not include step count

	/// Visual-related declarations.
	PImage fader; // Image that will be scaled for delayed-feedback effect.

	public void draw() // Analogous to loop().
		// Clears frame.

		// Reduces alpha (transparency) for incoming projection of image of
		// previous frame.
		tint(255, 255, 255, incomingSerial[5]);
		image(fader, 0, 0); // Projection of image of previous frame.
		// Disables transparency settings for projection of elements in current
		// frame.

		rectMode(CORNER); // Establishes top left corner as pixel (0,0).
		// Retrieval of Serial from Teensy.
		// Interpolates (blends) values of current ellipse dimensions with those
		// just read over Serial.

		// For reference/comparison.
		lastStep = currentStep;
		currentStep = incomingSerial[0];

		// Drawing ellipses of current frame to canvas.
		for (int i = 0; i < 4; i++) 		{ 			// Setting ellipse color. 			fill(incomingSerial[1], incomingSerial[2], incomingSerial[3]); 			// Draws the actual ellipse (per iteration of loop). 			ellipse(current[i][0], current[i][1], current[i][2], current[i][3]); 		} 		// Overwrites previously captured image with updated capture of the most recent frame. 		fader = get(0, 0, width, height); 	} 	// Retrieve Serial from Teensy. 	void getSerial() 	{ 		// Ensuring all 6 Serial values have been transmitted at a time. 		if (mySerial.available() >= 6)
			for (int i = 0; i < 6; i++)
				// The int() casting is apparently unnecessary
				// Commit new Serial values to memory.
				incomingSerial[i] = (;

				// Mapped values are arbitrary.
				// In this case, I'm using the dimensions of the canvas as the limits of the mapping.
				mappedSerial[currentStep][i] = (int) (map((float) (incomingSerial[i]), (float) (0.0), (float) (255.0),
						(float) (0.0), (float) (height)));

			// Debug
			// Prints Serial values to console.
			for (int i = 0; i < 6; i++)
				print(incomingSerial[i] + " ");
			println(); // New line.

	// Smoothly iterates between current positions/dimensions of objects on screen and their eventual targets,
	// as defined by the incoming Serial data.
	public void interpolate() 
		for (int i = 0; i < 4; i++)
			for (int j = 0; j < 5; j++)
				// Don't interpolate if the difference between the current position and target position 
				// is less than 3 pixels.
				if (abs(current[i][j] - mappedSerial[i][j + 1]) < 3) current[i][j] = mappedSerial[i][j + 1];
				// If the difference is greater than that, linearly interpolate.
				else current[i][j] = linInt(current[i][j], mappedSerial[i][j + 1], 0.1);


	// Linear interpolation. 
	// Method that combines map() and lerp() functionality 
	// into something easier for me to use in the Eclipse environment.
	public int linInt(int a, int b, double c)
		double delta = b - a; // Find difference between two points.
		delta *= c; // Multiply difference by some factor.
		return a + (int) (delta); // Add this scaled difference to first point.

Digital Electronics Lecture 2018 – Assignment for Week 13: Final Project Writeup (for Lecture, Week 3)

This week, I finished up all the hardware I’m going to work on in the time left devoted to this final project.

Back on Thursday, I installed LEDs in their holes and wired them up to the circuit board. First, I bent the positive end to an angle conducive to attaching a long piece of stripped, stranded wire. I soldered the four respective joints and cut the excess. Next, I applied some heat-shrink tubing around the joint to prevent shorting with the bases of the potentiometers or the ground wires on the LEDs (which were installed next).


To mount the LEDs in their holes, I applied some hot glue around the flanged end of each of the bulbs. Then I pressed them into the appropriate spots on the top of the panel.

I decided to use some tinned, non-insulated copper wire to connect all the grounds. I pulled off a piece from the spool (to straighten it), then wrapped it once around each of the LED leads. I soldered the joints and cut the excess wire. Finally, I installed a long piece of black wire to the exposed end on the newly-created grounding bus. There was no need to put heat-shrink tubing over the joint.


When this was all done, I used four zip-ties to consolidate the five wires (four outputs and one ground).


On the other end, I cut all the wires to the same length, and stripped a bit of conductor off each. I tinned the ends to prepare them for attachment to male pin headers. I placed the pin headers in a breadboard and tinned their ends. Then I melted the wires to the pins. I had to ensure that I was attaching the right wires to the correct rows to avoid confusion later.


At this point, I realized that I would need more female pin headers on my PCB so that I could manually connect the new ground pin to the grounding rail. So, much like before, I cut two bits of female pin headers to an appropriate length to straddle either side of the existing construction atop the board. Then I soldered the far ends of the female pin headers to ensure that they would be flush with the board. Once this was sorted out, the middle pins were easy enough to solder in place. For the new grounding connection, I simply took a piece of black, solid-core wire, and bent it to the same shape as I had originally on my breadboard. Essentially, I now have a custom-made breadboard that’s much smaller and lighter, containing only what I need in terms of connections.



By the end of that day in Lab, I had decided to create a box for my project. Some suggested holding this step until later, but I knew it would be nearly impossible to troubleshoot without some sort of stand atop which my monstrosity could rest. (This is similar to how a car mechanic uses a hydraulic lift to peer at the underbelly of a vehicle to perform sensitive work.)

I booked a time on Friday for the eLab in the afternoon. On a piece of paper, I sketched out a crude diagram of the box I wanted to make. I knew that Jack had already designed his to a height of 4 inches, so I used this dimension value as well. Then, I cut a plate for the bottom and two small sticks for the sides. This housing is not meant to be a fully enclosed box, just something to keep my hands free while tinkering. I was in a hurry, so instead of using the proper welding agent to bond the acrylic pieces, I settled for hot glue. Because this is technically not the best way to construct the box, I was suspecting the thing to collapse pretty quickly. Surprisingly, it actually has held up all week; my connections are pretty strong! when attaching pieces, I used other rectangles of acrylic to ensure that the pieces were being stuck together at exact 90º angles. A little bit of tape did the rest. It all worked on the first try! (Though I had to troubleshoot the printing of the laser. This was the first time that Franklin was not available to help me, so I made a few mistakes during the cutting process. But thanks to Franklin’s training, I was able to rectify anything I messed up. Thanks, Franklin.)



Finally, I was free to work on coding. I first got the lights flashing in the proper sequence. Then, I spent some time consolidating bits of code from different .ino files to get the serial properly sent to processing. I created a method that sends out all 6 values (the step number and the pot values for that step) at once when called.

On the Processing end, the serial data was fed into an array that updates every frame. Much like the toggle button syntax used in some of the labs, I recorded the last step value and compared it to the current step value. When they were no longer equal, I triggered an event. The test patch first drew ellipses in rapid succession, with their centers and major/minor axis values mapped to the five pots. The last row of pots was reserved for step length. I’m just using a simple delay() in the loop() in the C++ code on the Arduino side; no need to make things more complicated with millis() as of yet.

Since that point, I continued to work on different visuals. I’m still playing around with different ideas. Some friends were nice enough to make different suggestions. I also talked to Mort, who made suggestions I would only be able to implement in another iteration of this project (that’s for the summer). Each of these different designs have been turned into their own classes, so I can call as many instances of them as I want at a time. Their constructors pass in the relevant pot values, an update() method changes certain values per frame, and a sketch() function is called in the draw() function to put the visuals on the canvas.

Here are some examples of the sketches I’m playing around with:

Screen Shot 2018-04-25 at 4.42.16 PMScreen Shot 2018-04-25 at 12.23.13 AM

Screen Shot 2018-04-25 at 4.44.21 PMScreen Shot 2018-04-25 at 4.42.38 PM

Screen Shot 2018-04-25 at 4.47.33 PM.png

Screen Shot 2018-04-25 at 4.49.04 PM.png

Other than that, I’m basically done with the essential elements of this project! I’m so happy with how this turned out. In the time I have between studying for my other classes, I will continue to work on designing more visuals and sending different types of information via MIDI to a DAW.


Digital Electronics Lab 2018 – Assignment for Week 12: Final Project Progress Report Writeup #3

Today was a bunch more soldering and also largely the beginning of getting serial communication up and running.

With holes cut yesterday for four LEDs (indicators for the current step), I went about installing the lights. I soldered four long blue cables to the positive leads on the LEDs. Because the leads on LEDs are close together, I decided to put heat-shrink tubing on the connections so there would be no accidental shorting to ground. Then I pressed the bulbs through the holes and hot glued them. By the last of the four, I figured out a cleaner method of installation: create a small ring on the flanged end of the bulb, so less leaks out over the sides (it looks nicer with the clear acrylic). So, I reheated the joints, cleaned up the excess, and reinstalled the bulbs. Next, I took some solid-core, tinned copper wire and wrapped it around the negative leads of each LED, connecting them all in a row. Because it was of a small diameter, the wire bent very easily around the LED legs, and it was easy to solder. On one of the LEDs, I allowed a bit more metal to protrude so I could run a grounding wire back to the PCB. Once I soldered everything, I cleaned up the ends. There was no real need to cover these ends with heat-shrink tubing.


I collected all the long ends of wire and kept them together with four zip-ties. The ends were of slightly different length, so for the next step I trimmed them down so the ends were in line with one another. I stripped tiny bits off the ends, and tinned them. I also tinned five male pin headers (four signals and one ground), just like for the four columns of potentiometers. Then I fused the wires with the pins in the proper order. (My trick to keeping the wires in order is to label them with a silver sharpie, with the number of lines corresponding to their placement.)



Next, I realized that in order to connect a separate ground, I would benefit from adding more female pin headers. So, I took extra lengths of headers that I had cut yesterday and trimmed them down to straddle either side of the Teensy. I carefully soldered them flush with the other headers. (I learned from my mistake yesterday of not making sure the ends were flush with the surface of the circuit board.)


I plugged everything together and quickly wrote some code to test that they LEDs function properly — they do!


On the software side of things, I figured out how to send values in a way that did not require having to parse strings into integers. It was simply a matter of removing my string object on the processing side of things and changing the Serial.available() count from >0 to >=2.

That is all for today!

Digital Electronics Lecture 2018 – Assignment for Week 11: Final Project Writeup (for Lecture, Week 1)

As Mark suggested, I’ve spend most of my focus this week on the actual hardware for my project.

This past Friday afternoon, I travelled with Jack to pick up a 1/8″X18″X24″ sheet of clear acrylic at Canal Plastics.  (They have quite an interesting selection of different plastics there, who would have figured.)

In addition, my potentiometers (knurled shafts) and knobs arrived in the mail. It turns out that the knobs were poorly labelled – they are meant for pots with smooth shafts, but the description mislead me by saying “knurled.” That was annoying, so I then ordered 20 different knobs, which turned out to be correctly labelled. Also, as Mark suggested, I bought a pair of digital calipers. These would prove very useful in the coming days.

The latter shipment arrived on Monday. I booked a time to use the prototyping lab (in the basement of the Leslie eLab) for Tuesday during the weekend, indicating that I would need someone to stop by and assist me in the design of the Adobe Illustrator file.

IMG_7201Franklin, a guardian at the eLab, read my request, and set aside his time to help. I read out the measurements I acquired with my digital calipers of various important dimensions, including the diameter of the potentiometer shafts, the length and width of the stabilizing metallic protrusion on the sides of the pots, and the distance between these two items. I then determined how far apart I wanted the pots to be placed in relation to one another. Here is a list of the important measurements we found:

  1. Diameter of shaft: 0.27″ (radius = 0.135″)
  2. Distance between edge of shaft and stabilizing protrusion: 0.155″
  3. Width of protrusion: 0.05″
  4. Height of protrusion: 0.083″
  5. Distance (in both x and y-axes) between adjacent pot shaft centers (decided upon by me): 0.65″
  6. Sheet width (decided upon by me): 5.255″
  7. Sheet height (decided upon by me): 6.17″

We first cut a test piece to ensure the measurements were right before we went ahead and duplicated the holes for the other pots.

Carefully inputting these measurements one at a time into Illustrator, we came up with the following file:


Franklin doubled the pass of the laser, just to ensure that all the unwanted pieces would separate. The result was impressive: very clean and even. Thank you Franklin!


Popping out some of the small pieces proved difficult, but I eventually managed to wiggle them free with a very small box cutter:


The whole boxcutter process was reminiscent of wiggling out my baby teeth as a kid: some fell out easily, while others were rather stubborn.

To remove residue, I used cleaning pads containing isopropyl alcohol. This actually took a long time to do thoroughly.


When I arrived home in the evening, I began placing the 20 potentiometers in their spots. Strangely, it was easier to mount them on one face than the other. I suspect this is due to the fact that the laser may have done a slightly better job on one – the one that was directly facing the beam. Like before, some went in with an audible snap, while others required quite a bit of force on my part. (I just had to be careful not to break the acrylic.)


Finally, I placed on the knobs — the ones that had the knurled insides. However, they ended up being really long, and I’m afraid that they may fall off too easily. Therefore, I might try to use a hand power tool (like a Dremel) to shorten them.

So, here’s what I’m left with as of now! I’m quite happy and excited with how it’s turning out.



Time Spent: 3.5 hours.

What I have left to do

  • Solder the power and grounding wires.
  • solder wires to a board onto which the Teensy will be mounted.
  • Create a serial communication protocol
    • testing this protocol
  • Interfacing with Arduino and Processing
  • Building outwards: making commit functions and adding functionality
    • [simply dependent on time]

What left to buy:

  • Perhaps mounts or a box? Not essential at the moment.