extra test
Dependencies: DHT
Diff: newdemo.cpp
- Revision:
- 0:ef9b24f4c2d9
- Child:
- 1:61ad430f1e5d
diff -r 000000000000 -r ef9b24f4c2d9 newdemo.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/newdemo.cpp Wed May 10 13:19:59 2017 +0000 @@ -0,0 +1,382 @@ +#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 +*/