Prototype program for the Body Swap Machine

Dependencies:   mbed

main.cpp

Committer:
moshi
Date:
2017-03-25
Revision:
0:19ea917e5234

File content as of revision 0:19ea917e5234:

#include "mbed.h"

/***
/ Body Swap Machine Program 
***/

#define actuatorFrequency 250       //Frequency of actuator vibration[Hz]

#define sscTickerInterval 0.1       //Ticker Interval [s]
#define updateFrequency 20000       //Update frequency for sine wave[Hz]

#define MIN_TIME_DIFF 500           //Chatter elimination delay for tact switch [us]

DigitalOut led1(LED1);
DigitalOut led2(LED2);
DigitalOut led3(LED3);
DigitalOut led4(LED4);

AnalogIn ain1(p15);
AnalogIn ain2(p16);

InterruptIn buttonA(p12);           //Blue Button
InterruptIn buttonB(p13);           //Yellow Button
InterruptIn buttonC(p14);           //Red Button

SPI spi(p5, NC, p7);                //mosi (master output slave input), miso, sclk
DigitalOut cs(p8);                  //chip select pin
Serial pc(USBTX, USBRX);            //tx, rx

int phase[2] = {0};                 //current phase of sinusoid (int from 0 to 999)
char phasetick[2][1000] = {0};      //how much one ticker call moves the phase
int phasetickcounter = 0;           //which phasetick to use

float ms_passed_per_t = 0;          //how many milliseconds will pass per an increase in t

float amplitude[2] = {0, 0};    //Amplitude of vibration[%]
int frequency[2] = {0, 0};          //Frequency of vibration[Hz]

long int t = 0;                     //Time. Equivalent to (10^-4)s. Resets when going into state 3 or state 4

short waveTable[1100] = {0};        //table for output values in case of sine wave
                                    //waveTable[k][i] = 1/2 * ( 1 + sin( 2*PI * (i/1000 ) ), waveTable[1][i] = actual strength at those points

short DA[2] = {0};                  //table for actual binary passed to DA converter

short silence[4] = {4096,8192,12288,16384}; 
                                    //pass to DAC when output is zero
short channel[4] = {4096,8192,12288,16384};
                                    //binary for each channel

float adc1 = 0;                     //input from adc1
float adc2 = 0;
float volts1 = 0;                   //convert to voltage
float volts2 = 0;                   

float prev_button_press_A = -100;   //timing of previous button press[us]
float prev_button_press_B = -100; //timing of previous button press[us]   
float prev_button_press_C = -100; //timing of previous button press[us]     

float reset_pressed_time = false;       

Ticker time_ticker;                 //ticker

LocalFileSystem local("local");               // Create the local filesystem under the name "local"
FILE *fp;

//for measuring time
Timer time1;
int ttaken[100] = {0};
int cont = 0;
float ave = 0;
int max = 0;
//for measuring time

void vibration();
void waveDefine(int);


//time_ticker
void time(){

    //time1.start();

    t++;                                                //every 50us
    vibration();

    //resets time if t is greater than 1800000000 (30 minutes)
    
    if(t - 1800000000 > 0){
        t = 0;
    }
    
    if(t%20 == 0){
        
        amplitude[0] = ain1.read();     //reads input from sensor 1 (value 0~1) and inputs value into actuator vibration amplitude

    }else if(t%20 - 1 == 0){

        amplitude[1] = ain2.read();

    }

    /*
    time1.stop();
    
    if(cont < 99){
        ttaken[cont] = time1.read_us();
        cont++;
    }else if(cont == 99){
        ttaken[cont] = time1.read_us();
        for(int i = 0; i<100;i++){
            ave += ttaken[i];
            if(ttaken[i] > max){
                max = ttaken[i];
            }
        }
        ave = ave/100;
        cont = 1000;
        pc.printf("%f\r\n",ave);
    }
    
    time1.reset();
    */
    
}


void initVariables(){

    ms_passed_per_t = (float)1000.000 / (float)updateFrequency;
    t = 0;

    for(int i = 0; i < 2; i++){
        frequency[i] = actuatorFrequency;
    }

    amplitude[0] = 0.1;
    amplitude[1] = 0.1;

    buttonA.mode(PullUp);
    buttonB.mode(PullUp);
    buttonC.mode(PullUp);

}


