Project tutorial
Arduino Powered Player Pianos and Player Xylophones

Arduino Powered Player Pianos and Player Xylophones © GPL3+

Code your favorite music and play it on a Casio keyboard or on one of the two xylophones described in the project.

  • 3,894 views
  • 2 comments
  • 16 respects

Components and supplies

Necessary tools and machines

09507 01
Soldering iron (generic)

About this project

Arduino Powered Casio Player Piano and Player Xylophones

Introduction

These projects all began because of my son Steve's interest in antique doorbell chimes. You’re probably familiar with them, they play the “Westminster Chimes” notes on 4 tuned brass tubes about three feet long. Depending on the length of the tubes, they produce the notes F, A, G, C when they are tapped sharply at the top.

Steve owned a unit about 100 years old that was beyond salvation. The oil in the motor had congealed, the insulation was falling from the wires and the contacts of the distributor had burned out due to numerous short circuits. After some debate, (Steve was not one to give up easily when it came to preserving the originality of a precious antique) we decided to replace the guts of the chimes: the motor, the control unit and the solenoids that propel the plunger onto the tube. We picked an Arduino “Uno” the smallest computer of the Arduino family as the electronic brain to replace the motor and the distributor.

The Arduino family of computers is programmed using a derivative of the programming language called C. Simon Monk’s excellent book for beginners “Programming Arduino” is perfect for those who might like to get more familiar with this subject but -have no fear - it is not necessary to do any programming in order to complete these projects. Steve who like me worked at IBM for many years was an expert in C and C++ and did all the hard work for us.

The Projects

Arduino Powered Casio Player Piano

Arduino Powered Cool Xylo

Two related projects are described below: the 51 key Casio player piano and two player xylophones the “Cool Xylo," a 29 key player xylophone or a very inexpensive 13 key “Baby Xylo”. These projects are descendants of “A Thoroughly Modern Player Piano” which is a more elaborate 76 key player piano project that I completed last year. The 76 player piano project is described in a book of the same name and its features are described in my website “modernplayerpiano.com”.

The Casio 51 key player piano is a much simplified version of the 76 key player piano for several reasons. With fewer keys being activated, each one can be driven directly from a Mega 2560 port. Since doing the the 76 key project, I discovered the ULN 2803 driver which can drive a solenoid without additional components. The net result is that the shield design for the control unit of the Mega 2560 allows all the components to be placed on a 4 X 5 inch PC board. Including the cost of a Casio 61 key keyboard, the components for the 51 key player piano cost a little over $400.

The “Cool Xylo” uses the same shield and the same components to strike the bells (the metalbars) of the Xylophone. With fewer keys, this project is even simpler. In addition, the software uses the very basic Arduino sketch“Blink” to drive the solenoids. Budgeting $70 for a 30 key xylophone, the total cost of the “Cool Xylo” project is just over $200 while the “Baby Xylo” project with a $25 xylophone costs a little over $100.

Why Build These Projects?

For the DIYers, the hobbyists and the computer nerds, it is for the fun of it, There is something truly fascinating about watching the mini-robots operating in sequence and generating music. For the musically inclined, it could be to arrange music to their taste, to compose new songs or to practice on another instrument in concert with the melody from the player piano.

For young people who are all music lovers, the best reason is the hands-on learning experience that will increase the student's engagement and achievement. The student will learn the basics of the most in demand STEAM subjects: music, computer science, software, robots, and a little bit of engineering. I envision a father/daughter team or a group of pre-college students putting their heads together to solve a wiring problem or a software issue for a once in a lifetime learning experience that may lead to a high quality job in the future.

Capabilities

The videos of the Casio player piano and of the Cool Xylo player xylophone in action tell the story. The player piano song is Beethoven's Fur Elise which is a fairly difficult piece to play. Note that the beginning starts at the low volume setting which would happen when the “soft” pedal of a piano is depressed. The soft pedal is then released and the volume goes to normal. Next, we simulate depressing the “sustain” pedal. Then, we pick up the tempo to show that the beat of the music can be adjusted at will. A few bars of “When the Saints Go Marching In” were added to visually demonstrate the operation of the chords when 3 keys are depressed simultaneously.

The video of the “Cool Xylo”demonstrates what can be done with an inexpensive instrument and very basic software by playing a couple of simple songs “Twinkle, Twinkle Little Star” and “Joy to the World”. Because it is computer controlled, the striking of the bars is perfectly uniform and adjustable at plus or minus 14 milliseconds for each tap. The beat of the music and the length of the notes are determined by the delay before the next note is played.

Most popular music is written to be played on a guitar. Guitars have a range of 4 octaves (the equivalent of 48 keys on a piano or xylophone). So, unless your taste is for heavy classical, you should find millions of songs capable of being played on the instruments described here.

The Mega's ability to store 256, 0000 bytes in its memory and the efficient software used to play the songs provide at least 90 minutes of music from one upload of the Mega.

The image of the Universal Control Box shows a shield for the Mega 2560 (located below the shield) with 13 ULN 2803s drivers, 2 relays for sustain and volume, and 13 screw connectors for the cables to the solenoids.(This shield is not yet available but we will wire a breadboard). The control panel has a reset switch and an On/Off switch.

Overview of the Xylophone Projects

Xylophones

We start with an overview of the simpler xylophone projects and move on to the Casio player piano project after we have mastered the construction of the hardware and software of the player xylophones.

The bars that are tapped with mallets (with either hard rubber or plastic ends) are made of steel or wood depending on their ancestry. The African variety where “Xylos” means wood are made of very hard Rosewood from Honduras. The type with metal bars were originally from Germany taking the form of bells that were played way back in the 1500's. The correct name of this instrument is “Glockenspiel” not “Xylophone”as it is generally known.

Striking the bars is critical: the tap has to be sharp but if the mallet is not removed very quickly after the tap, the bar will not be able to ring or vibrate at its basic frequency which is determined by its length. So, the end of the solenoid shaft has to be at a good distance from the bar (about ¼ inch) to produce a sharp tap but the power to the solenoid has to removed quickly so that the spring can retract the solenoid shaft quickly to let the bar ring.

