Revised_10_29_2019
Dependencies: Harmonic_analyzer
main.cpp
00001 /*---------------------------------------------------------------------------- 00002 Code to generate a 1004Hz tone and complete a harmonic analysis on the output 00003 Note that the PWM output produces the 1004 Hz tone and is routed back into the 00004 analog input to complete harmonic analysis. In the hardware, the output of the 00005 PWM is routed to the analog in by a jumber wire. 00006 00007 Generate a 1004Hz tone with PWM, No DAC present within the board. PWM is the 00008 software DAC implementation in order to generate the sine wave 00009 ------------------------------------------------------------------------------- 00010 Note parts of the Code was borrowed online from: Wim Huiskamp 00011 https://os.mbed.com/users/wim/code/SineFromPWM/file/d274003b52e7/main.cpp/ 00012 -------------------------------------------------------------------------------- 00013 -------------------------------------------------------------------------------- 00014 Parts of the FFT analysis code was borrowed from Martin Simpson 00015 ---------------------------------------- 00016 Note parts of the Code was borrowed online from: Martin Simpson 00017 https://os.mbed.com/users/martinsimpson/code/CMSIS_FFT_mbed_os_DAC/file/05e2c9ca68e2/main.cpp/ 00018 00019 *----------------------------------------------------------------------------*/ 00020 00021 #include "mbed.h" 00022 /* Include arm_math.h mathematic functions */ 00023 #include "arm_math.h" 00024 /* Include mbed-dsp libraries */ 00025 #include "arm_common_tables.h" 00026 #include "arm_const_structs.h" 00027 #include "math_helper.h" 00028 00029 /* FFT settings */ 00030 #define SAMPLES 512 /* 256 real party and 256 imaginary parts */ 00031 #define FFT_SIZE SAMPLES / 2 /* FFT size is always the same size as we have samples, so 256 in our case */ 00032 00033 //Number of dutycycle steps for output wave 00034 #define SINE_STEPS 32 00035 //Frequency of output sine in Hz 00036 #define SINE_OUT_FREQ 1004 00037 00038 //Constants to compute the sine waveform 00039 //#define PI 3.141592f 00040 #define SINE_STEPS_RAD (2.0f * PI / (float)SINE_STEPS) 00041 00042 //Table to generate the sine waveform using dutycycles 00043 float sine_duty[SINE_STEPS]; 00044 00045 00046 //Frequency of Pulse Width Modulated signal in Hz 00047 #define PWM_FREQ 200000 00048 00049 //Sampling rate for FFT (50KHz) 00050 #define FFT_SAMP_FREQ 10000 00051 00052 //Ticker to update the PWM dutycycle 00053 Ticker pwm_ticker; 00054 00055 /* Global variables */ 00056 float32_t Input[SAMPLES]; 00057 float32_t Output[FFT_SIZE]; 00058 bool trig=0; 00059 /* MBED class APIs */ 00060 PwmOut led(LED1); 00061 AnalogIn myADC(PA_4); 00062 //PWM pin 00063 PwmOut PwmPin (PB_3); // set this pin for the analog output tone for the sine wave 00064 //AnalogOut myDAC(D13); 00065 Serial pc(USBTX, USBRX); 00066 Ticker timer; 00067 static int idx=0; 00068 void sample(){ 00069 trig=1; 00070 } 00071 00072 //Ticker calls this fucntion to update the PWM dutycycle 00073 void pwm_duty_updater() { 00074 00075 00076 PwmPin.write(sine_duty[idx]); // Set the dutycycle % to next value in array 00077 idx++; // Increment the idx 00078 if (idx == SINE_STEPS) idx=0; // Reset the idx when the end has been reached 00079 00080 } 00081 00082 int main() { 00083 00084 int i; 00085 00086 // Init the duty cycle array 00087 for (i=0; i<SINE_STEPS; i++) { 00088 sine_duty[i] = ( sin(i * SINE_STEPS_RAD) + 1.0f ) / 2.0f; // convert sine (-1.0 .. +1.0) into dutycycle (0.0 .. 1.0) 00089 } 00090 00091 // Set PWM frequency to 200 KHz (period = 5 us) 00092 PwmPin.period( 1.0f / (float) PWM_FREQ); 00093 00094 // Init the Ticker to call the dutycyle updater at the required interval 00095 // The update should be at (SINE_STEPS * SINE_OUT_FREQ) 00096 pwm_ticker.attach(&pwm_duty_updater, 1.0f / (float)(SINE_STEPS * SINE_OUT_FREQ)); 00097 00098 //arm_cfft_instance_f32 S; // ARM CFFT module 00099 float maxValue; // Max FFT value is stored here 00100 float maxIndex; // Index in Output array where max value is 00101 bool once=0; 00102 pc.baud(9600); 00103 pc.printf("Starting FFT\r\n"); 00104 timer.attach_us(&sample,100); //20us 50KHz sampling rate 00105 for (int i = 0; i < SAMPLES; i += 2) { 00106 while (trig==0){} 00107 trig=0; 00108 Input[i] = myADC.read(); //Real part NB 00109 Input[i + 1] = 0; //Imaginary Part set to zero 00110 } 00111 timer.detach(); 00112 // Init the Complex FFT module, intFlag = 0, doBitReverse = 1 00113 //NB using predefined arm_cfft_sR_f32_lenXXX, in this case XXX is 256 00114 arm_cfft_f32(&arm_cfft_sR_f32_len256, Input, 0, 1); 00115 00116 // Complex Magniture Module put results into Output(Half size of the Input) 00117 arm_cmplx_mag_f32(Input, Output, FFT_SIZE); 00118 // DC values present, need to remove that portion 00119 for (int i = 0; i < 127; ++i) 00120 Output[i] = Output[i + 1]; // copy next element left 00121 00122 //Calculates maxValue and returns corresponding value 00123 maxValue = Output[0]; 00124 maxIndex = 0; 00125 for (int i=0; i<FFT_SIZE/2 ; i++){ 00126 if (Output[i]>maxValue){ 00127 maxValue = Output[i]; 00128 maxIndex = i; 00129 } 00130 } 00131 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 00132 led.write(0.5f); // 50% duty cycle, relative to period 00133 float freq_bin; 00134 if (once==0){ 00135 for (int i=0; i<FFT_SIZE/2 ; i++){ 00136 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 00137 pc.printf("Frequency bin is %f\r\n",freq_bin); //Each bin 10KHz/2/128 = 39.06Hz resolution 00138 wait_us(100); 00139 pc.printf("Maximum output is %f\r\n",(Output[i]/maxValue)*0.9f); 00140 wait_us(100); 00141 } 00142 once = 1; 00143 } 00144 }
Generated on Thu Jul 28 2022 07:58:15 by
1.7.2