Kristen Fernandez / Mbed 2 deprecated FINAL_PROJECT

Dependencies:   FSR LSM9DS1_Library_cal USBMIDI mbed

Fork of LSM9DS1_Demo_wCal by jim hamblen

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 #include "mbed.h"
00002 #include "USBMIDI.h"
00003 #include "LSM9DS1.h"
00004 #include "math.h" 
00005 #include "FSR.h"
00006 
00007 #define PI 3.14159
00008 #define BUFFERSIZE 6
00009 
00010 // FSR
00011 FSR fsr_kick(p20, 10); // Pin 20 is used as the AnalogIn pin and a 10k resistor is used as a voltage divider
00012 FSR fsr_hh(p19, 10); // Pin 19 is used as the AnalogIn pin and a 10k resistor is used as a voltage divider
00013 bool hh_close = false;  // boolean to determine if hi-hat is closed or open
00014 bool kicked = false;
00015 
00016 // IMU
00017 LSM9DS1 IMU(p9, p10, 0xD6, 0x3C);
00018 LSM9DS1 IMU2(p28, p27, 0xD6, 0x3C);
00019 
00020 USBMIDI midi;
00021 
00022 Serial pc(USBTX, USBRX);
00023 DigitalOut led1(LED1);
00024 DigitalOut led2(LED2);
00025 DigitalOut led3(LED3);
00026 DigitalOut led4(LED4);
00027 
00028 Timer t;
00029 float t_prev = 0;
00030 float t_prev2 = 0;
00031 float t_curr = 0;
00032 float t_curr2 = 0;
00033 float t_gyroPrev = 0;
00034 float t_gyroPrev2 = 0;
00035 float t_gyroCurr = 0;
00036 float t_gyroCurr2 = 0;
00037 float delta_t = 0;
00038 
00039 float y_accel = 0;
00040 float y_accel2 = 0;
00041 
00042 int resetIndex = BUFFERSIZE - 2;
00043 float average[BUFFERSIZE] = {0};
00044 int avg_index = 0;
00045 float total = 0;
00046 float avg_thresh = 20;
00047 
00048 float average2[BUFFERSIZE] = {0};
00049 int avg_index2 = 0;
00050 float total2 = 0;
00051 float avg_thresh2;
00052 
00053 float prev_y_accel = 0;
00054 float curr_y_accel = 0;
00055 float y_accel_threshold = 0.8;
00056 bool check_y_accel = false;
00057 float t_prev_y_accel = 0;
00058 
00059 float prev_y_accel2 = 0;
00060 float curr_y_accel2 = 0;
00061 bool check_y_accel2 = false;
00062 float t_prev_y_accel2 = 0;
00063 
00064 int count2 = 0;
00065 int count = 0;
00066 
00067 bool detectHit = 0;
00068 bool detectHit2 = 0;
00069 bool detectUp = 0;
00070 bool detectUp2 = 0;
00071 
00072 float runningAvg = 0;
00073 float runningAvg2 = 0;
00074 
00075 float interval = 0.20;
00076 float hit_volume = 0;
00077 float hit_volume2 = 0;
00078 
00079 enum StateType {FRONT, SIDE, HIT};
00080 enum StateType2 {FRONT2, SIDE2, HIT2};
00081 
00082 StateType state = FRONT;   // Initial state is FRONT
00083 StateType2 state2 = FRONT2;
00084 
00085 void show_message(MIDIMessage msg) {
00086     switch (msg.type()) {
00087         case MIDIMessage::NoteOnType:
00088             printf("NoteOn key:%d, velocity: %d, channel: %d\n", msg.key(), msg.velocity(), msg.channel());
00089             break;
00090         case MIDIMessage::NoteOffType:
00091             printf("NoteOff key:%d, velocity: %d, channel: %d\n", msg.key(), msg.velocity(), msg.channel());
00092             break;
00093         case MIDIMessage::ControlChangeType:    
00094             printf("ControlChange controller: %d, data: %d\n", msg.controller(), msg.value());
00095             break;
00096         case MIDIMessage::PitchWheelType:
00097             printf("PitchWheel channel: %d, pitch: %d\n", msg.channel(), msg.pitch());
00098             break;
00099         default:
00100             printf("Another message\n");
00101     }    
00102 }
00103 
00104 
00105 int main()
00106 {
00107     midi.attach(show_message);         // call back for messages received 
00108     pc.baud(9600);
00109     pc.printf("Hello world!\n");
00110     
00111     // Initialize IMUs
00112     IMU.begin();
00113     if (!IMU.begin()) {
00114         pc.printf("Failed to communicate with LSM9DS1 - first.\n");
00115     }
00116     IMU.calibrate(1);
00117     
00118     IMU2.begin();
00119     if (!IMU2.begin()) {
00120         pc.printf("Failed to communicate with LSM9DS1 - second.\n");
00121     }
00122     IMU2.calibrate(1);    
00123     
00124     t.start(); // start timer
00125     
00126     while(1) {
00127         
00128         // Initialize acceleration and gyroscope data for both IMUs
00129         while(!IMU.accelAvailable());
00130         IMU.readAccel();
00131         while(!IMU.gyroAvailable());
00132         IMU.readGyro();
00133         
00134         while(!IMU2.accelAvailable());
00135         IMU2.readAccel();
00136         while(!IMU2.gyroAvailable());
00137         IMU2.readGyro();
00138         
00139         // Create variables for ease of use for acceleration
00140         y_accel = IMU.calcAccel(IMU.ay);
00141         y_accel2 = IMU2.calcAccel(IMU2.ay);
00142         
00143         // Initialize timer
00144         t_curr = t.read();
00145         t_curr2 = t_curr;
00146         
00147         
00148         /**
00149         * FSR detection
00150         */
00151         
00152         // Check if values from FSRs are above a threshold (to detect hit)
00153         if (fsr_kick.readRaw() > 0.3){
00154             // Sound will only play if foot is not on FSR (eliminates continuous noise playing if pedal is held down)
00155             if (kicked == false){
00156                 midi.write(MIDIMessage::NoteOn(45, fsr_kick.readRaw() * 127 + 30, 10)); // Play a kick, map the volume and boost the amplitude, channel 10
00157                 }
00158             kicked = true;
00159             }
00160         else {kicked = false;}
00161                 
00162         if (fsr_hh.readRaw() > 0.3){
00163             if (hh_close == false){
00164                 midi.write(MIDIMessage::NoteOn(42, fsr_hh.readRaw()*127, 10)); // Play a hi-hat pedal, map the volume, channel 10
00165             }           
00166             hh_close = true;
00167         }
00168         else {hh_close = false;} 
00169         
00170         
00171         /** 
00172         * Running average for hit detection
00173         */
00174         
00175         // First IMU
00176         total -= average[avg_index];
00177         average[avg_index] = IMU.calcGyro(IMU.gy);
00178         total += average[avg_index];
00179         if (avg_index > resetIndex) {
00180             avg_index = 0;
00181         } else {
00182             avg_index++;
00183         }
00184         
00185         // Second IMU
00186         total2 -= average2[avg_index2];
00187         average2[avg_index2] = IMU2.calcGyro(IMU2.gy);
00188         total2 += average2[avg_index2];
00189         if (avg_index2 > resetIndex) {
00190             avg_index2 = 0;
00191         } else {
00192             avg_index2++;
00193         }              
00194         
00195         /**
00196         * Hit detection
00197         */
00198         
00199         // Detect downward hit
00200          if (IMU.calcGyro(IMU.gy) > 35) {
00201             detectHit = 1; 
00202         }
00203         
00204         if (IMU2.calcGyro(IMU2.gy) > 35) {
00205             detectHit2 = 1; 
00206         }
00207         
00208         // Map gyroscope value ranges to volume ranges
00209         hit_volume = (runningAvg + 245) * (127) / (490);            
00210         hit_volume2 = (runningAvg2 + 245) * (127) / (490) + 15;
00211         
00212         // First IMU
00213         detectUp = IMU.calcGyro(IMU.gy) <= 0;
00214         runningAvg = total / BUFFERSIZE;
00215         
00216         // Check if drumstick is brought down and then brought back up (eliminates continous hit detection if drumstick is just held tilted down)
00217         // Then check if running average is greater than a threshold (to elimate noise)
00218         // Elimate debouncing by only allowing a hit to play if the time interval has passed   
00219         if (detectHit && detectUp && (runningAvg > avg_thresh) && (t_curr - t_prev) > interval) {
00220             // Depending on the state, play the corresponding instrument
00221             switch (state) {
00222                 case (FRONT):
00223                     midi.write(MIDIMessage::NoteOn(46, hit_volume, 10)); // Play ride sound
00224                     break;
00225                 case (SIDE):
00226                     if (hh_close) {
00227                         midi.write(MIDIMessage::NoteOn(40, hit_volume, 10)); // Play closed hi-hat sound
00228                     } else {
00229                         midi.write(MIDIMessage::NoteOn(41, hit_volume, 10)); // Play open hi-hat sound
00230                     }
00231                     break;
00232             }
00233             detectHit = 0;
00234             t_prev = t_curr;
00235             count = 0;
00236         }   
00237         
00238         // Second IMU
00239         detectUp2 = IMU2.calcGyro(IMU2.gy) <= 0;
00240         runningAvg2 = total2 / BUFFERSIZE;
00241         
00242         if (detectHit2 && detectUp2 && runningAvg2 > avg_thresh2  && (t_curr2 - t_prev2) > interval) {
00243             switch (state2) {
00244                 case (FRONT2):
00245                     midi.write(MIDIMessage::NoteOn(47, hit_volume2, 10)); // Play snare sound
00246                     break;
00247                 case (SIDE2):
00248                     midi.write(MIDIMessage::NoteOn(51, hit_volume2, 10)); // Play clap sound
00249                     break;
00250             }
00251             detectHit2 = 0;
00252             t_prev2 = t_curr2;
00253         }
00254         
00255         
00256         /**
00257         * Instrument switching detection
00258         */
00259         
00260         curr_y_accel = y_accel;
00261         curr_y_accel2 = y_accel2;
00262         
00263         check_y_accel = abs(curr_y_accel - prev_y_accel) >  y_accel_threshold;
00264         check_y_accel2 = abs(curr_y_accel2 - prev_y_accel2) >  y_accel_threshold;
00265         
00266         // Check that y accleration is above threshold; if it is, increase the count for the number of cycles it is above this threshold
00267         if (check_y_accel) {
00268             count++;
00269         }
00270         
00271         if (check_y_accel2) {
00272             count2++;
00273         }
00274             
00275         // First IMU
00276         switch (state) {
00277             case (FRONT):
00278                 // Check that y_accleration is above the threshold for at least 3 cycles
00279                 // Elimnate debouncing by only switching if a time interval has passed
00280                 if (check_y_accel && (count >= 3) && (t_curr - t_prev_y_accel) > 0.3) {
00281                     count = 0;
00282                     state = SIDE;
00283                     led1 = 1;
00284                     led2 = 0;
00285                     t_prev_y_accel = t_curr;
00286                 }      
00287                 break;
00288             case (SIDE):
00289                 if (check_y_accel && (count >= 3) && (t_curr - t_prev_y_accel) > 0.3) {
00290                     count = 0;
00291                     state = FRONT;
00292                     led1 = 0;
00293                     led2 = 1;
00294                     t_prev_y_accel = t_curr;
00295                 }
00296                 break;
00297         }
00298         prev_y_accel = curr_y_accel;
00299         
00300         //Second IMU
00301         switch (state2) {
00302             case (FRONT2):
00303                 if (check_y_accel2 && (count2 >= 3) && (t_curr - t_prev_y_accel2) > 0.3){
00304                     state2 = SIDE2;
00305                     count2 = 0; 
00306                     led4 = 1;
00307                     led3 = 0;
00308                     t_prev_y_accel2 = t_curr;
00309                 }       
00310                 break;
00311             case (SIDE2):
00312                 if (check_y_accel2 && (count2 >= 3) && (t_curr - t_prev_y_accel2) > 0.3){
00313                     state2 = FRONT2;
00314                     count2 = 0;
00315                     led4 = 0;
00316                     led3 = 1;
00317                     t_prev_y_accel2 = t_curr;
00318                 }
00319                 break;
00320         }
00321         prev_y_accel2 = curr_y_accel2;
00322     }
00323 }