I tried a variety of ends for the shaft. The solenoids come with an acorn nut that screws on the shaft. Because the nut is metal, it makes too much noise when it strikes the key. I tried rubber ends by using rounded off gum stimulator refills (used to floss one's teeth}. They worked well with the low frequencies bars but halfway through the scales they lost their power. I obtained the best results with plastic ends that I made from a cut-off wire nut (smallest size available) used to connect electrical wires together. For the best results, the distance that the shaft travels has to be uniform for all the keys, so the plastic end pieces must be cut, sanded round and attached to the shaft with care. See the photo below.

The o ring that comes with the solenoid does not do a good job reducing the noise generated by the shaft when it returns to its off position. We will talk more about selecting solenoids and the need for noise reduction when we discuss the solenoids in the Casio player piano project, for now, suffice to say that the Styrofoam washers seen on the picture below work much better.

Selecting a Xylophone

I experimented with 2 children's xylophones before investing all of $70 in the Ammoon. The Baby Xylos were somewhat disappointing because the volume is low (possibly, they were designed that way for inside use). I am not thrilled with the quality of the Ammoon either. Several keys had larger screws holding the bars in place and the o rings were missing.This caused the bars to touch the screws which results in a flat rendition of the notes. Repairing the problem was not difficult but it tells you that the quality is lacking. (Possibly, it is the best xylophone that can be bought at this price), but I would not recommend this instrument. The solution is to do more shopping by starting at a couple of good music stores and asking for their advice. In spite of these difficulties, the videos show that we accomplished our basic goal of making music.

Building the Cool Xylo

As shown in the photo of the Cool Xylo under construction above, I mounted the two sections of the xylophone on a 1 by 2 foot section of ½ inch thick plywood. The sections can be separated simply by removing the hinges. I then removed the H sharp key and shortened the frame in order to make more room for the control box. Four pieces of ¼ inch plywood, 1 ½ inches high, of the correct length were cut to cover the ends of the frames. They were attached to the frames with screws. They support the solenoid frame which we will build next.

Each of the two solenoid frames is constructed from three pieces of ½ x ¾ inch strips of wood. The two risers are 5 inches long. If an imaginary center line were drawn from the first to the last key, the risers would be mounted 5/8 inch back of the line so that the solenoid shafts hit the middle of the keys. That's all there is to the frames. They are glued and screwed in place but I would put off the gluing until the operation of the solenoids has been checked out and they are tuned correctly.

The frame on which the solenoids are mounted for the Baby Xylo is built the same way but the ½ x ¾ inch risers can be mounted directly to the frame of the instrument

Mounting the Solenoids

As we will see, I made an exhausting search for the best solenoids for these projects, the best compromise turned out to be the JK 0730B. The price varies all over the lot (from less than $3 to more than $10) but I always found them on Ebay for about $3. They come from China and take about 4 weeks for delivery. Once you get serious about doing the project, this is the first item to order.

The bar on which the solenoids are mounted is attached to the two risers with #8 oval head screws through a 3/16 inch rubber grommet to reduce the noise of the solenoids. The bar is aluminum 1/8 inch thick and 1 1/2 wide. It can be bought at Home Depot or at Ace Hardware.

The back of the solenoids have two threaded holes which accommodate M3 metric screws 6mm long.The screws need to be short so that they will not dig into the insulation around the solenoid's coil. To accomplish all of this, the ideal screws are steel, pan or round head screws, metric size M3, 6mm long. In quantities of 100 they cost about $6 from Grainger or Ace Hardware.

Mounting the Solenoid Bars

As I mentioned, the installation of the solenoids on the aluminum bar is critical. We will see that part of the 10mm of plunger travel (3/8 inch) will be used to quiet the solenoids. It is therefore critical that all solenoids line up in a straight line. Very slight misalignment of the solenoid can be corrected by enlarging the two mounting holes in the aluminum bar, but you should not plan on it.

To insure that the mounting holes are drilled uniformly in the aluminum bar, we will first build the simple jig that is shown below. To make sure that the jig performs its alignment properly, check it out as follows. Press the jig tightly and clamp it to the bottom of a leftover piece of aluminum bar. Drill pilot holes, then the 1/8 inch mounting holes. Mount three solenoids on the bar and make sure that the ends of the shafts line up in a straight line. One more hole has to be drilled in the aluminum bar for each solenoid in order to thread the solenoid wires to the back of the bar. The hole location is not critical but ¾ inch from the bottom and 1/8 inch from the side of the solenoid will work. Using a

countersinking drill bit, bevel the edges of the holes slightly so that the wires do not rub against the sharp edges.

The Jig

I made the jig from a kitchen cabinet hinge that I found in my junk box. Three things are important. One, the bottom of the jig must have a 90 degree bend about 1/8 inches wide. Two, the two small, 1/16 inch pilot holes (7/64 can be used as well) need to match the mounting holes of the solenoid exactly. Three, a centerline indicating the middle of the mounting holes must be marked at the top of the jig so that the jig can be lined up with the middle of the keys.

The next step is to mark the middle of each key on the aluminum bar. Go back to the imaginary center line where the solenoid shaft hits the keys. Divide the width of the bars by two and mark the spot on the bars then transfer the marking to the aluminum mounting bar. Then, align the center lines drawn on the bar with the centermark on the jig, then press the 90 degree bend of the jig firmly against the bottom of the bar and clamp it in place with vice grip pliers. If at all possible, drill the pilot holes and the 1/8 inch mounting holes in the aluminum bar on a small drill press. If a drill press is not available, clamp the bar vertically in a vice, then, using the level in your hand-drill, drill the holes as square and true as possible. Do not keep the drill bit in the pilot holes of the jig any longer that necessary - we don’t want the pilot holes to become oval or enlarged.

The solenoids can now be installed on the aluminum bar and the bar can be installed on the wood frame so that the plunger ends are all about 3/16 inch from the music bars. The aluminum bar will probably be readjusted for best performance and tuning later so at this point use only one screw at each end of the bar. This completes the mechanical installation of the solenoids, our musical mini-robots.

Wiring the Control Box

Each solenoid has two wires. One of the two will be connected to one of each of the other solenoid's wires and to +12 volts. The other wire is brought into the control box and wired to the screw connector which in turn is connected to the port driver.

Control Box Wiring

The control box houses the brain of the project which is an Arduino Mega 2560 microprocessor, it is the muscle car of the Arduino family of microprocessors. It has 54 digital output ports to be used as follows: port 0 is not used, when it is selected it causes the music to play a pause, ports 20 and 21 are reserved to simulate the action of piano's pedals, “soft” and“sustain”, the other 51 ports are used to depress keys or tap xylophone bars.

A shield is a PC (Printed Circuit) board that can be plugged into the connectors that surround the microprocessor. It is used to capture the outputs of the computer and turn them into usable functions. Looking at the photo of the Mega2560, below, we can see the connectors around the edges and we can imagine that if we turn the MPP-51 Universal shield (the following drawing) clockwise 90 degrees, it will plug right into Mega 2560. Building this shield is our next job

The Universal Shield Design

I call it a “Universal” shield design because it can be adapted to drive Baby Xylos with 8 keys as well as the 51 key Casio player piano. A simple Baby Xylo shield can also be built from one of the many Mega prototype shields available from Ebay for $3 to $6. When more keys have to be driven and the shield is expanded, it needs to be built on a 4 1/4 X 4 3/4 inch prototype PC board which can drive up to 51 keys. Before designing the Universal Shield described here, I built one of each of these wired shields and I am happy to report that they both worked very well.

The real PC board shield that I subsequently designed can best be seen in the photo of the player piano's control box. The problem with my Universal Shield is that it has four mistakes. Considering that it has 1696 traces and 879 pads that's not bad for a beginner. Nevertheless, it has to be revised, a new batch of boards have to be ordered and the revisions have to be checked out, so it will take a couple of months to complete this job. When the shield is available, I will advertise it on my website “modernplayerpiano.com”. Meanwhile, the 51 key shield can be wired on a breadboard or a prototype board as we will describe below.

Building a Universal Shield on a Prototype Board

The prototype board shown below is 4 ¼ inch wide by 4 ¾ inch high. It can be cut from a larger board such as the 5 X 7 inch board that is part of a 12 piece kit costing about $6 at Ebay. To fit between the cover mounts of the 5.3 X 5.3 case sold by All Electronics (Cat #1598-BSGY $10), about 1/8 X 1/2 inch has to be trimmed from the middle of the board.

Mounting the prototype board in the case is done with three 4/40 bolts 1¼ inch long, one is located above U10, another next to U6 and the third one is near pin 9 of U8.The bolt goes through the bottom of the case and is securely locked in place with a nut. Two more nuts are adjusted on the bolt to secure the board about 7/8 inch above the bottom. The Mega PC board does not need to be attached to the case.

Mounting the headers comes next. From All Electronics, order 2 ea DHS-20 headers and 2 ea. SHS-40 headers (They break easily, so I would order the extras). There are three 8-pin headers (one on the left side and two on the right side), one 10-pin header (right side near U10) and one 36-pin double row header (ports 22 to 36 on the bottom) to be installed. Carefully cut the header stock as needed for the correct number of pins for each header.

The components go on top of the board and are soldered on the bottom. But, the headers have to be installed from the bottom and can't be soldered on top because these are single-sided PC boards. Three strips of PC board about 3 inches long are cut from a spare prototype board, two of them are 3 holes wide and one is 4 holes wide (for the double wide header).

If at all possible, before cutting out the strips from the breadboard, thin the stock down to about one half of its thickness. This job can be done with a belt sander (don't even think of doing it on a table saw!) With a minimal amount of super glue, attach each of the strips where the headers are to be located so that the header pins can be soldered on the topside. Mark and double check to location of the headers. There should be 18 holes between the side headers and 8 holes from the edge of the prototype board to port 13. Practicing the installation of a strip and soldering a header to it on a spare prototype board is worthwhile exercise.

Soldering Tips

Unlike the pads of the manufactured PC boards which have a pad on the top and one on the bottom connected together using “through hole” technology, the pad of the prototype boards are on one side of the board only. Consequently, these pads are fragile: they have a minimal amount of strength and they detach from the board if too much heat is applied. When the components are inserted on the PC board, make sure that they are positioned correctly. Masking tape can generally position them tight and straight on the board so that they can be soldered correctly the first time.

A few more soldering tips:

Lightly sand the pads to remove any dirt or corrosion

Tin the wire or the pins to be soldered

Use a low wattage (25 or 30 watt) soldering iron to avoid getting the joint too hot

Use 1/32 inch solder wire

Use solder wire with 60% lead content (high tin content requires too much heat)

Keep the soldering iron tip tinned and clean, wipe it clean after each 3 solder joints

Work fast so that the pads are not overheated.

Installing the Components

Only four different components are needed for the full blown version of the shield: 3 resistors, 2 relays, 13 4-pin screw connectors and 13 18-pin sockets for the ULN 2803 ICs (Integrated Circuits). The relays and two of the three resistors are not needed for the xylophone control box. The location of components shown on the diagram above is not critical: the components may be moved a few holes one way or the other if desired (not the headers). The resistor sizes are described in the player piano section.

List of Components and Where to Buy Them

The components listed below are standard parts. By all means, buy them where you get the best deal. I bought them where noted but I did not do much shopping. 13 units of each group are needed for the Casio Player piano.

1. ULN 2803 Driver and the prototype boards : Ebay- $1 to $6 for 10 ULN 2803's and $6 for the boards

2. 18 pin IC sockets, relays, resistors, component case, solder, wire: All Electronics

3. 4 pin screw connectors, (green, 0.10 inch pitch): Ebay (page 5) $4 for 10 connectors.

Wiring the Components

#26 stranded wire available at All Electronics is a good size to hook-up the components. #24 solid wire or, for very short runs, bare wire can also be used.

As the chart above indicates, we start to wire at a port pin and go to the input pins of the ULN 2803. From the output pins of the ULN 2803, we wire to the screw connector pin. Note that 2 input pins and 2 output pins are connected together for each wire. We repeat this 53 times for the player piano and for as many times as there are keys for the xylophone players.

Miscellaneous Circuit Diagrams

A diagram of the driver circuit is shown below in the next set of diagrams. Note that this is a top view of the ULN 2803. There is a notch at the top of the IC to determine its orientation. The first pin on the left is pin 1. The numbering goes around the bottom so that pin 18 is on the right of the notch.

Note also that each wire goes to a pair of pins. That is done to put 2 driver circuits in parallel in order to handle the load. Each of the 8 circuits of the ULN 2803 can drive 500 milliamps but our solenoids require 800 ma, therefore, two circuits are needed. The wires from the ports to the input pins of the ULN 2803 start at the top of the board and pass through a hole (1/8 inch) to the bottom of the board.Twisting four color coded wires together through the hole makes makes it easier to connect to the correct pin of the driver. 13 wires starting at GND, daisy-chain to each pin 9 of each of the 13 ULN 2803s. Another 13 wires start at +12v and daisy-chain to each pin 10 of the ULN 2803s.

The color coded wire mentioned above can also be obtained by stripping the wires from a cable such as All Electronics Cat # CB-397.

The screw connector diagram shown next tell us that there are 4 pins in each connector and that each pin goes to an output of the ULN 2803. One wire from each solenoid is then connected to its assigned port when screwed in place.

The two relay diagrams indicate which port (20 or 21) controls their operation (the coil of the relay) and which pins are used to activate the circuits. In the case of the sustain relay, a normally closed circuit is opened when the relay is activated. In the case of the low volume relay, two normally closed contacts normally short out the resistors which were added in series with the speaker wires. When they open, they allow the resistors to become active in reducing the volume of the speakers.

The Control Panel and Its Circuits

The next set of diagrams show the wiring of the control panel and the control panel circuits. The control panel is the aluminum plate on which the Master Reset switch and the On/Off switch (with its LED indicator) are mounted. The +12 volt power connector and the power source for the Mega also originate from the panel. When the control box is used for a player piano, an additional hole (with grommet) is drilled for a cable which controls the Sustain and Low Volume functions.

The Master Reset switch is a momentary mini-toggle switch (All Electronics: Cat MTS-93 $2). The On/Off switch is a mini-toggle (A/E: Cat MTS-12 $2).The indicator is a 12 volt LED with a built-in resistor (A/E: CatLED-12R $1).

The 12 volt power comes from a 3 amp power supply such as the ones used for PCs. All Electronics has a number of them for about $6, check Cat PS 3332 or PS-123U. These power supplies have a 2.5 mm connector plug. A matching jack is mounted on the panel as shown. (A/E: DCJ-25 $2), it goes to the +12v post on the board after going through the On/Off switch. The last item to be installed is a plug connected to two 6-inch lengths of wire: one wire goes to the voltage dropping resistor(R3) and the other one goes to GND as shown on the diagram. The LED is connected between 12 volts and ground. Although the Mega's power source is rated for 12 volts (maximum), I reduce this voltage to 8 or 9 volts to keep the 3.3/5.0 volt supply regulator from overheating.

This completes the description of the circuits and of the wiring for the player xylophones. A description of the wiring for the player piano comes next.

Building the 51 Key Casio Player Piano

Compared to the player xylophone, there are three main areas where the player piano differs substantially: a) the mounting of the relays: a wooden crossbar replaces the frames and the solenoids are mounted in front to activate the white keys and in back to activate the black keys, b) the use of the solenoids: instead of tapping the note bars, the keys are depressed for the duration of the note, c) the circuits that simulate the operation of the pedals are activated. These differences will also cause a considerable impact on the software. Another minor difference is that the solenoid plunger is returned to its starting position by the key rather than by the solenoid spring which is not used.

Before mounting the crossbar with the solenoids, I stiffened the Casio keyboard by mounting it on a ¾ inch plywood board 10 X 33 inches (make sure that it is flat!) Without this base, the Casio sags enough to make the solenoids difficult to adjust. Towards the back, there are 2 embedded nuts that can be used to mount the base. In front, I screwed 3 #8 sheet metal screws into the 3 plastic feet of the Casio.They can be filled with epoxy for better holding power. Be sure to cut a hole in the base to access the battery box.

Mounting the Solenoids

The basic idea is to mount a straight 2 inch by ¾ inch wooden crossbar securely on the keyboard about ¼ inch above the keys and ¼ inch away from the front of the black keys. (See the photo above from the same kind of installation on a Yamaha Keyboard). It will become the base for the two aluminum bars on which the solenoids are mounted.

Finding a straight board (straight means not bowed and not twisted) is not always easy, but since this one is only 42 ½ inches long, a clear section can be cut from a 6 foot board 4 or 6 inches wide. #2 pine is fine as long as the section selected does not have any knots. Take advantage of Home Depot’s policy to allow customers to select the best piece of wood for their job.

The 2 inch wooden crossbar is mounted on a small support bracket (¼ inch plywood) 1 ½ X 2 ¾ inch at each end. The support brackets are in turn attached to the keyboard with 2 #8 oval head screws. A ¾ by 1 ½ inch wedge (¼ inch in front, flush in back) is used between the bracket and the crossbar so that it is mounted vertically (at 90 degrees from the keys). The brackets, wedges and the crossbar are all squeezed together with a 3 inch long 3/16 flat head screw with the nut on top at each end (see photo with the cover off).

The two aluminum bars are drilled for the solenoids using the drilling jig in the same way as it was done for the xylophones. The bar for the white keys is 33 inches long, drilled out for 36 solenoids of which 32 are active. The bar for the black keys is 27 inches long drilled out for 20 solenoids of which 19 are active.

After the solenoids are mounted on the aluminum bar, the bar is mounted on the crossbar with #8 oval head screws using rubber grommets so that the aluminum bar does not touch the crossbar in order to keep the solenoid noise from reverberating from the crossbar.

At each solenoid position, there is a 1/8 inch hole in the crossbar through which one of the solenoid wires passes and is attached to the +12 volt bus. The other one forms a cable that goes to the control box. Other 1/8 inch holes are drilled in the crossbar to lace the cables in place as needed.

At the right end of the crossbar a 4 X 4 inch square ¼ inch piece of plywood is attached to the top of the crossbar to support the control box.

Selecting the Solenoids

Because we need so many solenoids, we need a good quality device that is also inexpensive. The important specifications are as follows:

A “push” type (as opposed to the more common “pull” type) solenoid

Approximate size: ¾ x ¾ by 1.5 inches long

12 volt operation. 1 amp or less for the current

$3 or less for the price.

I ordered and checked out a dozen solenoids that were close to the specifications shown above. Of these, I selected the best five. I spent a lot of time testing the high quality Ledex, but finally concluded that its power was too low and that it would be too difficult to attach a foot to the end of the plunger shaft. The curves below show the power of these five solenoids depending on the amount of electrical power that is applied to them.

The x-axis shows the electrical power in watts. One watt is equal to one amp multiplied by one volt. So, if at 12 volts our test solenoid (type JF) draws one amp we find that it uses 12 watts and develops 9 oz. of force. Since depressing a piano key only requires 4 oz, we are comfortably in the operating zone.

The tests revealed that there were two possible problem areas. First, although the label on the solenoid says “1 amp,”the actual current at 12 volts DC is only.7 amps which reduces the electrical power to 8.4 watts. According to the curves, this reduces the strength to depress the keys to about 7 oz. Fortunately, we are still well into the operating zone.

The other potential problem has to do with the way we energize the solenoid. When we play a full note, the key will stay energized for 2 seconds (when the beat of the song is 120 beats per minute). But when we play a 1/16th note, the solenoid will only stay energized for 125 milliseconds (1/8 second). I checked to make sure that the short pulses and the lower than expected power would still allow the solenoid to activate the keys correctly and it does.

Every indication shows that the JF 0730 will operate the keys of the keyboard properly but that there were noise problems to resolve.

JF-0730 Solenoid Noise Problem

What noise level is considered too noisy and what is acceptable? I think that we should strive to keep the noise level equivalent to or less than the amount of noise created by the keys hitting bottom when they are played by hand. Just listening to the amount of noise that they make would be too subjective; we needed a better way of measuring sound levels. Fortunately, the smart phone came to the rescue with a sound measuring app.

Noise Reduction Techniques

Having settled on the JF-0730 as the best compromise as far as quality, size, power and price, the next step was to try various ways of reducing the excessive noise that the solenoid made when driving the keys. It’s worth mentioning that all the solenoids tested were too noisy and would have required modifications. Quiet solenoids do exist but they cost at least 5 times as much as the JF-0730. The drawing above shows the image of the solenoid, the operation of this simple device and the source of the noise.

It should be noted that the noise is greatly amplified when the solenoid is mounted on a solid surface. When the solenoid is activated in one's hand there is little noise. On the other hand, the noise becomes unacceptable when the solenoid is mounted firmly on a solid surface. We will therefore work on the mounting as well as on the solenoid itself.

There are three sources of unwanted noise but the main one is caused by the seating of the plunger when it slams against its stop. As the diagram above shows the plunger cone comes to rest in a V shaped part of the body of the solenoid. The main trade-off here is to reduce the noise without reducing the travel of the plunger anymore than is absolutely necessary.

I tried a variety of possible solutions including machining a grove in the cone and fitting a tiny rubber “o” ring in the grove. Nothing that I tried worked as well as simply stopping the plunger from hitting the cone at all. That can be done easily by fitting a Styrofoam washer or pad on the body of the plunger beneath the “C” clip. The fit should be tight so that the pad stays put on the plunger shaft. It should not be more than 1/8-inch thick nor anymore than 5/8-inch in diameter. I tried a number of other materials such as soft rubber, cork, foam, plastic, felt, balsa wood and Styrofoam ear plugs. I discovered the ear plugs late in the game but they work very well.

The simplest way to make these washers (to my knowledge, they cannot be bought) is to buy rigid ¾-inch thick closed cell insulation. Drill a 3/16-inch hole in the edge of the Styrofoam, and then cut 1/8-inch thick slices. The slices will further be cut in 5/8-inch squares and trimmed to round them off.

The second source of unwanted noise occurs when the foot of the shaft is pushed back to its rest position by the key after it has performed its task of playing a note. Here again, after trying a variety of materials, I could not find anything that worked better than a Styrofoam pad. In this case, the pad can be sliced thinner than 1/8-inch. It only needs to be slightly thicker than the brass lock-nut that holds the foot in place. With a 7/32 hole, the Styrofoam will fit over the nut. It can be glued to the foot so that it will not ride up and down on the shaft.

The third unwanted noise occurs when the end of the plunger shaft hits the keyboard key. We will describe a foot that reduces this noise in the next section.

A Jig to Slice the Styrofoam Pads

The picture below shows a miter box-like jig to slice Styrofoam or other material such as cork, rubber or balsa wood. This mini-miter box has a nice feature to determine the thickness of the washer-like wafer being cut. The material to be cut presses against an adjustable stop while it is sliced with a razor blade. This simple stop is a quarter inch locking nut that is adjusted in and out of the wood block at the end of the miter box groove. The best cutting devices are a serrated knife or a razor blade. My experience is that the razor blade works better.

Too late, I discovered that inexpensive ear plugs are about the right consistency to make good sound absorbing washers. Being round cylinders about ½ inch in diameter they only need to be drilled and sliced. To drill them, use a very high speed drill bit slightly larger in diameter than the finished result. The ear plugs can be obtained from Amazon, they can be used wherever a Styrofoam washer is called for.

The Solenoid Foot

The foot is an important part of the mini-robot solenoid design because it has to depress the keys reliably and quietly. The round metal acorn nut provided with the solenoid does not work for two reasons; one, over time it will damage the plastic top of the keys and two, it is very noisy. One might think that since the plunger already rests on the key no additional noise would be produced when it depresses the key farther but that is not the case. Once again a smart phone app - one allowing videos to be played in slow motion - was used to resolve the mystery.

What actually happens is that the plunger bounces when the key hits bottom. It is at that time that the noise is created. I first thought that a plastic or rubber cap could be fitted on the end of the plunger shaft to absorb the pressure, but that did not work well. The solutions described below are effective, but they are time consuming to build.

Both solutions involve screwing a foot on the shaft of the plunger. A brass nut must be purchased to replace the acorn nut furnished with the solenoid. The nut size is M-3, part # HN4B00300-100P1 at Grainger Industrial Supply (about $6 for 100).

The photo below shows two different feet that can be attached to the solenoid shaft. On the left, the nut is glued to the flat part of a 5/8-inch button (# 570000022 at Jo Ann’s Fabric; $1 for 20 buttons). Super glue works well but J-B Weld’s two-part epoxy (3960 PSI) is stronger. It does have a 24 hour cure time so it must remain undisturbed for that length of time. Be sure to sand off the glaze from the brass nuts and the buttons with medium sandpaper for a good bond. Apply some of the glue to the sides of the nut for maximum strength. Screw the nut on the shaft (3 turns) to keep the glue from filling the hole. Make sure that the shaft is at a 90 degree angle to the button while the glue dries.

As shown on the right, the brass nut is attached to a small round brass plate (the size of a dime) by soldering it on. I used some thick brass gasket material to make the small round plate but I realize that it is not easily available in small quantities. An automobile parts store might be able to help.

Before soldering the parts together, tin them by applying a thin layer of solder on the plate and to the nut after both have been sanded. Add a very small amount of solder when soldering the parts together at a 90 degree angle. Attach the nut to the shaft (3 turns) for ease of handling and to make sure that the solder does not fill the threads of the nut. The solder joint is easy to redo if the location or the angle is not right. It does take practice to do a good job. By all means, use the epoxy if the soldering is a problem.

Two more jobs need to be done to the foot to make it operate quietly. For the bottom of the foot, I got the best results from 1/16-inch stick-on foam which I bought at Home Depot. Stick-on felt works also, but I found it to be noisier. A 1/16-inch thick pad similar to the one below the C clip is needed to prevent the nut from hitting the body of the solenoid when the key pushes the plunger back up after the key is released. The sliced earplugs work very well at this location.

Measuring the Noise from the Solenoid Driven Keys

Measuring the amount of noise caused by the keys with the smartphone app is much easier when a diagnostic sketch which operates the keys one at a time is running in the Mega. Until we get to that point, the best solution is to generate 12 volts DC with eight 1.5- volt “D” batteries wired in series. After the solenoids have been installed, they can be checked out with the 12-volt battery supply. To add some versatility to the testing, build the “D” battery supply with taps so that voltages from 6 volts to 12 volts can easily be selected in 1.5 volt steps. Be advised that soldering wires to “D” batteries with a 25-watt soldering iron is difficult. The area has to be sanded clean and additional flux to what is in the soldering wire is needed. Make sure that the solder really melts into the battery material.

Until the diagnostic programs can be run, we will do our testing (noise and continuity tests of the cables) with the batteries. With the lower voltages (7.5, 9.0 and 10.5 volts), we will be able to perform “marginal” testing on the solenoids to make sure that they all operate at the same lower voltage. If they all work equally well at, say, 7.5 volts, it’s an acceptable result even if a few solenoids operate as low as 6 volts. That will tell us that they were installed and work correctly.

With the solenoids mounted as discussed above and modified for noise reduction, here are some representative noise measurements (three feet from the source of the noise) obtained in tests using the 12-volt battery to activate the solenoids.

Noise of the keys hitting bottom when pushed down by hand: approximately 23 db

Noise of depressing the keys with the modified JF-0730 solenoid: average: 25 db

Best results using a better quality solenoid (Ledex): average of many tests 22 db.

After the solenoids have all passed the battery test, they may be connected to the screw connectors which are powered by the drivers and the output ports of the Mega.

Miscellaneous Circuits

We have already talked about these circuits but a recap won 't hurt.

Control Panel Circuits.

The +12 v source comes from a plug-into-the-wall 3 Amp power supply. It proceeds from the jack installed on the panel to the On/Off switch, then powers the LED and also goes to the 12 volt terminal on the shield. On the shield, the 12 v circuit goes to pin 10 of all ULN 2803 that are being implemented and to a 12 v bus which feeds one side of all the solenoids.

The GND wire from the power jack goes to the GND terminal on the shield and to all the pin 9 of the the ULN 2803's. The shield GND and the Mega GND are connected together.

The power jack which plugs into the Mega's power plug is connected to two 6 inch wires. One wire goes from the voltage dropping series resistor (20 ohms, 2 watts) to the center terminal and the other wire goes to ground.

One side of the momentary master reset switch goes to GND and the other goes to the reset terminal of the Mega

Player Piano Circuits

The two Casio circuits that need to be implemented are: 1) activating the sustain circuit and 2) activating the low volume speaker output.

