Revised_10_29_2019

Dependencies:   Harmonic_analyzer

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

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 }