My ELEC2645 sensor project Bader Alathri 200826344

Dependencies:   FXOS8700Q N5110 SRF02 mbed

main.cpp

Committer:
fy13ba
Date:
2016-05-05
Revision:
0:fedc789ee1f0

File content as of revision 0:fedc789ee1f0:

/*

Bader Alathri
ELEC2645_project

*/


#include "main.h"

BusIn input(PTC5,PTC7); /// external button inputs (toggle,select)


struct State { /// struct to group state information
    int output;  /// output value
    float time;    /// time in state
    int nextState[4];  /// array of next states
};

typedef const struct State STyp;


STyp fsm[9] = { /// finite state machine (FSM) transition table
    {0,0.15,{0,1,3,0}},
    {1,0.15,{1,2,7,1}},
    {2,0.15,{2,0,8,2}},
    {3,0.15,{3,4,5,3}},
    {4,0.15,{4,3,6,4}},
    {5,0.15,{5,0,5,5}},
    {6,0.15,{6,0,6,6}},
    {7,0.15,{7,0,7,7}},
    {8,0.15,{8,0,8,8}}

};


int main()
{

    init_K64F();   /// initialise the board and serial port
    init_serial(); /// initialise serial port
    lcd.init(); /// initialise display
    brightness = 0.4; /// setting initial brightness value to 0.4
    lcd.setBrightness(brightness); /// sets lcd brightness to match 'brightness' variable
    toggle.rise(&toggle_isr); /// rising edge for interrupt input set to trigger ISR (toggle button)
    select.rise(&select_isr); /// rising edge for interrupt interrupt set to trigger ISR (select button)

    toggle.mode(PullDown); /// interrupt input pin set to pulldown mode (toggle button)
    select.mode(PullDown); /// interrupt input pin set to pulldown mode (select button)
    /// as both buttons are connected to 3V3

    int state = 0; /// intitial FSM state set to 0

    while(1) {

        int output; // /stores value of state output
        output = fsm[state].output;  /// set ouput depending on current state
        wait(fsm[state].time);       /// wait in that state for desired time
        state = fsm[state].nextState[input];  /// read input (BusIn) and update curent state

        if ( output == 0) { /// first state

            acc.disable(); /// disable accelerometer, from FXOS8700Q library
            ticker1.detach(); /// stops ticker from triggering timer1 ISR
            g_toggle_flag = 0; /// resets toggle flag to 0
            r_led = 0; /// turns off external red LED
            g_led = 0; /// turns off external green LED

            lcd.clear(); /// clears lcd
            lcd.drawCircle(3,12,1,1); /// displays small circle next to selected option
            /// display options on lcd
            lcd.printString("get distance",7,1);
            lcd.printString("spirit level",7,3);
            lcd.printString("brightness",7,5);



        } else if ( output == 1 ) { /// second state

            g_toggle_flag = 0; /// resets toggle flag to 0
            lcd.clear(); /// clears lcd
            lcd.drawCircle(3,28,1,1); /// displays small circle next to selected option
            /// display options on lcd
            lcd.printString("get distance",7,1);
            lcd.printString("spirit level",7,3);
            lcd.printString("brightness",7,5);



        } else if ( output == 2 ) { /// third state

            g_toggle_flag = 0; /// resets toggle flag to 0
            lcd.clear(); /// clears lcd
            lcd.drawCircle(3,44,1,1); /// displays small circle next to selected option
            /// display options on lcd
            lcd.printString("get distance",7,1);
            lcd.printString("spirit level",7,3);
            lcd.printString("brightness",7,5);




        } else if ( output == 3 ) { /// fourth state

            g_select_flag = 0; /// resets select flag to 0
            lcd.clear(); /// clears lcd
            lcd.drawCircle(3,12,1,1); /// displays small circle next to selected option
            /// display unit options on lcd
            lcd.printString("centimetres",7,1);
            lcd.printString("inches",7,3);

        } else if ( output == 4 ) { /// fifth state

            g_toggle_flag = 0; /// resets toggle flag to 0
            lcd.clear(); /// clears lcd
            lcd.drawCircle(3,28,1,1); /// displays small circle next to selected option
            /// display unit options on lcd
            lcd.printString("centimetres",7,1);
            lcd.printString("inches",7,3);

        } else if ( output == 5 && g_select_flag == 1 ) { /// sixth state, two conditions so that state triggers only once

            g_select_flag = 0; /// resets select flag to 0
            lcd.clear(); /// clears lcd
            measuring_transition(); /// displays transition while measurement is taking place
            get_average_distance_cm(); /// calculates average distance in cm from readings
            lcd.clear(); /// clears lcd



            if (g_error_flag) { /// checks if error flag is triggered
                g_error_flag = 0; /// resets error flag to 0
                measurement_error(); /// displays error message

            }


            else { /// if error flag was not triggered
                display_distance_cm(); /// displays distance in cm
                g_led = 1; /// turns on green external LED
            }
            lcd.refresh(); ///refreshes lcd
            sleep(); /// puts K64F into sleep mode
        }


        else if ( output == 6 && g_select_flag == 1 ) { /// seventh state, two conditions so that state triggers only once

            g_select_flag = 0; /// resets select flag to 0
            lcd.clear(); /// clears lcd
            measuring_transition(); /// displays transition while measurement is taking place
            get_average_distance_in(); ///c alculates average distance in inches from readings
            lcd.clear(); /// clears lcd


            if (g_error_flag) { /// checks if error flag is triggered
                g_error_flag = 0; /// resets error flag to 0
                measurement_error(); /// displays error message
            }


            else { /// if error flag was not triggered
                display_distance_in(); /// displays distance in inches
                g_led = 1; /// turns on green external LED
            }
            lcd.refresh(); /// refreshes lcd
            sleep(); /// puts K64F into sleep mode
        }

        else if ( output == 7 ) { /// eighth state

            acc.enable(); /// enabling FXOS8700 accelerometer, credit: https://developer.mbed.org/teams/Freescale/code/Hello_FXOS8700Q/
            ticker1.attach(&timer1_isr,0.125); /// attaching ticker1 to timer1 ISR
            /// ISR triggered every 0.125 seconds

            if (g_timer1_flag) { /// checks if ISR is triggered

                g_timer1_flag = 0; /// resets timer flag to 0

                get_z_axis_value(); ///calculates average z-axis reading
                lcd.clear(); /// clears lcd
                display_flatness(); /// displays whether surface is found to be flat
                lcd.refresh(); /// refreshes lcd
                sleep(); /// puts K64F into sleep mode
            }


        } else if ( output == 8 && g_select_flag == 1 ) { /// ninth state
            g_select_flag = 0; /// resets select flag to 0
            lcd.clear(); /// clears lcd
            adjust_brightness(); /// adjusts brightness according to current value of 'brightness' variable
            display_brightness(); /// displays brightness as a percentage on lcd
            lcd.refresh(); /// refreshes lcd
            sleep(); /// puts K64F into sleep mode

        }

    }
}


