Program implementing various applications of the ultrasonic distance sensor SRF02 combined with other components. Five different modules to show the various possible applications of the device. A focus on linear distance measurement, the synchronization of an alert/signalling system and accessibility.

Dependencies:   N5110 SRF02 beep mbed

obstacle.cpp

Committer:
MahletShimellis
Date:
2015-05-11
Revision:
1:37d0985c814e

File content as of revision 1:37d0985c814e:

/**
@file obstacle.cpp
@brief Program Implementation
*/

#include "mbed.h"
#include "SRF02.h"
#include "N5110.h"
#include "beep.h"
#include "obstacle.h"


//////////////////////////PART 1 - SETTING UP THE MEASUREMENTS//////////////////////////////

int timerFlag=0;
void timerExpired()
{
    timerFlag =1;
}

void error(int code)
{
    while(1) {
        leds = 0;
        wait(0.25);
        leds = code;
        wait(0.25);
    }
}

void measureExpired()
{
    measureFlag =1;
}


/*
void initTMP102()
{
    tmp102.frequency(400000); // set bus speed to 400 kHz
    int ack; // used to store acknowledgement bit
    char data[2]; // array for data
    char reg = CONFIG_REG; // register address
//////// Read current status of configuration register ///////

    ack = tmp102.write(TMP102_W_ADD,&reg,1); // send the slave write address and the configuration register address
    if (ack)
        error(1); // if we don't receive acknowledgement, flash error message
    ack = tmp102.read(TMP102_R_ADD,data,2); // read default 2 bytes from configuration register and store in buffer
    if (ack)
        error(2); // if we don't receive acknowledgement, flash error message
///////// Configure the register //////////
// set conversion rate to 1 Hz
    data[1] |= (1 << 6); // set bit 6
    data[1] &= ~(1 << 7); // clear bit 7

//////// Send the configured register to the slave ////////////

    ack = tmp102.write(TMP102_W_ADD,&reg,1); // send the slave write address and the configuration register address
    if (ack)
        error(3); // if we don't receive acknowledgement, flash error message
    ack = tmp102.write(TMP102_W_ADD,data,2); // send 2 data bytes to the configuration register
    if (ack)
        error(4); // if we don't receive acknowledgement, flash error message

}

float getTemperature()
{
    int ack; // used to store acknowledgement bit
    char data[2]; // array for data
    char reg = TEMP_REG; // temperature register address
    ack = tmp102.write(TMP102_W_ADD,&reg,1); // send temperature register address
    if (ack)
        error(5); // if we don't receive acknowledgement, flash error message
    ack = tmp102.read(TMP102_R_ADD,data,2); // read 2 bytes from temperature register and store in array
    if (ack)
        error(6); // if we don't receive acknowledgement, flash error message
    temperature = (data[0] << 4) | (data[1] >> 4);
    return temperature*0.0625;
}

float calcSoundSpeed(float temperature)
{
    return soundSpeed = temperature*0.6 + 331.3;
}

float calcSoundTimeDelay (int distance, float soundSpeed)
{   distance =srf.getDistanceCm();
    return soundTimeDelay = distance/soundSpeed;
}
*/


///////////////////PART 2 - Distance Upadate and Speed //////////////////////


void updateExpired()
{
    updateFlag=1;    ///
}

void update_distance_new()
{
    lastDistance = newDistance; ///updates the lastDistance variable by storing into it the previous distance measurement
    newDistance = srf.getDistanceCm();///updates the newDistance variable by adding to it the new distance measurement
}


///////////////////PART 3 - Distance Range Alert//////////////////////////////

void rangeExpired()
{
    rangeFlag =1;
}

struct State {
    float bOutput; /// buzzer output value
    int nextState[5]; /// array of next states
};
typedef const struct State STyp;

STyp fsm[5] = {
    {8000,{0,1,2,3,4}}, // State 0 - object at less than 20 cm away
    {2000,{0,1,2,3,4}}, // 1 - object in the 20-65cm range from the person
    {1000,{0,1,2,3,4}}, // 2 - object in the 65-110cm range from the person
    {500,{0,1,2,3,4}}, // 3 - object in the 110-155cm range from the person
    {200,{0,1,2,3,4}}, // 4 - object in the 155-200cm range from the person

};

void updateState()
{

    distance = srf.getDistanceCm();
    if(distance<=20) rangeState=0;
    else if((distance>20)&&(distance<=65))rangeState=1;
    else if ((distance>65)&&(distance<=110))rangeState=2;
    else if ((distance>110)&&(distance<=155))rangeState=3;
    else if ((distance>155)&&(distance<=200))rangeState=4;


    currentState = fsm[currentState].nextState[rangeState];
}

