Difference between revisions of "Automated Xylophone"

From Mech
Jump to navigationJump to search
Line 71: Line 71:


=== Commented Code ===
=== Commented Code ===
=== Main Code File ===
[Insert commented code] <br>
//Brandon Robins, Neil Tiwari, Jennifer Yong
//Team 24: Automated Xylophone Final Code
#include <18f4520.h>
#fuses HS,NOLVP,NOWDT,NOPROTECT
#use delay(clock=40000000)
#use i2c(MASTER, FAST, SCL=PIN_C3, SDA=PIN_C4, FORCE_HW) // use hardware i2c controller
#define EEPROM_WR 0xA0 // Define initial EEPROM write address block (See EEPROM data sheet)
#define EEPROM_RD 0xA1 // Define initial EEPROM read address block (See EEPROM data sheet)
#define LED_GND1 PIN_C7 // Define LED GND pins
#define LED_GND2 PIN_E1
#define LED_GND3 PIN_E2
#define LED_GND4 PIN_C6
/*#define SWT_GND1 PIN_C0 // Already defined in key.c as col0-3
#define SWT_GND2 PIN_C1
#define SWT_GND3 PIN_C2
#define SWT_GND4 PIN_C5
#define SWITCH1 PIN_B1 // Already defined in key.c as row0-3
#define SWITCH2 PIN_B2
#define SWITCH3 PIN_B3
#define SWITCH4 PIN_B4 */
#define SOL8 PIN_D0 // Define Solenoid Output Pins
#define SOL7 PIN_D1
#define SOL6 PIN_D2
#define SOL5 PIN_D3
#define SOL4 PIN_D4
#define SOL3 PIN_D5
#define SOL2 PIN_D6
#define SOL1 PIN_D7
//Include LCD and keypad multiplexing code files
#include "flex_lcd.c"
#include "key.c"
// Define Variables
int block = 1, sel_note, i, j = 1, note_lengths[4] = {1 2 4 8};
int16 address, dis_address = 1, duration, temp_duration, temp_note, value;
//char notes[] = {"R" "C" "C" "D" "D" "E" "F" "F" "G" "G" "A" "A" "B"}; // for use with 12 keys and 12 solenoids
char notes[] = {"R" "C" "D" "E" "F" "G" "A" "B" "C"};
//char note_quality[] = {"E" " " "#" " " "#" " " " " "#" " " "#" " " "#" " "}; // for use with 12 keys and 12 solenoids
char note_quality[] = {"E" " " " " " " " " " " " " " " "8" " " " " " " " "};
void write_eeprom(int16 address, int16 data) //Writing to the EEPROM function
{
i2c_start();
i2c_write(EEPROM_WR);
i2c_write(address>>8);
i2c_write(address);
i2c_write(data);
i2c_stop();
delay_ms(5); //Delay time needed in order to allow EEPROM to write data from buffer to memory sector
}

