Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed mbed-rtos SDFileSystem11
main.cpp@7:dd65856c3982, 2021-05-02 (annotated)
- Committer:
- cawald18
- Date:
- Sun May 02 20:07:22 2021 +0000
- Revision:
- 7:dd65856c3982
- Parent:
- 6:2450dc369670
Base Version 1.0;
Who changed what in which revision?
| User | Revision | Line number | New 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; |
| cawald18 | 1:ddbed1542633 | 22 | SDFileSystem sd(p5, p6, p7, p8, "sd"); |
| cawald18 | 0:6cc2c1f459f1 | 23 | Serial pc(USBTX, USBRX); // tx, rx |
| cawald18 | 7:dd65856c3982 | 24 | |
| cawald18 | 7:dd65856c3982 | 25 | class Note { //I use this to create a note object which contains |
| cawald18 | 7:dd65856c3982 | 26 | // The pitch, starting time, and duration(stop) of the note |
| cawald18 | 1:ddbed1542633 | 27 | public: |
| cawald18 | 1:ddbed1542633 | 28 | int midiNote; |
| cawald18 | 1:ddbed1542633 | 29 | float start; |
| cawald18 | 1:ddbed1542633 | 30 | float stop; |
| cawald18 | 1:ddbed1542633 | 31 | Note(int midi, float sta, float sto) { |
| cawald18 | 1:ddbed1542633 | 32 | start = sta; |
| cawald18 | 1:ddbed1542633 | 33 | stop = sto; |
| cawald18 | 1:ddbed1542633 | 34 | midiNote = midi; |
| cawald18 | 1:ddbed1542633 | 35 | } |
| cawald18 | 1:ddbed1542633 | 36 | }; |
| cawald18 | 1:ddbed1542633 | 37 | |
| cawald18 | 0:6cc2c1f459f1 | 38 | |
| cawald18 | 0:6cc2c1f459f1 | 39 | |
| cawald18 | 7:dd65856c3982 | 40 | DigitalOut led1(LED2); //Used simply for debugging, could add functionailty |
| cawald18 | 7:dd65856c3982 | 41 | // So the led lights up when the corresponding motor is playing |
| cawald18 | 7:dd65856c3982 | 42 | DigitalOut f1(p21); //Flipper functions used to generate tones |
| cawald18 | 5:bc7213111da0 | 43 | DigitalOut f2(p22); |
| cawald18 | 5:bc7213111da0 | 44 | DigitalOut f3(p23); |
| cawald18 | 7:dd65856c3982 | 45 | |
| cawald18 | 7:dd65856c3982 | 46 | DigitalOut m1e(p17); //THIS ENABLES THE MOTOR DRIVER PINS. It is important to turn |
| cawald18 | 7:dd65856c3982 | 47 | // it off when the motor is not playing a note because |
| cawald18 | 7:dd65856c3982 | 48 | //the motor will waste power otherwise in the idle state |
| cawald18 | 6:2450dc369670 | 49 | DigitalOut m2e(p18); |
| cawald18 | 6:2450dc369670 | 50 | DigitalOut m3e(p19); |
| cawald18 | 7:dd65856c3982 | 51 | |
| cawald18 | 7:dd65856c3982 | 52 | Ticker t1; //These are the ticker functions that call the flip functions |
| cawald18 | 5:bc7213111da0 | 53 | Ticker t2; |
| cawald18 | 5:bc7213111da0 | 54 | Ticker t3; |
| cawald18 | 7:dd65856c3982 | 55 | |
| cawald18 | 7:dd65856c3982 | 56 | float motor1stop; //These are the times each motor is going to stop at in seconds |
| cawald18 | 5:bc7213111da0 | 57 | float motor2stop; |
| cawald18 | 5:bc7213111da0 | 58 | float motor3stop; |
| cawald18 | 4:f14ca9203f62 | 59 | |
| cawald18 | 7:dd65856c3982 | 60 | Timer motor1timer; //Used to keep track of the time |
| cawald18 | 7:dd65856c3982 | 61 | void flip1() //These flip the output pins, generating a pulse |
| cawald18 | 5:bc7213111da0 | 62 | { |
| cawald18 | 5:bc7213111da0 | 63 | f1 = !f1; |
| cawald18 | 5:bc7213111da0 | 64 | } |
| cawald18 | 5:bc7213111da0 | 65 | void flip2() |
| cawald18 | 5:bc7213111da0 | 66 | { |
| cawald18 | 5:bc7213111da0 | 67 | f2 = !f2; |
| cawald18 | 5:bc7213111da0 | 68 | } |
| cawald18 | 5:bc7213111da0 | 69 | void flip3(){ |
| cawald18 | 5:bc7213111da0 | 70 | f3 = !f3; |
| cawald18 | 5:bc7213111da0 | 71 | } |
| cawald18 | 5:bc7213111da0 | 72 | /* |
| cawald18 | 5:bc7213111da0 | 73 | Takes the midi number in from the array and then converts it to a frequency in hz; |
| cawald18 | 5:bc7213111da0 | 74 | */ |
| cawald18 | 5:bc7213111da0 | 75 | float midi2freq(float midi){ |
| cawald18 | 5:bc7213111da0 | 76 | return 440.0*powf(2.0, (midi-69)/12); |
| cawald18 | 5:bc7213111da0 | 77 | } |
| cawald18 | 5:bc7213111da0 | 78 | |
| cawald18 | 0:6cc2c1f459f1 | 79 | int main() { |
| cawald18 | 7:dd65856c3982 | 80 | f1 = 0; //Initialize everything |
| cawald18 | 6:2450dc369670 | 81 | f2 = 0; |
| cawald18 | 6:2450dc369670 | 82 | f3 = 0; |
| cawald18 | 6:2450dc369670 | 83 | m1e = 0; |
| cawald18 | 6:2450dc369670 | 84 | m2e = 0; |
| cawald18 | 6:2450dc369670 | 85 | m3e = 0; |
| cawald18 | 6:2450dc369670 | 86 | motor1stop = 0; |
| cawald18 | 6:2450dc369670 | 87 | motor2stop = 0; |
| cawald18 | 6:2450dc369670 | 88 | motor3stop = 0; |
| cawald18 | 6:2450dc369670 | 89 | |
| cawald18 | 7:dd65856c3982 | 90 | bool holdNotes = 0; //Stop reading notes file once we have the next note |
| cawald18 | 7:dd65856c3982 | 91 | bool holdStart = 0; //Stop reading start times once we have parsed the starrt |
| cawald18 | 2:39d41fd0f52b | 92 | bool holdFinish = 0; //Stop reading in finish times |
| cawald18 | 7:dd65856c3982 | 93 | pc.baud(115200); //Baud rate used for debugging if needed |
| cawald18 | 7:dd65856c3982 | 94 | const char * d; //This is old when I was messing around with this stuff |
| cawald18 | 7:dd65856c3982 | 95 | //But im actually not sure if I used the names later, should probably check |
| cawald18 | 1:ddbed1542633 | 96 | std::string str = "123.4567"; |
| cawald18 | 1:ddbed1542633 | 97 | d = str.c_str(); |
| cawald18 | 1:ddbed1542633 | 98 | // convert string to float |
| cawald18 | 1:ddbed1542633 | 99 | float num_float = std::atof(d); |
| cawald18 | 1:ddbed1542633 | 100 | |
| cawald18 | 1:ddbed1542633 | 101 | // convert string to double |
| cawald18 | 6:2450dc369670 | 102 | //pc.printf("%f\n", num_float-1.0); |
| cawald18 | 7:dd65856c3982 | 103 | pc.printf("Im Alive"); |
| cawald18 | 1:ddbed1542633 | 104 | int temp = 0; |
| cawald18 | 1:ddbed1542633 | 105 | |
| cawald18 | 1:ddbed1542633 | 106 | pc.printf("Hello World!"); |
| cawald18 | 1:ddbed1542633 | 107 | string output = ""; |
| cawald18 | 1:ddbed1542633 | 108 | |
| cawald18 | 7:dd65856c3982 | 109 | FILE *fpn = fopen("/sd/notesmatrix.txt", "r"); //Fpn is a pointer to the notes file that contains the note values |
| cawald18 | 7:dd65856c3982 | 110 | FILE *fpstart = fopen("/sd/notesstart.txt", "r"); //Fpstart is a pointer to the file on the sd card that contains the start times |
| cawald18 | 7:dd65856c3982 | 111 | FILE *fpfinish = fopen("/sd/notesfinish.txt","r"); //Fpfinish is a pointer to the file on the sd card that says how long each note should last |
| cawald18 | 1:ddbed1542633 | 112 | unsigned char c; |
| cawald18 | 6:2450dc369670 | 113 | //pc.printf("I'm here\n"); |
| cawald18 | 7:dd65856c3982 | 114 | Note myNote = Note(0, 0, 0); //Create a blank note |
| cawald18 | 7:dd65856c3982 | 115 | motor1timer.start(); //Start the timer |
| cawald18 | 7:dd65856c3982 | 116 | while (!feof(fpn)){ // while not end of file, keep goig |
| cawald18 | 7:dd65856c3982 | 117 | while(!holdNotes) { //Make sure we haven't completed the note section yet |
| cawald18 | 1:ddbed1542633 | 118 | c = fgetc(fpn); // get a character/byte from the file |
| cawald18 | 7:dd65856c3982 | 119 | if(c == ','){ //If the character is a comma, we have parsed the full note |
| cawald18 | 1:ddbed1542633 | 120 | stringstream degree(output); |
| cawald18 | 7:dd65856c3982 | 121 | degree >> temp; //These are weird names I got from the example code I copied |
| cawald18 | 7:dd65856c3982 | 122 | // but basically this converts a string into a float |
| cawald18 | 6:2450dc369670 | 123 | //pc.printf("%d\n", temp); |
| cawald18 | 6:2450dc369670 | 124 | myNote.midiNote = temp; |
| cawald18 | 1:ddbed1542633 | 125 | output = ""; |
| cawald18 | 2:39d41fd0f52b | 126 | holdNotes = 1; |
| cawald18 | 1:ddbed1542633 | 127 | } else { |
| cawald18 | 7:dd65856c3982 | 128 | output += c; //If this isn't the end of the file, lets add the character we read onto the end |
| cawald18 | 1:ddbed1542633 | 129 | } |
| cawald18 | 2:39d41fd0f52b | 130 | } |
| cawald18 | 6:2450dc369670 | 131 | |
| cawald18 | 7:dd65856c3982 | 132 | output = ""; //Reset the output |
| cawald18 | 7:dd65856c3982 | 133 | while(!holdStart) { //Do the same thing as above but for the start times |
| cawald18 | 2:39d41fd0f52b | 134 | c = fgetc(fpstart); |
| cawald18 | 2:39d41fd0f52b | 135 | if(c == ','){ |
| cawald18 | 2:39d41fd0f52b | 136 | d = output.c_str(); |
| cawald18 | 2:39d41fd0f52b | 137 | num_float = std::atof(d); |
| cawald18 | 6:2450dc369670 | 138 | //pc.printf("%f\n", num_float); |
| cawald18 | 2:39d41fd0f52b | 139 | output = ""; |
| cawald18 | 2:39d41fd0f52b | 140 | myNote.start = num_float; |
| cawald18 | 2:39d41fd0f52b | 141 | holdStart = 1; |
| cawald18 | 2:39d41fd0f52b | 142 | } else { |
| cawald18 | 2:39d41fd0f52b | 143 | output+= c; |
| cawald18 | 2:39d41fd0f52b | 144 | } |
| cawald18 | 1:ddbed1542633 | 145 | |
| cawald18 | 2:39d41fd0f52b | 146 | } |
| cawald18 | 1:ddbed1542633 | 147 | output = ""; |
| cawald18 | 7:dd65856c3982 | 148 | while(!holdFinish){ //Do the same thing as above with durations |
| cawald18 | 1:ddbed1542633 | 149 | c = fgetc(fpfinish); |
| cawald18 | 1:ddbed1542633 | 150 | if(c == ','){ |
| cawald18 | 1:ddbed1542633 | 151 | d = output.c_str(); |
| cawald18 | 1:ddbed1542633 | 152 | num_float = std::atof(d); |
| cawald18 | 6:2450dc369670 | 153 | //pc.printf("%f\n", num_float); |
| cawald18 | 1:ddbed1542633 | 154 | output = ""; |
| cawald18 | 2:39d41fd0f52b | 155 | myNote.stop = num_float; |
| cawald18 | 2:39d41fd0f52b | 156 | holdFinish = 1; |
| cawald18 | 1:ddbed1542633 | 157 | } else { |
| cawald18 | 1:ddbed1542633 | 158 | output+= c; |
| cawald18 | 1:ddbed1542633 | 159 | } |
| cawald18 | 1:ddbed1542633 | 160 | |
| cawald18 | 7:dd65856c3982 | 161 | } //ONCE WE REACH THIS POINT ALL PARTS OF THE NOTE OBJECT SHOULD BE SET and USABLE |
| cawald18 | 7:dd65856c3982 | 162 | |
| cawald18 | 7:dd65856c3982 | 163 | /* |
| cawald18 | 7:dd65856c3982 | 164 | The next three functions check to see if the motors stop time has past |
| cawald18 | 7:dd65856c3982 | 165 | or will pass in the next ms. If so, it stops the motor from playing and |
| cawald18 | 7:dd65856c3982 | 166 | disables the pin. |
| cawald18 | 7:dd65856c3982 | 167 | */ |
| cawald18 | 7:dd65856c3982 | 168 | if((motor1stop-.001)< motor1timer.read()) { |
| cawald18 | 6:2450dc369670 | 169 | t1.detach(); |
| cawald18 | 6:2450dc369670 | 170 | m1e = 0; |
| cawald18 | 6:2450dc369670 | 171 | } |
| cawald18 | 7:dd65856c3982 | 172 | if((motor2stop-.001)< motor1timer.read()){ |
| cawald18 | 6:2450dc369670 | 173 | t2.detach(); |
| cawald18 | 6:2450dc369670 | 174 | m2e = 0; |
| cawald18 | 6:2450dc369670 | 175 | } |
| cawald18 | 7:dd65856c3982 | 176 | if((motor3stop-.001)< motor1timer.read()) { |
| cawald18 | 6:2450dc369670 | 177 | t3.detach(); |
| cawald18 | 6:2450dc369670 | 178 | m3e = 0; |
| cawald18 | 0:6cc2c1f459f1 | 179 | } |
| cawald18 | 2:39d41fd0f52b | 180 | |
| cawald18 | 7:dd65856c3982 | 181 | |
| cawald18 | 7:dd65856c3982 | 182 | /* |
| cawald18 | 7:dd65856c3982 | 183 | This now looks at the note object we currently have parsed in and sees |
| cawald18 | 7:dd65856c3982 | 184 | if it is time to try and assign it to a motor to be played. If it is not time, |
| cawald18 | 7:dd65856c3982 | 185 | we are simply going to keep looping until it is time. |
| cawald18 | 7:dd65856c3982 | 186 | */ |
| cawald18 | 6:2450dc369670 | 187 | if(myNote.start <= motor1timer.read()){ |
| cawald18 | 7:dd65856c3982 | 188 | if(motor1stop-.002 < motor1timer.read()) { //Check to see if the motor has stopped playing or is going to stop playing |
| cawald18 | 6:2450dc369670 | 189 | t1.attach(&flip1, .5/midi2freq(myNote.midiNote)); // |
| cawald18 | 7:dd65856c3982 | 190 | motor1stop = myNote.stop+motor1timer.read(); //Set the new stop time to be the current time plus the duration of the note |
| cawald18 | 7:dd65856c3982 | 191 | m1e = 1; //Enable the note |
| cawald18 | 7:dd65856c3982 | 192 | holdNotes = 0; //Reset the notes control to enable reading the next note |
| cawald18 | 6:2450dc369670 | 193 | holdStart = 0; |
| cawald18 | 6:2450dc369670 | 194 | holdFinish = 0; |
| cawald18 | 7:dd65856c3982 | 195 | } else if(motor2stop-.002 < motor1timer.read()) { |
| cawald18 | 6:2450dc369670 | 196 | t2.attach(&flip2, .5/midi2freq(myNote.midiNote)); |
| cawald18 | 6:2450dc369670 | 197 | motor2stop = myNote.stop+motor1timer.read(); |
| cawald18 | 6:2450dc369670 | 198 | m2e = 1; |
| cawald18 | 6:2450dc369670 | 199 | holdNotes = 0; |
| cawald18 | 6:2450dc369670 | 200 | holdStart = 0; |
| cawald18 | 6:2450dc369670 | 201 | holdFinish = 0; |
| cawald18 | 7:dd65856c3982 | 202 | } else if(motor3stop-.002 < motor1timer.read()) { |
| cawald18 | 6:2450dc369670 | 203 | t3.attach(&flip3, .5/midi2freq(myNote.midiNote)); |
| cawald18 | 6:2450dc369670 | 204 | motor3stop = myNote.stop+motor1timer.read(); |
| cawald18 | 6:2450dc369670 | 205 | m3e = 1; |
| cawald18 | 6:2450dc369670 | 206 | holdNotes = 0; |
| cawald18 | 6:2450dc369670 | 207 | holdStart = 0; |
| cawald18 | 6:2450dc369670 | 208 | holdFinish = 0; |
| cawald18 | 7:dd65856c3982 | 209 | } else { //If all three motors are playing something and it is time to play the new note, |
| cawald18 | 7:dd65856c3982 | 210 | // We simply do nothing with it and skip it |
| cawald18 | 6:2450dc369670 | 211 | holdNotes = 0; |
| cawald18 | 6:2450dc369670 | 212 | holdStart = 0; |
| cawald18 | 6:2450dc369670 | 213 | holdFinish = 0; |
| cawald18 | 6:2450dc369670 | 214 | } |
| cawald18 | 6:2450dc369670 | 215 | } //We have now finished assigning the note to be played |
| cawald18 | 6:2450dc369670 | 216 | led1 = !led1; |
| cawald18 | 6:2450dc369670 | 217 | |
| cawald18 | 6:2450dc369670 | 218 | |
| cawald18 | 6:2450dc369670 | 219 | } //End of while loop for playing |
| cawald18 | 6:2450dc369670 | 220 | motor1stop = 0; |
| cawald18 | 6:2450dc369670 | 221 | motor2stop = 0; |
| cawald18 | 6:2450dc369670 | 222 | motor3stop = 0; |
| cawald18 | 2:39d41fd0f52b | 223 | |
| cawald18 | 2:39d41fd0f52b | 224 | |
| cawald18 | 0:6cc2c1f459f1 | 225 | } |