Evan Zhang / Mbed 2 deprecated StepperMotorSong4180

Dependencies:   mbed mbed-rtos SDFileSystem11

main.cpp

Committer:
cawald18
Date:
2021-05-02
Revision:
7:dd65856c3982
Parent:
6:2450dc369670
Child:
8:202142fffa4e

File content as of revision 7:dd65856c3982:

/*
ECE 4180 Project - Stepper motor songs
Conner Awald and Evan Zhang

TO-DO: The program does not exit gracefully when reaching the end of the file. 
We should add a character that indicates the end of the file to the program.

Also need to add bluetooth control so the user can select a file to play from preinstalled songs
maybe also add stop start controls?

*/

#include "mbed.h"
#include "rtos.h"
#include "SDFileSystem.h"
#include <string>
#include <sstream>
#include <iostream>
#include <cstdlib>

Thread motor;
SDFileSystem sd(p5, p6, p7, p8, "sd");
Serial pc(USBTX, USBRX); // tx, rx

class Note { //I use this to create a note object which contains
            // The pitch, starting time, and duration(stop) of the note
public:
    int midiNote;
    float start;
    float stop;
    Note(int midi, float sta, float sto) {
        start = sta;
        stop = sto;
        midiNote = midi;
        }
    };
        


DigitalOut led1(LED2); //Used simply for debugging, could add functionailty
                        // So the led lights up when the corresponding motor is playing
DigitalOut f1(p21);     //Flipper functions used to generate tones
DigitalOut f2(p22);
DigitalOut f3(p23);

DigitalOut m1e(p17);  //THIS ENABLES THE MOTOR DRIVER PINS. It is important to turn
                        // it off when the motor is not playing a note because
                        //the motor will waste power otherwise in the idle state
DigitalOut m2e(p18);
DigitalOut m3e(p19);

Ticker t1;          //These are the ticker functions that call the flip functions
Ticker t2;
Ticker t3;

float motor1stop; //These are the times each motor is going to stop at in seconds
float motor2stop;
float motor3stop;

Timer motor1timer; //Used to keep track of the time
 void flip1() //These flip the output pins, generating a pulse
{
    f1 = !f1;
}
void flip2()
{
    f2 = !f2;
}
void flip3(){
    f3 = !f3;
}
/*
Takes the midi number in from the array and then converts it to a frequency in hz;
*/
float midi2freq(float midi){
    return 440.0*powf(2.0, (midi-69)/12);
}

int main() {
    f1 = 0; //Initialize everything
    f2 = 0;
    f3 = 0;
    m1e = 0;
    m2e = 0;
    m3e = 0;
    motor1stop = 0;
    motor2stop = 0;
    motor3stop = 0;

     bool holdNotes = 0; //Stop reading notes file once we have the next note
     bool holdStart = 0; //Stop reading start times once we have parsed the starrt
     bool holdFinish = 0; //Stop reading in finish times
     pc.baud(115200); //Baud rate used for debugging if needed
     const char * d;  //This is old when I was messing around with this stuff
                    //But im actually not sure if I used the names later, should probably check
     std::string str = "123.4567";
     d = str.c_str();
    // convert string to float
    float num_float = std::atof(d);

    // convert string to double
    //pc.printf("%f\n", num_float-1.0);
    pc.printf("Im Alive");
    int temp = 0;

    pc.printf("Hello World!");
    string output = "";

    FILE *fpn = fopen("/sd/notesmatrix.txt", "r"); //Fpn is a pointer to the notes file that contains the note values
    FILE *fpstart = fopen("/sd/notesstart.txt", "r"); //Fpstart is a pointer to the file on the sd card that contains the start times
    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
    unsigned char c;
    //pc.printf("I'm here\n");
    Note myNote = Note(0, 0, 0);        //Create a blank note
     motor1timer.start(); //Start the timer
    while (!feof(fpn)){                        // while not end of file, keep goig
        while(!holdNotes) { //Make sure we haven't completed the note section yet
           c = fgetc(fpn);                         // get a character/byte from the file
           if(c == ','){                //If the character is a comma, we have parsed the full note
               stringstream degree(output);
               degree >> temp;         //These are weird names I got from the example code I copied
                                        // but basically this converts a string into a float
               //pc.printf("%d\n", temp);
                myNote.midiNote = temp;
               output = "";
               holdNotes = 1;
           } else {
          output += c;      //If this isn't the end of the file, lets add the character we read onto the end
          }
        }

    output = "";            //Reset the output
        while(!holdStart) { //Do the same thing as above but for the start times
            c = fgetc(fpstart);
            if(c == ','){
                d = output.c_str();
                num_float = std::atof(d);
                //pc.printf("%f\n", num_float);
                output = "";  
                myNote.start = num_float;
                holdStart = 1;
            } else {
                output+= c;
             }
           
        }
    output = "";
    while(!holdFinish){         //Do the same thing as above with durations
        c = fgetc(fpfinish);
        if(c == ','){
            d = output.c_str();
            num_float = std::atof(d);
            //pc.printf("%f\n", num_float);
            output = "";  
            myNote.stop = num_float;
            holdFinish = 1;
        } else {
           output+= c;
           }
           
    } //ONCE WE REACH THIS POINT ALL PARTS OF THE NOTE OBJECT SHOULD BE SET and USABLE
    
    /*
    The next three functions check to see if the motors stop time has past
    or will pass in the next ms. If so, it stops the motor from playing and
    disables the pin.
    */
    if((motor1stop-.001)< motor1timer.read()) {
        t1.detach();
        m1e = 0;
    }
    if((motor2stop-.001)< motor1timer.read()){
        t2.detach();
        m2e = 0;
    }
    if((motor3stop-.001)< motor1timer.read()) {
        t3.detach();
        m3e = 0;
    }
    
    
    /*
    This now looks at the note object we currently have parsed in and sees
    if it is time to try and assign it to a motor to be played. If it is not time,
    we are simply going to keep looping until it is time.
    */
    if(myNote.start <= motor1timer.read()){
            if(motor1stop-.002 < motor1timer.read()) { //Check to see if the motor has stopped playing or is going to stop playing
                t1.attach(&flip1, .5/midi2freq(myNote.midiNote)); //
                motor1stop = myNote.stop+motor1timer.read(); //Set the new stop time to be the current time plus the duration of the note
                m1e = 1; //Enable the note
                holdNotes = 0; //Reset the notes control to enable reading the next note
                holdStart = 0;
                holdFinish = 0;
            } else if(motor2stop-.002 < motor1timer.read()) {
                t2.attach(&flip2, .5/midi2freq(myNote.midiNote));
                motor2stop = myNote.stop+motor1timer.read();
                m2e = 1;
                holdNotes = 0; 
                holdStart = 0;
                holdFinish = 0;
            } else if(motor3stop-.002 < motor1timer.read()) {
                t3.attach(&flip3, .5/midi2freq(myNote.midiNote));
                motor3stop = myNote.stop+motor1timer.read();
                m3e = 1;
                holdNotes = 0; 
                holdStart = 0;
                holdFinish = 0;
            } else { //If all three motors are playing something and it is time to play the new note,
                    // We simply do nothing with it and skip it
                holdNotes = 0; 
                holdStart = 0;
                holdFinish = 0;
                }
    } //We have now finished assigning the note to be played
    led1 = !led1;      
    
    
    } //End of while loop for playing    
    motor1stop = 0;
    motor2stop = 0;
    motor3stop = 0;
      
   
}