valeria toffoli
/
COG4050_analogSensor
fft+analohADXL100x
Fork of COG4050_blink by
main.cpp@2:dbe2cc9e3b23, 2018-11-05 (annotated)
- Committer:
- vtoffoli
- Date:
- Mon Nov 05 08:39:17 2018 +0000
- Revision:
- 2:dbe2cc9e3b23
- Parent:
- 1:f56db8105a6a
fft+analogADXL;
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
vtoffoli | 2:dbe2cc9e3b23 | 1 | #include <stdio.h> |
vtoffoli | 2:dbe2cc9e3b23 | 2 | #include <complex> |
vtoffoli | 2:dbe2cc9e3b23 | 3 | #include <math.h> |
APS_Lab | 0:74a0756399ff | 4 | #include "mbed.h" |
vtoffoli | 2:dbe2cc9e3b23 | 5 | #include "ADXL100x.h" |
vtoffoli | 2:dbe2cc9e3b23 | 6 | #include "FFT.h" |
vtoffoli | 2:dbe2cc9e3b23 | 7 | |
vtoffoli | 2:dbe2cc9e3b23 | 8 | FFT fft; |
vtoffoli | 2:dbe2cc9e3b23 | 9 | ADXL100x accl(D6, D7, D8, ADC_VIN0, 5, 3); |
vtoffoli | 2:dbe2cc9e3b23 | 10 | Serial pc(USBTX, USBRX); // tx, rx |
APS_Lab | 0:74a0756399ff | 11 | |
vtoffoli | 2:dbe2cc9e3b23 | 12 | // Interrupt and timer |
vtoffoli | 2:dbe2cc9e3b23 | 13 | Timer t; |
vtoffoli | 2:dbe2cc9e3b23 | 14 | Ticker tck; |
APS_Lab | 0:74a0756399ff | 15 | |
vtoffoli | 2:dbe2cc9e3b23 | 16 | // Const |
vtoffoli | 2:dbe2cc9e3b23 | 17 | const float sample_time = 0.03; |
vtoffoli | 2:dbe2cc9e3b23 | 18 | const int sample_num = 128; |
vtoffoli | 2:dbe2cc9e3b23 | 19 | #define M_PI 3.14159265358979323846 // Pi constant with double precision |
vtoffoli | 2:dbe2cc9e3b23 | 20 | uint16_t result; |
vtoffoli | 2:dbe2cc9e3b23 | 21 | |
vtoffoli | 2:dbe2cc9e3b23 | 22 | // Pin |
APS_Lab | 0:74a0756399ff | 23 | DigitalOut led1(LED1); |
vtoffoli | 1:f56db8105a6a | 24 | DigitalOut led2(LED2); |
vtoffoli | 2:dbe2cc9e3b23 | 25 | DigitalIn btn1(PB0); |
vtoffoli | 2:dbe2cc9e3b23 | 26 | DigitalIn btn2(PB1); |
vtoffoli | 2:dbe2cc9e3b23 | 27 | |
vtoffoli | 2:dbe2cc9e3b23 | 28 | // Variable |
vtoffoli | 2:dbe2cc9e3b23 | 29 | double data_array[sample_num]; |
vtoffoli | 2:dbe2cc9e3b23 | 30 | double time_array[sample_num]; |
vtoffoli | 2:dbe2cc9e3b23 | 31 | double dt_array[sample_num+1]; |
vtoffoli | 2:dbe2cc9e3b23 | 32 | complex<double> fft_array[sample_num]; |
vtoffoli | 2:dbe2cc9e3b23 | 33 | int index = 0; |
vtoffoli | 2:dbe2cc9e3b23 | 34 | bool alarm = false; |
vtoffoli | 2:dbe2cc9e3b23 | 35 | |
vtoffoli | 2:dbe2cc9e3b23 | 36 | /* -------------------------------------------------------------------------- */ |
vtoffoli | 2:dbe2cc9e3b23 | 37 | /* FFT ---------------------------------------------------------------------- */ |
vtoffoli | 2:dbe2cc9e3b23 | 38 | /* -------------------------------------------------------------------------- */ |
vtoffoli | 2:dbe2cc9e3b23 | 39 | /* |
vtoffoli | 2:dbe2cc9e3b23 | 40 | int log2(int N) //funzione per calcolare il logaritmo in base 2 di un intero |
vtoffoli | 2:dbe2cc9e3b23 | 41 | { |
vtoffoli | 2:dbe2cc9e3b23 | 42 | int k = N, i = 0; |
vtoffoli | 2:dbe2cc9e3b23 | 43 | while(k) { |
vtoffoli | 2:dbe2cc9e3b23 | 44 | k >>= 1; |
vtoffoli | 2:dbe2cc9e3b23 | 45 | i++; |
vtoffoli | 2:dbe2cc9e3b23 | 46 | } |
vtoffoli | 2:dbe2cc9e3b23 | 47 | return i - 1; |
vtoffoli | 2:dbe2cc9e3b23 | 48 | } |
vtoffoli | 2:dbe2cc9e3b23 | 49 | |
vtoffoli | 2:dbe2cc9e3b23 | 50 | int check(int n) //usato per controllare se il numero di componenti del vettore di input è una potenza di 2 |
vtoffoli | 2:dbe2cc9e3b23 | 51 | { |
vtoffoli | 2:dbe2cc9e3b23 | 52 | return n > 0 && (n & (n - 1)) == 0; |
vtoffoli | 2:dbe2cc9e3b23 | 53 | } |
vtoffoli | 2:dbe2cc9e3b23 | 54 | |
vtoffoli | 2:dbe2cc9e3b23 | 55 | int reverse(int N, int n) //calcola il reverse number di ogni intero n rispetto al numero massimo N |
vtoffoli | 2:dbe2cc9e3b23 | 56 | { |
vtoffoli | 2:dbe2cc9e3b23 | 57 | int j, p = 0; |
vtoffoli | 2:dbe2cc9e3b23 | 58 | for(j = 1; j <= log2(N); j++) { |
vtoffoli | 2:dbe2cc9e3b23 | 59 | if(n & (1 << (log2(N) - j))) |
vtoffoli | 2:dbe2cc9e3b23 | 60 | p |= 1 << (j - 1); |
vtoffoli | 2:dbe2cc9e3b23 | 61 | } |
vtoffoli | 2:dbe2cc9e3b23 | 62 | return p; |
vtoffoli | 2:dbe2cc9e3b23 | 63 | } |
vtoffoli | 2:dbe2cc9e3b23 | 64 | |
vtoffoli | 2:dbe2cc9e3b23 | 65 | void ordina(complex<double>* f1, int N) //dispone gli elementi del vettore ordinandoli per reverse order |
vtoffoli | 2:dbe2cc9e3b23 | 66 | { |
vtoffoli | 2:dbe2cc9e3b23 | 67 | complex<double> f2[sample_num]; |
vtoffoli | 2:dbe2cc9e3b23 | 68 | for(int i = 0; i < N; i++) |
vtoffoli | 2:dbe2cc9e3b23 | 69 | f2[i] = f1[reverse(N, i)]; |
vtoffoli | 2:dbe2cc9e3b23 | 70 | for(int j = 0; j < N; j++) |
vtoffoli | 2:dbe2cc9e3b23 | 71 | f1[j] = f2[j]; |
vtoffoli | 2:dbe2cc9e3b23 | 72 | } |
vtoffoli | 2:dbe2cc9e3b23 | 73 | |
vtoffoli | 2:dbe2cc9e3b23 | 74 | void transform(complex<double>* f, int N) //calcola il vettore trasformato |
vtoffoli | 2:dbe2cc9e3b23 | 75 | { |
vtoffoli | 2:dbe2cc9e3b23 | 76 | ordina(f, N); //dapprima lo ordina col reverse order |
vtoffoli | 2:dbe2cc9e3b23 | 77 | complex<double> W[N / 2]; //vettore degli zeri dell'unità. |
vtoffoli | 2:dbe2cc9e3b23 | 78 | //Prima N/2-1 ma genera errore con ciclo for successivo |
vtoffoli | 2:dbe2cc9e3b23 | 79 | //in quanto prova a copiare in una zona non allocata "W[N/2-1]" |
vtoffoli | 2:dbe2cc9e3b23 | 80 | W[1] = polar(1., -2. * M_PI / N); |
vtoffoli | 2:dbe2cc9e3b23 | 81 | W[0] = 1; |
vtoffoli | 2:dbe2cc9e3b23 | 82 | for(int i = 2; i < N / 2; i++) |
vtoffoli | 2:dbe2cc9e3b23 | 83 | W[i] = pow(W[1], i); |
vtoffoli | 2:dbe2cc9e3b23 | 84 | int n = 1; |
vtoffoli | 2:dbe2cc9e3b23 | 85 | int a = N / 2; |
vtoffoli | 2:dbe2cc9e3b23 | 86 | for(int j = 0; j < log2(N); j++) { |
vtoffoli | 2:dbe2cc9e3b23 | 87 | for(int i = 0; i < N; i++) { |
vtoffoli | 2:dbe2cc9e3b23 | 88 | if(!(i & n)) { |
vtoffoli | 2:dbe2cc9e3b23 | 89 | //ad ogni step di raddoppiamento di n, vengono utilizzati gli indici |
vtoffoli | 2:dbe2cc9e3b23 | 90 | //'i' presi alternativamente a gruppetti di n, una volta si e una no. |
vtoffoli | 2:dbe2cc9e3b23 | 91 | complex<double> temp = f[i]; |
vtoffoli | 2:dbe2cc9e3b23 | 92 | complex<double> Temp = W[(i * a) % (n * a)] * f[i + n]; |
vtoffoli | 2:dbe2cc9e3b23 | 93 | f[i] = temp + Temp; |
vtoffoli | 2:dbe2cc9e3b23 | 94 | f[i + n] = temp - Temp; |
vtoffoli | 2:dbe2cc9e3b23 | 95 | } |
vtoffoli | 2:dbe2cc9e3b23 | 96 | } |
vtoffoli | 2:dbe2cc9e3b23 | 97 | n *= 2; |
vtoffoli | 2:dbe2cc9e3b23 | 98 | a = a / 2; |
vtoffoli | 2:dbe2cc9e3b23 | 99 | } |
vtoffoli | 2:dbe2cc9e3b23 | 100 | } |
vtoffoli | 2:dbe2cc9e3b23 | 101 | |
vtoffoli | 2:dbe2cc9e3b23 | 102 | void FFT(complex<double>* f, int N, double d) |
vtoffoli | 2:dbe2cc9e3b23 | 103 | { |
vtoffoli | 2:dbe2cc9e3b23 | 104 | transform(f, N); |
vtoffoli | 2:dbe2cc9e3b23 | 105 | for(int i = 0; i < N; i++) |
vtoffoli | 2:dbe2cc9e3b23 | 106 | f[i] *= d; //moltiplica il vettore per il passo in modo da avere il vettore trasformato effettivo |
vtoffoli | 2:dbe2cc9e3b23 | 107 | } |
vtoffoli | 2:dbe2cc9e3b23 | 108 | */ |
vtoffoli | 2:dbe2cc9e3b23 | 109 | /* -------------------------------------------------------------------------- */ |
vtoffoli | 2:dbe2cc9e3b23 | 110 | |
vtoffoli | 2:dbe2cc9e3b23 | 111 | void check_accel(){ |
vtoffoli | 2:dbe2cc9e3b23 | 112 | uint16_t result = accl.scanx(); |
vtoffoli | 2:dbe2cc9e3b23 | 113 | pc.printf("%12d \t %6f \t \r\n", result, accl.accelScale(result, 12)); |
vtoffoli | 2:dbe2cc9e3b23 | 114 | result = accl.standard_dev(12); |
vtoffoli | 2:dbe2cc9e3b23 | 115 | pc.printf("standard dev: %6f \t \r\n", result); |
vtoffoli | 2:dbe2cc9e3b23 | 116 | } |
vtoffoli | 2:dbe2cc9e3b23 | 117 | |
vtoffoli | 2:dbe2cc9e3b23 | 118 | void check_fft(){ |
vtoffoli | 2:dbe2cc9e3b23 | 119 | /*if (!btn1) { |
vtoffoli | 2:dbe2cc9e3b23 | 120 | // collect data |
vtoffoli | 2:dbe2cc9e3b23 | 121 | t.start(); |
vtoffoli | 2:dbe2cc9e3b23 | 122 | for(int j = 0; j < 128; j++){ |
vtoffoli | 2:dbe2cc9e3b23 | 123 | data_array[j]= ain0.read_u16(); |
vtoffoli | 2:dbe2cc9e3b23 | 124 | t.stop(); |
vtoffoli | 2:dbe2cc9e3b23 | 125 | time_array[j]= t.read(); |
vtoffoli | 2:dbe2cc9e3b23 | 126 | t.start();} |
vtoffoli | 2:dbe2cc9e3b23 | 127 | // plot x[t] data |
vtoffoli | 2:dbe2cc9e3b23 | 128 | double time=time_array[0]; |
vtoffoli | 2:dbe2cc9e3b23 | 129 | double dt=0; |
vtoffoli | 2:dbe2cc9e3b23 | 130 | pc.printf("data \t \r\n"); |
vtoffoli | 2:dbe2cc9e3b23 | 131 | for(int j = 1; j < 128; j++){ |
vtoffoli | 2:dbe2cc9e3b23 | 132 | dt = (dt + (time_array[j]-time ))/2; |
vtoffoli | 2:dbe2cc9e3b23 | 133 | time = time_array[j]; |
vtoffoli | 2:dbe2cc9e3b23 | 134 | pc.printf("%6f \t %f \t %6f \t \r\n", data_array[j].real(), data_array[j].imag(), time_array[j]);} |
vtoffoli | 2:dbe2cc9e3b23 | 135 | // compute FFT |
vtoffoli | 2:dbe2cc9e3b23 | 136 | pc.printf("fft \t \r\n"); |
vtoffoli | 2:dbe2cc9e3b23 | 137 | FFT(data_array, 128, dt); |
vtoffoli | 2:dbe2cc9e3b23 | 138 | for(int j = 0; j < 128; j++){ pc.printf("X[f] value: 0x%04X \r\n", data_array[j]);} |
vtoffoli | 2:dbe2cc9e3b23 | 139 | }*/ |
vtoffoli | 2:dbe2cc9e3b23 | 140 | } |
vtoffoli | 2:dbe2cc9e3b23 | 141 | |
vtoffoli | 2:dbe2cc9e3b23 | 142 | void fill_array(){ |
vtoffoli | 2:dbe2cc9e3b23 | 143 | if (index >= 128){} |
vtoffoli | 2:dbe2cc9e3b23 | 144 | else {index = index +1;} |
vtoffoli | 2:dbe2cc9e3b23 | 145 | } |
vtoffoli | 2:dbe2cc9e3b23 | 146 | |
vtoffoli | 2:dbe2cc9e3b23 | 147 | void clear_array(double* f, int N){ |
vtoffoli | 2:dbe2cc9e3b23 | 148 | for (int i=0; i<N; i++){f[i] = 0;} |
vtoffoli | 2:dbe2cc9e3b23 | 149 | } |
vtoffoli | 2:dbe2cc9e3b23 | 150 | /* -------------------------------------------------------------------------- */ |
APS_Lab | 0:74a0756399ff | 151 | |
APS_Lab | 0:74a0756399ff | 152 | int main() { |
vtoffoli | 2:dbe2cc9e3b23 | 153 | pc.baud(9600); |
vtoffoli | 2:dbe2cc9e3b23 | 154 | pc.printf("Analog AD sensor Demo: START\n"); |
vtoffoli | 2:dbe2cc9e3b23 | 155 | while(true){ |
vtoffoli | 2:dbe2cc9e3b23 | 156 | t.start(); |
vtoffoli | 2:dbe2cc9e3b23 | 157 | if(!btn1){ // COLLECT DATA |
vtoffoli | 2:dbe2cc9e3b23 | 158 | pc.printf("Data collecting, please wait 3 minute \t\r\n"); |
vtoffoli | 2:dbe2cc9e3b23 | 159 | index=0; clear_array(data_array, sample_num); |
vtoffoli | 2:dbe2cc9e3b23 | 160 | tck.attach(&fill_array, sample_time); // the address of the function to be attached (array_fill) and the interval (1 seconds) |
vtoffoli | 2:dbe2cc9e3b23 | 161 | while(index <= 127){ |
vtoffoli | 2:dbe2cc9e3b23 | 162 | result = accl.scanx(); |
vtoffoli | 2:dbe2cc9e3b23 | 163 | data_array[index] = accl.accelScale(result, 12); |
vtoffoli | 2:dbe2cc9e3b23 | 164 | time_array[index] = t.read(); |
vtoffoli | 2:dbe2cc9e3b23 | 165 | //pc.printf("Data index %d \t \r\n", index); |
vtoffoli | 2:dbe2cc9e3b23 | 166 | } |
vtoffoli | 2:dbe2cc9e3b23 | 167 | tck.attach(NULL, 10); // stop to call the function (array_fill) |
vtoffoli | 2:dbe2cc9e3b23 | 168 | for(int j = 0; j < 128; j++){ dt_array[j+1] = time_array[j+1]-time_array[j];} |
vtoffoli | 2:dbe2cc9e3b23 | 169 | pc.printf("data \t \r\n"); |
vtoffoli | 2:dbe2cc9e3b23 | 170 | for(int j = 0; j < 128; j++){ pc.printf("%6f \t %6f \t %6f \t \r\n", data_array[j], time_array[j], dt_array[j+1]);} |
vtoffoli | 2:dbe2cc9e3b23 | 171 | } |
vtoffoli | 2:dbe2cc9e3b23 | 172 | t.stop(); |
vtoffoli | 2:dbe2cc9e3b23 | 173 | if(!btn2){ // PERFORM FFT |
vtoffoli | 2:dbe2cc9e3b23 | 174 | led2 = !led2 ; |
vtoffoli | 2:dbe2cc9e3b23 | 175 | pc.printf("x[n] data fft \t \r\n"); |
vtoffoli | 2:dbe2cc9e3b23 | 176 | for(int j = 0; j < 128; j++){ |
vtoffoli | 2:dbe2cc9e3b23 | 177 | fft_array[j] = data_array[j]; |
vtoffoli | 2:dbe2cc9e3b23 | 178 | pc.printf("real part \t %6f \t imaginary part \t %6f \t \r\n", fft_array[j].real(), fft_array[j].imag());} |
vtoffoli | 2:dbe2cc9e3b23 | 179 | fft.fourier(fft_array, 128, sample_time); |
vtoffoli | 2:dbe2cc9e3b23 | 180 | pc.printf("X[f] data fft \t \r\n"); |
vtoffoli | 2:dbe2cc9e3b23 | 181 | for(int j = 0; j < 128; j++){ |
vtoffoli | 2:dbe2cc9e3b23 | 182 | pc.printf("real part \t %6f \t imaginary part \t %6f \t \r\n", fft_array[j].real(), fft_array[j].imag());} |
vtoffoli | 2:dbe2cc9e3b23 | 183 | } |
vtoffoli | 2:dbe2cc9e3b23 | 184 | } |
vtoffoli | 2:dbe2cc9e3b23 | 185 | pc.printf("Analog AD sensor Demo: STOP\n"); |
vtoffoli | 2:dbe2cc9e3b23 | 186 | } |