Introduction: Arduino - Play the Piezo

Play The Piezo !
The aim of this project is to generate music through motion thanks to accelerometers.

- 1 3-axis accelerometer
- 1 arduino card
- 1 speaker
- 1 song able to challenge the crap sound of the speaker

The code is basic : the song rhythm is implemented and before each time step, the glove senses the gravity direction and chooses one of the three notes of the song.

The code is below.

You can watch the video on Youtube.

Get news and updates on my page. Currently I am collecting funds against Cancer, please donate!

/*
December 28 2012 - Sebastien RUBRECHT
Attempt to play a cool music with a crap speaker, hoping that the "cool" will compensate the "crap".
The music is "where is my mind" from The Pixies, which is really easy to play.
*/

#define AUTO 0 // Automatic mode : if 1, the music is played automatically.

// Pins
const int analogInPinX = 0;  // Analog input pin that the Accelerometer's first pin is attached to
const int analogInPinY = 1;  // Analog input pin that the Accelerometer's second pin is attached to
const int analogInPinZ = 2;  // Analog input pin that the Accelerometer's third pin is attached to
const int tone1Pin = 9;  // tone output signal

const int highPin1 = 11;  //5 V alimentation
const int highPin2 = 12;  //5 V alimentation
const int lowPin1 = 5; //ground for one of the 2 accelerometer gnd.
const int lowPin2 = 6; //ground for one of the 2 accelerometer gnd.

const int ledOKPinGnd = 8;  //ground for OK Pin
const int ledOKPinH = 10; // 5 V alimentation for OK Pin
const int ledNOKPinGnd = 2; //ground for NOK Pin
const int ledNOKPinH = 4;  // 5 V alimentation for NOK Pin

//constant values
const float freq_rediese0 = 38.9;//frequency of a sharp Re in Hz, for octave 0
const float freq_mi0 = 41.2;//frequency of a Mi in Hz, for octave 0
const float freq_soldiese0 = 51.9;//frequency of a sharp Sol in Hz, for octave 0

//constant user defined parameters
const int octave=4;//octave number. Be careful, below 2(low) and above 6 (acute), it gets very ugly
const int temps=380;//number of milliseconds for 1 musical note. 380 is the real rhythm, but beginning with 600 is easier to learn

//variables
float freq_rediese = freq_rediese0*pow(2, octave); //frequency of a sharp Re in Hz, for the retained octave
float freq_mi = freq_mi0*pow(2, octave);//frequency of a Mi in Hz, for the retained octave
float freq_soldiese = freq_soldiese0*pow(2, octave);//frequency of a sharp Sol in Hz, for the retained octave

int noire;//time of a crotchet note
int croche;//temps of a quaver note
float frequence;//frequency played

int sensorValue1;        // value read from the Accelerometer's first pin
int sensorValue2;        // value read from the Accelerometer's second pin
int sensorValue3;        // value read from the Accelerometer's second pin

void setup() {
  pinMode(tone1Pin, OUTPUT);

  pinMode(highPin1, OUTPUT);
  pinMode(highPin2, OUTPUT);
  pinMode(lowPin1, OUTPUT);
  pinMode(lowPin2, OUTPUT);

  pinMode(ledOKPinGnd, OUTPUT);
  pinMode(ledOKPinH, OUTPUT);
  pinMode(ledNOKPinGnd, OUTPUT);
  pinMode(ledNOKPinH, OUTPUT);

  digitalWrite(lowPin1, LOW);
  digitalWrite(lowPin2, LOW);
  digitalWrite(highPin1, HIGH);
  digitalWrite(highPin2, HIGH);

  digitalWrite(ledOKPinGnd, LOW);
  digitalWrite(ledNOKPinGnd, LOW);
}

void loop() {
  noire= temps;
  croche = temps/2;

  //"where is my mind" is 4 * (1mi + 1sol#) ; 2 * (1re# + 1sol#); 2 * (1mi + 1/2mi + 1/2re#).
  for(int j=0; j<4 ; j++) //4 * (1mi + 1sol#)
  {
    frequence = acqNote(freq_mi); //gets the direction of the higher acceleration from the sensor and returns the assofrequency. The theoretical good one is a Mi.
    note(frequence, noire);// plays the frequency returned at the previous line during 1 "noire" time.
    frequence = acqNote(freq_soldiese);
    note(frequence, noire);
  }
  for(int j=0; j<2 ; j++) //2 * (1re# + 1sol#);
  {
    frequence = acqNote(freq_rediese);
    note(frequence, noire);
    frequence = acqNote(freq_soldiese);
    note(frequence, noire);
  }
  for(int j=0; j<2 ; j++) // 2 * (1mi + 1/2mi + 1/2re#)
  {
    frequence = acqNote(freq_mi);
    note(frequence, noire);
    frequence = acqNote(freq_mi);
    note(frequence, croche);
    frequence = acqNote(freq_rediese);
    note(frequence, croche);
  }
}

void note(float freq, int duration)
{
  //The function "note"  plays a note at frequency "freq" (Hz) during "duration" (ms)

  //conversion of the frequency into a semi period
  double semiperiod_micros =1/(double(freq))*1000000*0.5;

  long duree=long(duration);
  unsigned long a = millis();
  while (millis() < (a+duree))
  {
    digitalWrite(tone1Pin, HIGH);
    delayMicroseconds(int(semiperiod_micros));  
    digitalWrite(tone1Pin, LOW);
    delayMicroseconds(int(semiperiod_micros));
  }
  //In order to separate the notes (it sounds better), small delays.
  if (duration>300)
  {delay(15);}
  else
  {delay(7);}
}

float acqNote(float freq_ref){

  //"acqNote" gets the acceleration in the 3 directions from the sensor, selects the highest and returns the associated frequency.
  // If it matches the theoretical good frequency "freq_ref", it switches on the green led, else the red led.

  float freq;

  // reads the both analog input values:
  sensorValue1 = analogRead(analogInPinX); 
  sensorValue2 = analogRead(analogInPinY); 
  sensorValue3 = analogRead(analogInPinZ);

  //returns the index of the max of 3 values
  if ((max(max(sensorValue1,sensorValue2),sensorValue3))==sensorValue1){
    freq = freq_rediese;
  }
  else if ((max(max(sensorValue1,sensorValue2),sensorValue3))==sensorValue2){
    freq = freq_mi;
  }
  else {
    freq = freq_soldiese;
  }

  //switches on the green led if the frequency found is the theoretical good one, else the red one.
  if (freq==freq_ref){
    digitalWrite(ledOKPinH,HIGH);
    digitalWrite(ledNOKPinH,LOW);
  }
  else{
    digitalWrite(ledOKPinH,LOW);
    digitalWrite(ledNOKPinH,HIGH);
  }
  if (AUTO){
    return freq_ref;
  }
  else {
    return freq;
  }

};