A program to automatically tune a guitar. Written by Justin Reidhead and Steven Swenson

Dependencies:   FFT FrequencyFinder Motor NewTextLCD PinDetect mbed strings

Committer:
melangeaddict
Date:
Sun Apr 15 00:37:37 2012 +0000
Revision:
2:9c0a83c5ded5
Parent:
1:4a82a5178506
Child:
3:c672e782f19b
Uncommented mbed parts

Who changed what in which revision?

UserRevisionLine numberNew contents of line
melangeaddict 2:9c0a83c5ded5 1 #include "mbed.h"
melangeaddict 2:9c0a83c5ded5 2 #include "Motor.h"
melangeaddict 2:9c0a83c5ded5 3 #include "FrequencyFinder.h"
melangeaddict 2:9c0a83c5ded5 4 #include "NewTextLCD.h"
melangeaddict 2:9c0a83c5ded5 5 #include "PinDetect.h"
melangeaddict 2:9c0a83c5ded5 6 #include "strings.h"
melangeaddict 2:9c0a83c5ded5 7 #include <iostream>
melangeaddict 2:9c0a83c5ded5 8 #include <stdio.h>
melangeaddict 2:9c0a83c5ded5 9 #include <vector>
melangeaddict 2:9c0a83c5ded5 10
melangeaddict 2:9c0a83c5ded5 11 using namespace std;
melangeaddict 2:9c0a83c5ded5 12 //***************************************************
melangeaddict 2:9c0a83c5ded5 13 //***************Globals*****************************
melangeaddict 2:9c0a83c5ded5 14 PinDetect string_but(p11);
melangeaddict 2:9c0a83c5ded5 15 PinDetect pitch_but(p12);
melangeaddict 2:9c0a83c5ded5 16 PinDetect start_but(p13);
melangeaddict 2:9c0a83c5ded5 17 PinDetect mode_but(p14);
melangeaddict 2:9c0a83c5ded5 18
melangeaddict 2:9c0a83c5ded5 19 DigitalOut led1(LED1);
melangeaddict 2:9c0a83c5ded5 20 DigitalOut led2(LED2);
melangeaddict 2:9c0a83c5ded5 21
melangeaddict 2:9c0a83c5ded5 22 TextLCD lcd(p23,p24,p25,p26,p27,p28);
melangeaddict 2:9c0a83c5ded5 23 Motor motor(p20,p21,p22);//enable, direction, step
melangeaddict 2:9c0a83c5ded5 24 FrequencyFinder guitar(p19);//input
melangeaddict 2:9c0a83c5ded5 25
melangeaddict 2:9c0a83c5ded5 26 int selected_string;
melangeaddict 2:9c0a83c5ded5 27 bool current_mode;
melangeaddict 2:9c0a83c5ded5 28 bool start_tuning;
melangeaddict 2:9c0a83c5ded5 29 bool up, down;
melangeaddict 2:9c0a83c5ded5 30
melangeaddict 2:9c0a83c5ded5 31 vector<strings> strings_array;
melangeaddict 2:9c0a83c5ded5 32
melangeaddict 2:9c0a83c5ded5 33 //***************************************************
melangeaddict 2:9c0a83c5ded5 34 //*****************constants*************************
melangeaddict 2:9c0a83c5ded5 35 const bool tuning_mode=false;
melangeaddict 2:9c0a83c5ded5 36 const bool winding_mode=true;
melangeaddict 2:9c0a83c5ded5 37
melangeaddict 2:9c0a83c5ded5 38 //***************************************************
melangeaddict 2:9c0a83c5ded5 39 //******************prototypes***********************
melangeaddict 2:9c0a83c5ded5 40 void device_init();
melangeaddict 2:9c0a83c5ded5 41
melangeaddict 2:9c0a83c5ded5 42 void string_sel();
melangeaddict 2:9c0a83c5ded5 43 void pitch_sel();
melangeaddict 2:9c0a83c5ded5 44 void start();
melangeaddict 2:9c0a83c5ded5 45 void stop();
melangeaddict 2:9c0a83c5ded5 46 void mode();
melangeaddict 2:9c0a83c5ded5 47 void do_nothing();
melangeaddict 2:9c0a83c5ded5 48 void wind_up();
melangeaddict 2:9c0a83c5ded5 49 void wind_down();
melangeaddict 2:9c0a83c5ded5 50
melangeaddict 2:9c0a83c5ded5 51 void button_init();
melangeaddict 2:9c0a83c5ded5 52 void setup_buttons();
melangeaddict 2:9c0a83c5ded5 53 void output_menu();
melangeaddict 2:9c0a83c5ded5 54 void motor_calibration();
melangeaddict 2:9c0a83c5ded5 55 bool check_threshold(float);
melangeaddict 2:9c0a83c5ded5 56 //*************************************************
melangeaddict 2:9c0a83c5ded5 57 //*********************main************************
melangeaddict 2:9c0a83c5ded5 58 int main() {
melangeaddict 2:9c0a83c5ded5 59 lcd.cls();
melangeaddict 2:9c0a83c5ded5 60 lcd.printf("Perfect\n Pitch");
melangeaddict 2:9c0a83c5ded5 61
melangeaddict 2:9c0a83c5ded5 62 wait(.5);
melangeaddict 2:9c0a83c5ded5 63
melangeaddict 2:9c0a83c5ded5 64 device_init();
melangeaddict 2:9c0a83c5ded5 65
melangeaddict 2:9c0a83c5ded5 66 int state=0,next_state=0;
melangeaddict 2:9c0a83c5ded5 67 //float old_freq=0;
melangeaddict 2:9c0a83c5ded5 68 float new_freq=0;
melangeaddict 2:9c0a83c5ded5 69 float desired_freq=0;
melangeaddict 2:9c0a83c5ded5 70 strings *temp=&strings_array[0];
melangeaddict 2:9c0a83c5ded5 71 while (1) {
melangeaddict 2:9c0a83c5ded5 72
melangeaddict 2:9c0a83c5ded5 73 state=next_state;
melangeaddict 2:9c0a83c5ded5 74
melangeaddict 2:9c0a83c5ded5 75 switch (state) {
melangeaddict 2:9c0a83c5ded5 76 //------------------------------------
melangeaddict 2:9c0a83c5ded5 77 case 0://Stay here till the user selects the string and pitch
melangeaddict 2:9c0a83c5ded5 78 if (start_tuning==true) {
melangeaddict 2:9c0a83c5ded5 79 next_state=1;
melangeaddict 2:9c0a83c5ded5 80 } else {
melangeaddict 2:9c0a83c5ded5 81 next_state=0;
melangeaddict 2:9c0a83c5ded5 82 }
melangeaddict 2:9c0a83c5ded5 83
melangeaddict 2:9c0a83c5ded5 84 break;
melangeaddict 2:9c0a83c5ded5 85 //----------------------------------------
melangeaddict 2:9c0a83c5ded5 86 case 1://motor calibration state
melangeaddict 2:9c0a83c5ded5 87 motor_calibration();
melangeaddict 2:9c0a83c5ded5 88 next_state=2;
melangeaddict 2:9c0a83c5ded5 89 break;
melangeaddict 2:9c0a83c5ded5 90 //-----------------------------------------
melangeaddict 2:9c0a83c5ded5 91 case 2://begin the actual tuning
melangeaddict 2:9c0a83c5ded5 92 temp=&strings_array[selected_string];
melangeaddict 2:9c0a83c5ded5 93 desired_freq=temp->get_freq();
melangeaddict 2:9c0a83c5ded5 94
melangeaddict 2:9c0a83c5ded5 95 next_state=3;
melangeaddict 2:9c0a83c5ded5 96 break;
melangeaddict 2:9c0a83c5ded5 97 //-----------------------------------------
melangeaddict 2:9c0a83c5ded5 98 case 3:
melangeaddict 2:9c0a83c5ded5 99 new_freq=guitar.find_frequency();
melangeaddict 2:9c0a83c5ded5 100 if (check_threshold(new_freq)) {
melangeaddict 2:9c0a83c5ded5 101 if ((desired_freq-.5)<new_freq && (desired_freq+.5)>new_freq) {//We are within .5Hz of the desired frequency
melangeaddict 2:9c0a83c5ded5 102 lcd.cls();
melangeaddict 2:9c0a83c5ded5 103 lcd.printf("String %d\ntuned",selected_string);
melangeaddict 2:9c0a83c5ded5 104 wait(.5);
melangeaddict 2:9c0a83c5ded5 105
melangeaddict 2:9c0a83c5ded5 106 start_tuning=false;
melangeaddict 2:9c0a83c5ded5 107 next_state=0;
melangeaddict 2:9c0a83c5ded5 108 } else if ((desired_freq-.5)>new_freq) {
melangeaddict 2:9c0a83c5ded5 109 //motor(up,# of steps);
melangeaddict 2:9c0a83c5ded5 110 next_state=3;
melangeaddict 2:9c0a83c5ded5 111 } else {
melangeaddict 2:9c0a83c5ded5 112 //motor(down,# of steps);
melangeaddict 2:9c0a83c5ded5 113 next_state=3;
melangeaddict 2:9c0a83c5ded5 114 }
melangeaddict 2:9c0a83c5ded5 115 } else {
melangeaddict 2:9c0a83c5ded5 116 next_state=3;
melangeaddict 2:9c0a83c5ded5 117 }
melangeaddict 2:9c0a83c5ded5 118
melangeaddict 2:9c0a83c5ded5 119 //TODO:Determine number of steps per frequency change
melangeaddict 2:9c0a83c5ded5 120 //old_freq=new_freq;
melangeaddict 2:9c0a83c5ded5 121 break;
melangeaddict 2:9c0a83c5ded5 122 //-----------------------------------------
melangeaddict 2:9c0a83c5ded5 123 default:
melangeaddict 2:9c0a83c5ded5 124 break;
melangeaddict 2:9c0a83c5ded5 125 }
melangeaddict 2:9c0a83c5ded5 126 wait_ms(5);
melangeaddict 2:9c0a83c5ded5 127
melangeaddict 2:9c0a83c5ded5 128 if (start_tuning==false) {//If the stop button is pressed, the state machine returns to user input
melangeaddict 2:9c0a83c5ded5 129 next_state=0;
melangeaddict 2:9c0a83c5ded5 130 }
melangeaddict 2:9c0a83c5ded5 131 }
melangeaddict 2:9c0a83c5ded5 132
melangeaddict 2:9c0a83c5ded5 133 // return 0;
melangeaddict 2:9c0a83c5ded5 134 }
melangeaddict 2:9c0a83c5ded5 135
melangeaddict 2:9c0a83c5ded5 136 //***************************************************
melangeaddict 2:9c0a83c5ded5 137 //******************functions************************
melangeaddict 2:9c0a83c5ded5 138 void output_menu() {
melangeaddict 2:9c0a83c5ded5 139 lcd.cls();
melangeaddict 2:9c0a83c5ded5 140 strings temp=strings_array[selected_string];
melangeaddict 2:9c0a83c5ded5 141 lcd.printf("Select String: %d\nSelect Pitch: %s",selected_string,temp.get_note().c_str());
melangeaddict 2:9c0a83c5ded5 142 }
melangeaddict 2:9c0a83c5ded5 143
melangeaddict 2:9c0a83c5ded5 144 //***************************************************
melangeaddict 2:9c0a83c5ded5 145 void button_init() {
melangeaddict 2:9c0a83c5ded5 146 string_but.mode( PullDown );
melangeaddict 2:9c0a83c5ded5 147 string_but.setSampleFrequency();
melangeaddict 2:9c0a83c5ded5 148
melangeaddict 2:9c0a83c5ded5 149 pitch_but.mode( PullDown );
melangeaddict 2:9c0a83c5ded5 150 pitch_but.setSampleFrequency();
melangeaddict 2:9c0a83c5ded5 151
melangeaddict 2:9c0a83c5ded5 152 start_but.mode( PullDown );
melangeaddict 2:9c0a83c5ded5 153 start_but.setSampleFrequency();
melangeaddict 2:9c0a83c5ded5 154
melangeaddict 2:9c0a83c5ded5 155 mode_but.mode( PullDown );
melangeaddict 2:9c0a83c5ded5 156 mode_but.setSampleFrequency();
melangeaddict 2:9c0a83c5ded5 157 }
melangeaddict 2:9c0a83c5ded5 158
melangeaddict 2:9c0a83c5ded5 159 //***************************************************
melangeaddict 2:9c0a83c5ded5 160 void setup_buttons() {
melangeaddict 2:9c0a83c5ded5 161 if (current_mode==tuning_mode) {
melangeaddict 2:9c0a83c5ded5 162 string_but.attach_asserted(&string_sel);
melangeaddict 2:9c0a83c5ded5 163 pitch_but.attach_asserted(&pitch_sel);
melangeaddict 2:9c0a83c5ded5 164 start_but.attach_asserted(&start);
melangeaddict 2:9c0a83c5ded5 165 mode_but.attach_asserted(&mode);
melangeaddict 2:9c0a83c5ded5 166 } else {
melangeaddict 2:9c0a83c5ded5 167 string_but.attach_asserted(&wind_up);
melangeaddict 2:9c0a83c5ded5 168 pitch_but.attach_asserted(&wind_down);
melangeaddict 2:9c0a83c5ded5 169 start_but.attach_asserted(&do_nothing);
melangeaddict 2:9c0a83c5ded5 170 mode_but.attach_asserted(&mode);
melangeaddict 2:9c0a83c5ded5 171 }
melangeaddict 2:9c0a83c5ded5 172 }
melangeaddict 2:9c0a83c5ded5 173 //***************************************************
melangeaddict 2:9c0a83c5ded5 174 void string_sel() {
melangeaddict 2:9c0a83c5ded5 175 selected_string++;
melangeaddict 2:9c0a83c5ded5 176 if (selected_string>6)
melangeaddict 2:9c0a83c5ded5 177 selected_string=1;
melangeaddict 2:9c0a83c5ded5 178
melangeaddict 2:9c0a83c5ded5 179 output_menu();
melangeaddict 2:9c0a83c5ded5 180 }
melangeaddict 2:9c0a83c5ded5 181 //***************************************************
melangeaddict 2:9c0a83c5ded5 182 void pitch_sel() {
melangeaddict 2:9c0a83c5ded5 183 strings *temp=&strings_array[selected_string];
melangeaddict 2:9c0a83c5ded5 184 temp->inc_index();
melangeaddict 2:9c0a83c5ded5 185
melangeaddict 2:9c0a83c5ded5 186 output_menu();
melangeaddict 2:9c0a83c5ded5 187 }
melangeaddict 2:9c0a83c5ded5 188 //***************************************************
melangeaddict 2:9c0a83c5ded5 189 void start() {
melangeaddict 2:9c0a83c5ded5 190 start_tuning=true;
melangeaddict 2:9c0a83c5ded5 191 }
melangeaddict 2:9c0a83c5ded5 192 //***************************************************
melangeaddict 2:9c0a83c5ded5 193 void mode() {
melangeaddict 2:9c0a83c5ded5 194 if (current_mode==tuning_mode) {
melangeaddict 2:9c0a83c5ded5 195 current_mode=winding_mode;
melangeaddict 2:9c0a83c5ded5 196 lcd.cls();
melangeaddict 2:9c0a83c5ded5 197 lcd.printf("Winding Mode");
melangeaddict 2:9c0a83c5ded5 198 wait(1);
melangeaddict 2:9c0a83c5ded5 199 } else {
melangeaddict 2:9c0a83c5ded5 200 current_mode=tuning_mode;
melangeaddict 2:9c0a83c5ded5 201 lcd.cls();
melangeaddict 2:9c0a83c5ded5 202 lcd.printf("Tuning Mode");
melangeaddict 2:9c0a83c5ded5 203 wait(1);
melangeaddict 2:9c0a83c5ded5 204 }
melangeaddict 2:9c0a83c5ded5 205 setup_buttons();
melangeaddict 2:9c0a83c5ded5 206 }
melangeaddict 2:9c0a83c5ded5 207 //***************************************************
melangeaddict 2:9c0a83c5ded5 208 void stop() {
melangeaddict 2:9c0a83c5ded5 209 start_tuning=false;
melangeaddict 2:9c0a83c5ded5 210 }
melangeaddict 2:9c0a83c5ded5 211 //***************************************************
melangeaddict 2:9c0a83c5ded5 212 void do_nothing() {
melangeaddict 2:9c0a83c5ded5 213 return;
melangeaddict 2:9c0a83c5ded5 214 }
melangeaddict 2:9c0a83c5ded5 215 //***************************************************
melangeaddict 2:9c0a83c5ded5 216 void wind_up() {
melangeaddict 2:9c0a83c5ded5 217 motor.motor_turn(1,10);
melangeaddict 2:9c0a83c5ded5 218 }
melangeaddict 2:9c0a83c5ded5 219 //***************************************************
melangeaddict 2:9c0a83c5ded5 220 void wind_down() {
melangeaddict 2:9c0a83c5ded5 221 motor.motor_turn(0,10);
melangeaddict 2:9c0a83c5ded5 222 }
melangeaddict 2:9c0a83c5ded5 223 //***************************************************
melangeaddict 2:9c0a83c5ded5 224 void device_init() {
melangeaddict 2:9c0a83c5ded5 225 strings string1(1);
melangeaddict 2:9c0a83c5ded5 226 strings string2(2);
melangeaddict 2:9c0a83c5ded5 227 strings string3(3);
melangeaddict 2:9c0a83c5ded5 228 strings string4(4);
melangeaddict 2:9c0a83c5ded5 229 strings string5(5);
melangeaddict 2:9c0a83c5ded5 230 strings string6(6);
melangeaddict 2:9c0a83c5ded5 231 strings_array.push_back(string1);
melangeaddict 2:9c0a83c5ded5 232 strings_array.push_back(string2);
melangeaddict 2:9c0a83c5ded5 233 strings_array.push_back(string3);
melangeaddict 2:9c0a83c5ded5 234 strings_array.push_back(string4);
melangeaddict 2:9c0a83c5ded5 235 strings_array.push_back(string5);
melangeaddict 2:9c0a83c5ded5 236 strings_array.push_back(string6);
melangeaddict 2:9c0a83c5ded5 237
melangeaddict 2:9c0a83c5ded5 238 selected_string=1;
melangeaddict 2:9c0a83c5ded5 239 current_mode=tuning_mode;
melangeaddict 2:9c0a83c5ded5 240 start_tuning=false;
melangeaddict 2:9c0a83c5ded5 241 up=true;
melangeaddict 2:9c0a83c5ded5 242 down=false;
melangeaddict 2:9c0a83c5ded5 243
melangeaddict 2:9c0a83c5ded5 244 button_init();
melangeaddict 2:9c0a83c5ded5 245
melangeaddict 2:9c0a83c5ded5 246 output_menu();
melangeaddict 2:9c0a83c5ded5 247 }
melangeaddict 2:9c0a83c5ded5 248 //***************************************************
melangeaddict 2:9c0a83c5ded5 249 void motor_calibration() {
melangeaddict 2:9c0a83c5ded5 250 lcd.cls();
melangeaddict 2:9c0a83c5ded5 251 lcd.printf("Calibrate Motor");
melangeaddict 2:9c0a83c5ded5 252
melangeaddict 2:9c0a83c5ded5 253 float freq=0, freq_up=0, freq_down=0;
melangeaddict 2:9c0a83c5ded5 254 bool done=false;
melangeaddict 2:9c0a83c5ded5 255 lcd.cls();
melangeaddict 2:9c0a83c5ded5 256 lcd.printf("Please pluck\nstring");
melangeaddict 2:9c0a83c5ded5 257
melangeaddict 2:9c0a83c5ded5 258 //motor.motor_turn(up,25)//TODO: Adjust the number of steps here
melangeaddict 2:9c0a83c5ded5 259 //On second thought, we don't need to tune up and down for this, we can find the current frequency
melangeaddict 2:9c0a83c5ded5 260 //and then turn the peg for the two frequencies!
melangeaddict 2:9c0a83c5ded5 261 while (!done) {
melangeaddict 2:9c0a83c5ded5 262 freq=guitar.find_frequency();
melangeaddict 2:9c0a83c5ded5 263
melangeaddict 2:9c0a83c5ded5 264 if (check_threshold(freq)) {
melangeaddict 2:9c0a83c5ded5 265 freq_up=freq;
melangeaddict 2:9c0a83c5ded5 266 done=true;
melangeaddict 2:9c0a83c5ded5 267 }
melangeaddict 2:9c0a83c5ded5 268 }
melangeaddict 2:9c0a83c5ded5 269 motor.motor_turn(down,25);//TODO: Adjust the number of steps here
melangeaddict 2:9c0a83c5ded5 270 done=false;
melangeaddict 2:9c0a83c5ded5 271 while (!done) {
melangeaddict 2:9c0a83c5ded5 272 freq=guitar.find_frequency();
melangeaddict 2:9c0a83c5ded5 273
melangeaddict 2:9c0a83c5ded5 274 if (check_threshold(freq)) {
melangeaddict 2:9c0a83c5ded5 275 freq_down=freq;
melangeaddict 2:9c0a83c5ded5 276 done=true;
melangeaddict 2:9c0a83c5ded5 277 }
melangeaddict 2:9c0a83c5ded5 278 }
melangeaddict 2:9c0a83c5ded5 279
melangeaddict 2:9c0a83c5ded5 280 if (freq_up<freq_down) {
melangeaddict 2:9c0a83c5ded5 281 down=true;
melangeaddict 2:9c0a83c5ded5 282 up=false;
melangeaddict 2:9c0a83c5ded5 283 }
melangeaddict 2:9c0a83c5ded5 284
melangeaddict 2:9c0a83c5ded5 285 lcd.cls();
melangeaddict 2:9c0a83c5ded5 286 lcd.printf("Calibration Done");
melangeaddict 2:9c0a83c5ded5 287 }
melangeaddict 2:9c0a83c5ded5 288 //**********************************************
melangeaddict 2:9c0a83c5ded5 289 bool check_threshold(float freq) {
melangeaddict 2:9c0a83c5ded5 290 if (freq>500) {
melangeaddict 2:9c0a83c5ded5 291 lcd.cls();
melangeaddict 2:9c0a83c5ded5 292 lcd.printf("Pluck string \nagain");
melangeaddict 2:9c0a83c5ded5 293 return false;
melangeaddict 2:9c0a83c5ded5 294 } else
melangeaddict 2:9c0a83c5ded5 295 return true;
melangeaddict 2:9c0a83c5ded5 296 }