int16 read_eeprom(int16 address) // Reading from the EEPROM function
{
i2c_start();
i2c_write(EEPROM_WR);
i2c_write(address>>8);
i2c_write(address);
i2c_start();
i2c_write(EEPROM_RD);
value = i2c_read(0);
i2c_stop();
return(value);
}
// Edit Address Block allows you to change which address block is being written too
int edit_block_select()
{
char keypress;
kbd_init();
printf(lcd_putc,"\fEdit Address\n Block # %02d",block);
while(1){
keypress = kbd_getc();
if ((keypress == 'C') && (block < 10)){
block++;
printf(lcd_putc,"\fEdit Address\n Block # %02d",block);
}
if ((keypress == '9') && (block > 1)){
block--;
printf(lcd_putc,"\fEdit Address\n Block # %02d",block);
}
if (keypress == 'D'){
return block;
break;
}
if (keypress == '*'){
break;
}
}
}
//This part of the code lets the user select keys for use in edit mode
void key_select()
{
dis_address = 1;
if (block == 1) address = 0;
if (block == 2) address = 500;
if (block == 3) address = 1000;
if (block == 4) address = 1500;
if (block == 5) address = 2000;
if (block == 6) address = 2500;
if (block == 7) address = 3000;
if (block == 8) address = 3500;
if (block == 9) address = 4000;
if (block == 10) address = 4500;
sel_note = read_eeprom(address);
duration = read_eeprom(address+1);
if (sel_note > 12) sel_note = 1;
//if (duration > 8) duration = 2;
duration = note_lengths[1];
kbd_init();
printf(lcd_putc,"\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat",block,dis_address,notes[sel_note],note_quality[sel_note],duration);
while (1) {
keypress = kbd_getc(); //Get keypad input from key.c
if (keypress == '1') {
sel_note = 1;
printf(lcd_putc,"\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat",block,dis_address,notes[sel_note],note_quality[sel_note],duration);
}
if (keypress == '2') {
sel_note = 2;
printf(lcd_putc,"\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat",block,dis_address,notes[sel_note],note_quality[sel_note],duration);
}
if (keypress == '3') {
sel_note = 3;
printf(lcd_putc,"\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat",block,dis_address,notes[sel_note],note_quality[sel_note],duration);
}
if (keypress == 'A') {
sel_note = 4;
printf(lcd_putc,"\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat",block,dis_address,notes[sel_note],note_quality[sel_note],duration);
}
if (keypress == '4') {
sel_note = 5;
printf(lcd_putc,"\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat",block,dis_address,notes[sel_note],note_quality[sel_note],duration);
}
if (keypress == '5') {
sel_note = 6;
printf(lcd_putc,"\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat",block,dis_address,notes[sel_note],note_quality[sel_note],duration);
}
if (keypress == '6') {
sel_note = 7;
printf(lcd_putc,"\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat",block,dis_address,notes[sel_note],note_quality[sel_note],duration);
}
if (keypress == 'B') {
sel_note = 8;
printf(lcd_putc,"\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat",block,dis_address,notes[sel_note],note_quality[sel_note],duration);
}
if ((keypress == '7') && (j < 3)) {
//sel_note = 9;
j++;
duration = note_lengths[j];
printf(lcd_putc,"\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat",block,dis_address,notes[sel_note],note_quality[sel_note],duration);
}
if ((keypress == '8') && (j > 0)) {
//sel_note = 10;
j--;
duration = note_lengths[j];
printf(lcd_putc,"\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat",block,dis_address,notes[sel_note],note_quality[sel_note],duration);
}
if ((keypress == 'C') && (dis_address < 250)) {
address+=2;
dis_address++;
printf(lcd_putc,"\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat",block,dis_address,notes[sel_note],note_quality[sel_note],duration);
}
if ((keypress == '9') && (dis_address > 1)) {
address-=2;
dis_address--;
printf(lcd_putc,"\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat",block,dis_address,notes[sel_note],note_quality[sel_note],duration);
}
if (keypress == '*') {
//real_time_mode();
}
if (keypress == '0') {
break;
}
if (keypress == '#') {
sel_note = 0;
printf(lcd_putc,"\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat",block,dis_address,notes[sel_note],note_quality[sel_note],duration);
}
// The D key acts like the Enter key. In this case this allows for writing to the EEPROM.
if (keypress == 'D') {
write_eeprom(address,sel_note);
address++;
write_eeprom(address,duration);
address++;
dis_address++;
temp_note = read_eeprom(address);
temp_duration = read_eeprom(address+1);
if (temp_note > 12) sel_note = 1;
else sel_note = temp_note;
if (temp_duration > 8) duration = 2;
else duration = temp_duration;
printf(lcd_putc,"\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat",block,dis_address,notes[sel_note],note_quality[sel_note],duration);
}
}
}
//In Playback mode user can select which address block to play. The xylophone then plays this address block back.
int playback_block_select()
{
char keypress;
kbd_init();
printf(lcd_putc,"\fPlay Address\n Block # %02d",block);
while(1){
keypress = kbd_getc();
if ((keypress == 'C') && (block < 10)){
block++;
printf(lcd_putc,"\fPlay Address\n Block # %02d",block);
}
if ((keypress == '9') && (block > 1)){
block--;
printf(lcd_putc,"\fPlay Address\n Block # %02d",block);
}
if (keypress == '#'){
break;
}
if (keypress == '*'){
return block;
break;
}
}
}

