Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**
- * Arduino Coursework 2 for Physical Computing: Input & Output - James Wilkinson
- * recTone - v0.1
- *
- * INSTRUCTIONS:
- * Open up the Serial Port and Enter any of the notes which are shown in the below table.
- * You can enter a comma (,) to add an extra long delay when playing tunes.
- * When a sequence of notes have been entered representing your favourite tune, simply
- * enter "p" to start playing the notes in sequence.
- *
- * You can also use the Potentiometer to control the delay which occurs between each note to get the tune sounding accurate.
- *
- * When the tune has finished, you can start again without having to restart the program!
- *
- * INSTRUCTIONS FOR SETTING THE BOARD UP:-
- * Black wire from neg -> GND
- * Red wire from pos -> 5v
- * White wire from J16 to pin 9
- * Resistor from J17 to negative
- * Red wire from e8 to positive
- * White wire from e7 to analogue 0
- * Black wire from e6 to negative
- * Potentiometer in a6, a7 and a8
- *
- *
- * James Wilkinson - 21604819 - Edge Hill University
- * May 2013.
- * REF: Uses an extracted piece of code to determine the frequency of each note.
- * Developed by (cleft) 2005 D. Cuartielles for K3 - see below calculation:
- *
- * The calculation of the tones is made following the mathematical
- * operation:
- *
- * timeHigh = period / 2 = 1 / (2 * toneFrequency)
- *
- * where the different tones are described as in the table:
- *
- * note frequency period timeHigh
- * c 261 Hz 3830 1915
- * d 294 Hz 3400 1700
- * e 329 Hz 3038 1519
- * f 349 Hz 2864 1432
- * g 392 Hz 2550 1275
- * a 440 Hz 2272 1136
- * b 493 Hz 2028 1014
- * C 523 Hz 1912 956
- *
- * see:
- * http://www.arduino.cc/en/Tutorial/Melody
- *
- *
- */
- // Define the pin in which the speaker is plugged into it
- // const(ant) variables tell the compiler it can't be modified and allows for more efficient compiling.
- // Since there is never any need to edit this on runtime (and technicaly it cant be anyway unless it reads from something) declare this const
- int const SPEAKER_PIN = 9;
- // Potentiometer pin ("dial") - used to read analog inputs from it when deciding the duration for each note
- int const DIAL_PIN = 0;
- // Represents how many microseconds the recording should delay for when a command
- // is entered into the input. By default it's 200 ms.
- int const COMMA_DELAY_MS = 400;
- // Since C is compiled code and memory is allocated statically it does not
- // support dynamic arrays. Therefore a limit must be forced upon the maximum notes that can be recorded.
- // Should more notes be required, feel free to increase.
- int const MAX_RECORDED_NOTES = 64;
- // definitions for the notes together with the frequency as according to the above table
- char const names[] = { 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C' };
- int const tones[] = { 1915, 1700, 1519, 1432, 1275, 1136, 1014, 956 };
- // These two store the data for the recording of the notes
- int recordedNotes[MAX_RECORDED_NOTES];
- int recorded_notes_idx = 0;
- /**
- * playTone
- * Sends the instruction to the piezo element to play the tone at the stated frequency
- * and duration passed to the function
- * @param int tone - reprensents the frequency value for the note to be played - see playNote
- * @param int duration - integer value representing the duration for the note to be played in microseconds
- **/
- void playTone(int tone, int duration)
- {
- for (long i = 0; i < duration * 1000L; i += tone * 2)
- {
- digitalWrite(SPEAKER_PIN, HIGH);
- delayMicroseconds(tone);
- digitalWrite(SPEAKER_PIN, LOW);
- delayMicroseconds(tone);
- }
- }
- /**
- * playNote
- * Play's the given note represented by a letter for the purposes of readability
- * for the duration stated (in microseconds)
- * @param char note the note to play
- * @param int duration the time, in microseconds, that the note should play for.
- **/
- void playNote(char note, int duration)
- {
- // play the tone corresponding to the note name
- // For the sake of adding more notes in the future I've removed the
- // hardcoded value of 8 to the correct value of the size of the array
- for (int i = 0; i < sizeof(tones); i++)
- {
- if (names[i] != note)
- continue;
- // No need to continue looping once our note has been found
- playTone(tones[i], duration);
- break;
- }
- }
- /**
- * getToneDuration
- * Returns an integer representing the duration
- * that each tone should be as according to the potentiometer (aka dial)
- * @return int duration
- **/
- int getToneDuration()
- {
- return (0 + analogRead(DIAL_PIN));
- }
- /**
- * addNoteToIndex
- * Appends a note to the array index accordingly providing that the note is valid.
- * @param char note represents the note to record - also supports commas (,) for pausing in between
- **/
- void addNoteToIndex(char note)
- {
- // Only add valid notes to the index and don't forget to support commas
- if(!isValidNote(note) && note != ',')
- {
- return;
- }
- // Check for buffer overflows within the array and prevent them.
- if(recorded_notes_idx >= MAX_RECORDED_NOTES)
- {
- // if the max is reached just play the recording.
- playRecording();
- return;
- }
- // Simply add it to the array and increase the integer
- // representing the index so we can monitor it later
- recordedNotes[recorded_notes_idx] = note;
- recorded_notes_idx++;
- Serial.print(note);
- Serial.print(" ");
- }
- /**
- * playRecording
- * This simply plays back the recording by looping through the stored notes
- * in the recordedNotes array. It also searches for any commas to check for extra long
- * delays. Once a tune has finished playing back, the counter is reset to make room for a new
- * tune to be entered.
- */
- void playRecording()
- {
- // First of all make sure at least one note has been recorded
- if(recorded_notes_idx == 0)
- return;
- // Loop through the array and playback any notes accordingly.
- // Watch out for commas - if a comma is included, it means there should be a
- // slightly longer delay regrdless of the potentiometer when moving on to the next note
- for(int i = 0; i < recorded_notes_idx; i++)
- {
- if(recordedNotes[i] == ',')
- {
- delay(COMMA_DELAY_MS);
- continue;
- }
- // Okay now just play the note accordingly
- playNote(recordedNotes[i], getToneDuration());
- // Add just a short hardcoded delay
- // I would've liked to have based this delay on another potentiometer switch but unfortunately
- // do not have the resources now
- delay(200);
- }
- // Reset the counter back to 0 so that another can be played
- recorded_notes_idx = 0;
- Serial.println("Tune played!");
- }
- /**
- * This function returns an integer representing a true/false indication
- * as to whether an input is a valid note or not. Necessary for error checking
- * prior to processing
- * @param int input - represents the input value which is returned from Serial.read()
- *
- UPDATE: Whilst using a switch/case statement is one practical way of doing this,
- it just hit me - why not just use a loop?!
- switch(input)
- {
- case 'c': return 1;
- case 'd': return 1;
- case
- default: return 0;
- }
- */
- int isValidNote(char note)
- {
- for(int i = 0; i < sizeof(names); i++)
- {
- if(note == names[i])
- return 1;
- }
- return 0;
- }
- /**
- * Called once (i.e. equivilant to main) upon initialisation
- **/
- void setup()
- {
- Serial.begin(9600);
- pinMode(SPEAKER_PIN, OUTPUT);
- Serial.print("recTone v0.1\nINSTRUCTIONS:\nEnter any sequence of the following notes:\nc, d, e, f, g, a, b, C\nEnter a comma (,) for an additional pause\nEnter p to start playback\nNotes Entered:\n");
- }
- /**
- * This is a repeating function that is consistently, repeatively called throughout
- * the programs life. It handles the reading of input from the console to detect for the
- * input of notes and if a note is valid it will play it accordingly
- **/
- void loop()
- {
- // Detect if any input has been given in the serial panel
- if(Serial.available() > 0)
- {
- int serialInput = Serial.read();
- if(serialInput == 'p')
- {
- playRecording();
- }
- else
- {
- addNoteToIndex(serialInput);
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment