Phantom Piano by Weapons D&D
Our goal for this project was to build a piano that is able to play by itself, commonly known as a phantom piano. Our method was to use a computer system powering a circuit that was attached to each key in an octave on a children's piano. Following a long process of brainstorming, debugging, and building, we were able to create this system, attach it to the piano, and build a covering around the components to finish our creation of a phantom piano.
Along the way, we encountered multiple difficulties within each element. With the coding, our main problem was being able to call for a note to be played multiple times in a row. After some trouble shooting, we realized that the code was going too fast, and we were having trouble untriggering the note before calling it again. That was solved by using a “default” that called for none of the notes to play, so that a rest period could take place before playing another note. The next problem was with the circuit. Becoming familiarized with the components of the circuit, including a relay and op amp, proved to be difficult in itself, but after extensive research, we found a way to connect the circuit to a solenoid actuator, and triggering it using a labjack and a larger battery source. This was the most important part of the project, and also the most difficult problem to overcome. The last problem was with the solenoids themselves. Some faulty solenoids proved to be unsolvable, and caused a single note not able to be played. Apart from the struggles, the project proved to come together seamlessly, with a final product that could play any song, even with notes being able to be played at one time! Although the phantom aspect was catered to only one octave of the piano, using this method, upscaling to more octaves- or even a whole piano- is possible with more equipment and time. Through this instructable, we will go over every main component of the component, including the supplies, circuit, coding, piano build, and even a demonstration of our completed project playing a song!
Supplies
Main Items:
2 U3 Labjacks, with USB cables - $155 each from Labjack
12 Solenoid Actuators - $12 each on Amazon (We recommend getting an extra or two, for a total of 13+, since these can easily burn out)
Toy Piano - $54 on Amazon
12 Tnisesm 3V Relays - $9 for 6 on Amazon (We recommend getting an extra 6-pack, for a total of 18 since these can be a bit finnicky)
12+ LM358P Op Amps - $7 for 50 on Amazon
Optional: Op Amp sockets - $7 for 20 on Amazon
Fishing Line - $7 on Amazon
Gorilla Glue - $5 on Amazon
In addition to all of the above items, you will need a few other things:
Plenty of wires
A power supply for the solenoids. The minimum rated power is 12V and 1A, but we recommend going higher for multiple solenoids active at once. Ours is capable of about 30V and 3A.
A power supply for the op amps, which does not have to be very powerful at all.
A soldering kit for working with the wires
Sheets of a durable and cuttable material, such as plexiglass, wood, or thick plastic, which will be used to enclose the circuit, solenoids, and Labjacks. We used one plexiglass slab and several sheets of thick plastic.
A long circuit board, about 15 inches long and about 4-5 inches wide
A laptop that can support two U3 Labjacks simultaneously (Windows seems to be the most compatible)
The Circuit
Rationale
In order to independently control the solenoids with the computer, we need some kind of interface between code and reality. The Labjack fits this role perfectly, since it has voltage outputs that can be directly controlled by python code.
The original plan was to attach each output on the Labjack to each solenoid, therefore allowing for independent control of every solenoid. We stuck to this plan in principle, but it did require several adjustments.
First of all, a Labjack only has 6 voltage outputs. Since we wanted to play an entire octave, which is 12 notes, then using two Labjacks would give us a perfect number of outputs. Once we got two Labjacks working with one computer simultaneously, we had exactly the number of outputs that we needed.
Getting the Labjacks to activate the solenoids was more difficult than originally foreseen. We quickly realized that the solenoids require much more current than the Labjack can output. So, we needed to use a stronger power supply to power the solenoids. Then, the question arose: how do we activate the power supply with the Labjack? The solution was to use a relay, which is a circuit switch activated by current. The plan was to have the power supply on at all times, and for the Labjack to simply activate a relay that closes a circuit between the power supply and a solenoid. Thus, we would need 12 relays, one for each solenoid, and to have all 12 relays connected in parallel to the same “beefy” power supply.
Yet, there was one more issue: the Labjack wasn’t even powerful enough to activate our dinky 3V relays. So, we needed to introduce op amps. By building a simple follower circuit, these op amps can maintain the output voltage of the Labjack above 3V and finally grant us the power to activate the solenoids with the relays.
Building the Circuit
We recommend creating a prototype circuit on a breadboard before committing to the permanently soldered circuit, just to make sure that things are working properly. The prototype doesn’t have to be full scale, since each op amp, relay, and solenoid chain is a copy of the last. In other words, the circuit is modular, and creating only one or two modules as a prototype is a good idea. Once you have one or two modules of the circuit complete on a breadboard, solder all twelve modules onto your circuit board.
Above you will see a circuit diagram. The diagram represents one module of the 12-module circuit, except for a few small caveats. Each of the op amps are connected to the op amp power supply in parallel, and each of the solenoids are connected to the “beefy” power supply in parallel. Also note that each op amp in the diagram represents one side of the LM358P unit; each of these units operates as two independent op amps, but each unit only needs one power supply. Other than that, repeating this module 12 times will produce the circuit that we used for our piano.
For the rest of this section, we will describe details about the circuit that aren’t already present on the circuit diagram, such as the pin layout of the op amps and relays.
Let’s discuss how to use the op amps. First of all, we recommend using the op amp sockets linked on the supplies section. This will save you a lot of time if any of your op amps fail, which is likely to happen, since re-soldering an entire op amp is a lot of work. Each LM358P unit has eight pins, as shown in the pin diagram above. For each unit, connect pin 8 to the positive terminal of the op amp power supply, and pin 4 to the negative terminal of the op amp power supply, which you must also connect to the labjack ground. Since each unit represents two op amps, connect each of the labjack outputs to each of the noninverting inputs, which are pins 3 and 5. Using another wire, solder pins 2 and 1 together as well as pins 6 and 7. Then, solder wires to pin 1 and pin 7 to use as outputs to your relays.
As for the relays, connect the output from the op amp (pins 1 and 7 on the op amp) to pin 1 on the relay. Pin 8 should be connected to the same ground as the op amp. Then, for each relay, connect pin 2 to the “beefy” power supply, and pin 4 to each solenoid.
The Code
The code consisted of multiple parts: extracting information from the song document, sorting the information in an orderly fashion, matching the information with the defined variables, and commanding the Labjack to output voltage. First of all, we had to define 12 lists, each of which corresponded to a particular note in the octave; for example, [1,0,0,0,0,0,0,0,0,0,0,0] corresponded to the note C. We used a dictionary to do this.
Extracting notes from a song document was not easy; the file kept on yielding a long preamble that had nothing to do with the information we wanted. We created a new string with the relevant information by cutting out unwanted parts; since the character “@” was not used in the preamble at all, we placed it before the relevant information, found the placement of this character in the string, and then cut out every string element up to the character. With only the string we wanted left, we had to read the note and beats. An issue we ran into was that the python code was unable to recognize separate lines in the text file. Therefore we used the character “\” to separate out different lines (corresponding to different chords). Initially we used is.alpha() function to identify notes, but then we ran into the problem of not being able to extract C#, for example. We decided to use lower case c to denote C#, similarly for the other sharp notes. Each chord became a single list, and the entire song was expressed as a list of lists. All the chords were a list of lists, and the beats corresponding to each chord was another list. Since the length of the list with beats were equal to the length of the number of chords, we were able to match the chord with its beat by using a loop function. After that we had to name each labjack in the code. d1 was the first labjack, and we identified it using the serial number, and d2 was the second labjack with its corresponding serial number. With this, we could have each labjack control 6 notes at a time, so we created a chart assigning each output of the labjack to a note. Then we used an if statement to correctly identify which output we wanted. For example, DAC1 of the first labjack will correspond to the list [0,1,0,0,0,0,0,0,0,0,0,0], and will be equivalent to “DAC1-1”. However, the code itself cannot identify the first or second labjack, so we split “DAC1-1” into a list of two elements, “DAC1” and “1”, with the first element being the output of a specific labjack and the second element telling us which labjack to use. If the second element equaled “1” then we used d1 and if it equaled “2” we used d2. After playing a chord, we had to let the program sleep for a very short while so the circuit does not have to handle so much voltage at a time. We let it sleep for 0.1 seconds, and afterwards we turned off the note by commanding the labjack to turn off its output. We did this by defining an offNote() function, which is similar to the function playNote() except that it does the opposite. Then we would turn off the note for the time the note is played minus 0.1 seconds.
The Piano
In order to put together a working phantom piano, we first had to figure out how exactly the piano functioned. We took apart the piano piece by piece. We found that the whole set of keys was able to detach from the piano stand, and we were also able to deconstruct each part of the stand to obtain a collection of wooden slabs in their simplest form. We got a non-electrical piano so we could make use of the hammers that are used to create the noise when the piano is played. This way, we were able to completely separate the keys from the piano stand, and furthermore, the individual notes off of the piano.
We then took off each note and drilled a hole beneath them, and attached a string using tape and superglue to fall through the hole. These strings were used for leverage to pull the keys down from below, which we then were able to connect to the solenoids. The solenoid actuators are small mechanical devices that are triggered to pull a rod in when a current passes through it. To make the phantom piano look phantom, we had to position the solenoids behind the piano for the full effect. We subsequently found that the best way to go about this was to trace the strings through the inside of the piano (which we were able to do by taking off the underside and front walls of the piano) and out the bottom to the solenoids in the back.
The solenoids were superglued to a sheet of plexiglass that was attached to the feet of the piano, acting as a false backing for the components. Then, testing each string for the right tension given the position of the solenoid, we were able to test to see if the note was able to be played by the triggered solenoid. After each solenoid was positioned and tethered to the note, we then moved on to attaching the circuit.
There was a part of the circuit for each note, which then had to be soldered to each solenoid. The circuit was then attached to the back of the piano by taping it in place for easy access in case there were any malfunctions. The circuit also had to be soldered to wires coming out of the labjacks, which also were taped to each side of the back of the piano.
The solenoids in place also had to be grounded to a power source to make them function properly. We decided that we were able to solder each one together in a large bundle, soldered to a single wire that was grounded (which worked flawlessly despite its size). We then attached everything to power and were able to play the piano from our computer!
Although everything was working, we finally had to cover up the components for a finished phantom look. Using the three slabs of thick plastic, we cut out each portion to fit the piano, and a small section was cut out of the bottom for the outgoing wires that were connected to the piano and the power source. From there, the piano setup was complete!
Demo
Looking Ahead
Looking ahead, we must fix the keys for G# and C# since they malfunction. We know that C# doesn’t work because the solenoid burned out due to our negligence. We could obtain a new solenoid for C#; however, we do not know what is causing G# to not work. We could definitely re-solder the circuit and use another solenoid and see if that works.
We can make the notes play simultaneously by using the multiprocess function. So far we have been relying on how quickly python codes run to make notes play simultaneously, but if we were to truly discuss it we must have functions running simultaneously as opposed to having them run line by line (albeit very quickly). The code was also unable to read decimal numbers as beats since we used the .isnumeric() function to identify the beats from the song string. This could be another improvement on the phantom piano. We could also add more notes to play instead of just a single octave. The toy piano came with 25 keys, and we only created circuits for twelve notes. This would be done by learning to use three or more labjacks at once, replicating the circuits for the extra keys, and defining additional key variables in the code.