/* Tone Generator * ----------- * * Program to play a tone based upon turned knobs. * By Tom Music * */ // SETUP ============================================ // Digital Pins #define pinSpeaker 11 #define pinStartStop 12 #define pinPlaySandbox 3 // Analog Pins #define pinTone 0 #define pinDuration 1 // Note frequencies are seperated by octave, starting with G2. // 0 is used as a value to denote a rest. // These values are all multiplied by 10 to increase resolution and still fit in a whole number long noteList[] = { 0, 980, 1038, 1100, 1165, 1235, 1308, 1386, 1468, 1556, 1648, 1756, 1850, 1960, 2076, 2200, 2331, 2469, 2616, 2772, 2937, 3111, 3296, 3492, 3700, 3920, 4153, 4400, 4662, 4939, 5232, 5544, 5873, 6222, 6593, 6985, 7400, 7840, 8306, 8800, 9323, 9878, 10460, 11090, 11750, 12450, 13190, 13970, 14800, 17600, 18650, 19790, 20930, 22170, 23490, 24890, 26370, 27940, 29600, 31360, 33220, 35200, 37290, 39510, 41860}; int noteCount = 0; void setup() { pinMode(pinSpeaker, OUTPUT); pinMode(pinStartStop, INPUT); pinMode(pinPlaySandbox, INPUT); digitalWrite(pinPlaySandbox, HIGH); // Sizeof() returns bytes, and this is an array of Longs (which are 4 bytes each) noteCount = sizeof(noteList) / 4; // Notify user of processor boot via serial connection Serial.begin(9600); Serial.print ("I'm awake!"); Serial.println(); } // ========== PLAY A TONE USING PULSE WIDTH MODULATION void playTone(long toneValue, long toneDuration) { long elapsedTime = 0; long tonePeriods = 0; tonePeriods = (10000000 / toneValue); // Tones of 0 represent rests, anything higher gets played if (toneValue > 0) { while (elapsedTime < toneDuration) { // Sound waves are created by pulsing the speaker between high and low digitalWrite(pinSpeaker, HIGH); delayMicroseconds(tonePeriods / 2); digitalWrite(pinSpeaker, LOW); delayMicroseconds(tonePeriods / 2); // Keep track of how long we have pulsed, so we know when to stop elapsedTime += (tonePeriods); } } } // ========== SCALE INPUT VALUES // Modified by Tom Music from source available here: // http://www.arduino.cc/playground/Main/Autoscale long autoScale(long originalMin, long originalMax, long newBegin, long newEnd, long inputValue) { long zeroRefOriginalMax = 0; long zeroRefnewEnd = 0; long zeroRefCurVal = 0; long rangedValue = 0; boolean invFlag = 0; // Check for out of range inputValues if (inputValue < originalMin) { inputValue = originalMin; } if (inputValue > originalMax) { inputValue = originalMax; } // Zero-reference the values zeroRefOriginalMax = originalMax - originalMin; if (newEnd > newBegin){ zeroRefnewEnd = newEnd - newBegin; } else { zeroRefnewEnd = newBegin - newEnd; invFlag = 1; } zeroRefCurVal = inputValue - originalMin; if (originalMin > originalMax ) { return 0; } if (invFlag == 0) { rangedValue = ((zeroRefCurVal * zeroRefnewEnd) / zeroRefOriginalMax) + newBegin; } else { // invert the ranges rangedValue = newBegin - ((zeroRefCurVal * zeroRefnewEnd) / zeroRefOriginalMax); } return rangedValue; } // ========== MAIN EXECUTION LOOP void loop() { long currentTone = 0; long currentDuration = 0; long bufferTone = 0; long bufferDuration = 0; long currentTempo = 10000; // - Not used yet // long pauseBetweenNotes = 1000; // - Not used yet // int playSandbox = true; // - Not used yet // playSandbox = digitalRead(pinPlaySandbox); bufferTone = analogRead(pinTone); bufferDuration = analogRead(pinDuration); bufferTone = autoScale(0, 1023, 0, noteCount - 1, bufferTone); currentTone = noteList[bufferTone]; currentDuration = autoScale(0, 1023, 0, 128, bufferDuration); // - Not used yet // if (playSandbox == LOW) { // Debugging Code // Serial.print (noteCount); // Serial.print ("\t"); // Serial.print (bufferTone); // Serial.print ("\t"); // Serial.print (currentTone); // Serial.print (currentDuration); // Serial.println(); playTone(currentTone, currentDuration * currentTempo); // } // - Not used yet // delayMicroseconds(pauseBetweenNotes); }