The sustain circuit is activated by connecting two wires to a normally closed contact of the sustain relay (as shown on page 17). These wire are connected to a ¼ inch audio plug (All Electronics Cat # SPH $1) that fits into the Casio sustain jack.

The last circuit reduces the volume of the Casio speakers by inserting a resistor (about 20 ohms, 2 watts) in series with each speaker. One of the speaker wires is disconnected from the speaker and connected to a resistor mounted on the shield PC board. The other end of the resistor is connected to the empty terminal of the speaker with a new wire. Two more wires are connected to the resistor, they go to each side of a normally closed contact of the volume relay (also shown on page 17). When the low volume relay is turned off the resistors are shorted out and the volume is normal. When the volume relay is picked up the series resistors reduce the speaker volume. If desired, these speaker wires can also be connected through ¼ inch audio plugs and jacks installed at the back of the Casio.

This completes the installation of the electronics for the Casio player piano. We have shown how to build the player xylophone by installing the aluminum bar with the solenoid mini-robots on the frames and by installing them on the crossbar of the Casio keyboard. We have discussed the wiring of the shields and driving the output of the ports to operate the solenoids. We will discuss music basics next and then the software that operates the solenoids to produce the music.

Sheet Music and Musical Symbols

Background

Computers are really dumb. Every minor detail has to be explained to them and they only know 1’s and 0’s. To make up for this, they are lightning fast - in the half second that it takes to play a quarter-note, the Aduino Mega performs 8 million operations.We don’t have to be concerned that it will be overworked: between bursts of activity, it idles most of the time.

To make our computer activate the mini-robots, we will write a sketch (programs are called sketches in Arduino-speak), named“Robo-C” for the player piano and use “Blink” for the player xylophone. Eight bits of note information are provided to Robo-C for each consecutive note found in the sheet music of a song.

The job of the Robo-C sketch (which is uploaded with the song code from the PC to the Mega computer) is to interpret the note's eight bits of information, activate the solenoid and move onto the next note. Once you get used to the routines and the terms used to describe them, it is really very simple. All that is needed is to code the eight bits of information for each note and upload the Robo-C sketch which has been written and debugged for you. The Blink sketch used for the xylophone is part of the Arduino library and is, therefore, easily available.

Just a word about the Arduino IDE software (Integrated Development Environment). It is open source software (which means that it’s free and can used by anyone without worrying about patents or copyrights). It is similar to “Word” or “Open Office”; it is used to write the sketches, compile them, edit and manage the files and bring up the serial monitor to debug the sketches. An updated version of the IDE is always available, download it to your PC according to the Arduino instructions. Since the Robo-C sketch has been written for you, there is no need to learn a great deal about C++ or about writing sketches. That said, writing a simple sketch to turn an LED on and off using Simon Monk’s book is a worthwhile exercise and is recommended.

My experience with the Arduino IDE is very good and the new version is better yet. I have been mystified at times with error messages such as “Cannot find Com 3” when I was using Com 12 (disconnecting the USB cable and resetting the Mega and the PC resolved the problem) - some of the cryptic comments from the compiler are less than helpful to solve typing errors - but overall it is more than adequate for this project.

We will now look at the sheet music and the musical symbols that are used to tell the pianist (in our case, the coder) how to make our player piano play some tunes.

Sheet Music and Musical Symbols

The first piano invented by Bartholomeo Cristofori in 1722, was a direct descendant of the harpsichord. It had 49 keys(four octaves) which grew to 61 keys (five octaves) by the late 1700’s. By the early 1800’s, motivated by composers like Beethoven, manufacturers built 73 key pianos. Then, about 150 years ago, pianos reached their present 88 keys (seven + octaves). The human ear has trouble assimilating higher or lower pitched notes, so that this range is not likely to be expanded.

Sheet music looks like the sample below. It can be bought at music stores or obtained on-line by looking up the name of the song. To understand the Robo-C sketch that we’ll be using to direct the operation of the player piano, it’s important to understand the symbols and the conventions used in sheet music. Although we won’t examine every symbol used in sheet music, we will describe all the basic ones as well as the ones that we will code in the Robo-C.

Staffs

When we look at the sheet music written for the piano, we first notice that there are two sets of five lines and 4 spaces running across the page. They are called the “Staff.” Every line and every space represents a different pitch for the notes. The pitch or the frequency of the note located on or between the lines increases as it is located on a higher line or space.

This is the treble staff. The treble clef (the large fancy symbol to the far left) shows the musician that the staff is treble. Since it curls around the G line, it is also called a G clef. The treble staff begins with the first note on the first line, this is an E. Each successive space and line is the next letter in the musical alphabet which ranges from A to G. The 7 notes from G to F constitute one octave.

Pictured above is the bass staff (pronounced “base staff”), also known as an F clef because it locates the line F between its two dots. The bass staff uses the same musical alphabet as the treble staff but the letters start in different places. Instead of an E, the bottom note on the first line is a G and the last note on the top line is an A.

Measures

The vertical lines on the staff mark the measures. Measures are used to divide and organize the music. A fraction (such as 4/4) determines how many beats there are in a measure (in this case 4). The thick double bars mark the beginning and end of a piece of music. Measures are sometimes marked with sequential numbers to make navigating a piece of music easier. The first measure would be measure one, the second measure two and so on.

Ledger Lines

The ledger lines are found above and below the staffs. They provide the needed space to show notes that have a higher or lower pitch than the ones that can be shown on the staffs. They follow the same alphabet pattern that is used on the staff just as if there were more lines and spaces available. They are very useful because, at a glance, you can determine how many keys will be needed to play a certain piece of music. Most pop music will have at most two ledger lines but classical pieces may have six or more.

Cleffs

On the left side of the top staff is a symbol known as the “Treble Clef” or “G Clef.” It looks somewhat like a G and its center is located on the second line of the top staff, which makes the notes on that line have a pitch of “G.”

On the left of the bottom staff, there another symbol called the “Bass Clef” or the “F Clef” because its center and the semi-colon to its right are centered on the fourth line (counting from the bottom). The notes on that line have the pitch of an “F.”

When the top staff and the bottom staff are joined by a brace, it turns the two staffs into a “Grand Staff” which contains all the notes for that musical selection. On the piano, the top staff notes are played mostly by the right hand and the bottom staff notes are played mostly by the left hand.

The Rhythm, Tempo or the Beat of the Music

3/4 Time

When you tap your foot or clap your hands to the beat of a song, you are tapping in synch with the measures of the song. The duration of this recurring beat is determined by the fraction located on the first grand staff after the treble clef and the bass clef. Being a fraction, it has a numerator on top and a denominator on the bottom. The numerator tells us how many beats there are in each measure and the denominator tells us which note has the beat. In “Fur Elise” the song shown above, the fraction 3/4 tells us that there are 3 beats per measure and that the quarter note has the beat. Looking at the sheet music of “Fur Elise” again, notice that since the quarter note has the beat, you find 3 quarter notes in each measure (or the equivalent, 6 eighth notes or a half note and a quarter note since each of these groups have the same duration). On the first page of Fur Elise, most notes are eighths and quarters with a single half note.

These simple fractions determining the beat, also known as time signatures, include 2/4 for two-step country music, 3/4 mostly for waltzes (also known as 3/4 time) and 4/4 for popular music.

The Notes and the Rests

The five notes shown below are called the naturals. They’re played on the white keys and vary in duration. Compared to a quarter note which may have the beat, a whole note will last 4 times as long as the quarter note and a sixteenth note will have a duration of one fourth that of the quarter note.

The rests are places where the musician or coder does not play anything. Their symbols and their note equivalents are also shown below. On the first line, on the left, we see a whole note with its equivalent whole rest. On the right, we find a quarter note and its quarter rest. On the second line, we show a half note and a half rest on the left and an eighth note and an eighth rest on the right.Between the two lines we find the sixteenth note and its equivalent sixteenth rest. (Courtesy of Method Behind the Music)

The Accidentals

While it’s known that the history of the accidentals (the black keys) dates back to the Middle Ages, the etymology of the name is a mystery. In any case, they are closely related to their natural equivalent note - the note that follows the symbol. In the diagram below, we see three symbols telling us that the note that follows is: either a sharp, a flat, or it negates the previous symbol. The first note is a sharp which raises the pitch of the note by one semitone (a half step higher than the natural next to it). The second note is a flat which reduces the pitch of the note by one semitone. The third symbol tells us to discontinue the action of either of the first two symbols. (Diagram courtesy of Wikipedia)

Notes with a Dot

The dot next to a note indicates that its duration is 50% greater than normal. The dotted note shown below has a duration half way between a quarter note and a half note.

Beamed Notes

The beam across the top of notes is the equivalent of putting a little flag on each note. The one shown below is for eighth-notes, if they were sixteenth-notes, there would be two horizontal beams to replace two little flags on each note.

Ties and Slurs

Ties and slurs are the arcs that indicate that the two connected notes are to be played or sung together as one note while adding their time duration. Ties (shown below) are for identical notes, while slurs are arcs used to connect notes of a different pitch.

Dynamics of the Song

The intensity or volume of the notes vary from very soft to “piano” in the middle, to very loud. The symbols go from ppp to p (piano), and from p to fff (fortissimo), very loud.

Chords

As the diagram shows, chords are played when several notes are shown in the same vertical position indicating that they are played simultaneously.

Metronome Mark

Maelzel’s Metronome shown below indicates the tempo or beat of the music. In this case, exactly 120 quarters-notes fit into one minute of time.

Each quarter note has, therefore, a duration of ½ second or 500 milliseconds. Since the tempo of the rendition is at the discretion of the musician, you seldom see this symbol in sheet music.

Sustain Symbol

Ped is the only symbol for sustain that I could find. It is rarely used. The musician determines when he wants to use sustain just as he decides on the loudness and tempo. He could use it for the entire rendition or he may not use it all.

Other Symbols

There are many other musical symbols but you are not likely to run into them in the sheet music that you buy. If you do, check out Wiki under “List of Musical Symbols” where you will find many more.

An interesting aside concerns tuning the piano (to 440HZ with a pitch fork), it is the next higher A note after middle C which is tuned to 440 Hz and controls the tuning of the entire piano. The other six A notes are adjusted to double or to one half of this frequency as we progress up or down the keyboard. All other notes are tuned to the harmonics of the A notes. Player keyboards which are controlled by crystal oscillators with a fixed frequency never need to be tuned.

The chart above which is used with the Casio player piano shows the two staffs with the note middle C on the ledger line between the staffs. Starting at middle C and going up in pitch we can see that middle C is activated by port 36. The highest pitched key shown on the chart is a D, played by selecting port 51. Going down in pitch from middle C we can go to C2 (14 white keys away from middle C). C2 is activated when port 22 is selected. A similar chart showing the port numbers of the black keys is shown on page 55.

These brief instructions are all we need to know to code the music found in sheet music so that the notes can be interpreted by the Arduino sketches Robo-C or Blink to make the player piano or the player xylophone activate the mini-robots that make the music.

Arduino IDE and Musical Sketches

The Arduino Family of Computers

The Arduino phenomenon is about 10 years old. It started as a teaching device for students interested in computer science but it found many other enthusiastic users (approaching a million today) because of its low cost, ease of use and because it is an open source device. Open source means that the service is free and that there are no patents or copyrights to worry about. Anyone can use the hardware or the software as they see fit at no cost without the concern that they might be stealing someone’s ideas. The only thing that cannot be used freely is the Arduino name.

The name Arduino came from the name of a bar in the city of Ivrea, Italy (now part of the city of Turin) where the founders used to meet. The bar itself was named after Arduin of Ivrea who was the king of Italy from 1002 to 1014. A subsequent dispute over the registration of the name caused the Arduino company to change the name of all Arduino products sold outside of the US to Genuino. For more information about it, the Arduino web site, Wikipedia and numerous books have much more to say about this exciting company, its products and its rapid rise in popularity.

Arduino Computers

The Arduino web site tells us that there are 17 “official” Arduino computers available. That includes the Lillypad which is actually a wearable computer. About 15 older models are considered obsolete and have been retired but they may very well be on computer stores shelves somewhere.

There are many clones on the market, but the real thing is inexpensive, reliable and of very high quality, so we will stick to the official brand. This is the third project that I have worked on using Arduino boards (I used the Uno for the other projects). The rugged reliability impressed me most. When doing research and development work, the oscilloscope is used constantly. In my hands, scope probes are weapons of electronic destruction. Flimsy circuits would not last long, but I can report that I have only burned out two Uno’s and one Mega. Selecting the Mega 2560 for these projects was easy. We needed as many digital ports as possible to drive all the piano keys. The 54 ports and the 256 Kilobytes (KBs) of storage inthe Mega 2560 providing about 2 hour's worth of music fit the bill perfectly.

Arduino Shields

In addition to the good selection of computers, there is a large and varied collection of Arduino shields available (probably in the hundreds). Shields are PC boards (such as our breadboard) that perform functions such as driving robot motors or connecting to the Internet. There is even a new shield for one of the latest in high tech innovations: 3D printing.

The clever part of the Arduino shields is that they plug into the connectors mounted all around the Arduino computer board. Moreover, they can be stacked on top of one another for additional circuits. If there were such a thing as a player piano shield with, say, 25 solenoid drivers in each shield, we could stack two or three of them on the Mega board, attach the solenoid wires to them and the entire wiring job would be done. I’ll be designing one soon!

The Mega 2560

Now that we have selected the Mega 2560, let us see what is on the board and what makes its microprocessor, the ATmega1280 tick. Don’t let the microprocessor’s small size fool you. Itis very powerful and enormously complex: the data sheets for this microprocessor total 407 pages of small print. An interesting aspect of this device is that it is preloaded with a simple program that turns on an LED as soon as the power is applied for the first time from the USB cable or from an outside source of power. The orange LED near digital output port #13 blinks so as to say “Hello World!”. Atmel, an American company, has manufactured more than 500 million of these units. I annotated the image of the Mega on page 12 with the name of important components.

The Arduino IDE

When we refer to the Arduino IDE (Integrated Development Environment) we are talking about all the open source Arduino software that supports the development of all types of projects. The main uses of the IDE software that we download from the Arduino website are as follows.

1. Word processing. When we type the sketch or code the music we use word processing software similar to Microsoft Word or Open Office. With this software we are able to open new and old files and assign names to them so that they can be saved and retrieved.

2. Editor. This section of the word processor software makes it possible to “Copy” and “Paste” and, very importantly, to “Undo” errors. Copy and paste is very useful when coding music because it is so repetitive.

3. Compiler. After a music sketch has been created, it is checked by the “verify” software which is part of the compiler. The words, the capital letters and the punctuation all have to be exactly correct or the verifier will reject it (and let you know about it!). Fortunately, the player piano sketch Robo-C has been written for you so that this is not an issue. The compiler’s main function is to translate the written words of the sketch into the 1’s and 0’s that computers understand. Any error in syntax discovered by the compiler is called out and must be corrected before anything else can proceed.

4. Drivers. They are needed so that your PC can communicate with the Arduino board using the USB channel. The installation of the drivers is not difficult; it is part of the installation of the Arduino IDE and it is explained step by step.

After the music has been coded, the entire sketch is verified to make sure that there are no errors and, it is then compiled. This compiled data is then transferred and stored in the Mega’s flash memory by the bootloader. All this activity takes place at the press of the upload button (right arrow). If the Mega’s power is turned on, the music will start. It can be restarted at the beginning by pressing “Reset.” To stop it, the power is turned off.

After the IDE has been downloaded and the Mega is connected to the PC, you can test it out by trying the following. Select the Arduino logo on your desktop. You will see a bare bones sketch with only the two commands that are needed for every sketch -“void setup” and “void loop”. Go to “File” in the left hand upper corner and click on “Examples.” Select: “01 Basics, ” then click on the third item in the list, “Blink.” You will now have a real sketch called Blink in front of you.

To upload it on the Mega board, select the arrow pointing to the right. Assuming that the software drivers and the cable have been installed properly and that the correct microprocessor and communication channel (usually 3) have been selected, the sketch will be sent to the Mega. The LED tied to channel 13 will blink once every second. If you want to play with the sketch just a little bit, you can change the 1000 millisecond (ms.) delay to 100 ms. in both places and upload the sketch again. Now you will see the LED blink ten times faster.

The Sketch “Blink” Plays Music

Computer languages (that the sketch “Blink” is written in) are somewhat like spoken and written languages such as English. Whereas there are thousands of words and definitions in English, there are only a few hundred in C or C++, the parents of the Arduino language used to write the sketches. The sketches Robo-C and Blink which we will use to play music have less than 50 words and commands. The comments that I have added come after the “//”, explain what the commands do. Incidentally, // can also be used to “comment out” some part of the sketch or, if a large section needs to be commented out, the symbols “/*” and “*/” can be used at the beginning and end of the section to be commented out.

//The sketch Blink
void setup()                                   // the setup function runs once 
{                       
pinMode(13, OUTPUT);                 //initialize digital pin 13 as an output
}
void loop()                                     // the loop function runs over and over again
{
digitalWrite(13, HIGH);                 // turn the LED on (HIGH is the voltage level)
delay(1000);                                 // wait for a second
digitalWrite(13, LOW);                  // turn the LED off by making the voltage LOW
delay(1000);                                 // wait for a second
}

How “Blink” Works

Notice that the two required functions in all sketches, the set-up function and the loop function, are present. Their parentheses are empty which means that there are no parameters associated with them. Right after each of these two functions, we see an open curly brace “{“ and after the function has been specified, we see a closed curly brace “}“. After “void loop, ”we also see an open curly brace and a closed curly brace after the four lines of code that comprise the loop. These curly braces come in pairs and delineate the code to be executed before proceeding to the next instruction.

After the void setup, we find the command, pinMode (13, OUTPUT). PinMode refers to the pin of port 13 (one of the Mega’s 54 ports) and it also sets the port to be an output port (as opposed to an input port). To activate a port you need to select it and also to tell the Arduino Mega whether it is used as an input or an output port. This instruction will run once, and then the computer will proceed to the next line of code or instruction which is “void loop.”

I then replaced the #13 in three places in the sketch (port number and write command) with #30 which is the Cool Xylo's port number for the note “Middle C.” As expected, after uploading the sketch into a completely wired control box, the solenoid for middle C operated.

An extension of this exercise is to create music. We need to find the best time delay to strike the key and release it in order to simulate striking the key with a mallet. Replace the first delay with a 15 instead of 1000. Now, the solenoid will only be energized for 15 milliseconds at that point the spring will retract the plunger and allow the selected bar to ring at its given frequency. There is a considerable range to the striking delay, use the time that works best for the whole keyboard. There is nothing to stop you from using a different delay for some of the keys but it would complicate the coding of the music

The next delay determines the length of the note. For a song that has a beat of 120 beats per minute and a quarter note having the beat, the quarter note will last 500 ms. So, if you are playing a string of quarter notes the second delay will be 500 each time. If you were to code a full note, you would use a 2000 ms delay or 125 ms delay for a sixteenth note. Should you want to pick up the beat by 10%, reduce the delay of each note by 10%.

Let us put all this together and code the scales and the simple song “Twinkle, Twinkle Little Star”. Note that the name of the key is shown next to the SOLPIN #defines

// Scales and “Twinkle, Twinkle, Little Star” 
#define SOLPIN_1 27          // “G”. Output port 27 will activate key G
#define SOLPIN_2 28          // “A”
#define SOLPIN_3 29          // “B”
#define SOLPIN_4 30         // “C”  Output port 30 will activate Middle C
#define SOLPIN_5 31          // “D”
#define SOLPIN_6 32          // “E”
#define SOLPIN_7 33          // “F”
#define SOLPIN_8 34          // “G”
#define SOLPIN_9 35          // “A”             
#define SOLPIN_1036         // “B”
#define SOLPIN_1137         // “C”
#define SOLPIN_1238         // “D”
#define SOLPIN_1339         // “E”
#define SOLPIN_1440         // “F”           
#define SOLPIN_1541         // “G”
#define SOLPIN_1642         // “A”
#define SOLPIN_1743         // “B”
#define SOLPIN_1844         // “C”. Output port 44 will activate key C
#defineSOLTIME_DURATION_A 15                //solenoid pulse duration
#defineSOLTIME_DURATION_B 500             //quarter note duration
#defineSOLTIME_DURATION_C 1000           //half note duration
#defineSOLTIME_DURATION_D 2000          // full note duration
#defineSOLTIME_DURATION_S 500             // quarter note duration (scales}
void setup()                                          // The setup function runs once                                                 when 
{                                                             //  press reset or power the board,
pinMode(SOLPIN_1, OUTPUT);            //  initializes the output ports 
pinMode(SOLPIN_2, OUTPUT);
pinMode(SOLPIN_3, OUTPUT);
pinMode(SOLPIN_4, OUTPUT);
pinMode(SOLPIN_5, OUTPUT);
pinMode(SOLPIN_6, OUTPUT);
pinMode(SOLPIN_7, OUTPUT);
pinMode(SOLPIN_8, OUTPUT);
pinMode(SOLPIN_9, OUTPUT);              
pinMode(SOLPIN_10, OUTPUT);
pinMode(SOLPIN_11, OUTPUT);
pinMode(SOLPIN_12, OUTPUT);
pinMode(SOLPIN_13, OUTPUT);
pinMode(SOLPIN_14, OUTPUT);                 
pinMode(SOLPIN_15, OUTPUT);
pinMode(SOLPIN_16, OUTPUT);
pinMode(SOLPIN_17, OUTPUT);
pinMode(SOLPIN_18, OUTPUT);
}      
void loop()                           
{                                                              //the loop function runs over and over 
                                                         // plays the 18 notescales 
digitalWrite(SOLPIN_1, HIGH);            //turn solenoid 27 on ("G")
delay(SOLTIME_DURATION_A);       //wait for the delay period A
digitalWrite(SOLPIN_1, LOW);             //turn the solenoid off 
delay(SOLTIME_DURATION_S);        //wait for the delay period S
digitalWrite(SOLPIN_2, HIGH);            //Activate the next solenoid     
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_2, LOW);                   
delay(SOLTIME_DURATION_S);
digitalWrite(SOLPIN_3, HIGH);            
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_3, LOW);                   
delay(SOLTIME_DURATION_S);
digitalWrite(SOLPIN_4, HIGH);                   
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_4, LOW);                   
delay(SOLTIME_DURATION_S);
digitalWrite(SOLPIN_5, HIGH);                 
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_5, LOW);                   
delay(SOLTIME_DURATION_S);
digitalWrite(SOLPIN_6, HIGH);                 
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_6, LOW);                   
delay(SOLTIME_DURATION_S);
digitalWrite(SOLPIN_7, HIGH);                
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_7, LOW);                   
delay(SOLTIME_DURATION_S);
digitalWrite(SOLPIN_8, HIGH);            
delay(SOLTIME_DURATION_A);       
digitalWrite(SOLPIN_8, LOW);              
delay(SOLTIME_DURATION_S);  
digitalWrite(SOLPIN_9, HIGH);                
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_9, LOW);                   
delay(SOLTIME_DURATION_S);
digitalWrite(SOLPIN_10, HIGH);            
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_10, LOW);                   
delay(SOLTIME_DURATION_S);
digitalWrite(SOLPIN_11, HIGH);                   
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_11, LOW);                   
delay(SOLTIME_DURATION_S);
digitalWrite(SOLPIN_12, HIGH);                 
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_12, LOW);                   
delay(SOLTIME_DURATION_S);
digitalWrite(SOLPIN_13, HIGH);                 
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_13, LOW);                   
delay(SOLTIME_DURATION_S);
digitalWrite(SOLPIN_14, HIGH);                   
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_14, LOW);                   
delay(SOLTIME_DURATION_S);
digitalWrite(SOLPIN_15, HIGH);                 
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_15, LOW);                   
delay(SOLTIME_DURATION_S);
digitalWrite(SOLPIN_16, HIGH);               
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_16, LOW);                   
delay(SOLTIME_DURATION_S);
digitalWrite(SOLPIN_17, HIGH);   
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_17, LOW);                   
delay(SOLTIME_DURATION_S);
digitalWrite(SOLPIN_18, HIGH);                 
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_18, LOW);                   
delay(SOLTIME_DURATION_S);          //end of playing the 18 note Scales
delay (2000); 
//Start coding "Twinkle Twinkle Little Star'
digitalWrite(SOLPIN_4, HIGH);            //turn on solenoid 4 
delay(SOLTIME_DURATION_A);         //wait for delay period A
digitalWrite(SOLPIN_4, LOW);             //turn off solenoid 4    
delay(SOLTIME_DURATION_B);         //wait for delay period B
digitalWrite(SOLPIN_4, HIGH);                
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_4, LOW);                   
delay(SOLTIME_DURATION_B);
digitalWrite(SOLPIN_8, HIGH);            
delay(SOLTIME_DURATION_A);           
digitalWrite(SOLPIN_8, LOW);              
delay(SOLTIME_DURATION_B);  
digitalWrite(SOLPIN_8, HIGH);                
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_8, LOW);                   
delay(SOLTIME_DURATION_B);
digitalWrite(SOLPIN_9, HIGH);            
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_9, LOW);                   
delay(SOLTIME_DURATION_B);
digitalWrite(SOLPIN_9, HIGH);                   
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_9, LOW);                   
delay(SOLTIME_DURATION_B);
digitalWrite(SOLPIN_8, HIGH);            //turn the solenoid on 
delay(SOLTIME_DURATION_A);        //wait for the delay period
digitalWrite(SOLPIN_8, LOW);             //turn the solenoid off   
delay(SOLTIME_DURATION_C);        //wait for the delay period
digitalWrite(SOLPIN_7, HIGH);            
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_7, LOW);                   
delay(SOLTIME_DURATION_B);
digitalWrite(SOLPIN_7, HIGH);                   
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_7, LOW);                   
delay(SOLTIME_DURATION_B);
digitalWrite(SOLPIN_6, HIGH);                 
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_6, LOW);                   
delay(SOLTIME_DURATION_B);
digitalWrite(SOLPIN_6, HIGH);                 
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_6, LOW);                   
delay(SOLTIME_DURATION_B);
digitalWrite(SOLPIN_5, HIGH);                 
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_5, LOW);                   
delay(SOLTIME_DURATION_B);
digitalWrite(SOLPIN_5, HIGH);                 
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_5, LOW);                   
delay(SOLTIME_DURATION_B);
digitalWrite(SOLPIN_4, HIGH);                
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_4, LOW);                   
delay(SOLTIME_DURATION_C);
digitalWrite(SOLPIN_8, HIGH);            //turn the solenoid on 
delay(SOLTIME_DURATION_A);        //wait for the delay period
digitalWrite(SOLPIN_8, LOW);             //turn the solenoid off   
delay(SOLTIME_DURATION_B);        //wait for the delay period
digitalWrite(SOLPIN_8, HIGH);                
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_8, LOW);                   
delay(SOLTIME_DURATION_B);
digitalWrite(SOLPIN_7, HIGH);            
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_7, LOW);                   
delay(SOLTIME_DURATION_B);
digitalWrite(SOLPIN_7, HIGH);                   
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_7, LOW);                   
delay(SOLTIME_DURATION_B);
digitalWrite(SOLPIN_6, HIGH);                 
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_6, LOW);                   
delay(SOLTIME_DURATION_B);
digitalWrite(SOLPIN_6, HIGH);                 
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_6, LOW);                   
delay(SOLTIME_DURATION_B);
digitalWrite(SOLPIN_5, HIGH);                
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_5, LOW);                   
delay(SOLTIME_DURATION_C);
digitalWrite(SOLPIN_8, HIGH);            //turn the solenoid on 
delay(SOLTIME_DURATION_A);       //wait for the delay period
digitalWrite(SOLPIN_8, LOW);             //turn the solenoid off   
delay(SOLTIME_DURATION_B);       //wait for the delay period
digitalWrite(SOLPIN_8, HIGH);                
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_8, LOW);                   
delay(SOLTIME_DURATION_B);
digitalWrite(SOLPIN_7, HIGH);            
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_7, LOW);                   
delay(SOLTIME_DURATION_B);
digitalWrite(SOLPIN_7, HIGH);                   
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_7, LOW);                   
delay(SOLTIME_DURATION_B);
digitalWrite(SOLPIN_6, HIGH);                 
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_6, LOW);                   
delay(SOLTIME_DURATION_B);
digitalWrite(SOLPIN_6, HIGH);                 
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_6, LOW);                   
delay(SOLTIME_DURATION_B);
digitalWrite(SOLPIN_5, HIGH);                
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_5, LOW);                   
delay(SOLTIME_DURATION_C);
digitalWrite(SOLPIN_4, HIGH);            //turn the solenoid on 
delay(SOLTIME_DURATION_A);       //wait for the delay period
digitalWrite(SOLPIN_4, LOW);             //turn the solenoid off   
delay(SOLTIME_DURATION_B);       //wait for the delay period
digitalWrite(SOLPIN_4, HIGH);                
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_4, LOW);                   
delay(SOLTIME_DURATION_B);
digitalWrite(SOLPIN_8, HIGH);            
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_8, LOW);                   
delay(SOLTIME_DURATION_B);
digitalWrite(SOLPIN_8, HIGH);                   
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_8, LOW);                   
delay(SOLTIME_DURATION_B);
digitalWrite(SOLPIN_9, HIGH);                 
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_9, LOW);                   
delay(SOLTIME_DURATION_B);
digitalWrite(SOLPIN_9, HIGH);                 
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_9, LOW);                   
delay(SOLTIME_DURATION_B);
digitalWrite(SOLPIN_8, HIGH);                
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_8, LOW);                   
delay(SOLTIME_DURATION_C);
digitalWrite(SOLPIN_7, HIGH);            //turn the solenoid on 
delay(SOLTIME_DURATION_A);       //wait for the delay period
digitalWrite(SOLPIN_7, LOW);             //turn the solenoid off   
delay(SOLTIME_DURATION_B);       //wait for the delay period
digitalWrite(SOLPIN_7, HIGH);                
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_7, LOW);                   
delay(SOLTIME_DURATION_B);
digitalWrite(SOLPIN_6, HIGH);            
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_6, LOW);                   
delay(SOLTIME_DURATION_B);
digitalWrite(SOLPIN_6, HIGH);                   
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_6, LOW);                   
delay(SOLTIME_DURATION_B);
digitalWrite(SOLPIN_5, HIGH);                 
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_5, LOW);                   
delay(SOLTIME_DURATION_B);
digitalWrite(SOLPIN_5, HIGH);                 
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_5, LOW);                   
delay(SOLTIME_DURATION_B);
digitalWrite(SOLPIN_4, HIGH);                
delay(SOLTIME_DURATION_A);                          
digitalWrite(SOLPIN_4, LOW);                   
delay(SOLTIME_DURATION_C);
delay (2000);
}    

