extra test

Dependencies:   DHT

newdemo.cpp

Committer:
elt14lpo
Date:
2017-05-10
Revision:
0:ef9b24f4c2d9
Child:
1:61ad430f1e5d

File content as of revision 0:ef9b24f4c2d9:

#include "mbed.h"
#include <iostream>     /*  cout */
//#include <stdio.h>      /* printf */
#include <math.h>       /* sin */
#include <vector> 
#include <stdlib.h>     /* abs */
#include <stdio.h>
#include <AnalogIn.h>
#include <stdint.h>
#//include <DHT.h>
#include<sstream>

//using namespace std;

/* DEBUG FUNCTION
// ersätter Debug(xyz) med xyz , där xyz är din kod
//För att aktivera:
#define Debug(xyz) xyz

//För att "stänga av":   
#define Debug(xyz)

//I din kod, skriv din debug kod liknande så här:
Debug( std::cout << "My text: " << myVariable << std::endl; );

*/

#define Debug(x) x
#define DebugPrintState(y) y
#define DebugArcSin(z) z


//----------VARIABLES HERE
int dataLength = 1000;
double temp = 25;
double hum = 10;
double micDist = 150; //millimeters
float threshold_1 = 0; //value when going to active mode channel 1  //old hardcoded value = 330
float threshold_2 = 0; //value when going to active mode channel 2 //old hardcoded value = 200
float threshold_adjust = -75;  //used to adjust threshold to slightly below max value 
bool calibratedStatus = false;      //flag to make sure Nuclueo only calibrated once for background noise
int positionOfMaxVal_1; 
int positionOfMaxVal_2;
const double PI = 3.14159265358979323846;

// State machine
int    STATE;
//const int NONE     = -1;
const int IDLE  = 0;
const int CALIBRATE = 1;
const int LISTEN = 2;
const int ACTIVELISTEN = 3;
const int CALC  = 4;
const int CALC_ERROR = 5;
const int SEND   = 6;
//const int WAIT     = 9;

//dataLength behövs kanske inte, vector klassen kan växa med behov
std::vector<float> channel_1(dataLength);
std::vector<float> channel_2(dataLength);
std::vector<int> timestamps_1(dataLength);
std::vector<int> timestamps_2(dataLength);

AnalogIn mic1(A0);
AnalogIn mic2(A1);
AnalogIn mic3(A2);

//TIMER
Timer t;

//led can be used for status
DigitalOut led1(LED1);


//----------FUNCTIONS HERE
//Calculating distance between sound and camera
double calcDist(double t, double v){
    double s = t*v;
    return s;
}

//Calculating angle in radians, D distance between mic1 and mic2
double calcAng(double s, double D){
    double ang = asin(s/D);
    if (ang < 0){           // if angle negative, add 180 degrees
        return ang + PI ;
    } else
    return ang;
}

//Assuming the input value is temp as a number in degrees celcius and humidity as procent
double calcSoundSpeed(double temp, double hum){
    //Calculations were done in Matlab
    double speed = 331.1190 + 0.6016*temp + 0.0126*hum;
    return speed;
}

//translate angle to number for camera
string convertAngToCamNbr(double ang){
    ang = ang*(180 / PI);  //radianer till grader
    double angValues = 270;
    int stepValues = 50000;
    string tiltNumber = " 18000";   //hårdkodat Camera Pan värde
    
    double oneAng = stepValues/angValues;
    double cameraAngNumber = ang*oneAng;
    int panInt = (int)(cameraAngNumber);  //double to int
    //int to string
    string panNumber;
    ostringstream convert;
    convert << panInt;
    panNumber = convert.str();
    
    string send = panNumber + tiltNumber;
    return send;    
}


//calc time delay by finding peak values in 2 vectors
//channel = 1 or 2
int FindPeak(int channel){
    
    std::vector<float> channel_curr(dataLength); //temporary vector with channel voltage values
    
    //if channel 1 then set current channel to channel 1
    if (channel == 1){
        channel_curr = channel_1;
    }
    else channel_curr = channel_2;
    
    //reset max value & sum value
    float valueMax = 0;
    
    //reset array position
    int positionOfMaxVal = 0;
    
    //find largest value & mark that position in vectors
    for (int position = 0; position < channel_curr.size(); position++) {
        float val = abs(channel_curr[position]);
        if (val > valueMax ){
            valueMax = val;
            positionOfMaxVal = position;
        }
    }    
    return positionOfMaxVal;
}