///////////////////PART 4 - Beam Pattern ///////////////////////////////////

double angleArray[5]= {0,10,20,30,40}; /*!<array of angles from the center of the sensor*/


void beamExpired()
{
    beamFlag=1;
}

double convertDegrees(double angleDegrees)
{
     ///uses equivalence of 2pi and 180 degrees
    return angleDegrees*3.16/180;     
}

void drawSemiCircle()
{
//draws a semi circle on the screen of radius equal to the distance from the object
    int radius = srf.getDistanceCm(); /// int radius = ((30*srf.getDistanceCm())/20); other possibility
    lcd.drawCircle(WIDTH/2,1,radius,0);  /// x,y,radius,transparent with outline
    lcd.drawLine(WIDTH/2,1,WIDTH/2,radius,2); ///draws one diameter
    lcd.refresh();
}

void drawBeamLines()
{
///draws a beam line for each calcualted value
    lcd.drawLine(WIDTH/2,1,WIDTH/2+l,h,2);
    lcd.drawLine(WIDTH/2,1,WIDTH/2-l,h,2);
    lcd.refresh();
}

double lat(double a, double d)
{
    return (tan(a) *d);
}

double hyp(double a, double d)
{
    return ((tan(a) *d)/sin(a));
}

/////////////////////////PART 5 - the Wall Follower Simulation //////////////////////

void wallExpired()
{
    wallFlag=1;
}

void moveForward()
{
/// sets pixel to move forward

    for(int k=0; k<=22; k++) {
        lcd.setPixel(16,k);  /// (x,y) starting point of the pixel - here fixed x coordinate - vertical movement
        wait(0.2);  ///can be considered as the "speed of the movement" because it defines the rate if change of pixel - delay between two k values
        pix++;  ///increments the pix vlaue for each increase in k
        lcd.refresh();
    }
}

void turnLeftForward_one()
{
///sets the pixel to turn left forward

    for(int l=0; l<=64; l++) {
        lcd.setPixel(l+16,22);  /// (x,22) starting point of the pixel - here fixed y coordinate - horizontal movement
        wait(0.2);
        pix=pix+1; ///increments the pix vlaue for each increase in l
        lcd.refresh();
    }

}

void turnLeftForward_two()
{
///sets the pixel to turn right forward -one

    for (int m=0; m<=16; m++) {
        lcd.setPixel(80,m+22);  /// (80,y) starting point of the pixel - here fixed x coordinate - vertical movement
        wait(0.2);
        pix=pix+1; ///increments the pix vlaue for each increase in m
        lcd.refresh();
    }

}

void turnRightForward()
{
///sets the pixel to turn right forward -two

    for(int n=0; n<=78; n++) {
        lcd.setPixel(80-n,38);  /// (x,38) starting point of the pixel - here fixed y coordinate - horizontal movement- x=80-n because counting down from the end x=80 to he beginning x=2 of the screen
        wait(0.2);
        pix=pix+1; ///increments the pix vlaue for each increase in n
        lcd.refresh();
    }
    //lcd.refresh();
}


///intial beep zero move forward
void beep_zero()
{
    int sound_zero = 200; /// local varaible integer gives specific frequency value for the buzzer
    float time_zero = 0.22; /// local varaible integer gives specific time for the buzzer
    buzzer.beep(sound_zero,time_zero);

}

///turns on beep one Turn Left
void beep_one()
{
    int sound_one = 600;
    float time_one = 0.2;
    buzzer.beep(sound_one,time_one);
}

/// turns on beep two Trun Left and move Forward
void beep_two()
{
    int sound_two = 800;
    float time_two = 0.23;
    buzzer.beep(sound_two,time_two);
}

//turns on beep three Turn Right
void beep_three()
{
    int sound_three = 1600;
    float time_three = 0.2;
    buzzer.beep(sound_three,time_three);
}

/// turns on beep four Turn Right and move Forward
void beep_four()
{
    int sound_four = 2000;
    float time_four = 0.14;
    buzzer.beep(sound_four,time_four);
}

/// turns on beep five Stop Dead End
void beep_five()
{
    int sound_five = 2600;
    float time_five = 0.6;
    buzzer.beep(sound_five,time_five);
}

void toggle_red()
{
    red=!red; ///toggle red led
}
void toggle_yellow()
{
    yellow=!yellow;  ///toggles yellow led
}
void toggle_green()
{
    green=!green;  ///toggles green led
}