The Scales and “Twinkle, Twinkle Little Star”

The code for the scales and for “Twinkle” is shown above. Note the following:

  • We are only coding the 18 “white” keys. If accidentals needed to be played, we would extent the “#define” list and assign port numbers to them.
  • The #defines for SOLPIN 1 to 18 show the port number and the name of the key (G to C). Note that middle C is port 30 for xylophones.
  • We only “#define” a single delay for the strike time (SOLTIME_DURATION_A 15). We could have “#define” other delays say, 10ms or 20ms to make the key sound softer or louder.
  • Only three of the delays which determine the length of the note are “#define”. The other two for the eighth and sixteenth notes would be defined if they were to be played in the song. Upload the above code in your xylophone Mega control box and the music will play on either xylophone.

Chords

Playing two-note chords is easy with Blink. It is simply a matter of adding a line of code for the second note below the code of the first note in order to activate both notes. Also, a second line of code is added below the line of code that turns the first note off in order to turn off the second note. The result is that we have 6 lines of code for at two-note chord.

Robo-C and the Player Piano

Robo-C is the name of the sketch that will play music on a player piano such as the Casio described above. It is similar to “Blink” but has additional features: rather than striking the piano keys, it holds them depressed according to the type of note. For instance, a quarter-note may be depressed for 500 ms. The added features consist of simulating the use of the piano pedals, the capability of selecting from as many as 51 keys, selecting the beat of the song and playing multi-key chords.