void playback_mode()
{
playback_block_select();
dis_address = 1;
if (block == 1) address = 0;
if (block == 2) address = 500;
if (block == 3) address = 1000;
if (block == 4) address = 1500;
if (block == 5) address = 2000;
if (block == 6) address = 2500;
if (block == 7) address = 3000;
if (block == 8) address = 3500;
if (block == 9) address = 4000;
if (block == 10) address = 4500;
for (i=0; i<250; i++){
value = read_eeprom(address); // Send data from analog input to write function
printf(lcd_putc,"\fAddress: %03lu\nNote: %c%c",dis_address,notes[value],note_quality[value]);
delay_ms(250);
if (value == 1){
output_high(SOL1); //This section outputs the lows and highs to the solenoids in order to hit the keys
delay_ms(100);
output_low(SOL1);
}
if (value == 2){
output_high(SOL2);
delay_ms(100);
output_low(SOL2);
}
if (value == 3){
output_high(SOL3);
delay_ms(100);
output_low(SOL3);
}
if (value == 4){
output_high(SOL4);
delay_ms(100);
output_low(SOL4);
}
if (value == 5){
output_high(SOL5);
delay_ms(100);
output_low(SOL5);
}
if (value == 6){
output_high(SOL6);
delay_ms(100);
output_low(SOL6);
}
if (value == 7){
output_high(SOL7);
delay_ms(100);
output_low(SOL7);
}
if (value == 8){
output_high(SOL8);
delay_ms(100);
output_low(SOL8);
}
address+=2;
dis_address++;
}
}
//In real time mode the user presses a key and the solenoids are activated to hit the keys
void real_time_mode()
{
kbd_init();
lcd_putc("\fReal Time Mode\n");
while (1) {
keypress = kbd_getc();
if (keypress == '1'){
output_high(SOL1);
delay_ms(100);
output_low(SOL1);
}
if (keypress == '2'){
output_high(SOL2);
delay_ms(100);
output_low(SOL2);
}
if (keypress == '3'){
output_high(SOL3);
delay_ms(100);
output_low(SOL3);
}
if (keypress == 'A'){
output_high(SOL4);
delay_ms(100);
output_low(SOL4);
}
if (keypress == '4'){
output_high(SOL5);
delay_ms(100);
output_low(SOL5);
}
if (keypress == '5'){
output_high(SOL6);
delay_ms(100);
output_low(SOL6);
}
if (keypress == '6'){
output_high(SOL7);
delay_ms(100);
output_low(SOL7);
}
if (keypress == 'B'){
output_high(SOL8);
delay_ms(100);
output_low(SOL8);
}
if (keypress == '*'){
edit_block_select();
key_select();
}
if (keypress == '0'){
playback_mode();
}
}
}
//Where the code starts
void main()
{
lcd_init(); // Always call this first.
lcd_putc("\fHello There...\n");
kbd_init();
real_time_mode();
}



== Results and Next Steps ==
== Results and Next Steps ==

Revision as of 11:20, 18 March 2009

Team Members

[Include team picture]

  • Brandon Robins (Senior in Mechanical Engineering and Music Performance, Northwestern University)
  • Neil Tiwari (Masters Student in Biomedical Engineering and Kind of a Big Deal, Northwestern University)
  • Jenny Yong (Senior in Mechanical Engineering, Northwestern University)

Overview

The goal of this project was to have a user input a sequence of notes and have a PIC controlled solenoid sytem hit a xylophone to generate tones. Our automated xylophone operates in two settings -- real time mode and playback mode. In real time mode, the user inputs notes using the keypad and they get played back on the xylophone instantaneously. In playback mode, a user can use the keypad and LCD screen to verify and store over 250 notes in sequence including rests to be played back on the xylophone at a later time.