void move()
{
    if (pix<=22) {
        lcd.printString(" Forward ",32,0);
        beep_ticker_zero.attach(&beep_zero, 0.61); //move forward
        toggle_green_ticker.attach(&toggle_green, 0.61);
        moveForward();
    }

    beep_ticker_zero.detach();
    beep_ticker_one.attach(&beep_one, 0.2);//turn left
    lcd.printString(" T Left ",32,0);
    toggle_green_ticker.detach();
    toggle_red_ticker.attach(&toggle_red,0.1);
    wait(0.5);
    beep_ticker_one.detach();
   

    if (22<pix && pix<86) {
        toggle_red_ticker.detach();
        lcd.printString(" Forward ",32,0);
        beep_ticker_two.attach(&beep_two, 0.66); //turn left and move forward
        toggle_green_ticker.attach(&toggle_green, 0.66);
        turnLeftForward_one();
    }

    beep_ticker_two.detach();
    beep_ticker_three.attach(&beep_three,0.2);//turn right
    lcd.printString(" T Right ",32,0);
    toggle_green_ticker.detach();
    toggle_red_ticker.attach(&toggle_red,0.1);
    wait(0.5);
    beep_ticker_three.detach();
    

    if(86<pix && pix<102) {
        toggle_red_ticker.detach();
        lcd.printString(" Forward ",32,0);
        toggle_green_ticker.attach(&toggle_green, 0.76);
        beep_ticker_four.attach(&beep_four, 0.76);//turn right and move forward
        turnLeftForward_two();
    }

    beep_ticker_four.detach();
    beep_ticker_three.attach(&beep_three,0.2);//turn right
    lcd.printString(" T Right ",32,0);
    toggle_red_ticker.attach(&toggle_red,0.1);
    wait(0.5);
    beep_ticker_three.detach();
   

    if (102<pix) {
        toggle_red_ticker.detach();
        beep_ticker_four.attach(&beep_four,0.8);///turn right and move forward- function called every 0.8s
        toggle_green_ticker.attach(&toggle_green, 0.76); /// toggle green led function called every 0.76s
        lcd.printString(" Forward ",32,0);
        turnRightForward();
    }

    beep_ticker_four.detach();
    toggle_green_ticker.detach();
    lcd.printString("  STOP!! ",32,0);
    toggle_red_ticker.attach(&toggle_red,0.1);
    beep_ticker_five.attach(&beep_five,0.8);//stop dead end
}

void drawMaze()
{
    lcd.drawRect(0,0,12,25,1);  /// top left filled rectangle-green on report
    lcd.drawRect(20,0,10,20,1); /// top middle filled rectangle-orange on report
    lcd.drawRect(30,10,52,10,1); /// top right filled rectangle-pink on report
    lcd.drawRect(0,25,76,10,1); /// middle filled rectangle-purple on report
    lcd.drawRect(0,40,80,1,1); /// bottom filled rectangle-red on report
    lcd.drawRect(0,36,1,4,1); /// dead end small filled rectangle-black on report
    lcd.refresh();
}

///////////////////////////////Transitions/User interface (button) selection and event order elements//////////////////////////////////

void buttonPressed()
{
    buttonFlag++;  ///increments and keepd the value of the buttonFlag counter for every button press
    if ( buttonFlag > 4) {  /// sets the limit value of the buttonFlag before going back to zero => five different flag states to be used for the five different modules
        buttonFlag = 0;
    }
}


void manageScreen()
{
    if ( buttonFlag== 0) {
        measureFlag = !measureFlag; /// toggles measureFlag - if the flag is intially low then it goes high for buttonFlag = 0 - first screen view
    }
    if ( buttonFlag == 1) {
        updateFlag = !updateFlag; /// toggles updateFlag - if the flag is intially low then it goes high for buttonFlag = 1 - first button press - second screen view
    }
    if ( buttonFlag == 2) {

        rangeFlag = !rangeFlag;  /// toggles rangeFlag - if the flag is intially low then it goes high for buttonFlag = 2 - second button press - third screen view
    }
    if ( buttonFlag == 3) {
        beamFlag = !beamFlag;  /// toggles beamFlag - if the flag is intially low then it goes high for buttonFlag = 3 - third button press - fourth screen view
    }
    if ( buttonFlag == 4) {
        wallFlag = !wallFlag;  /// toggles wallFlag - if the flag is intially low then it goes high for buttonFlag = 4 - fourth button press - fifth screen view
    }

    if(measureFlag == 1) {
        measure_ticker.attach(&update_distance_new,1.0);
        //  temperature_ticker.attach(&getTemperature,1.0);
    } else {
        measure_ticker.detach();
    }

    if(updateFlag == 1) {

        update_ticker.attach(&updateExpired,2.0);

    } else {
        update_ticker.detach();     // detach ticker
    }

    if(rangeFlag == 1) {
        range_ticker.attach(&rangeExpired,3.0);
    } else {
        range_ticker.detach();
    }

    if(beamFlag == 1) {
        beam_ticker.attach(&beamExpired,1.0);
    } else {
        beam_ticker.detach();
    }

    if(wallFlag == 1) {
        wall_ticker.attach(&wallExpired, 4.0);
    } else {
        wall_ticker.detach();
    }
}





