Concept
While looking for ideas for the musical instrument, I came across something called HID (Human Interface Devices). These are devices that can be used to substitute for Devices that are used to interact with the computer, such as a keyboard or a mouse. Unfortunately , The Arduino UNO board that we use is not HID compatible. Why did we need this? because we wanted to do something unique and use something unconventional for the digital input part of the assignment. This is when we came across the MakeyMakey board by Sparkfun. Using this board, we can use anything with a weak conductivity as a button that send an input to the computer. We can then use the computer as an interface between Arduino and Makey Makey and use the output of Makey Makey as an input to the Arduino via the Serial.
Once we had this figured out, It opened great possibilities. For the purpose of this assignment, we decided to draw a piano on a piece of paper and use each part as a button ( so a sound plays whenever you touch the paper).
Technical Plan (Abstract overview)
For Arduino UNO
- Takes input from the serial , and reads it
- Converts the letter input to a corresponding frequency (taking digital input)
- Offsets the frequency by reading the value on the potentiometer (taking analog input)
- Uses tone function to play this frequency on the buzzer
For Makey Makey
- Takes input from the paper buttons and send a keystroke to the keyboard corresponding to what button is pressed.
- Presses enter automatically so that the keystroke is entered in the serial of the Arduino board.
Other Technicalities
- We need to make sure that the piano sounds good , for this we will use notes corresponding to an actual scale . The default scale we are using here is the C major Scale on the 4th Octave consisting of the notes C , D, E ,F , G, A and B .
- While drawing the piano , we need to make sure that the keys are separated and each key separately conducts electricity.
- Use alligator clips properly and make sure the connections work
- Since the Arduino board default firmware can only output 6 letters ( w,a,s,d,f,g), we need to configure it to replace some other outputs with letters. Here, we have reprogrammed it to output ‘h’ instead of the Up arrow and used ‘ ‘ (Blank space) as an input as well .
To use:
- Connect both Arduino UNO and Makey Makey to the computer
- Upload Code on Makey Makey
- Open new Window of Arduino IDE and upload code on Arduino UNO
- Open the Serial monitor and click on it to place the computer cursor there.
- Start taking input from Makey Makey
Code
Code for the Arduino UNO board :
#include "pitches.h" #include <Keyboard.h> const int BUZZER_PIN = 8; // Pin for the buzzer const int potentiometerPin = A0; // Pin for the potentiometer const int duration = 200; // Duration of the tone unsigned long lastPotReadTime = 0; // Variable to store the last time potentiometer was read int offset =0; void setup() { Serial.begin(9600); pinMode(BUZZER_PIN, OUTPUT); } void loop() { // Read the potentiometer value only once every second unsigned long currentTime = millis(); if (currentTime - lastPotReadTime >= 1000) { offset = analogRead(potentiometerPin) / 3; // Offset the frequency based on potentiometer reading lastPotReadTime = currentTime; // Print the potentiometer value Serial.println(offset); } // Check if there's any character available in the serial buffer if (Serial.available() > 0) { char receivedChar = Serial.read(); int frequency = 0; // Frequency value for the tone // Map received character to frequency switch (receivedChar) { case 'w': frequency = NOTE_C5; break; case 'a': frequency = NOTE_D5; break; case 's': frequency = NOTE_E5; break; case 'd': frequency = NOTE_F5; break; case 'f': frequency = NOTE_G5; break; case 'g': frequency = NOTE_A5; break; case 'h': frequency = NOTE_C6; break; case ' ': frequency = NOTE_B5; break; default: break; // Do nothing if character is not recognized } if (frequency != 0) { tone(BUZZER_PIN, frequency + offset, duration); // Play the tone delay(duration); // Wait for the tone to complete noTone(BUZZER_PIN); // Stop the tone } } } //CCDCFE //CCDCGF // for happy Birthday first two lines
Relevant Code for the Makey Makey board
To press enter (write newline) along with the character void updateInputStates() { inputChanged = false; for (int i=0; i<NUM_INPUTS; i++) { inputs[i].prevPressed = inputs[i].pressed; // store previous pressed state (only used for mouse buttons) if (inputs[i].pressed) { if (inputs[i].bufferSum < releaseThreshold) { inputChanged = true; inputs[i].pressed = false; if (inputs[i].isKey) { Keyboard.release(inputs[i].keyCode); } if (inputs[i].isMouseMotion) { mouseHoldCount[i] = 0; // input becomes released, reset mouse hold } } else if (inputs[i].isMouseMotion) { mouseHoldCount[i]++; // input remains pressed, increment mouse hold } } else if (!inputs[i].pressed) { if (inputs[i].bufferSum > pressThreshold) { // input becomes pressed inputChanged = true; inputs[i].pressed = true; if (inputs[i].isKey) { Keyboard.press(inputs[i].keyCode); // Print the key code before pressing Enter Keyboard.write('\n'); } } } } #ifdef DEBUG3 if (inputChanged) { Serial.println("change"); } #endif }
2. To configure the outputs of Makey Makey
#include "Arduino.h" /* ///////////////////////////////////////////////////////////////////////// // KEY MAPPINGS: WHICH KEY MAPS TO WHICH PIN ON THE MAKEY MAKEY BOARD? // ///////////////////////////////////////////////////////////////////////// - edit the keyCodes array below to change the keys sent by the MaKey MaKey for each input - the comments tell you which input sends that key (for example, by default 'w' is sent by pin D5) - change the keys by replacing them. for example, you can replace 'w' with any other individual letter, number, or symbol on your keyboard - you can also use codes for other keys such as modifier and function keys (see the the list of additional key codes at the bottom of this file) */ int keyCodes[NUM_INPUTS] = { // top side of the makey makey board KEY_UP_ARROW, // up arrow pad KEY_DOWN_ARROW, // down arrow pad KEY_LEFT_ARROW, // left arrow pad KEY_RIGHT_ARROW, // right arrow pad ' ', // space button pad MOUSE_LEFT, // click button pad // female header on the back left side 'w', // pin D5 'a', // pin D4 's', // pin D3 'd', // pin D2 'f', // pin D1 'g', // pin D0aa // female header on the back right side 'h', // pin A5 MOUSE_MOVE_DOWN, // pin A4 MOUSE_MOVE_LEFT, // pin A3 MOUSE_MOVE_RIGHT, // pin A2 MOUSE_LEFT, // pin A1 MOUSE_RIGHT // pin A0 }; /////////////////////////// // NOISE CANCELLATION ///// /////////////////////////// #define SWITCH_THRESHOLD_OFFSET_PERC 5 // number between 1 and 49 // larger value protects better against noise oscillations, but makes it harder to press and release // recommended values are between 2 and 20 // default value is 5 #define SWITCH_THRESHOLD_CENTER_BIAS 55 // number between 1 and 99 // larger value makes it easier to "release" keys, but harder to "press" // smaller value makes it easier to "press" keys, but harder to "release" // recommended values are between 30 and 70 // 50 is "middle" 2.5 volt center // default value is 55 // 100 = 5V (never use this high) // 0 = 0 V (never use this low ///////////////////////// // MOUSE MOTION ///////// ///////////////////////// #define MOUSE_MOTION_UPDATE_INTERVAL 35 // how many loops to wait between // sending mouse motion updates #define PIXELS_PER_MOUSE_STEP 4 // a larger number will make the mouse // move faster #define MOUSE_RAMP_SCALE 150 // Scaling factor for mouse movement ramping // Lower = more sensitive mouse movement // Higher = slower ramping of speed // 0 = Ramping off #define MOUSE_MAX_PIXELS 10 // Max pixels per step for mouse movement /* /////////////////////////// // ADDITIONAL KEY CODES /// /////////////////////////// - you can use these codes in the keyCodes array above - to get modifier keys, function keys, etc KEY_LEFT_CTRL KEY_LEFT_SHIFT KEY_LEFT_ALT KEY_LEFT_GUI KEY_RIGHT_CTRL KEY_RIGHT_SHIFT KEY_RIGHT_ALT KEY_RIGHT_GUI KEY_BACKSPACE KEY_TAB KEY_RETURN KEY_ESC KEY_INSERT KEY_DELETE KEY_PAGE_UP KEY_PAGE_DOWN KEY_HOME KEY_END KEY_CAPS_LOCK KEY_F1 KEY_F2 KEY_F3 KEY_F4 KEY_F5 KEY_F6 KEY_F7 KEY_F8 KEY_F9 KEY_F10 KEY_F11 KEY_F12 */
Connections and Schematics
Images and Video
Challenges
- Could not use a direct serial communication between Arduino and Makey Makey because the Makey Makey has only 2 digital output pins. The work around to this was using the PC as an interface.
- Had to find the right notes so that the piano would sound good , after a bit of experimentation , the 4th Octave of the C scale sounded very good so we decided to go with it.
- Had to find a correct value for the potentiometer offset, which we found through some experimentation.
- Had to find a way to enter the output of makey makey in the serial of Arduino UNO for communication . Used the Laptop keyboard as an interface for this.
- Had trouble using analogRead and Tone together. So,had to use the concept ofBlinkWithoutDelay using mills() function to take analogRead input only once every second.
Reflections and Further Improvements
This could be improved by :
Adding more notes
Better range
Improving aesthetics
It could be possible to ground without using one hand so that both hands are free.
Since we are using tone(), we cannot press multiple keys at the same time .
Overall, The project turned out very well. Exploring using a different board also using Arduino to make a project that is interactable in a creative way was a great experience. This inspires us to explore further and discover new types of boards and sensors. We hope to use what we have learned in our final projects too .