Click here to check out other Mechatronics projects!

Operating the Automated Xylophone

[Include picture for description of keypad] The user interface includes a keypad containing 16 buttons, arranged as seen above.

Real Time Mode

In Real Time Mode, buttons 1-8 are used to determine xylophone note. As soon as a button is depressed, it will immediately trigger a solenoid to play the chosen note.

Playback Mode

To enter playback programming mode, you hit button 16 -- the edit button. Playback programming mode allows you to store 256 notes, including rests, per block. Once in edit mode, you have access to buttons 1-12. As in Real Time Mode, buttons 1-8 still determine which note should be played. Buttons 9 and 10 will adjust the note duration to shorter and longer respectively. Buttons 11 and 12 will adjust the which sequential number is being programmed. Button 11 will lower the note number, while button 12 will increase the note number. Rests can be programmed using button <n>. To enter and store a note, you use the enter button, button <m>. Once you have finished entering the string of notes you would like to store, you hit button <o>.

To listen to the stored song, you hit button 16, the edit button again.

Parts List

Coming soon . . .

Mechanical Components

Electronic Components

The Xylophone

The xylophone that we selected can be found and purchased here.

Mechanical Design

[Include pictures of interior of wooden casing]

Mechanical Interface

Our mechanical design was fairly simple and straightforward. We needed to determine the optimal way for the solenoids to hit the xylophone keys, and a way to support them in that position. Initially, we found it to be most intuitive for the solenoids to strike downward onto the keys. However, that design would require us to keep the solenoids powered during rest. Therefore, we choose to have our solenoids strike from below the xylophone which allows us to keep them powered off while inactive.

One feature of our mechanical design is that with the xylophone chosen as the bars are hit, the piano keys depress. This design creates the appearance of a phantom piano player.

Solenoid Positioning

To improve aesthetics and support the xylophone at the proper height, we created a wooden housing for the solenoids. Within the housing, our solenoids rest on an aluminum beam which hold them at the appropriate height. On our aluminum beam, we have a ladder-like structure made of foam core to hold the solenoids in place.

Foam core was also placed underneath each bar of the xylophone, as is shown. The purpose of this addition was to allow a greater acceptable surface for the solenoid to interact with the xylophone. Tape was also placed around the piston of the solenoids, as can be seen in the photos. This technique was a temporary solution to prevent the solenoids from banging on the aluminum beam and keep them at an operable height once powered at 12 V. The xylophone is placed on top of the wooden housing with the bars properly aligned with the solenoids.

Electrical Design

Circuit Diagram

[Insert picture of circuit and circuit diagram]

Creating the Automated Xylophone did require some intricate circuitry, as can be seen in the picture of our circuit and our circuit diagram. The most complicated aspects included powering our solenoids using an external power supply and relays, connecting the LCD screen to our PIC and using an EEPROM to store our song information in playback mode. More detailed descriptions of these steps can be found below.

Powering the Solenoids

Since the solenoids need to operate at full voltage and required a lot of current, we were unable to power them using the PIC. Instead, we worked with an external power supply and relays.
[More description needed]

Connecting the LCD

The LCD screen allows the user to monitor his progress in programming for Playback Mode.
[More information or a link necessary]

Using an EEPROM

For our Automated Xylophone, an EEPROM is used to store all of the note information during playback mode. More information on connecting an EEPROM to a PIC can be found here and here.

Code

Multiplexing

[Insert some background info and explanation of multiplexing]

Commented Code

Main Code File

//Brandon Robins, Neil Tiwari, Jennifer Yong //Team 24: Automated Xylophone Final Code

  1. include <18f4520.h>
  2. fuses HS,NOLVP,NOWDT,NOPROTECT
  3. use delay(clock=40000000)
  4. use i2c(MASTER, FAST, SCL=PIN_C3, SDA=PIN_C4, FORCE_HW) // use hardware i2c controller
  5. define EEPROM_WR 0xA0 // Define initial EEPROM write address block (See EEPROM data sheet)
  6. define EEPROM_RD 0xA1 // Define initial EEPROM read address block (See EEPROM data sheet)
  7. define LED_GND1 PIN_C7 // Define LED GND pins
  8. define LED_GND2 PIN_E1
  9. define LED_GND3 PIN_E2
  10. define LED_GND4 PIN_C6

/*#define SWT_GND1 PIN_C0 // Already defined in key.c as col0-3

  1. define SWT_GND2 PIN_C1
  2. define SWT_GND3 PIN_C2
  3. define SWT_GND4 PIN_C5
  4. define SWITCH1 PIN_B1 // Already defined in key.c as row0-3
  5. define SWITCH2 PIN_B2
  6. define SWITCH3 PIN_B3
  7. define SWITCH4 PIN_B4 */
  8. define SOL8 PIN_D0 // Define Solenoid Output Pins
  9. define SOL7 PIN_D1
  10. define SOL6 PIN_D2
  11. define SOL5 PIN_D3
  12. define SOL4 PIN_D4
  13. define SOL3 PIN_D5
  14. define SOL2 PIN_D6
  15. define SOL1 PIN_D7

//Include LCD and keypad multiplexing code files

  1. include "flex_lcd.c"
  2. include "key.c"


// Define Variables int block = 1, sel_note, i, j = 1, note_lengths[4] = {1 2 4 8}; int16 address, dis_address = 1, duration, temp_duration, temp_note, value; //char notes[] = {"R" "C" "C" "D" "D" "E" "F" "F" "G" "G" "A" "A" "B"}; // for use with 12 keys and 12 solenoids char notes[] = {"R" "C" "D" "E" "F" "G" "A" "B" "C"}; //char note_quality[] = {"E" " " "#" " " "#" " " " " "#" " " "#" " " "#" " "}; // for use with 12 keys and 12 solenoids char note_quality[] = {"E" " " " " " " " " " " " " " " "8" " " " " " " " "};

void write_eeprom(int16 address, int16 data) //Writing to the EEPROM function {

  i2c_start();
  i2c_write(EEPROM_WR);
  i2c_write(address>>8);
  i2c_write(address);
  i2c_write(data);
  i2c_stop();
  delay_ms(5);   //Delay time needed in order to allow EEPROM to write data from buffer to memory sector

}

int16 read_eeprom(int16 address) // Reading from the EEPROM function {

  i2c_start();
  i2c_write(EEPROM_WR);
  i2c_write(address>>8);
  i2c_write(address);
  i2c_start();
  i2c_write(EEPROM_RD);  
  value = i2c_read(0);
  i2c_stop(); 
  return(value);

}


// Edit Address Block allows you to change which address block is being written too int edit_block_select() { char keypress; kbd_init(); printf(lcd_putc,"\fEdit Address\n Block # %02d",block); while(1){

  keypress = kbd_getc();
  
     if ((keypress == 'C') && (block < 10)){
     block++;
     printf(lcd_putc,"\fEdit Address\n  Block # %02d",block);
     }
     if ((keypress == '9') && (block > 1)){
     block--;
     printf(lcd_putc,"\fEdit Address\n  Block # %02d",block);
     }
     if (keypress == 'D'){
     return block;
     break;
     }
     if (keypress == '*'){
     break;
     }
  }

}


//This part of the code lets the user select keys for use in edit mode void key_select() { dis_address = 1;

  if (block == 1) address = 0;
  if (block == 2) address = 500;
  if (block == 3) address = 1000;
  if (block == 4) address = 1500;
  if (block == 5) address = 2000;
  if (block == 6) address = 2500;
  if (block == 7) address = 3000;
  if (block == 8) address = 3500;
  if (block == 9) address = 4000;
  if (block == 10) address = 4500;