int main()
{
    lcd.init(); //initializes the LCD display
///  initTMP102();

    lcd.normalMode();      /// normal colour mode
    lcd.setBrightness(0.5); /// put LED backlight on 50%
    button.rise(&buttonPressed); /// indicates that the button has been pressed. button flag rises when button pressed

    measure_ticker.attach(&measureExpired,1.0);
    update_ticker.attach(&updateExpired,2.0);
    beam_ticker.attach(&beamExpired,3.0);
    //  update_ticker_two.attach(&update_distance_new,2.0);
    range_ticker.attach(&rangeExpired,4.0);
    wall_ticker.attach(&wallExpired, 5.0);


    while(1) {
        // distance = srf.getDistanceCm();

        manageScreen();
        if (timerFlag) {
            timerFlag=0;   ///reset flag


            if(measureFlag) {
                lcd.clear();
                measureFlag =0;  ///reset flag

                char buffer[14];

                distance = srf.getDistanceCm();  /// same idea with floats
                float length = sprintf(buffer,"D = %.2f cm",distance);
                if (length <= 14)
                    lcd.printString(buffer,0,4);

            /*    temperature = getTemperature();
                     int lengthT = sprintf(buffer,"T = %.2f C",temperature); /// print formatted data to buffer
                     if (lengthT <= 14)  /// if string will fit on display
                         lcd.printString(buffer,0,5);
               
                soundSpeed = calcSoundSpeed(temperature);
                soundTimeDelay = calcSoundTimeDelay(distance, soundSpeed);
                */
            }
            lcd.refresh();


            if(updateFlag) {
                lcd.clear();
                updateFlag=0;  ///reset flag
                char bufferOne[14]; ///character array that stores the values of the newDistance variable
                char bufferTwo[14];///character array that stores the values of the lastDistance variable



                float lengthN = sprintf(bufferOne,"Dn = %.2f cm",distance);
                if (lengthN <= 14)
                    lcd.printString(bufferTwo,0,4);

                float lengthL = sprintf(bufferTwo,"Dl = %.2f cm",lastDistance);
                if (lengthL <= 14)
                    lcd.printString(bufferTwo,0,5);
            }
            lcd.refresh();


            if (rangeFlag) {
                lcd.clear();
                rangeFlag=0;  ///reset  flag
                char buffer[14];

                //   distance = srf.getDistanceCm();  // same idea with floats
                float length = sprintf(buffer," %.2f cm",distance);
                if (length <= 14) {
                    lcd.printString(buffer,11,2);
                }

                buzzerFrequency=fsm[currentState].bOutput;  /// retrieves the buzzer frequency associated to the currentState from the FSM definition
                buzzer.beep(buzzerFrequency,1);
                float lengthB = sprintf(buffer," %.2f hz",buzzerFrequency);
                if (lengthB <= 14) {
                    lcd.printString(buffer,11,4);
                }
                lcd.refresh();
            }


            if (beamFlag) {
                lcd.clear();
                beamFlag =0;

                z++;
                if (z>=5) z=0;
                angleDegrees = angleArray[z];
                angleRadians=convertDegrees(angleDegrees);
                a=angleRadians;

                drawSemiCircle();
                d =srf.getDistanceCm();
//simply assigns the function results under conditions (a,d) to the distance variable values. calls the pointers defined previously
                lateralDistance = 2*lat(a,d);
                h = hyp(a,d);

                drawBeamLines();

            }
            lcd.refresh();


            if (wallFlag) {
                lcd.clear();
                wallFlag=0; ///reset flag
                drawMaze();  ///draws the screen backgroung structure
                move();    ///controls the movement and associated signals for the moving pixel point
            }

        }
    }
}