void init_serial()
{

    pc.baud(115200); /// set to highest baud - ensure terminal software matches
}

void init_K64F()
{
    /// on-board LEDs are active-low, so set pin high to turn them off.
    red_led = 1;
    green_led = 1;
    blue_led = 1;

}

void timer1_isr()
{
    g_timer1_flag = 1;  /// set timer1 flag in ISR
}

void select_isr()
{
    g_select_flag = 1; /// set select flag in ISR
}

void toggle_isr()
{
    g_toggle_flag = 1; /// set toggle flag in ISR
}

void measurement_error()
{
    lcd.printString("error",25,2); /// displays 'error' on lcd
    r_led = 1; /// turns on external red LED

}

void measuring_transition()
{
    /// turns off external LEDs
    r_led = 0;
    g_led = 0;
    lcd.printString("measuring...",10,2); /// displays measuring message on lcd
}

void get_average_distance_cm()
{
    total_distance = 0.0; /// resets value for total distance
    average_distance_cm = 0.0; /// resets value for average distance (cm)
    for ( int i=0; i<10; i++) { /// 10 iterations

        float distance = sensor.getDistanceCm(); /// gets 1 distance reading from sensor in cm
        total_distance = total_distance + distance; /// stores sum of readings

        if ( distance >= 249 ) { /// if a single measurement is above the range of the sensor

            g_error_flag = 1; /// trigger error flag


        }

        else if ( distance <= 15 ) { /// if a single measurement is below the range of the sensor

            g_error_flag = 1; /// trigger error flag

        }
        pc.printf("Distance = %.2f cm\n",distance); /// prints distance measurements to pc in cm
    }

    average_distance_cm = total_distance/10; /// calculates average distance in cm
}

