Evan Zhang / Mbed 2 deprecated StepperMotorSong4180

Dependencies:   mbed mbed-rtos SDFileSystem11

Committer:
aurora_aeterna
Date:
Mon May 03 17:27:51 2021 +0000
Revision:
8:202142fffa4e
Parent:
7:dd65856c3982
Child:
9:3e69e012c73a
with bluetooth song select

Who changed what in which revision?

UserRevisionLine numberNew contents of line
cawald18 7:dd65856c3982 1 /*
cawald18 7:dd65856c3982 2 ECE 4180 Project - Stepper motor songs
cawald18 7:dd65856c3982 3 Conner Awald and Evan Zhang
cawald18 7:dd65856c3982 4
cawald18 7:dd65856c3982 5 TO-DO: The program does not exit gracefully when reaching the end of the file.
cawald18 7:dd65856c3982 6 We should add a character that indicates the end of the file to the program.
cawald18 7:dd65856c3982 7
cawald18 7:dd65856c3982 8 Also need to add bluetooth control so the user can select a file to play from preinstalled songs
cawald18 7:dd65856c3982 9 maybe also add stop start controls?
cawald18 7:dd65856c3982 10
cawald18 7:dd65856c3982 11 */
cawald18 7:dd65856c3982 12
cawald18 0:6cc2c1f459f1 13 #include "mbed.h"
cawald18 0:6cc2c1f459f1 14 #include "rtos.h"
cawald18 1:ddbed1542633 15 #include "SDFileSystem.h"
cawald18 1:ddbed1542633 16 #include <string>
cawald18 1:ddbed1542633 17 #include <sstream>
cawald18 1:ddbed1542633 18 #include <iostream>
cawald18 1:ddbed1542633 19 #include <cstdlib>
cawald18 1:ddbed1542633 20
cawald18 0:6cc2c1f459f1 21 Thread motor;
aurora_aeterna 8:202142fffa4e 22 Thread tpause;
aurora_aeterna 8:202142fffa4e 23
cawald18 1:ddbed1542633 24 SDFileSystem sd(p5, p6, p7, p8, "sd");
aurora_aeterna 8:202142fffa4e 25 Serial blue(p13,p14);
cawald18 0:6cc2c1f459f1 26 Serial pc(USBTX, USBRX); // tx, rx
cawald18 7:dd65856c3982 27
cawald18 7:dd65856c3982 28 class Note { //I use this to create a note object which contains
cawald18 7:dd65856c3982 29 // The pitch, starting time, and duration(stop) of the note
cawald18 1:ddbed1542633 30 public:
cawald18 1:ddbed1542633 31 int midiNote;
cawald18 1:ddbed1542633 32 float start;
cawald18 1:ddbed1542633 33 float stop;
cawald18 1:ddbed1542633 34 Note(int midi, float sta, float sto) {
cawald18 1:ddbed1542633 35 start = sta;
cawald18 1:ddbed1542633 36 stop = sto;
cawald18 1:ddbed1542633 37 midiNote = midi;
cawald18 1:ddbed1542633 38 }
cawald18 1:ddbed1542633 39 };
cawald18 1:ddbed1542633 40
aurora_aeterna 8:202142fffa4e 41 volatile int pause = 0;
cawald18 0:6cc2c1f459f1 42
cawald18 7:dd65856c3982 43 DigitalOut led1(LED2); //Used simply for debugging, could add functionailty
cawald18 7:dd65856c3982 44 // So the led lights up when the corresponding motor is playing
aurora_aeterna 8:202142fffa4e 45 DigitalOut led2(LED3);
aurora_aeterna 8:202142fffa4e 46 DigitalOut led3(LED4);
aurora_aeterna 8:202142fffa4e 47
cawald18 7:dd65856c3982 48 DigitalOut f1(p21); //Flipper functions used to generate tones
cawald18 5:bc7213111da0 49 DigitalOut f2(p22);
cawald18 5:bc7213111da0 50 DigitalOut f3(p23);
cawald18 7:dd65856c3982 51
cawald18 7:dd65856c3982 52 DigitalOut m1e(p17); //THIS ENABLES THE MOTOR DRIVER PINS. It is important to turn
cawald18 7:dd65856c3982 53 // it off when the motor is not playing a note because
cawald18 7:dd65856c3982 54 //the motor will waste power otherwise in the idle state
cawald18 6:2450dc369670 55 DigitalOut m2e(p18);
cawald18 6:2450dc369670 56 DigitalOut m3e(p19);
cawald18 7:dd65856c3982 57
cawald18 7:dd65856c3982 58 Ticker t1; //These are the ticker functions that call the flip functions
cawald18 5:bc7213111da0 59 Ticker t2;
cawald18 5:bc7213111da0 60 Ticker t3;
cawald18 7:dd65856c3982 61
cawald18 7:dd65856c3982 62 float motor1stop; //These are the times each motor is going to stop at in seconds
cawald18 5:bc7213111da0 63 float motor2stop;
cawald18 5:bc7213111da0 64 float motor3stop;
cawald18 4:f14ca9203f62 65
aurora_aeterna 8:202142fffa4e 66 char *targmatrix = "/sd/Zelda/notesmatrix.txt"; // testing
aurora_aeterna 8:202142fffa4e 67 char *targstart = "/sd/Zelda/notesstart.txt";
aurora_aeterna 8:202142fffa4e 68 char *targfinish = "/sd/Zelda/notesfinish.txt";
aurora_aeterna 8:202142fffa4e 69
cawald18 7:dd65856c3982 70 Timer motor1timer; //Used to keep track of the time
cawald18 7:dd65856c3982 71 void flip1() //These flip the output pins, generating a pulse
cawald18 5:bc7213111da0 72 {
cawald18 5:bc7213111da0 73 f1 = !f1;
cawald18 5:bc7213111da0 74 }
cawald18 5:bc7213111da0 75 void flip2()
cawald18 5:bc7213111da0 76 {
cawald18 5:bc7213111da0 77 f2 = !f2;
cawald18 5:bc7213111da0 78 }
cawald18 5:bc7213111da0 79 void flip3(){
cawald18 5:bc7213111da0 80 f3 = !f3;
cawald18 5:bc7213111da0 81 }
cawald18 5:bc7213111da0 82 /*
cawald18 5:bc7213111da0 83 Takes the midi number in from the array and then converts it to a frequency in hz;
cawald18 5:bc7213111da0 84 */
cawald18 5:bc7213111da0 85 float midi2freq(float midi){
cawald18 5:bc7213111da0 86 return 440.0*powf(2.0, (midi-69)/12);
cawald18 5:bc7213111da0 87 }
cawald18 5:bc7213111da0 88
aurora_aeterna 8:202142fffa4e 89 // bluetooth pause thread
aurora_aeterna 8:202142fffa4e 90
aurora_aeterna 8:202142fffa4e 91 void Bpause(void const *arguments){
aurora_aeterna 8:202142fffa4e 92 while(1){
aurora_aeterna 8:202142fffa4e 93 char bnum = 0;
aurora_aeterna 8:202142fffa4e 94 char bhit = 0;
aurora_aeterna 8:202142fffa4e 95 if (blue.getc()=='!'){
aurora_aeterna 8:202142fffa4e 96 if (blue.getc()=='B'){
aurora_aeterna 8:202142fffa4e 97 bnum = blue.getc(); //button number
aurora_aeterna 8:202142fffa4e 98 bhit = blue.getc(); //1=hit, 0=release
aurora_aeterna 8:202142fffa4e 99 if (blue.getc()==char(~('!' + 'B' + bnum + bhit))) { //checksum OK?
aurora_aeterna 8:202142fffa4e 100 switch (bnum) {
aurora_aeterna 8:202142fffa4e 101 case '7': //button 7 left arrow play
aurora_aeterna 8:202142fffa4e 102 pause = 0;
aurora_aeterna 8:202142fffa4e 103 break;
aurora_aeterna 8:202142fffa4e 104 case '8': //button 8 right arrow pause
aurora_aeterna 8:202142fffa4e 105 pause = 1;
aurora_aeterna 8:202142fffa4e 106 break;
aurora_aeterna 8:202142fffa4e 107 default:
aurora_aeterna 8:202142fffa4e 108 break;
aurora_aeterna 8:202142fffa4e 109 }
aurora_aeterna 8:202142fffa4e 110 }
aurora_aeterna 8:202142fffa4e 111 }
aurora_aeterna 8:202142fffa4e 112 }
aurora_aeterna 8:202142fffa4e 113 Thread::wait(500);
aurora_aeterna 8:202142fffa4e 114 }
aurora_aeterna 8:202142fffa4e 115 }
aurora_aeterna 8:202142fffa4e 116
aurora_aeterna 8:202142fffa4e 117 // bluetooth input parsing function
aurora_aeterna 8:202142fffa4e 118
aurora_aeterna 8:202142fffa4e 119 int bluehelp(){
aurora_aeterna 8:202142fffa4e 120 char bnum = 0;
aurora_aeterna 8:202142fffa4e 121 char bhit = 0;
aurora_aeterna 8:202142fffa4e 122 if (blue.getc()=='!'){
aurora_aeterna 8:202142fffa4e 123 if (blue.getc()=='B'){
aurora_aeterna 8:202142fffa4e 124 bnum = blue.getc(); //button number
aurora_aeterna 8:202142fffa4e 125 bhit = blue.getc(); //1=hit, 0=release
aurora_aeterna 8:202142fffa4e 126 if (blue.getc()==char(~('!' + 'B' + bnum + bhit))) { //checksum OK?
aurora_aeterna 8:202142fffa4e 127 switch (bnum) {
aurora_aeterna 8:202142fffa4e 128 case '1': //number button 1 zelda
aurora_aeterna 8:202142fffa4e 129 targmatrix = "/sd/Zelda/notesmatrix.txt";
aurora_aeterna 8:202142fffa4e 130 targstart = "/sd/Zelda/notesstart.txt";
aurora_aeterna 8:202142fffa4e 131 targfinish = "/sd/Zelda/notesfinish.txt";
aurora_aeterna 8:202142fffa4e 132 return 1;
aurora_aeterna 8:202142fffa4e 133 case '2': //number button 2 meg
aurora_aeterna 8:202142fffa4e 134 targmatrix = "/sd/meglovania/notesmatrix.txt";
aurora_aeterna 8:202142fffa4e 135 targstart = "/sd/meglovania/notesstart.txt";
aurora_aeterna 8:202142fffa4e 136 targfinish = "/sd/meglovania/notesfinish.txt";
aurora_aeterna 8:202142fffa4e 137 return 1;
aurora_aeterna 8:202142fffa4e 138 case '3': //number button 3 wii
aurora_aeterna 8:202142fffa4e 139 targmatrix = "/sd/wii/notesmatrix.txt";
aurora_aeterna 8:202142fffa4e 140 targstart = "/sd/wii/notesstart.txt";
aurora_aeterna 8:202142fffa4e 141 targfinish = "/sd/wii/notesfinish.txt";
aurora_aeterna 8:202142fffa4e 142 return 1;
aurora_aeterna 8:202142fffa4e 143 case '4': //number button 4 fight
aurora_aeterna 8:202142fffa4e 144 targmatrix = "/sd/FightSong/notesmatrix.txt";
aurora_aeterna 8:202142fffa4e 145 targstart = "/sd/FightSong/notesstart.txt";
aurora_aeterna 8:202142fffa4e 146 targfinish = "/sd/FightSong/notesfinish.txt";
aurora_aeterna 8:202142fffa4e 147 return 1;
aurora_aeterna 8:202142fffa4e 148 case '5': //number 5 reset
aurora_aeterna 8:202142fffa4e 149 return 5;
aurora_aeterna 8:202142fffa4e 150 default:
aurora_aeterna 8:202142fffa4e 151 break;
aurora_aeterna 8:202142fffa4e 152 }
aurora_aeterna 8:202142fffa4e 153 }
aurora_aeterna 8:202142fffa4e 154 }
aurora_aeterna 8:202142fffa4e 155 }
aurora_aeterna 8:202142fffa4e 156 return -1;
aurora_aeterna 8:202142fffa4e 157 }
aurora_aeterna 8:202142fffa4e 158
cawald18 0:6cc2c1f459f1 159 int main() {
aurora_aeterna 8:202142fffa4e 160 start:
cawald18 7:dd65856c3982 161 f1 = 0; //Initialize everything
cawald18 6:2450dc369670 162 f2 = 0;
cawald18 6:2450dc369670 163 f3 = 0;
cawald18 6:2450dc369670 164 m1e = 0;
cawald18 6:2450dc369670 165 m2e = 0;
cawald18 6:2450dc369670 166 m3e = 0;
cawald18 6:2450dc369670 167 motor1stop = 0;
cawald18 6:2450dc369670 168 motor2stop = 0;
cawald18 6:2450dc369670 169 motor3stop = 0;
aurora_aeterna 8:202142fffa4e 170
aurora_aeterna 8:202142fffa4e 171 Thread Thread(Bpause); // may not work
cawald18 6:2450dc369670 172
cawald18 7:dd65856c3982 173 bool holdNotes = 0; //Stop reading notes file once we have the next note
cawald18 7:dd65856c3982 174 bool holdStart = 0; //Stop reading start times once we have parsed the starrt
cawald18 2:39d41fd0f52b 175 bool holdFinish = 0; //Stop reading in finish times
cawald18 7:dd65856c3982 176 pc.baud(115200); //Baud rate used for debugging if needed
cawald18 7:dd65856c3982 177 const char * d; //This is old when I was messing around with this stuff
cawald18 7:dd65856c3982 178 //But im actually not sure if I used the names later, should probably check
cawald18 1:ddbed1542633 179 std::string str = "123.4567";
cawald18 1:ddbed1542633 180 d = str.c_str();
cawald18 1:ddbed1542633 181 // convert string to float
cawald18 1:ddbed1542633 182 float num_float = std::atof(d);
cawald18 1:ddbed1542633 183
cawald18 1:ddbed1542633 184 // convert string to double
cawald18 6:2450dc369670 185 //pc.printf("%f\n", num_float-1.0);
cawald18 7:dd65856c3982 186 pc.printf("Im Alive");
cawald18 1:ddbed1542633 187 int temp = 0;
cawald18 1:ddbed1542633 188
cawald18 1:ddbed1542633 189 pc.printf("Hello World!");
cawald18 1:ddbed1542633 190 string output = "";
aurora_aeterna 8:202142fffa4e 191
aurora_aeterna 8:202142fffa4e 192 // select the song with bluetooth
aurora_aeterna 8:202142fffa4e 193 songselect:
aurora_aeterna 8:202142fffa4e 194 led2 = 1;
aurora_aeterna 8:202142fffa4e 195 int songret = bluehelp();
aurora_aeterna 8:202142fffa4e 196 if (songret != 1)
aurora_aeterna 8:202142fffa4e 197 {
aurora_aeterna 8:202142fffa4e 198 led2 = !led2;
aurora_aeterna 8:202142fffa4e 199 goto songselect;
aurora_aeterna 8:202142fffa4e 200 }
aurora_aeterna 8:202142fffa4e 201 // blue helper function should have selected a song for us by here
aurora_aeterna 8:202142fffa4e 202 pc.printf(targmatrix);
aurora_aeterna 8:202142fffa4e 203 FILE *fpn = fopen(targmatrix, "r"); //Fpn is a pointer to the notes file that contains the note values
aurora_aeterna 8:202142fffa4e 204 FILE *fpstart = fopen(targstart, "r"); //Fpstart is a pointer to the file on the sd card that contains the start times
aurora_aeterna 8:202142fffa4e 205 FILE *fpfinish = fopen(targfinish,"r"); //Fpfinish is a pointer to the file on the sd card that says how long each note should last
aurora_aeterna 8:202142fffa4e 206 unsigned char c;
cawald18 1:ddbed1542633 207
cawald18 7:dd65856c3982 208 Note myNote = Note(0, 0, 0); //Create a blank note
cawald18 7:dd65856c3982 209 motor1timer.start(); //Start the timer
aurora_aeterna 8:202142fffa4e 210 led3 = 1;
cawald18 7:dd65856c3982 211 while (!feof(fpn)){ // while not end of file, keep goig
aurora_aeterna 8:202142fffa4e 212 while(pause){
aurora_aeterna 8:202142fffa4e 213 Thread::wait(100);
aurora_aeterna 8:202142fffa4e 214 }
cawald18 7:dd65856c3982 215 while(!holdNotes) { //Make sure we haven't completed the note section yet
cawald18 1:ddbed1542633 216 c = fgetc(fpn); // get a character/byte from the file
cawald18 7:dd65856c3982 217 if(c == ','){ //If the character is a comma, we have parsed the full note
cawald18 1:ddbed1542633 218 stringstream degree(output);
cawald18 7:dd65856c3982 219 degree >> temp; //These are weird names I got from the example code I copied
cawald18 7:dd65856c3982 220 // but basically this converts a string into a float
cawald18 6:2450dc369670 221 //pc.printf("%d\n", temp);
cawald18 6:2450dc369670 222 myNote.midiNote = temp;
cawald18 1:ddbed1542633 223 output = "";
cawald18 2:39d41fd0f52b 224 holdNotes = 1;
cawald18 1:ddbed1542633 225 } else {
cawald18 7:dd65856c3982 226 output += c; //If this isn't the end of the file, lets add the character we read onto the end
cawald18 1:ddbed1542633 227 }
cawald18 2:39d41fd0f52b 228 }
cawald18 6:2450dc369670 229
cawald18 7:dd65856c3982 230 output = ""; //Reset the output
cawald18 7:dd65856c3982 231 while(!holdStart) { //Do the same thing as above but for the start times
cawald18 2:39d41fd0f52b 232 c = fgetc(fpstart);
cawald18 2:39d41fd0f52b 233 if(c == ','){
cawald18 2:39d41fd0f52b 234 d = output.c_str();
cawald18 2:39d41fd0f52b 235 num_float = std::atof(d);
cawald18 6:2450dc369670 236 //pc.printf("%f\n", num_float);
cawald18 2:39d41fd0f52b 237 output = "";
cawald18 2:39d41fd0f52b 238 myNote.start = num_float;
cawald18 2:39d41fd0f52b 239 holdStart = 1;
cawald18 2:39d41fd0f52b 240 } else {
cawald18 2:39d41fd0f52b 241 output+= c;
cawald18 2:39d41fd0f52b 242 }
cawald18 1:ddbed1542633 243
cawald18 2:39d41fd0f52b 244 }
cawald18 1:ddbed1542633 245 output = "";
cawald18 7:dd65856c3982 246 while(!holdFinish){ //Do the same thing as above with durations
cawald18 1:ddbed1542633 247 c = fgetc(fpfinish);
cawald18 1:ddbed1542633 248 if(c == ','){
cawald18 1:ddbed1542633 249 d = output.c_str();
cawald18 1:ddbed1542633 250 num_float = std::atof(d);
cawald18 6:2450dc369670 251 //pc.printf("%f\n", num_float);
cawald18 1:ddbed1542633 252 output = "";
cawald18 2:39d41fd0f52b 253 myNote.stop = num_float;
cawald18 2:39d41fd0f52b 254 holdFinish = 1;
cawald18 1:ddbed1542633 255 } else {
cawald18 1:ddbed1542633 256 output+= c;
cawald18 1:ddbed1542633 257 }
cawald18 1:ddbed1542633 258
cawald18 7:dd65856c3982 259 } //ONCE WE REACH THIS POINT ALL PARTS OF THE NOTE OBJECT SHOULD BE SET and USABLE
cawald18 7:dd65856c3982 260
cawald18 7:dd65856c3982 261 /*
cawald18 7:dd65856c3982 262 The next three functions check to see if the motors stop time has past
cawald18 7:dd65856c3982 263 or will pass in the next ms. If so, it stops the motor from playing and
cawald18 7:dd65856c3982 264 disables the pin.
cawald18 7:dd65856c3982 265 */
cawald18 7:dd65856c3982 266 if((motor1stop-.001)< motor1timer.read()) {
cawald18 6:2450dc369670 267 t1.detach();
cawald18 6:2450dc369670 268 m1e = 0;
cawald18 6:2450dc369670 269 }
cawald18 7:dd65856c3982 270 if((motor2stop-.001)< motor1timer.read()){
cawald18 6:2450dc369670 271 t2.detach();
cawald18 6:2450dc369670 272 m2e = 0;
cawald18 6:2450dc369670 273 }
cawald18 7:dd65856c3982 274 if((motor3stop-.001)< motor1timer.read()) {
cawald18 6:2450dc369670 275 t3.detach();
cawald18 6:2450dc369670 276 m3e = 0;
cawald18 0:6cc2c1f459f1 277 }
cawald18 2:39d41fd0f52b 278
cawald18 7:dd65856c3982 279
cawald18 7:dd65856c3982 280 /*
cawald18 7:dd65856c3982 281 This now looks at the note object we currently have parsed in and sees
cawald18 7:dd65856c3982 282 if it is time to try and assign it to a motor to be played. If it is not time,
cawald18 7:dd65856c3982 283 we are simply going to keep looping until it is time.
cawald18 7:dd65856c3982 284 */
cawald18 6:2450dc369670 285 if(myNote.start <= motor1timer.read()){
cawald18 7:dd65856c3982 286 if(motor1stop-.002 < motor1timer.read()) { //Check to see if the motor has stopped playing or is going to stop playing
cawald18 6:2450dc369670 287 t1.attach(&flip1, .5/midi2freq(myNote.midiNote)); //
cawald18 7:dd65856c3982 288 motor1stop = myNote.stop+motor1timer.read(); //Set the new stop time to be the current time plus the duration of the note
cawald18 7:dd65856c3982 289 m1e = 1; //Enable the note
cawald18 7:dd65856c3982 290 holdNotes = 0; //Reset the notes control to enable reading the next note
cawald18 6:2450dc369670 291 holdStart = 0;
cawald18 6:2450dc369670 292 holdFinish = 0;
cawald18 7:dd65856c3982 293 } else if(motor2stop-.002 < motor1timer.read()) {
cawald18 6:2450dc369670 294 t2.attach(&flip2, .5/midi2freq(myNote.midiNote));
cawald18 6:2450dc369670 295 motor2stop = myNote.stop+motor1timer.read();
cawald18 6:2450dc369670 296 m2e = 1;
cawald18 6:2450dc369670 297 holdNotes = 0;
cawald18 6:2450dc369670 298 holdStart = 0;
cawald18 6:2450dc369670 299 holdFinish = 0;
cawald18 7:dd65856c3982 300 } else if(motor3stop-.002 < motor1timer.read()) {
cawald18 6:2450dc369670 301 t3.attach(&flip3, .5/midi2freq(myNote.midiNote));
cawald18 6:2450dc369670 302 motor3stop = myNote.stop+motor1timer.read();
cawald18 6:2450dc369670 303 m3e = 1;
cawald18 6:2450dc369670 304 holdNotes = 0;
cawald18 6:2450dc369670 305 holdStart = 0;
cawald18 6:2450dc369670 306 holdFinish = 0;
cawald18 7:dd65856c3982 307 } else { //If all three motors are playing something and it is time to play the new note,
cawald18 7:dd65856c3982 308 // We simply do nothing with it and skip it
cawald18 6:2450dc369670 309 holdNotes = 0;
cawald18 6:2450dc369670 310 holdStart = 0;
cawald18 6:2450dc369670 311 holdFinish = 0;
cawald18 6:2450dc369670 312 }
cawald18 6:2450dc369670 313 } //We have now finished assigning the note to be played
cawald18 6:2450dc369670 314 led1 = !led1;
cawald18 6:2450dc369670 315
aurora_aeterna 8:202142fffa4e 316 //if(!feof(fpn)) goto start;
cawald18 6:2450dc369670 317
cawald18 6:2450dc369670 318 } //End of while loop for playing
cawald18 6:2450dc369670 319 motor1stop = 0;
cawald18 6:2450dc369670 320 motor2stop = 0;
cawald18 6:2450dc369670 321 motor3stop = 0;
aurora_aeterna 8:202142fffa4e 322 // close all the files before trying reopen
aurora_aeterna 8:202142fffa4e 323 pc.printf("attempt to close files\n");
aurora_aeterna 8:202142fffa4e 324 fclose(fpn);
aurora_aeterna 8:202142fffa4e 325 fclose(fpstart);
aurora_aeterna 8:202142fffa4e 326 fclose(fpfinish);
aurora_aeterna 8:202142fffa4e 327 pc.printf("files closed");
aurora_aeterna 8:202142fffa4e 328 //while(bluehelp() != 5){
aurora_aeterna 8:202142fffa4e 329 // Thread::wait(100);
aurora_aeterna 8:202142fffa4e 330 // }
aurora_aeterna 8:202142fffa4e 331 //goto start;
cawald18 0:6cc2c1f459f1 332 }