Code your favorite music and play it on a Casio keyboard or one of the two xylophones described in the project.
Devices and components
Arduino Mega 2560 Rev3
Materials and tools
Soldering iron (generic)
Project description
Casio Player piano and xylophones powered by Arduino
Introduction
The projects
Why build these projects?
Abilities
Overview of Xylophone projects
Xylophones
Choosing a xylophone
Build the Cool Xylo
Mounting the solenoids
Mounting the solenoid bars
The Jig
Wiring the control box
The design of the universal shield
Build a Universal Shield on a Prototype Board
Soldering Tips
Installing Components
List of components and where to buy them
Component Wiring
Various circuit diagrams
The control panel and its circuits
Building the 51-key Casio Player piano
Mounting the solenoids
Selection of solenoids
JF-0730 solenoid noise problem
Noise reduction techniques
A template for slicing polystyrene pads
The solenoid foot
Measuring the Noise from the Solenoid Driven Keys
Various circuits
Control panel circuits.
Player Piano Circuits
Sheet music and musical symbols
Background
Sheet music and musical symbols
Measures
Ledger lines
Cleffs
The rhythm, tempo or rhythm of music
3/4 Time
Notes and silences
The accidentals
Notes with a period
Notes transmitted
Links and insults
Song dynamics
Chords
Metronome mark
Hold symbol
Other symbols
Arduino IDE and music sketches
The Arduino family of computers
Arduino Computers
Arduino Shields
The Mega 2560
The Arduino IDE
//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
}
// 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”
We only code the 18 “white” keys. If accidentals were to be played, we would expand the "#define" list and assign port numbers to them.
The #defines for SOLPIN 1 through 18 display the port number and key name (G through C). Note that the middle C is port 30 for the xylophones.
We only\t“#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 that determine the duration of the note are “#define”. The other two eighth notes and sixteenth notes would be defined if they were to be played in the song. Download the code above into your Mega xylophone control box and the music will be played on either xylophone.
Chords
Robo-C Sketch Intro Code
Song 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
Note duration
#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
Solenoid Activation
#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
Enabling Sustain and Low Volume features
#define SUSTAIN_ON 1
#define SUSTAIN_OFF 2
#define VOLUME_LOW 1
#define VOLUME_FULL 2
Activating Chord Software
#define CHORD_START1
#define
#define CHORD_END 3
Define keys and ports
#define WHITE_KEY 0
#define BLACK_KEY 1
#define
#define
#define
#define
#define SONG_END255
static int beatMult[] = {0, 16, 8, 4, 2, 1}
Structuring the note
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[] = {
“Elise Fur” coding
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 },
//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
{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 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
{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 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 },
The Robo-C code
{SONG_END, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, WHITE_KEY},
};
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
{
\tif(pSong->Port== SONG_END) {
\t\tpSong= Elise;
\t\tdelay(2000);
\t}
playTune(pSong);
}
Robo-C
This is the code that controls the player piano
1{SONG_END, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, WHITE_KEY},
2 };
3 //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.
4
5 struct myNote * pSong = Elise;
6 void setup() //the setup routine runs once when the reset switch is pressed
7 // the digital pins are initialized as outputs
8 {
9 pSong = Elise;
10
11 int i = START_BLACK_KEY; //Reset ports 0 to 19
12 while(i <= END_BLACK_KEY) {
13 pinMode(i, OUTPUT);
14 digitalWrite(i, LOW);
15 i++;
16 }
17 i = START_WHITE_KEY; //Reset ports 22 to 53
18 while(i <= END_WHITE_KEY) {
19 pinMode(i, OUTPUT);
20 digitalWrite(i, LOW);
21 i++;
22 }
23 {
24 pinMode(20, OUTPUT); //Set up the ports to activate the sustain and volume relays
25 pinMode(21, OUTPUT);
26 }
27 }
28 void playTune(struct myNote * pTune) {
29 byte Port1 = pTune->Port; // Select a Port
30 int Soltime= pTune->Soltime; // Select one of 4 setting for the solenoids
31 if(Port1 == SONG_END) { // End the song when Port 255 is detected
32 pSong = pTune;
33 return;
34 }
35 if(pTune->Sustain == 1) { // Turns on the sustain feature on Port 20
36 digitalWrite(20, HIGH);
37 }
38 if(pTune->Sustain == 0) { //Turns off the sustain feature on Port 20
39 digitalWrite(20, LOW);
40 }
41 if(pTune->Volume == 1) { // Turns the volume feature to low on Port 21
42 digitalWrite(21, HIGH);
43 }
44 if(pTune->Volume == 0) { //Turns the volume feature to full on Port 21
45 digitalWrite(21, LOW);
46 }
47 int beat = pTune->Beat ; // Establishes the beat time of the song (millisecs)
48 beat = beat * beatMult[pTune->Duration]/4; // Establishes the duration of the 5 notes
49 // from Full to one Sixteenth based on the beat (millisecs)
50 int durMS = beat * Soltime/4 ; // Establishes the amount of time that the solenoids
51 // are energized .25,.50,.75 or 1.0 of the beat time (millisecs)
52 if(pTune->BlackKey == HIGH) { // the black keys are driven directly from a Mega port in this version
53 digitalWrite(5, pTune->blackStateP5); // of Robo-C. These 7 lines of code are not used.
54 digitalWrite(6, pTune->blackStateP6);
55 digitalWrite(7, pTune->blackStateP7);
56 digitalWrite(8, pTune->blackStateP8);
57 digitalWrite(9, pTune->blackStateP9);
58 } else {
59 if(Port1) {
60 digitalWrite(Port1, HIGH); // Execute command HIGH for the designated white or black note
61 } // Energize the solenoids for time duration durMs
62 }
63 struct myNote * pChordTune = pTune;
64
65 if((pChordTune->Chord == CHORD_START) || (pChordTune->Chord == CHORD_CONTINUE)) {
66 pChordTune++; // Combine individual notes into chords
67 playTune(pChordTune);
68 }
69 if((pTune->Chord == CHORD_END) || (pTune->Chord == 0)) {
70 delay (durMS); // Determines the length of time that the
71 } // Solenoid is energized. One delay per chord
72
73 if(pTune->BlackKey == HIGH) { //Turn off the black keys (ports 0 to 19) after the end of the durMS delay
74 int i = START_BLACK_KEY;
75 while(i <= END_BLACK_KEY) {
76 pinMode(i, OUTPUT);
77 digitalWrite(i, LOW);
78 i++;
79 }
80 }else {
81 int i = START_BLACK_KEY;
82 while(i <= END_BLACK_KEY) {
83 pinMode(i, OUTPUT);
84 digitalWrite(i, LOW);
85 i++;
86 }
87 i = START_WHITE_KEY; //Turn off the white keys (ports 22 to 53) after the end of the durMS delay
88 while(i <= END_WHITE_KEY) {
89 pinMode(i, OUTPUT);
90 digitalWrite(i, LOW);
91 i++;
92 }
93 }
94 // Now wait out the beat time (the duration of the note)
95 if((pTune->Chord == CHORD_END) || (pTune->Chord == 0)) {
96 pTune++;
97 pSong = pTune;
98 delay (beat-durMS); //After the completion of the note or chord, select the next note
99
100 //Serial.begin(9600); // Activate the Serial Monitor (commented out unless needed)
101 //int n = (beat-durMS);
102 //Serial.println (n) ;
103 }
104 }
105 void loop() // the loop routine runs over and over
106 {
107 if(pSong->Port == SONG_END) {
108 pSong = Elise;
109 delay(2000);
110 }
111 playTune(pSong);
112 }
113
Downloadable files
Control panel diagrams
Overview
Control panel diagrams
Universal Shield Wiring Diagram
Arduino Shield Point-to-Point Wiring Overview
Universal Shield Wiring Diagram
Circuit diagram
Overview of the control panel and its circuits
Circuit diagram
Control panel diagrams
Overview
Control panel diagrams
Universal Shield Wiring Diagram
Arduino Shield Point-to-Point Wiring Overview
Universal Shield Wiring Diagram
Circuit diagram
Overview of the control panel and its circuits
Circuit diagram
Note: Content and images are from: https://projecthub.arduino.cc/, with some modifications.
If you want it removed due to copyright reasons, please leave a comment. Thank you.
I want to share this article more widely so that everyone knows about Arduino and your project.