3 Simple Ways to
Share What You Make

With Instructables you can share what you make with the world — and tap into an ever-growing community of creative experts.

PhotosPhotos

Share one or more photos of a project, recipe, or whatever you've made, quickly and easily.

Step by StepStep-By-Step

Share your step-by-step photos with text instructions of what you made so others can do it too!

VideoVideo

Share your how-to video. You'll need your embed code from a video site such as YouTube.

How to build an Air Guitar with Arduino, aka the AIRduino Guitar

Step 5Code

Here is the Arduino code required:

The real-time sound generation part is taken from this great tutorial.

------------------------------------------------------
// An array containing the waveform
// of a guitar sound
char waveform[] =
{125, 148, 171, 194, 209, 230, 252, 255,
253, 244, 235, 223, 207, 184, 169, 167,
163, 158, 146, 131, 126, 129, 134, 127,
105, 80, 58, 51,38, 22, 12,  2, 10, 35,
58, 75, 89, 103, 120, 141, 150, 148, 145,
144, 140, 129, 116, 105, 95, 86, 75, 72,
73, 76, 88, 103, 117, 121, 120, 115, 120,
143, 159, 162, 156, 155, 163, 184, 202,
214, 215, 211, 213, 212, 205, 196, 182,
162, 142, 118, 99, 84, 68, 54, 40, 28,
19, 10,  7,  0,  0,  5,  9, 14, 21, 33,
49, 59, 65, 75, 92, 110};

// We use this waveform to change the
// volume of the output
char waveformVolume[] =
{125, 148, 171, 194, 209, 230, 252, 255,
253, 244, 235, 223, 207, 184, 169, 167,
163, 158, 146, 131, 126, 129, 134, 127,
105, 80, 58, 51,38, 22, 12,  2, 10, 35,
58, 75, 89, 103, 120, 141, 150, 148, 145,
144, 140, 129, 116, 105, 95, 86, 75, 72,
73, 76, 88, 103, 117, 121, 120, 115, 120,
143, 159, 162, 156, 155, 163, 184, 202,
214, 215, 211, 213, 212, 205, 196, 182,
162, 142, 118, 99, 84, 68, 54, 40, 28,
19, 10,  7,  0,  0,  5,  9, 14, 21, 33,
49, 59, 65, 75, 92, 110};
// An array used as a buffer to avoid
// erroneous punctual distance
// measurements
unsigned int distance_buffer[] = {16000,
16000, 16000, 16000, 16000, 16000, 16000,
16000, 16000, 16000, 16000, 16000, 16000,
16000, 16000, 16000};

const int distance_length = 3;
int distance_index = 0;

// The overflow values for 2 octaves
int frequencies[] = { 39, 42, 44, 47,
50, 52, 56, 59, 63, 66, 70, 74, 79,
84, 89, 94, 100, 105, 112, 118, 126,
133, 141, 149};

// Initial pitch
int pitch = 160;

// Initial volume and acceleration
// parameter
int lastAcc = 0;
float volume = 0;

//audio playback on pin 3
byte speakerpin = 3;

//index variable for position in
//waveform
volatile byte waveindex = 0
volatile byte currentvalue = 0;

// Pin used for ultra-sonic sensor
const int pingPin = 7;

// Pins for the potentiometers
const int sustainPin = 1;
const int sensitivityPin = 2;

// Pins for each finger of the left
// hand
const int finger1 = 9;
const int finger2 = 10;
const int finger3 = 11;
const int finger4 = 12;

int fingerValue = 0;

long duration, inches, cm;

void setup() {

pinMode(3,OUTPUT); //Speaker on pin 3

pinMode(finger1,INPUT);
pinMode(finger2,INPUT);
pinMode(finger3,INPUT);
pinMode(finger4,INPUT);


/**************************
    PWM audio configuration
****************************/
//set Timer2 to fast PWM mode
//(doubles PWM frequency)
bitSet(TCCR2A, WGM21);
bitSet(TCCR2B, CS20);
bitClear(TCCR2B, CS21);
bitClear(TCCR2B, CS22);

//enable interrupts now that registers
// have been set
sei();


/*************************
Timer 1 interrupt configuration
*************************/
//disable interrupts while
// registers are configured
cli();

/* Normal port operation, pins disconnected
from timer operation (breaking pwm) */
bitClear(TCCR1A, COM1A1);
bitClear(TCCR1A, COM1A1);
bitClear(TCCR1A, COM1A1);
bitClear(TCCR1A, COM1A1);

/* Mode 4, CTC with TOP set by register
OCR1A. Allows us to set variable timing for
the interrupt by writing new values to
OCR1A. */
bitClear(TCCR1A, WGM10);
bitClear(TCCR1A, WGM11);
bitSet(TCCR1B, WGM12);
bitClear(TCCR1B, WGM13);

/* set the clock prescaler to /8.  */
bitClear(TCCR1B, CS10);
bitSet(TCCR1B, CS11);
bitClear(TCCR1B, CS12);

/* Disable Force Output Compare for
Channels A and B. */
bitClear(TCCR1C, FOC1A);
bitClear(TCCR1C, FOC1B);

/* Initializes Output Compare
Register A at 160 to set the
initial pitch */
OCR1A = 160;

//disable input capture interrupt
bitClear(TIMSK1, ICIE1);
//disable Output
//Compare B Match Interrupt
bitClear(TIMSK1, OCIE1B);
//enable Output
//Compare A Match Interrupt
bitSet(TIMSK1, OCIE1A);
//disable Overflow Interrupt
bitClear(TIMSK1, TOIE1);

// enable interrupts now that
// registers have been set
sei();
}