sel_note = read_eeprom(address); duration = read_eeprom(address+1); if (sel_note > 12) sel_note = 1; //if (duration > 8) duration = 2; duration = note_lengths[1]; kbd_init(); printf(lcd_putc,"\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat",block,dis_address,notes[sel_note],note_quality[sel_note],duration);

  while (1) {
 
  keypress = kbd_getc(); //Get keypad input from key.c

     if (keypress == '1') {
        sel_note = 1;
        printf(lcd_putc,"\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat",block,dis_address,notes[sel_note],note_quality[sel_note],duration);
     }
     if (keypress == '2') {
        sel_note = 2;
        printf(lcd_putc,"\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat",block,dis_address,notes[sel_note],note_quality[sel_note],duration);
     }
     if (keypress == '3') {
        sel_note = 3;
        printf(lcd_putc,"\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat",block,dis_address,notes[sel_note],note_quality[sel_note],duration);
     }
     if (keypress == 'A') {
        sel_note = 4;
        printf(lcd_putc,"\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat",block,dis_address,notes[sel_note],note_quality[sel_note],duration);
     }
     if (keypress == '4') {
        sel_note = 5;
        printf(lcd_putc,"\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat",block,dis_address,notes[sel_note],note_quality[sel_note],duration);
     }
     if (keypress == '5') {
        sel_note = 6;
        printf(lcd_putc,"\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat",block,dis_address,notes[sel_note],note_quality[sel_note],duration);
     }
     if (keypress == '6') {
        sel_note = 7;
        printf(lcd_putc,"\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat",block,dis_address,notes[sel_note],note_quality[sel_note],duration);
     }
     if (keypress == 'B') {
        sel_note = 8;      
        printf(lcd_putc,"\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat",block,dis_address,notes[sel_note],note_quality[sel_note],duration);
     }
     if ((keypress == '7') && (j < 3)) {
        //sel_note = 9;
        j++;
        duration = note_lengths[j];
        printf(lcd_putc,"\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat",block,dis_address,notes[sel_note],note_quality[sel_note],duration);
     }
     if ((keypress == '8') && (j > 0)) {
        //sel_note = 10;
        j--;
        duration = note_lengths[j];
        printf(lcd_putc,"\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat",block,dis_address,notes[sel_note],note_quality[sel_note],duration);
     }
     if ((keypress == 'C') && (dis_address < 250)) {
        address+=2;
        dis_address++;
        printf(lcd_putc,"\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat",block,dis_address,notes[sel_note],note_quality[sel_note],duration);
     }
     if ((keypress == '9') && (dis_address > 1)) {
        address-=2;
        dis_address--;
        printf(lcd_putc,"\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat",block,dis_address,notes[sel_note],note_quality[sel_note],duration);
     }
     if (keypress == '*') {
        //real_time_mode();
     }
     if (keypress == '0') {
        break;
     }     
     if (keypress == '#') {
        sel_note = 0;
        printf(lcd_putc,"\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat",block,dis_address,notes[sel_note],note_quality[sel_note],duration);
     }

     // The D key acts like the Enter key. In this case this allows for writing to the EEPROM.
     if (keypress == 'D') {    
        write_eeprom(address,sel_note);
        address++;
        write_eeprom(address,duration);
        address++;
        dis_address++;
        temp_note = read_eeprom(address);
        temp_duration = read_eeprom(address+1);
           if (temp_note > 12) sel_note = 1;
           else sel_note = temp_note;
           
           if (temp_duration > 8) duration = 2;
           else duration = temp_duration;
        printf(lcd_putc,"\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat",block,dis_address,notes[sel_note],note_quality[sel_note],duration);
     }    
  }

}

//In Playback mode user can select which address block to play. The xylophone then plays this address block back. int playback_block_select() { char keypress; kbd_init(); printf(lcd_putc,"\fPlay Address\n Block # %02d",block);

  while(1){
     keypress = kbd_getc();
 
     if ((keypress == 'C') && (block < 10)){
     block++;
     printf(lcd_putc,"\fPlay Address\n  Block # %02d",block);
     }
  
     if ((keypress == '9') && (block > 1)){
     block--;
     printf(lcd_putc,"\fPlay Address\n  Block # %02d",block);
     }

     if (keypress == '#'){
     break;
     }
     if (keypress == '*'){
     return block;
     break;
     }
  }

}