double FindTimeDelay(int positionOfMaxVal_1, int positionOfMaxVal_2){
    double timemax_1 = timestamps_1[positionOfMaxVal_1];
    double timemax_2 = timestamps_2[positionOfMaxVal_2];
    double delay = timemax_1 - timemax_2;
    return delay/1000; //if negative near microphone 1, if positive near micropnone 2
}


//get voltage value which represents audio amplitude from microphone 
float getAudioValue(AnalogIn micX) {
    return 1000*micX.read();        
}


bool overThreshold(float micValue_1, float micValue_2){
    if ((micValue_1 > threshold_1) || (micValue_2 > threshold_2)){
        return true;
        }
    else return false;
}

//true if voltage value in microphone is above the current threshold value
bool calibrateThreshold(float micValue, float currentThreshold){
    if ( micValue > currentThreshold ){
        return true;
    } else return false;
}


// main() runs in its own thread in the OS
int main() {
    t.start(); // start timer
    
    //while (true) {
        led1 = !led1;
        wait(0.5);
        
     
     //STATE MACHINE  
    STATE = IDLE;
    //int counter = 0;
    while (true) {
        switch (STATE) {
            

            case IDLE: //always start here
            DebugPrintState( std::cout << "Nucleo state is IDLE: " << STATE << std::endl; );
            Debug( wait(0.5); );
            if (!calibratedStatus)  STATE = CALIBRATE;
            else STATE = LISTEN;
            break;

            
            case CALIBRATE:
            DebugPrintState( std::cout << "Nucleo state is CALIBRATE: " << STATE << std::endl; );
            Debug( wait(1); );
            //listen for X seconds to background noise, to set accurate threshold value
            // This should be done only once when rebooting Nucleo
            float startTime = t.read_us();
            float offsetTime = 3000; // milliseconds
            float blinkTime = 500;
            while (t.read_us() < (startTime + offsetTime) ) {
                float micValue_1 = getAudioValue(mic1);
                if ( calibrateThreshold(micValue_1, threshold_1) ){
                    threshold_1 = micValue_1 - threshold_adjust;       //threshold value updated
                }
                float micValue_2 = getAudioValue(mic2);
                if ( calibrateThreshold(micValue_2, threshold_2) ){
                    threshold_2 = micValue_2 - threshold_adjust;       //threshold value updated
                }
                //make LED blink every 500 ms
                if ( t.read_us() > (startTime + blinkTime) ){
                    led1 = !led1;
                    blinkTime = blinkTime + 500;
                }
            }
            
            calibratedStatus = true;
            STATE = LISTEN; //next state
            break;
            

            case LISTEN:
            DebugPrintState( std::cout << "Nucleo state is LISTEN: " << STATE << std::endl; );
            //Debug( wait(0.5); );
            float micValue_1 = getAudioValue(mic1);
            float micValue_2 = getAudioValue(mic2);
            if(overThreshold(micValue_1, micValue_2) == true){ //if sound above threshold go to activelisten state
                //std::cout << "over Threshold!" << std::endl;
                STATE = ACTIVELISTEN;
            }else {
                    //std::cout << "under Threshold!" << std::endl;
                    STATE = LISTEN;
            }
            break;
            

           case ACTIVELISTEN:
           DebugPrintState( std::cout << "Nucleo state is ACTIVELISTEN: " << STATE << std::endl; );
           //Debug( wait(0.5); );
            //put value into array, start timer
            for(int i= 0; i < dataLength; i++){
                if (t.read_us() >= INT_MAX){
                std::cout << "time out" << std::endl;
            }
            //get audio  & timestamp values from microphones
            channel_1[i] = getAudioValue(mic1);
            timestamps_1[i] = t.read_us();
            channel_2[i] = getAudioValue(mic2);
            timestamps_2[i] = t.read_us();    
            }
            //go to state CALC
            STATE = CALC;
            break;
            
            case CALC:
            DebugPrintState( std::cout << "Nucleo state is CALC: " << STATE << std::endl; );
            //Debug( wait(0.5); );
            
            int positionOfMaxVal_1 = FindPeak(1);
            int positionOfMaxVal_2 = FindPeak(2);
            //run functions
            double timedelay = FindTimeDelay(positionOfMaxVal_1, positionOfMaxVal_2); //milliseconds
            double speed = calcSoundSpeed(temp, hum); //meters per second
            double distance = calcDist(timedelay/1000, speed); //millimeters
            double angle = calcAng((double)distance, micDist); //15cm = 150mm, double type cast because of asin function in angle calculation
            //go to state SEND if no calc_error
            
            Debug(
            std::cout << "max position for channel 1: " << positionOfMaxVal_1+1 << std::endl;
            std::cout << "max position for channel 2: " << positionOfMaxVal_2+1 << std::endl;
            std::cout << "run FindPeak, delay is: " << timedelay << "milliseconds" << std::endl;
            std::cout << "run calcDist, delta s is: " << distance << "millimeters" << std::endl;
            std::cout << "run calcAngle, angle is: " << angle << "radians" << std::endl;
            std::cout<<" run convertAngToCamNbr, coordinates: "<< convertAngToCamNbr(angle)<<std::endl; //return "panNumber tiltNumber";
            );
            Debug( wait(5); );
            
            if (angle > (3 * PI )/2 || angle < 0 ){        //vinkel larger than 270 eller minde än noll
                STATE = CALC_ERROR;
            } else {
                STATE = SEND;
            }
            break; 
 
            case CALC_ERROR:
            DebugPrintState( std::cout << "Nucleo state is CALC_ERROR: " << STATE << std::endl; );
            Debug( wait(0.5); );
            //error message 
            std::cout << "Error. angle not within limits 0 -270 degrees" << std::endl;
            //nollställ vektorer, , stoppa klockan , osv
            STATE = LISTEN;
            break;
            
            case SEND:
            DebugPrintState( std::cout << "Nucleo state is SEND: " << STATE << std::endl; );
            Debug( wait(0.5); );
            // send coordinates to serial port to camera
            std::cout<<convertAngToCamNbr(angle)<<std::endl; //return "panNumber tiltNumber";
            Debug( wait(0.5); );
            STATE = IDLE;
            break;
            }
    }  
}
        
 
 //GAMMAL TEST KOD NEDANFÖR
        