// Timer overflow handler
ISR(TIMER1_COMPA_vect) {

 /* timer1 ISR.  Every time it
 is called it sets speakerpin to the
 next value in waveform[]. Frequency
 modulation is done by changing the
 timing between successive calls of
 this  function, e.g. for a 1KHz tone,
 set the  timing so that it runs
 through waveform[] 1000 times
 a second. */

 // reset waveindex if it has reached
 // the end of the array

 if (waveindex > 102) {
  waveindex = 0;
 }

 //Set the output value
 if (volume > 0.03) {
  analogWrite(speakerpin,
   waveformVolume[waveindex]);
 }
 waveindex++;

 // Update the pitch
 OCR1A = pitch;



void loop()
{
 // Desactivate interputs, send a ping
 // message and wait for the answer.
 cli();
 pinMode(pingPin, OUTPUT);
 digitalWrite(pingPin, LOW);
 delayMicroseconds(2);
 digitalWrite(pingPin, HIGH);
 delayMicroseconds(5);
 digitalWrite(pingPin, LOW);
 duration = pulseIn(pingPin, HIGH, 2000);
 sei();
 // convert the time into a distance
 // in centimetres
 // and store in buffer
 distance_buffer[distance_index++
  % distance_length] = duration / 20;

 //Find in the buffer the shortest
 // distance measured
 cm = 16000;
 for(int i = 0; i < distance_length; i++) {
  cm = min(cm, distance_buffer[i]);
 }

 // Check which fingers are pressed
 fingerValue = 5;
 if(!digitalRead(finger4)){
  fingerValue = 4;
 }
 if(!digitalRead(finger3)){
  fingerValue = 3;
 }
 if(!digitalRead(finger2)){
  fingerValue = 2;
 }
 if(!digitalRead(finger1)){
  fingerValue = 1;
 }

 // Update the sustain and
 // sensitivity values
 float sustain =
 map(analogRead(sustainPin), 0,
  1024, 101, 130) / 100.0;
 int sensitivity =
    map(analogRead(sensitivityPin),
    0, 1024, 100, 200);

 // Update the volume
 volume = volume / sustain;
 if (volume < 0) {
  volume = 0;
 }
 
 // Check the accelerometer
 int acc = analogRead(0);
 int accDiff = lastAcc - acc;

 // Update the volume value
 if (accDiff > 5 * (200 - sensitivity)) {
  volume += (float)
   pow(accDiff,
       sensitivity / 100.0) / 50000;
 }
 lastAcc = acc;

 // Check that volume is not higher than 1
 if(volume > .95) {
  volume = .95;
 }

 // Update the volume in the waveform
 for(int i = 0; i <= 102; i++) {
  waveformVolume[i] =
   ((waveform[i] - 127) * volume) + 127;
 }

 // Set the pitch according to the distance
 // between the two hands and the
 // fingers pressed
 if(cm < 102 && cm > 0) {
  if(cm > 30) {
   pitch = frequencies[7 +
    (((cm - 30) / 24) * 4 + fingerValue - 1)];
  }else{
   pitch = map(cm, 0, 30, 39, 79);
  }
 }else{
  pitch = frequencies[7 +
   (((102 - 30) / 24) * 4 + fingerValue - 1)];
 }

 // Delay to avoid bouncing signals
 delay(50);
}

------------------------------------------------------


« Previous StepDownload PDFView All StepsNext Step »

Pro

Get More Out of Instructables

Already have an Account?

close

All Steps Viewing
View all steps of an Instructable on the same page when you're a Pro Member.

Upgrade to Pro today!
2
Followers
1
Author:Jell