void get_average_distance_in()
{
    total_distance = 0.0; /// resets value for total distance
    average_distance_in = 0.0; /// resets value for average distance (inches)
    for ( int i=0; i<10; i++) { /// 10 iterations

        float distance = sensor.getDistanceCm(); /// gets 1 distance reading from sensor in cm
        total_distance = total_distance + distance; /// stores sum of readings

        if ( distance >= 249 ) { /// if a single measurement is above the range of the sensor

            g_error_flag = 1; /// trigger error flag


        }

        else if ( distance <= 15 ) { /// if a single measurement is below the range of the sensor

            g_error_flag = 1; /// trigger error flag

        }
        pc.printf("Distance = %.2f cm\n",distance); /// prints distance measurements to pc in cm
    }

    average_distance_in = (total_distance/10) * 0.394; /// calculates average distance in cm then converts it to inches
}

void display_distance_cm()
{
    /// prints value of distance and units
    lcd.printString("Distance:",15,1);
    char buffer[14];
    float length = sprintf(buffer,"%.2f cm",average_distance_cm); /// print formatted data to buffer
    lcd.printString(buffer,17,3); /// display on lcd

}

void display_distance_in()
{
    lcd.printString("Distance:",15,1);
    char buffer[14];
    float length = sprintf(buffer,"%.2f inches",average_distance_in); /// print formatted data to buffer
    lcd.printString(buffer,9,3); /// display on lcd

}


void get_z_axis_value()
{

    int16_t raZ; /// variable for storing z-axis reading taken from FXOS8700Q library
    /// from FXOS8700Q library

    acc.getAxis(acc_data); /// gets data from accelerometer, from FXOS8700Q library



    acc.getZ(&raZ); /// get z-axis reading, from FXOS8700Q library



    int total_z = 0; /// variable to store sum of z-axis values

    for ( int i=0; i<10; i++) { /// 10 iterations

        int z = raZ; /// variable to store single z-axis reading, from FXOS8700Q library
        total_z = total_z + z; /// summing z-axis readings

        wait (0.01); /// delay of 0.01 seconds between loop iterations
    }

    average_z = total_z / 10 ; /// calculates average z-axis value

    pc.printf("Z=%.2f\n  ", average_z); /// prints average z-axis value to pc
}

void display_flatness()
{
    if ((average_z <= 280) && (average_z >= 80)) { ///if average z-axis value within specified range (vertically flat)
        r_led = 0; /// turns off external red LED
        g_led = 1; /// turns on external green LED
        lcd.printString("vertically",7,1); /// displays 'vertically flat' message on lcd
        lcd.printString("flat",30,3);
    }

    else if ((average_z <= 4160) && (average_z >= 4147)) { ///if average z-axis value within specified range (horizontaly flat)
        r_led = 0; /// turns off external red LED
        g_led = 1; /// turns on external green LED
        lcd.printString("horizontally",7,1); /// displays 'horizontaly flat' message on lcd
        lcd.printString("flat",30,3);
    }

    else if ((average_z <= -3860) && (average_z >= -3880)) { ///if average z-axis value within specified range (horizontaly flat)
        r_led = 0; /// turns off external red LED
        g_led = 1; /// turns on external green LED
        lcd.printString("horizontally",7,1);  /// displays 'horizontaly flat' message on lcd
        lcd.printString("flat",30,3);
    }

    else { /// otherwise if average z-axis value within specified ranges (not flat)
        r_led = 1; /// turns on external red LED
        g_led = 0; /// turns off external green LED
        lcd.printString("not flat",18,2); /// displays 'not flat' message on lcd

    }
        
}

void adjust_brightness()
{
    if ( brightness == 1.0 ) { /// if the brightness value is at 1.0
        brightness = 0.0; /// set brightness back to 0
    } else { /// if the brightness value is not 1.0
        brightness = brightness + 0.2; /// increase its value by 0.2
    }

    lcd.setBrightness(brightness); /// sets lcd brightness to valeu of 'brightness' variable
}

void display_brightness()
{
    lcd.printString("brightness:",7,1);
    int brightness_percentage = brightness * 100; /// calculates brightness percentage
    char buffer[14];
    float length = sprintf(buffer,"%d%%",brightness_percentage); /// print formatted data to buffer
    lcd.printString(buffer,31,3); /// display on lcd
}