void setWaveTable(){
    
    /***
    / Sets the Sine Wave Table
    ***/

    double temp = 0.0;
    double ttactual = 0.0;              //actual(optimal) value of phasetic in double
    double ticksum = 0.0;               //sum of all ticker calls

    for(int i = 0; i < 2; i++){

        phase[i] = 0;
        ttactual = 1000.0 * frequency[i] / updateFrequency;

        if(ttactual == (int)ttactual){
            for(int j = 0; j < 1000; j++){
                phasetick[i][j] = (int)(ttactual);              //if the tick in phase is an integer, simply input the integer
            }
            ticksum = ttactual*100;
            
        }else{
            for(int j = 0; j < 1000; j++){                      //if the tick in phase is NOT an integer
                phasetick[i][j] = (int)(ttactual);              //cast value to integer (integer < double) and input
                ticksum += phasetick[i][j];                     //find sum of phases

                if(ttactual * (j + 1.0) - ticksum >= 0.99999){  //if difference between target and actual sum is equal to or greater than 1
                    phasetick[i][j]++;                          //add 1
                    ticksum++;                                  //add 1
                    
                }
            }
        }
    }

    for(int k = 0; k < 1100; k++){
        temp = (sin(2.0*3.14159*k/1000)*0.5+0.5)*0x3FF;
        waveTable[k] = (short)temp;
    }

}


void vibration(){
    phasetickcounter++;

    if(phasetickcounter >= 1000)
        phasetickcounter = 0;

    for(int i = 0; i < 2; i++){                           // i=channel number
        
        //Part 1 : tick the phase
        phase[i] += phasetick[i][phasetickcounter];

        if(phase[i] >= 1000)
            phase[i] -= 1000;
        //Part 1 end

        //Part 2 : change input to relevant data
        waveDefine(i);
        //Part 2 End.

        //Part 3: write input
        cs = 0;                 //enable clock
        spi.write(DA[i]);
        cs = 1;                 //disable clock and load data
        //part 3 end
    }
}


void waveDefine(int i){

    double inputvalue =  0;

    //amplitude[i] = 1;         //temporary measure - change this to sensor input
    //notQuiet[i] = 1;

    inputvalue = amplitude[i] * (double)waveTable[phase[i]];
    DA[i] = (((i&0x07)+1)<<12)|((((int)inputvalue)&0x3FF)<<2);

    return;
}

void writeVoltage(){

    if(t - prev_button_press_A > MIN_TIME_DIFF){
        led2 = 1;
        prev_button_press_A = t;
        adc1 = ain1.read();
        adc2 = ain2.read();
        volts1 = adc1 * 3.3;
        volts2 = adc2 * 3.3;

        fp = fopen("/local/out.csv", "a");
        // prints sensor 1 voltage, sensor 2 voltage, time[seconds]
        fprintf(fp, "%.5f, %.5f, %.3f\n",volts1,volts2,(float)t/20000);
        fclose(fp);
        led2 = 0;
    }
}

void softReset_f(){

    if(t - prev_button_press_C > MIN_TIME_DIFF){
        prev_button_press_C = t;
        reset_pressed_time = t;
        led4 = 1;
    }
}

void softReset_r(){

    if(t - prev_button_press_C > MIN_TIME_DIFF){
        prev_button_press_C = t;
        led4 = 0;
        if(t - reset_pressed_time > 20000){
            NVIC_SystemReset();
        }
    }
}
/*
void blinkLED1(){

    if(t - prev_button_press_A > MIN_TIME_DIFF){
        prev_button_press_A = t;
        led2 = !led2;
    }
}
*/
void blinkLED2(){

    if(t - prev_button_press_B > MIN_TIME_DIFF){
        prev_button_press_B = t;
        led3 = !led3;
    }
}

/*
void blinkLED3_f(){

    if(t - prev_button_press_C > MIN_TIME_DIFF){
        prev_button_press_C = t;
        reset_pressed_time = t;
    }
}

void blinkLED3_r(){

    if(t - prev_button_press_C > MIN_TIME_DIFF){
        prev_button_press_C = t;

        if(t - reset_pressed_time > 20000){
            led4 = !led4;
        }
    }
}
*/

int main() {

    initVariables();
    setWaveTable();

    // Setup SPI communications w/ DA converter
    spi.format(16,0);
    spi.frequency(10000000);    //10MHz

    //attack ticker
    time_ticker.attach_us(&time,1000000 / updateFrequency);  //Every (10^-4)s

    //attach button
    buttonA.fall(&writeVoltage);
    buttonB.fall(&blinkLED2);

    //attach reset button (Resets mbed if RED button is pressed for more than 1 second and released)
    buttonC.fall(&softReset_f);
    buttonC.rise(&softReset_r);

    //test serial output
    pc.printf("Hello, world!\n\r");

    //LED1 Blink every 0.5s
    while(1){
        wait(0.5);
        led1 = !led1;
        pc.printf("S1: %f\r\n", amplitude[0]);
        pc.printf("S2: %f\r\n", amplitude[1]);
    }

}