void playback_mode() {

  playback_block_select();
  dis_address = 1;
  if (block == 1) address = 0;
  if (block == 2) address = 500;
  if (block == 3) address = 1000;
  if (block == 4) address = 1500;
  if (block == 5) address = 2000;
  if (block == 6) address = 2500;
  if (block == 7) address = 3000;
  if (block == 8) address = 3500;
  if (block == 9) address = 4000;
  if (block == 10) address = 4500;

     for (i=0; i<250; i++){
          value = read_eeprom(address); // Send data from analog input to write function  
          printf(lcd_putc,"\fAddress: %03lu\nNote: %c%c",dis_address,notes[value],note_quality[value]);
          delay_ms(250);
          if (value == 1){
             output_high(SOL1);            //This section outputs the lows and highs to the solenoids in order to hit the keys
             delay_ms(100);
             output_low(SOL1);
          }
          if (value == 2){
             output_high(SOL2);
             delay_ms(100);
             output_low(SOL2);
          }
          if (value == 3){
             output_high(SOL3);
             delay_ms(100);
             output_low(SOL3);
          }
          if (value == 4){
             output_high(SOL4);
             delay_ms(100);
             output_low(SOL4);
          }
          if (value == 5){
             output_high(SOL5);
             delay_ms(100);
             output_low(SOL5);
          }
          if (value == 6){
             output_high(SOL6);
             delay_ms(100);
             output_low(SOL6);
          }
          if (value == 7){
             output_high(SOL7);
             delay_ms(100);
             output_low(SOL7);
          }
          if (value == 8){
             output_high(SOL8);
             delay_ms(100);
             output_low(SOL8);
          }
          address+=2;
          dis_address++;
     }

}

//In real time mode the user presses a key and the solenoids are activated to hit the keys void real_time_mode() { kbd_init(); lcd_putc("\fReal Time Mode\n");

  while (1) {
  keypress = kbd_getc();
          if (keypress == '1'){
             output_high(SOL1);
             delay_ms(100);
             output_low(SOL1);
          }
          if (keypress == '2'){
             output_high(SOL2);
             delay_ms(100);
             output_low(SOL2);
          }
          if (keypress == '3'){
             output_high(SOL3);
             delay_ms(100);
             output_low(SOL3);
          }
          if (keypress == 'A'){
             output_high(SOL4);
             delay_ms(100);
             output_low(SOL4);
          }
          if (keypress == '4'){
             output_high(SOL5);
             delay_ms(100);
             output_low(SOL5);
          }
          if (keypress == '5'){
             output_high(SOL6);
             delay_ms(100);
             output_low(SOL6);
          }
          if (keypress == '6'){
             output_high(SOL7);
             delay_ms(100);
             output_low(SOL7);
          }
          if (keypress == 'B'){
             output_high(SOL8);
             delay_ms(100);
             output_low(SOL8);
          }
          if (keypress == '*'){
              edit_block_select();
              key_select();
          }
          if (keypress == '0'){
              playback_mode();
          }
  }

}

//Where the code starts void main() {

  lcd_init();  // Always call this first.
  lcd_putc("\fHello There...\n");
  kbd_init();
  real_time_mode();

}


Results and Next Steps

Results

Our Automated Xylophone operated as expected, with full capability in both Real Time Mode and Playback Mode. We were also able to get excellent sound on our xylophone. A video of our Automated Xylophone playing in Real Time Mode can be found here. A video of our Automated Xylophone playing in Playback Mode can be found here.

Next Steps

Given more time, potential next steps include:

  • Allowing the keypad to use wireless connectivity to send information to the xylophone
  • Creating an enclosure for the circuitry
  • Creating a more permanent housing for the solenoids and xylophone
  • Incorporating the RGB LEDs on the Keypad


References