For each note, a block of information (described below) is generated to define all the features of the note. An example will make it clear.

Illustrated below in block form are the eight pieces of information separated by commas that make up a line of code for each note. The coding for a middle C could be as follows:

{36, 0, 0, 0, 0, 0, BEAT_100, 0, 0, DURATION_FULL, SOLTIME_A, 0, WHITE_KEY},

Block 1 and 8. In block one we select the port number of the key (port 36 for middle C). The 5 zero's following the port number are used when Robo drives an extended 76 key keyboard. In that case the black and white keys are decoded individually. In our case, only the port number is entered and block 8 is always labeled “White Key”.

Block 2. The beat of the song to which your foot or hands keep in step, varies greatly between songs. When you buy the sheet music of a composer like Beethoven, don’t expect a metronome value to tell you what the beat is. At the start of the music, it might just say “Poco Moto.” A virtuoso pianist playing a version of “Fur Elise” is recorded on my Yamaha keyboard. The beat varies between roughly 100 to 140 beats per minute. 110 BPMs would be a good starting point. Since the beat can be changed one note at a time, the music coder is capable of speeding up the beat or slowing the beat down at will, as we did for the video.

We saw that the “#defines” are the definition of the many variables that we need to play a note. In Robo-C, they determine the beat and they range between 60 and 300 beats per minute as determined by a metronome. At the mid-point, “BEAT_120” is associated with 500. That simply means that at 120 beats per minute, the duration of each beat is 500 milliseconds. This number is one of three factors that determines how long the solenoid remains energized when it is used to play a note.

Blocks 3 and 4. These two boxes are easy. If the music coder desires to use the sustain feature or the low volume feature, he simply places a 1 in box three and/or in box four. Sustain and/or low volume will become active starting with that note and stay active as long as the following notes have 1’s in these boxes. These two features simulate the action of the left and right piano pedals. They are turned off when a 0 is detected in these positions. As with the other information, commas are placed after the 1’s or 0’s.

Blocks 5 and 6. Looking at any sheet music, we see notes of different duration from full notes with open circles to sixteenth notes with the double tails. From our example, where the quarter note had the beat, we would expect the full note to last four times as long as the quarter note and the sixteenth note to last one quarter of the quarter note’s duration. Using this information, Robo-C will determine that when the beat is 120 beats per minute, the quarter note should last 500ms, the full note should last 2 seconds while the sixteenth note should last 125ms according to the #defines for DURATION