/*
    
    //read audio values and time stamps in ms
        //make sure that timestamp does not exceed INT_MAX to be able to use int
        for(int i= 0; i < dataLength; i++){
            if (t.read_ms() >= INT_MAX){
                std::cout << "time out" << std::endl;
            }
            channel_1[i] = getAudioValue(mic1);
            timestamps_1[i] = t.read_ms();
            channel_2[i] = getAudioValue(mic2);
            timestamps_2[i] = t.read_ms();    
         }

*/     
        //skriv ut alla element i kanal 0
       /* std::cout << "channel_1: ";
        for(int i=0; i<channel_1.size(); ++i){
            std::cout << channel_1[i] << ' ';   
        }
        std::cout << std::endl; */
        
        /*
        //skriv ut alla time element i kanal 0
        std::cout << "timestamps_1: ";
        for(int i=0; i<timestamps_1.size(); ++i){
            std::cout << timestamps_1[i] << ' ';   
        }
        std::cout << std::endl;
        */
    
    /*
     //skriv ut alla element i kanal 1
        std::cout << "channel_2: ";
        for(int i=0; i<channel_2.size(); ++i){
            std::cout << channel_2[i] << ' ';
        }
        std::cout << std::endl;
      */
      /*  
        //skriv ut alla time element i kanal 1
        std::cout << "timestamps_2: ";
        for(int i=0; i<timestamps_2.size(); ++i){
            std::cout << timestamps_2[i] << ' ';   
        }
        std::cout << std::endl;
        */
  /*      
    int positionOfMaxVal_1 = FindPeak(0);
    int positionOfMaxVal_2 = FindPeak(1);
   
    
    double timedelay = FindTimeDelay(positionOfMaxVal_1, positionOfMaxVal_2); //milliseconds
    double speed = calcSoundSpeed(temp, hum); //meters per second
    double distance = calcDist(timedelay/1000, speed); //millimeters
    double angle = calcAng((double)distance, micDist); //15cm = 150mm, double type cast because of asin function in angle calculation
    
    std::cout << "max position for channel 0: " << positionOfMaxVal_1+1 << std::endl;
    std::cout << "max position for channel 1: " << positionOfMaxVal_2+1 << std::endl;
    std::cout << "run FindPeak, delay is: " << timedelay << "milliseconds" << std::endl;
    std::cout << "run calcDist, delta s is: " << distance << "millimeters" << std::endl;
    std::cout << "run calcAngle, angle is: " << angle << "degrees" << std::endl;
    std::cout<<"run convertAngToCamNbr, coordinates"<<convertAngToCamNbr(angle)<<std::endl; //return "panNumber tiltNumber";
        
    t.stop(); //Stop timer
*/