Working code for pc app 12/01/2018 commit
Dependencies: mbed MS5607 mbed-dsp
Fork of Turrentine_Code by
main.cpp@8:206c2ae7f49f, 2018-02-13 (annotated)
- Committer:
- AlexStokoe
- Date:
- Tue Feb 13 18:08:53 2018 +0000
- Revision:
- 8:206c2ae7f49f
- Parent:
- 7:1a4bbff83b4d
- Child:
- 9:28366bbbb13a
Code to work with new software, pc logging capability
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
AlexStokoe | 0:2c6d81be69d8 | 1 | #include "mbed.h" |
intrinseca | 3:c80aa39db5bb | 2 | #include "MS5607SPI.h" |
intrinseca | 3:c80aa39db5bb | 3 | #include "arm_math.h" |
AlexStokoe | 0:2c6d81be69d8 | 4 | |
AlexStokoe | 0:2c6d81be69d8 | 5 | #define M_PI 3.14159265358979323846 |
AlexStokoe | 0:2c6d81be69d8 | 6 | |
intrinseca | 2:3d3e21c907e4 | 7 | #define N_SAMPLES 1024 |
intrinseca | 1:ab3dacbfcde6 | 8 | |
intrinseca | 4:d4804771134a | 9 | #define PEAK_SEARCH_START 1 //first bin to include in peak search |
intrinseca | 4:d4804771134a | 10 | #define PEAK_SEARCH_END 50 //last bin to include in peak search |
intrinseca | 4:d4804771134a | 11 | #define SUM_AROUND_PEAK 1 //+/- this many bins |
intrinseca | 4:d4804771134a | 12 | |
intrinseca | 4:d4804771134a | 13 | #define REGRESSION_SLOPE 53.77986f //from Excel fit to test data |
intrinseca | 4:d4804771134a | 14 | #define REGRESSION_INTERCEPT -80.07f |
intrinseca | 4:d4804771134a | 15 | |
intrinseca | 5:44cfc3e81d1c | 16 | float thresholds[] = {0.f, 10.f, 30.f, 50.f, 70.f}; //estimated t90 thresholds to turn on LEDs |
intrinseca | 4:d4804771134a | 17 | |
AlexStokoe | 0:2c6d81be69d8 | 18 | //mbed class def |
AlexStokoe | 0:2c6d81be69d8 | 19 | Serial pc(USBTX, USBRX); // tx, rx |
intrinseca | 3:c80aa39db5bb | 20 | MS5607SPI pressure_sensor(p5, p6, p7, p8); // mosi, miso, sclk, cs |
AlexStokoe | 0:2c6d81be69d8 | 21 | |
intrinseca | 5:44cfc3e81d1c | 22 | #define N_LEDS 4 |
intrinseca | 5:44cfc3e81d1c | 23 | PwmOut leds[N_LEDS] = {LED1, LED2, LED3, LED4}; |
AlexStokoe | 0:2c6d81be69d8 | 24 | |
intrinseca | 5:44cfc3e81d1c | 25 | DigitalOut motor(p26); |
AlexStokoe | 0:2c6d81be69d8 | 26 | |
intrinseca | 3:c80aa39db5bb | 27 | Timer sample_timer; |
intrinseca | 3:c80aa39db5bb | 28 | Timer iter_timer; |
AlexStokoe | 0:2c6d81be69d8 | 29 | |
intrinseca | 3:c80aa39db5bb | 30 | float p_data[N_SAMPLES]; |
intrinseca | 3:c80aa39db5bb | 31 | float p_data_raw[N_SAMPLES]; |
intrinseca | 3:c80aa39db5bb | 32 | float f_data[N_SAMPLES]; |
intrinseca | 3:c80aa39db5bb | 33 | float mag_data[N_SAMPLES / 2 + 1]; |
AlexStokoe | 0:2c6d81be69d8 | 34 | |
intrinseca | 1:ab3dacbfcde6 | 35 | unsigned int tData[N_SAMPLES]; |
AlexStokoe | 0:2c6d81be69d8 | 36 | |
intrinseca | 3:c80aa39db5bb | 37 | arm_rfft_fast_instance_f32 rfft; |
AlexStokoe | 0:2c6d81be69d8 | 38 | |
AlexStokoe | 0:2c6d81be69d8 | 39 | float duty = 1; |
AlexStokoe | 0:2c6d81be69d8 | 40 | |
AlexStokoe | 0:2c6d81be69d8 | 41 | int round(float number) |
AlexStokoe | 0:2c6d81be69d8 | 42 | { |
AlexStokoe | 0:2c6d81be69d8 | 43 | return (number >= 0) ? (int)(number + 0.5) : (int)(number - 0.5); |
AlexStokoe | 0:2c6d81be69d8 | 44 | } |
AlexStokoe | 0:2c6d81be69d8 | 45 | |
intrinseca | 1:ab3dacbfcde6 | 46 | int main() |
intrinseca | 1:ab3dacbfcde6 | 47 | { |
intrinseca | 3:c80aa39db5bb | 48 | printf("Turrentine\n"); |
intrinseca | 3:c80aa39db5bb | 49 | |
intrinseca | 3:c80aa39db5bb | 50 | //Configure PC serial link |
AlexStokoe | 0:2c6d81be69d8 | 51 | pc.baud(115200); |
intrinseca | 3:c80aa39db5bb | 52 | |
intrinseca | 3:c80aa39db5bb | 53 | //Configure motor PWM |
intrinseca | 3:c80aa39db5bb | 54 | motor = 0; |
intrinseca | 2:3d3e21c907e4 | 55 | |
intrinseca | 2:3d3e21c907e4 | 56 | printf("Pump On\n"); |
intrinseca | 2:3d3e21c907e4 | 57 | //turn pump on |
intrinseca | 5:44cfc3e81d1c | 58 | motor = duty; |
intrinseca | 2:3d3e21c907e4 | 59 | |
intrinseca | 1:ab3dacbfcde6 | 60 | printf("Start loop\n"); |
intrinseca | 3:c80aa39db5bb | 61 | int iter_counter = 0; //Iteration counter |
intrinseca | 3:c80aa39db5bb | 62 | iter_timer.start(); |
AlexStokoe | 7:1a4bbff83b4d | 63 | float temperature_raw = pressure_sensor.getRawTemperature(); |
intrinseca | 4:d4804771134a | 64 | printf("fsmpl titer mean_press fmax sum_peak t90\n"); |
AlexStokoe | 8:206c2ae7f49f | 65 | int a = 0; |
intrinseca | 3:c80aa39db5bb | 66 | //program loop |
intrinseca | 3:c80aa39db5bb | 67 | while(1) { |
AlexStokoe | 7:1a4bbff83b4d | 68 | temperature_raw = pressure_sensor.getRawTemperature(); |
AlexStokoe | 7:1a4bbff83b4d | 69 | |
AlexStokoe | 8:206c2ae7f49f | 70 | while (a<2000){ |
AlexStokoe | 8:206c2ae7f49f | 71 | pressure_sensor.getRawPressure(); |
AlexStokoe | 8:206c2ae7f49f | 72 | a++; |
AlexStokoe | 8:206c2ae7f49f | 73 | } |
AlexStokoe | 8:206c2ae7f49f | 74 | a = 0; |
intrinseca | 3:c80aa39db5bb | 75 | sample_timer.reset(); |
intrinseca | 3:c80aa39db5bb | 76 | sample_timer.start(); |
AlexStokoe | 8:206c2ae7f49f | 77 | |
intrinseca | 3:c80aa39db5bb | 78 | //Capture raw pressure samples |
intrinseca | 1:ab3dacbfcde6 | 79 | for(int i = 0; i < N_SAMPLES; i++) { |
intrinseca | 3:c80aa39db5bb | 80 | p_data_raw[i] = pressure_sensor.calculatePressure(pressure_sensor.getRawPressure(), temperature_raw); |
intrinseca | 3:c80aa39db5bb | 81 | p_data[i] = p_data_raw[i]; |
intrinseca | 1:ab3dacbfcde6 | 82 | } |
intrinseca | 3:c80aa39db5bb | 83 | |
intrinseca | 3:c80aa39db5bb | 84 | sample_timer.stop(); |
AlexStokoe | 8:206c2ae7f49f | 85 | |
AlexStokoe | 7:1a4bbff83b4d | 86 | //Output raw data |
AlexStokoe | 7:1a4bbff83b4d | 87 | printf("$RAW\n"); |
AlexStokoe | 7:1a4bbff83b4d | 88 | for(int i = 0; i < N_SAMPLES; i++) { |
AlexStokoe | 7:1a4bbff83b4d | 89 | printf("$%f\n", p_data_raw[i]); |
AlexStokoe | 7:1a4bbff83b4d | 90 | //pressure_sensor.calculatePressure(pressure_sensor.getRawPressure(), temperature_raw); |
AlexStokoe | 7:1a4bbff83b4d | 91 | } |
AlexStokoe | 7:1a4bbff83b4d | 92 | printf("$ENDRAW\n"); |
AlexStokoe | 8:206c2ae7f49f | 93 | |
intrinseca | 3:c80aa39db5bb | 94 | //http://www.keil.com/pack/doc/CMSIS/DSP/html/group__RealFFT.html |
intrinseca | 3:c80aa39db5bb | 95 | //Compute the RFFT |
intrinseca | 3:c80aa39db5bb | 96 | // |
intrinseca | 3:c80aa39db5bb | 97 | //p_data is trashed in the process |
intrinseca | 3:c80aa39db5bb | 98 | //Result is packaged as [real_0, real_N/2, real_1, imag_1, real_2, imag_2 ... real_N/2-1, imag_N/2-1] |
intrinseca | 3:c80aa39db5bb | 99 | arm_rfft_fast_init_f32(&rfft, N_SAMPLES); |
intrinseca | 3:c80aa39db5bb | 100 | arm_rfft_fast_f32(&rfft, p_data, f_data, 0); |
intrinseca | 3:c80aa39db5bb | 101 | |
intrinseca | 3:c80aa39db5bb | 102 | //http://www.keil.com/pack/doc/CMSIS/DSP/html/group__cmplx__mag.html |
intrinseca | 3:c80aa39db5bb | 103 | //Convert to magntiude, skip over the DC and fundamental terms |
intrinseca | 3:c80aa39db5bb | 104 | |
intrinseca | 3:c80aa39db5bb | 105 | arm_cmplx_mag_f32(&f_data[2], &mag_data[1], (N_SAMPLES / 2) - 1); |
intrinseca | 3:c80aa39db5bb | 106 | //Fill in the first and last terms from the first entry in f_data |
intrinseca | 3:c80aa39db5bb | 107 | mag_data[0] = f_data[0]; |
intrinseca | 3:c80aa39db5bb | 108 | mag_data[N_SAMPLES / 2] = f_data[1]; |
intrinseca | 3:c80aa39db5bb | 109 | |
intrinseca | 3:c80aa39db5bb | 110 | |
intrinseca | 3:c80aa39db5bb | 111 | |
intrinseca | 4:d4804771134a | 112 | //Find peak in spectrum |
intrinseca | 4:d4804771134a | 113 | float max_mag = -1; |
intrinseca | 4:d4804771134a | 114 | int max_mag_i = -1; |
intrinseca | 4:d4804771134a | 115 | for(int i = PEAK_SEARCH_START + SUM_AROUND_PEAK; i < PEAK_SEARCH_END; i++){ |
intrinseca | 4:d4804771134a | 116 | //printf("%10f ", mag_data[i]); |
intrinseca | 4:d4804771134a | 117 | if(mag_data[i] > max_mag) { |
intrinseca | 4:d4804771134a | 118 | max_mag_i = i; |
intrinseca | 4:d4804771134a | 119 | max_mag = mag_data[i]; |
intrinseca | 4:d4804771134a | 120 | } |
intrinseca | 4:d4804771134a | 121 | } |
intrinseca | 4:d4804771134a | 122 | //printf("\n"); |
intrinseca | 4:d4804771134a | 123 | |
intrinseca | 4:d4804771134a | 124 | //Sum surrounding |
intrinseca | 4:d4804771134a | 125 | float sum = 0.f; |
intrinseca | 4:d4804771134a | 126 | for(int i = max_mag_i - SUM_AROUND_PEAK; i < (max_mag_i + SUM_AROUND_PEAK + 1); i++) { |
intrinseca | 4:d4804771134a | 127 | sum += mag_data[i]; |
intrinseca | 4:d4804771134a | 128 | //printf("%10f ", mag_data[i]); |
intrinseca | 1:ab3dacbfcde6 | 129 | } |
intrinseca | 3:c80aa39db5bb | 130 | |
intrinseca | 4:d4804771134a | 131 | //printf("\n"); |
intrinseca | 4:d4804771134a | 132 | |
intrinseca | 4:d4804771134a | 133 | //Scale by N_SAMPLES to recover pressure in Pa |
intrinseca | 4:d4804771134a | 134 | sum /= N_SAMPLES; |
intrinseca | 4:d4804771134a | 135 | |
intrinseca | 4:d4804771134a | 136 | //Apply inverse of logarithmic regression from test data |
intrinseca | 4:d4804771134a | 137 | float t90 = exp((sum + 80.07) / 53.77986); |
intrinseca | 4:d4804771134a | 138 | |
intrinseca | 4:d4804771134a | 139 | |
intrinseca | 4:d4804771134a | 140 | //Output iteration data |
intrinseca | 4:d4804771134a | 141 | iter_counter++; |
AlexStokoe | 8:206c2ae7f49f | 142 | printf("$DATA %.2f,%.2f,%.1f,%.1f,%1.5e,%.1f\n", iter_timer.read(), 1000000 / (sample_timer.read_us() / N_SAMPLES), f_data[0] / N_SAMPLES, max_mag_i, sum, t90); |
intrinseca | 3:c80aa39db5bb | 143 | |
intrinseca | 3:c80aa39db5bb | 144 | //Set LEDs based on thresholds |
intrinseca | 5:44cfc3e81d1c | 145 | for(int i = 0; i < N_LEDS; i++) { |
intrinseca | 5:44cfc3e81d1c | 146 | leds[i] = 0; |
intrinseca | 5:44cfc3e81d1c | 147 | |
intrinseca | 5:44cfc3e81d1c | 148 | if(t90 >= thresholds[i + 1]) { |
intrinseca | 5:44cfc3e81d1c | 149 | leds[i] = 1; |
intrinseca | 5:44cfc3e81d1c | 150 | } else if(i < (N_LEDS - 1)) { |
intrinseca | 5:44cfc3e81d1c | 151 | leds[i] = (t90 - thresholds[i]) / (thresholds[i + 1] - thresholds[i]); |
intrinseca | 5:44cfc3e81d1c | 152 | } |
intrinseca | 4:d4804771134a | 153 | } |
intrinseca | 3:c80aa39db5bb | 154 | |
intrinseca | 3:c80aa39db5bb | 155 | //break; |
intrinseca | 1:ab3dacbfcde6 | 156 | } |
AlexStokoe | 0:2c6d81be69d8 | 157 | } |