Dependencies: Harmonic_analyzer
main.cpp
- Committer:
- nmaududi
- Date:
- 2019-10-29
- Revision:
- 1:d0115b825d39
- Parent:
- 0:05e2c9ca68e2
File content as of revision 1:d0115b825d39:
/*---------------------------------------------------------------------------- Code to generate a 1004Hz tone and complete a harmonic analysis on the output Note that the PWM output produces the 1004 Hz tone and is routed back into the analog input to complete harmonic analysis. In the hardware, the output of the PWM is routed to the analog in by a jumber wire. Generate a 1004Hz tone with PWM, No DAC present within the board. PWM is the software DAC implementation in order to generate the sine wave ------------------------------------------------------------------------------- Note parts of the Code was borrowed online from: Wim Huiskamp https://os.mbed.com/users/wim/code/SineFromPWM/file/d274003b52e7/main.cpp/ -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- Parts of the FFT analysis code was borrowed from Martin Simpson ---------------------------------------- Note parts of the Code was borrowed online from: Martin Simpson https://os.mbed.com/users/martinsimpson/code/CMSIS_FFT_mbed_os_DAC/file/05e2c9ca68e2/main.cpp/ *----------------------------------------------------------------------------*/ #include "mbed.h" /* Include arm_math.h mathematic functions */ #include "arm_math.h" /* Include mbed-dsp libraries */ #include "arm_common_tables.h" #include "arm_const_structs.h" #include "math_helper.h" /* FFT settings */ #define SAMPLES 512 /* 256 real party and 256 imaginary parts */ #define FFT_SIZE SAMPLES / 2 /* FFT size is always the same size as we have samples, so 256 in our case */ //Number of dutycycle steps for output wave #define SINE_STEPS 32 //Frequency of output sine in Hz #define SINE_OUT_FREQ 1004 //Constants to compute the sine waveform //#define PI 3.141592f #define SINE_STEPS_RAD (2.0f * PI / (float)SINE_STEPS) //Table to generate the sine waveform using dutycycles float sine_duty[SINE_STEPS]; //Frequency of Pulse Width Modulated signal in Hz #define PWM_FREQ 200000 //Sampling rate for FFT (50KHz) #define FFT_SAMP_FREQ 10000 //Ticker to update the PWM dutycycle Ticker pwm_ticker; /* Global variables */ float32_t Input[SAMPLES]; float32_t Output[FFT_SIZE]; bool trig=0; /* MBED class APIs */ PwmOut led(LED1); AnalogIn myADC(PA_4); //PWM pin PwmOut PwmPin (PB_3); // set this pin for the analog output tone for the sine wave //AnalogOut myDAC(D13); Serial pc(USBTX, USBRX); Ticker timer; static int idx=0; void sample(){ trig=1; } //Ticker calls this fucntion to update the PWM dutycycle void pwm_duty_updater() { PwmPin.write(sine_duty[idx]); // Set the dutycycle % to next value in array idx++; // Increment the idx if (idx == SINE_STEPS) idx=0; // Reset the idx when the end has been reached } int main() { int i; // Init the duty cycle array for (i=0; i<SINE_STEPS; i++) { sine_duty[i] = ( sin(i * SINE_STEPS_RAD) + 1.0f ) / 2.0f; // convert sine (-1.0 .. +1.0) into dutycycle (0.0 .. 1.0) } // Set PWM frequency to 200 KHz (period = 5 us) PwmPin.period( 1.0f / (float) PWM_FREQ); // Init the Ticker to call the dutycyle updater at the required interval // The update should be at (SINE_STEPS * SINE_OUT_FREQ) pwm_ticker.attach(&pwm_duty_updater, 1.0f / (float)(SINE_STEPS * SINE_OUT_FREQ)); //arm_cfft_instance_f32 S; // ARM CFFT module float maxValue; // Max FFT value is stored here float maxIndex; // Index in Output array where max value is bool once=0; pc.baud(9600); pc.printf("Starting FFT\r\n"); timer.attach_us(&sample,100); //20us 50KHz sampling rate for (int i = 0; i < SAMPLES; i += 2) { while (trig==0){} trig=0; Input[i] = myADC.read(); //Real part NB Input[i + 1] = 0; //Imaginary Part set to zero } timer.detach(); // Init the Complex FFT module, intFlag = 0, doBitReverse = 1 //NB using predefined arm_cfft_sR_f32_lenXXX, in this case XXX is 256 arm_cfft_f32(&arm_cfft_sR_f32_len256, Input, 0, 1); // Complex Magniture Module put results into Output(Half size of the Input) arm_cmplx_mag_f32(Input, Output, FFT_SIZE); // DC values present, need to remove that portion for (int i = 0; i < 127; ++i) Output[i] = Output[i + 1]; // copy next element left //Calculates maxValue and returns corresponding value maxValue = Output[0]; maxIndex = 0; for (int i=0; i<FFT_SIZE/2 ; i++){ if (Output[i]>maxValue){ maxValue = Output[i]; maxIndex = i; } } led.period( 1.0/ (((10000.0/2.0)/128.00)*maxIndex+39.06)*1000);// LED blinking at 1 sec if fundamental frequency is 1004 Hz led.write(0.5f); // 50% duty cycle, relative to period float freq_bin; if (once==0){ for (int i=0; i<FFT_SIZE/2 ; i++){ freq_bin = ((FFT_SAMP_FREQ /2)/128.00)*i+39.06; // DC value shows up in the FFT analysis, removing the DC part, as result, need to add 39.68 Hz pc.printf("Frequency bin is %f\r\n",freq_bin); //Each bin 10KHz/2/128 = 39.06Hz resolution wait_us(100); pc.printf("Maximum output is %f\r\n",(Output[i]/maxValue)*0.9f); wait_us(100); } once = 1; } }