I say“should” last 500ms because these note duration are multiplied by one more factor the “SOLTIME, ” which is the amount of time that the solenoid is energized, as recorded in Box 6. For normal notes, this multiplier is set at 75%. So in our example the actual duration time of the solenoid closure will be 375 ms. Let’s be clear, when the beat is 120 BPM, the note duration for a quarter note is 500ms -that is set in concrete. The next note will not start before the 500ms have elapsed. However, the solenoid duration may cause the key to be depressed for a shorter period of time. While normal (B) is 75% of beat, we will see that SOLTIME occasionally ranges from 25% to 100% of the beat (according to the #defines for SOLTIME) in order to play chords correctly and/or to play notes lasting 50% longer than normal (when there is a dot next to the note).

Block 7. While coding the average piece of music is straightforward and easy to do once you get the hang of it and start remembering a few of the common port numbers, coding the chords takes some thinking. The example above has no chords, which is reflected with the 0 in box 7.

If this line of code were the first note of a chord we would call it “Start” in Box 7. Then, assuming that there are four notes in the chord, we write a second line of code for the second note in the chord and call it “Continue.” We repeat this for the third note in the chord. For the last note, we write another line of code and call it “End.” For a two-note chord there would only be a “Start” and an “End” in Box 7 of the two lines of code.

It does not matter which note is called note “one, ” since by the definition, all notes of a chord are played simultaneously. To keep it simple, I call to top note on the scale“note one” and the bottom note on the scale, “note four.” Since we only have five fingers on each hand, few chords are found with more than 4 notes! The Robo-C sketch will sort out these four lines of code and play all the notes at the same time, then move onto the next note. In the Robo-C sketch’s interpretation of chords, the soltime value assigned to the “END” note applies to the entire chord.

Introductory Code of the Robo-C Sketch

Robo-C is the name I gave to the sketch that we will use to activate the mini-robots of the Casio player piano. It performs the same function as “Blink” did to play music on the xylophones. It assumes that the wiring of the control box is as shown on page 15. It is very closely related to a sketch named “Robo” which I used for the 3 configurations of the player piano (50, 60 and 76 active keys) as described in the the book “A Thoroughly Modern Player Piano” Robo can be downloaded from my website “modernplayerpiano.com” at no cost. Except for the port assignments and the port numbers for sustain and volume control, it is exactly the same as Robo-C which we will describe. By downloading Robo you can check your Robo-C code for errors or copy and paste most of the code.

Before we really get serious about coding music or describing the Robo-C sketch, we need to describe the range of choices that is available to the coder to specify the characteristics of each note as shown in the blocks of information described above. Note that the order in which the “#define” choices are listed does not have to correspond to the order in the line of code. The correct order will be set by the structure of the array as we will see below.

Beat of the Song

The “#defines” for the beats are shown below. When coding a song, I use the same beat number for an entire page for the first cut at coding the music. For example BEAT_150, which is a fast beat whose quarter note duration is 400 ms. I will then listen to the rendition and try a slower beat, say, BEAT_120. But I will use the following trick: instead of going through the whole page of coding and replacing all the 150’s with 120’s, I will simply replace the 400 (in BEAT_150 400) with 500 and do a compile/upload. Like magic, Robo-C will change the beat of all the notes on the page of music and the song will be played at a slower beat. You can continue making changes to this “global” beat number until you find your preferred beat.

#define BEAT_60 999        //Number of ms for various beats 
#define BEAT_70 857        // according to the metronome's "beats per minute”
#define BEAT_80 750
#define BEAT_90 666
#define BEAT_100 600
#define BEAT_110 550
#define BEAT_120 500
#define BEAT_130 467
#define BEAT_140 433
#define BEAT_150 400
#define BEAT_160 375
#define BEAT_170 352
#define BEAT_180 333
#define BEAT_300 200            //Used for very short “Blip” notes

Duration of the notes

What we are defining in this section is the duration of the notes from full notes to notes that last only one sixteenth the duration of a full note

#define DURATION_FULL 1       //Defines the multiplier needed 
#define DURATION_HALF 2      // to determine the length of the note
#define DURATION_QUARTER 3
#define DURATION_EIGHTH 4
#define DURATION_SIXTEENTH 5    

The numbers 1, 2, 3, 4, 5 are used to select a multiplier from 16 to 1 which will be used in the Robo-C formula to determine the duration of notes based on the beat of the song. When the quarter note has the beat, it's time duration will be equal to the beat time listed in the #define number selected. A full note will last four times longer than the quarter note and a sixteenth note will last one quarter of its duration. The reason for using all integers instead of fractions is that the Mega microprocessor handles calculations using integers much better and faster than fractions.

The last line of the #define code starting with “static” needs some explanation. The keyword “static” is used so that the variable (in this case “beatMult”) will only be initiated the first time the function is called. It is then set in concrete and cannot be changed. The [] tells us that beatMult is inthe form of an array instead of a single integer. An array is used to contain a list of similar variables which can be accessed with a pointer to select their value depending on their position in the list. As we can see, the values in the array are within the curly braces and separated by commas. Robo-C will sort all this information out to determine the correct duration of the notes.

Solenoid Activation

As we discussed above, the solenoids can be activated for 100% of the time as calculated for the note being coded or for a lesser amount of time namely, 75%, 50% or 25% of the time. This feature is necessary for some cords, notes with dots and certain very short notes (“blip notes”) that are sometimes found in the sheet music. SOLTIME_B (the normal setting) would therefore reduce the 100% solenoid duration as calculated from the beat, to a duration of 75%.

#define SOLTIME_A 4  //Solenoid is energized for 100% of the note's duration
#define SOLTIME_B 3  //Solenoid is energized for 75% of the note's duration
#define SOLTIME_C 2  //Solenoid is energized for 50% of the note's duration 
#define SOLTIME_D 1  //Solenoid is energized for 25% of the note's duration    

Activating the Sustain and Low Volume Features

Activating the sustain feature or the lower volume feature (a sound level called “piano, ” incidentally) simply involves selecting ports 20 and 21 and keeping these ports active (high) for as long as the music coder desires. SUSTAIN_ON is defined as a 1 while SUSTAIN_OFF is defined as a 2. VOLUME_LOW is defined as a 1 and VOLUME_HIGH is defined as a 2. We will see later that the Robo-C sketch will interpret these values by turning ports 20 and 21 on or off. (Robo used ports 18 and 19) The #define code is shown below.

#define SUSTAIN_ON 1
#define SUSTAIN_OFF 2
#define VOLUME_LOW 1
#define VOLUME_FULL 2

Activating the Chord Software

To play chords it is necessary to select several notes and play them simultaneously. This is done by replacing the 0 which would be in box 7 for a “non-chord” note. The first note of a chord is called “CHORD_START.” If the chord has two notes the next note is called “CHORD_END” in box 7. If there are more than two notes the second and the following notes are called “CHORD_CONTINUE.” The sequence is, Start, Continue, End, with the possibility of more than one “Continue.” The code for the chord #defines is shown below.

#define CHORD_START1
#define
#define CHORD_END 3    

Defining the Keys and Ports

The ports are last to be defined although they appear first in the line of code. They will be decoded to activate the solenoids which, in turn, depress the keys. First, we have to know if it is a white or a black key. Using Robo-C, the answer, in box 8, is always “WHITE” because the 51 active keys are all powered by an individual port. The black keys use ports 1 to 19 while the white keys use ports 22 to 53. Robo-C can therefore power 51 of the Casio's 61 keys.

#define WHITE_KEY 0
#define BLACK_KEY 1
#define
#define
#define
#define
#define SONG_END255
static int beatMult[] = {0, 16, 8, 4, 2, 1}    

The next to last line tells us that while Robo is cycling (looping) through the notes, if it runs into a port 255 (which does not exist) it means that it has reached the end of the song, Robo will then restart playing the song or move on to the first note of the next song.

Structuring the Note

Now that we know what all our choices are, we will structure them in the order required by the line of code used for each note and, at the same time, we will assign the most efficient number of bits to the variables in the structure.

struct myNote
{    
byte Port;
byte blackStateP5: 1;
byte blackStateP6: 1;
byte blackStateP7: 1;
byte blackStateP8: 1;
byte blackStateP9: 1;
int Beat; 
byte Sustain : 2; 
byte Volume : 2;
byte Duration: 4;
byte Soltime: 4;
byte Chord : 4;
byte BlackKey : 4;
} Note;
struct myNoteElise[] = {    

The structure above (which is used in Robo and Robo-C) is similar to an array in that it contains bits of information that can be assessed by their location in the structure with a pointer. A useful feature of this structure is that each bit of information can be assigned the minimum number of bits needed to define it in order to make the code more efficient.

This structure is named “myNote” and declared using the expression: struct myNote. Curly braces open and close the structure. Within the curly braces we find all the items that are needed to define a note. We have talked many times about the eight pieces of information needed to define a note. Defining a port requires 6 pieces of information in this structure, one for the white keys and 5 for the black keys whose port selection is coded in binary. This feature is not used in Robo-C but it does no harm to leave it in.

This first “struct” declaration is used to pack the data efficiently. Port and beat require a byte to specify their value but the rest of the information does not require an entire byte to specify its value. Notice that after the colon there is a number from 1 to 7. It indicates the number of bits required to specify the function. For example, sustain and low volume require two bits each. This is important because it makes the coding of the notes more efficient. Therefore, it uses less memory and provides more room to upload more notes or songs at one time.

After closing this structure we open a new structure that will contain all the note data to play a song. In this case, it will be Beethoven’s “Elise”. The declaration is written as follows: “struct myNote Elise[] =”. We now open a curly brace and the music coder can start coding each note with the eight bits of information needed for each note.

“struct” is used in C to define a variable in a way similar to an array. Strangely, while “struct” is not mentioned in Simon Monk’s book nor in the definition of terms in the Arduino IDE language reference, it compiles perfectly well. This is not a fluke. If an error is made while coding, the compiler is quick to pick it up and let you know about it.

This discussion concludes the preliminaries for the coding of the music which we will continue to describe below. Think about this section as being the foreplay for the music.

Coding“Fur Elise”

Now that we understand the basics of coding music, we will code the first 10 measures of Beethoven’s “Fur Elise.” Most of the notes of this fairly difficult piece are eighth notes, so the pianist has to play fast to keep up with the beat (not a problem for our mini-robots!) A friend of mine told me that when he learned to play the piano he had to practice this very piece every day for a year before he felt confident that he was playing it correctly. Coding it is a piece of cake compared to that ordeal!

The 3/4 fraction shown on the first staff (see the sheet music of Fur Elise below) tells us that the quarter note has the beat and that “Elise” is played in three quarter time (like a waltz). Not much help from the words “Poco Moto” to tell us what the beat is so, we will try 110 BPM as a starting point. The letters pp tells us that the volume is somewhat less than average. When you type “Poco Moto” into Google, you get all sorts of answers about the tempo of “Elise” some of them are very funny, but no signs of a metronome number that we can use. There is also a wealth of information about who the mysterious Elise might have been. And, of course there are numerous versions of the song “Fur Elise, ” including a 60 minute rendition backed by a full symphony orchestra.

The first measure has only two notes but we immediately bump into an accidental. It is the sharp next to white D (port # 44). From the chart above, we determine that its port number is 15. Make a note of this port number on the chart, we will see this note many more times.

We will abbreviate the words referring to the chords so that they fit on one line of type. (Remember not to use these abbreviations when coding the songs in the sketches).

CHORD_START is abbreviated as: C_S
CHORD_CONTINUE is abbreviated as: C_C
CHORD_END is abbreviated as: C_E
The two lines of code for measure 1 look like this.    
//Measure 1
{45, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_B, 0, WHITE_KEY },
{15, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_B, 0, WHITE_KEY },

In measure 2, the right hand does all the work playing the melody since we have nothing but a long pause in the bass staff. The melody consists of six eighth notes one of which is an accidental. This very same measure is repeated two more times on this page. Copy and Paste from the Edit menu will come in handy here and many more times thereafter.

The designation for a sharp closely resembles a number sign (#), and it is active for the entire measure once it is displayed. In this case, it applies to the second note (another D) in the measure. But notice that there is a second D in this measure and that this second D is a natural. In order to cancel the effect of the first #, a new symbol resembling a "b" with a tail at the bottom disables the previous #.

The third symbol having to do with accidentals also looks like a b (without the tail), and it tells us that the next note is a flat. Remember that a sharp or flat (a black note) is higher or lower by ½ pitch compared to the natural (white note) next to it.There are no flats in the music on this page, but they would be coded the same way as the sharps. The line of code for this sharp is the same as for the sharp in measure 1, so it can be copied and pasted.

//Measure 2
{45, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_B, 0, WHITE_KEY },
{15, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_B, 0, WHITE_KEY },
{45, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_B, 0, WHITE_KEY },
{42, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_B, 0, WHITE_KEY },
{44, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_B, 0, WHITE_KEY },
{43, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_B, 0, WHITE_KEY },    

Measure 3 is the first of a dozen measures with at two-note chord as the first note. It is used to emphasize the beat. In most cases, they are quarter notes combined with eighth notes. The quarter note will be divided into two eighth notes of which the first one will have a soltime of 100% (A) so that it will play continuously until the second eighth note comes along to re-energize the solenoid.

//Measure 3
{41, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_A, C_S, WHITE_KEY },
{27, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_A, C_E, WHITE_KEY },
{41, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_B, C_S, WHITE_KEY },
{31, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_B, C_E, WHITE_KEY },
{34, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_B, 0, WHITE_KEY },
{36, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_B, 0, WHITE_KEY },
{38, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_B, 0, WHITE_KEY },
{41, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_B, 0, WHITE_KEY },

Except for the accidentals, measures 4 and 5 are very much like measure 3. The eight notes can be copied and pasted but the port numbers must be changed appropriately.

//Measure 4
{42, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_A, C_S, WHITE_KEY },
{24, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_A, C_E, WHITE_KEY },
{42, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_B, C_S WHITE_KEY },
{31, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_B, C_E, WHITE_KEY },
{7, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_B, 0, WHITE_KEY },
{38, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_B, 0, WHITE_KEY },
{12, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_B, 0, WHITE_KEY },
{42, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_B, 0, WHITE_KEY },
//Measure 5
{43, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_A, C_S, WHITE_KEY },
{27, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_A, C_E, WHITE_KEY },
{43, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_B, C_S, WHITE_KEY },
{31, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_B, C_E, WHITE_KEY },
{34, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_B, 0, WHITE_KEY },
{38, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_B, 0, WHITE_KEY },
{45, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_B, 0, WHITE_KEY },
{15, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_B, 0, BLACK_KEY },

Measure 6 is an exact duplicate of measure 2, and measure 7 is an exact duplicate of measure 3. You know what to do: copy and paste these 2 measures along with the measure numbers, which will be changed to 6 and 7.

//Measure 6
{45, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_B, 0, WHITE_KEY },
{15, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_B, 0, WHITE_KEY },
{45, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_B, 0, WHITE_KEY },
{42, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_B, 0, WHITE_KEY },
{44, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_B, 0, WHITE_KEY },
{43, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_B, 0, WHITE_KEY },
//Measure 7
{41, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_A, C_S, WHITE_KEY },
{27, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_A, C_E, WHITE_KEY },
{41, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_B, C_S WHITE_KEY },
{31, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_B, C_E, WHITE_KEY },
{34, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_B, 0, WHITE_KEY },
{36, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_B, 0, WHITE_KEY },
{38, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_B, 0, WHITE_KEY },
{41, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_B, 0, WHITE_KEY },

Measure 8 is almost the same as measure 4 except for the fourth and fifth notes. Copy and paste measure 4 and make the two applicable changes.

//Measure 9
{41, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_A, C_S, WHITE_KEY },
{27, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_A, C_E, WHITE_KEY },
{41, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_A, C_S, WHITE_KEY },
{31, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_A, C_E, WHITE_KEY },
{41, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_A, C_S, WHITE_KEY },
{34, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_A, C_E, WHITE_KEY },
{41, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_B, 0, WHITE_KEY },
{45, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_B, 0, WHITE_KEY },
{15, 0, 0, 0, 0, 0, BEAT_110, 0, 0, DURATION_EIGHTH, SOLTIME_B, 0, WHITE_KEY },    

Repeat the code of measures 1 thru 8 by copying and pasting them. In the second go-round we skip measure 9 and code measure 10 which is close to our familiar measure 7. Copy and paste measure 7 and modify the ports of the last 3 notes.

The rest of the coding of the first page is normal except for a couple of oddities worth mentioning. In measures 11, 12 and 13, Beethoven throws us another curve by starting the measure with a quarter note with a dot which means that it has a duration equal to three eighth notes. We will code such duration with two eighth notes with 100% soltime and the third as an eighth-note with a 75% soltime. These 3 notes will be paired with the appropriate eighth notes in the bass staff to make three two-note chords. The other three notes in these measures are normal eighth notes.

Everything looked normal in measure 14 until the last note which is preceded by (horrors) a treble clef. This means that the notes on the bass staff are played as if they were on the treble staff until we run into a bass clef on the next line which will bring things back to normal. Fortunately, with our mini-robots, we don’t have to worry about which hand or finger to use! We will simply code this note, our first eighth note with a tail, as an E (port number 38). Measure 7 is similar to measure 14 only the port numbers have to be updated.

We now stop describing the coding of the music and move on to the description of the core Robo-C code which transforms all this information into activating an output port

The Robo-C Code

We have now reached the final step in describing the Robo-C sketch. The first section listed mostly the #defines while the second section showed the coding of the notes. This is the code that transforms all this information into the selection, activation and timing of the ports which, in turn, depress the appropriate keys to generate the music.

{SONG_END, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, WHITE_KEY},               
};

Song end tells us that the coding of the scales and of the two songs is done and that the time has come to play the first note of music. The comments after the “//” explain what Robo-C is doing.

struct myNote * pSong = Elise;                     
voidsetup()                                       //the setup routine runs once when Reset,
                                                     //the digital pins are initialized as outputs 
{
pSong= Elise;
inti = START_BLACK_KEY;               //Reset ports 0 to 19
while(i<= END_BLACK_KEY)  {
pinMode(i, OUTPUT);
digitalWrite(i, LOW);
i++;
}
i= START_WHITE_KEY;                      //Reset ports 22 to 53
while(i<= END_WHITE_KEY)  {
pinMode(i, OUTPUT);
digitalWrite(i, LOW);
i++;    
}
{
pinMode(20, OUTPUT);                             //Set up the ports to activate
pinMode(21, OUTPUT);                             // the sustain and volume relays
}
}
voidplayTune(struct myNote * pTune) {
bytePort1 = pTune->Port;                   // Select a Port
intSoltime= pTune->Soltime;            // Select one of 4 setting for the solenoids                                       
if(Port1== SONG_END) {                  // End the song when Port 255 is detected
pSong= pTune;
return;
}
if(pTune->Sustain== 1) {                    // Turns on the sustain feature on Port 20
digitalWrite(20, HIGH);
}
if(pTune->Sustain== 0) {                   //Turns off the sustain feature on Port 20
digitalWrite(20, LOW);
}
if(pTune->Volume== 1) {                  // Turns the volume feature to low on Port 21
digitalWrite(21, HIGH);
}
if(pTune->Volume== 0) {                //Turns the volume feature to full on Port 21
digitalWrite(21, LOW);
}
intbeat = pTune->Beat ;                  // Establishes the beat time of the song
beat= beat * beatMult[pTune->Duration]/4;    // Establishes the duration 
                                                                   // of the 5 notes from full to                                                      
                                                                  // one sixteenth based on the beat
intdurMS =  beat  * Soltime/4 ;                     // Establishes the duration that
                                                                 // the solenoids are energized:              
                                                                  //.25,.50,.75, 1.0 of beat time                                                                                                                                                        
if(pTune->BlackKey== HIGH) {                   
digitalWrite(5, pTune->blackStateP5);
digitalWrite(6, pTune->blackStateP6);
digitalWrite(7, pTune->blackStateP7);
digitalWrite(8, pTune->blackStateP8);
digitalWrite(9, pTune->blackStateP9);    
}else { 
if(Port1){
digitalWrite(Port1, HIGH);      // Execute command HIGH for the designated note                                                                             
}                                               // Energize the solenoids for time duration durMs 
structmyNote * pChordTune = pTune;
if((pChordTune->Chord== CHORD_START) || (pChordTune->Chord == CHORD_CONTINUE)) {
pChordTune++;                        // Combine individual notes into chords
playTune(pChordTune);
}
if((pTune->Chord== CHORD_END) || (pTune->Chord == 0)) {  
delay(durMS);                       //Determines the length of time that the 
}                                              //solenoid is energized. One delay per chord 
if(pTune->BlackKey== HIGH) {             //Turn off the black keys (ports 0 to 19) 
inti = START_BLACK_KEY;                   //after the end of the durMS delay
while(i<= END_BLACK_KEY)  {
pinMode(i, OUTPUT);
digitalWrite(i, LOW);
i++;                   
}    
}else{
inti = START_BLACK_KEY;                                 
while(i<= END_BLACK_KEY)  {
pinMode(i, OUTPUT);
digitalWrite(i, LOW);
i++;
}
i= START_WHITE_KEY;                       //Turn off the white keys (ports 22 to 53)
while(i<= END_WHITE_KEY)  {          // after the end of the durMS delay
pinMode(i, OUTPUT);
digitalWrite(i, LOW);
i++;
}
}
//Now wait out the beat time (Duration of the note)  
if((pTune->Chord == CHORD_END) || (pTune->Chord == 0)) {
pTune++;
pSong= pTune;   
delay(beat-durMS);                //After the completion of the note or chord,     
                                           //select the next note   
//Serial.begin(9600);            //Activate the Serial Monitor (commented out)
//intn = (beat-durMS);    
//Serial.println(n) ;
}
}    
voidloop() // the loop routine runs over and over 
{     
	if(pSong->Port== SONG_END) {
		pSong= Elise;
		delay(2000);
	}
playTune(pSong); 
}     

The three pages of Robo-C code shown above select a note or a chord and play it according to the instructions provided by the music coder. It will then loop over to the next note and perform the same functions again and again with new sets of instructions for each note until it reaches the end of the song.

That completes all the information that is needed to build the two player xylophones and the 51 key Casio player piano. Good luck and enjoy good music.

Code

Robo-CC/C++
This is the code that drives the player piano
{SONG_END, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, WHITE_KEY},               
          };
   //This the end of the coding of the scales and of the song. We will now generate the first note as explained in the comments.

    struct  myNote * pSong = Elise;                     
    void setup()                                                 //the setup routine runs once when the reset switch is pressed
                                                                        // the digital pins are initialized as outputs 
        {
     pSong = Elise;
  
     int i = START_BLACK_KEY;                 //Reset ports 0 to 19
     while(i <= END_BLACK_KEY)  {
     pinMode(i, OUTPUT);
     digitalWrite(i, LOW);
      i++;
           }
     i = START_WHITE_KEY;                      //Reset ports 22 to 53
     while(i <= END_WHITE_KEY)  {
     pinMode(i, OUTPUT);
     digitalWrite(i, LOW);
     i++;
	}
    {
     pinMode(20, OUTPUT);                             //Set up the ports to activate the sustain and volume relays
     pinMode(21, OUTPUT);
      }
    } 
     void playTune(struct myNote * pTune) {
     byte Port1 = pTune->Port;                          // Select a Port
     int Soltime= pTune->Soltime;                    // Select one of 4 setting for the solenoids                                       
     if(Port1 == SONG_END) {                        // End the song when Port 255 is detected
     pSong = pTune;
     return;
      }
             if(pTune->Sustain == 1) {                            // Turns on the sustain feature on Port 20
      digitalWrite(20, HIGH);
      }
            if(pTune->Sustain == 0) {                             //Turns off the sustain feature on Port 20
      digitalWrite(20, LOW);
      } 
         if(pTune->Volume == 1) {                               // Turns the volume feature to low on Port 21
      digitalWrite(21, HIGH);
      }
           if(pTune->Volume == 0) {                            //Turns the volume feature to full on Port 21
      digitalWrite(21, LOW);
      }
            int beat = pTune->Beat ;                              // Establishes the beat time of the song (millisecs)
      beat = beat * beatMult[pTune->Duration]/4;    // Establishes the duration of the 5 notes
                                                                                // from Full to one Sixteenth based on the beat (millisecs)
      int durMS =  beat  * Soltime/4 ;                        // Establishes the amount of time that the solenoids
                                                                                 // are energized .25,.50,.75 or 1.0 of the beat time (millisecs)
      if(pTune->BlackKey == HIGH) {                     // the black keys are driven directly from a Mega port in this version
      digitalWrite(5, pTune->blackStateP5);             // of Robo-C. These 7 lines of code are not used.
      digitalWrite(6, pTune->blackStateP6);
      digitalWrite(7, pTune->blackStateP7);
      digitalWrite(8, pTune->blackStateP8);
      digitalWrite(9, pTune->blackStateP9);    
     } else { 
       if(Port1) {
       digitalWrite(Port1, HIGH);                               // Execute command HIGH for the designated white or black note
             }                                                                   // Energize the solenoids for time duration durMs 
      }     
     struct myNote * pChordTune = pTune;
     
     if((pChordTune->Chord == CHORD_START) || (pChordTune->Chord == CHORD_CONTINUE)) {
        pChordTune++;                                                  // Combine individual notes into chords
        playTune(pChordTune);
        }
              if((pTune->Chord == CHORD_END) || (pTune->Chord == 0)) {  
      delay (durMS);                                                    // Determines the length of time that the 
      }                                                                           // Solenoid is energized. One delay per chord 
    
      if(pTune->BlackKey == HIGH) {                     //Turn off the black keys (ports 0 to 19) after the end of the durMS delay
      int i = START_BLACK_KEY;
      while(i <= END_BLACK_KEY)  {
      pinMode(i, OUTPUT);
      digitalWrite(i, LOW);
         i++;
            }
      }else {
         int i = START_BLACK_KEY;                                 
     while(i <= END_BLACK_KEY)  {
     pinMode(i, OUTPUT);
     digitalWrite(i, LOW);
      i++;
        }
            i = START_WHITE_KEY;                        //Turn off the white keys (ports 22 to 53) after the end of the durMS delay
      while(i <= END_WHITE_KEY)  {
      pinMode(i, OUTPUT);
      digitalWrite(i, LOW);
      i++;
       }
     } 
     // Now wait out the beat time (the duration of the note)  
                	      if((pTune->Chord == CHORD_END) || (pTune->Chord == 0)) {
      pTune++;
      pSong = pTune;   
      delay (beat-durMS);                                         //After the completion of the note or chord, select the next note       
        
     //Serial.begin(9600);                                          // Activate the Serial Monitor (commented out unless needed)
     //int n = (beat-durMS);
     //Serial.println (n) ;
       }
     }     
      void loop() // the loop routine runs over and over 
     {      
	if(pSong->Port == SONG_END) {
		pSong = Elise;
		delay(2000);
	}
       playTune(pSong);  
      }           

Schematics

Wiring Chart of the Universal Shield
Overview of the point to point wiring for the Arduino shield
Image1 blcql8bep4
Circuit Diagram
Overview of the Control Panel and its Circuits
Image2 lm6uopeddg
Control Panel Diagrams
Overview
Image3 mir6wx11xt

Comments

Similar projects you might like

Wifi Arduino-based Music Player

Project showcase by Vaughn Kottler

  • 3,967 views
  • 2 comments
  • 9 respects

Dooreo - The Alexa Powered Automatic Door Opener

Project tutorial by Keith Caskey

  • 2,745 views
  • 0 comments
  • 12 respects

A Weird Arduino Powered Clock

Project tutorial by Dante Roumega

  • 12,523 views
  • 3 comments
  • 30 respects

Mobile Weather Station Being Powered by Solar Energy

Project tutorial by Kutluhan Aktar

  • 2,543 views
  • 0 comments
  • 12 respects

Snacks Vending Machine Powered By Arduino

Project tutorial by Sevenmojoe

  • 17,648 views
  • 13 comments
  • 84 respects

Arduino MEGA Guitar Pedal

Project tutorial by electrosmash

  • 17,539 views
  • 2 comments
  • 105 respects
Add projectSign up / Login