#include <otSerial.h> #include <otMalloc.h> #include <otPrintf.h> #include <otTimer.h> #include <otMalloc.h> #include <otADS868x.h> #include <otFFT.h> #include <otMath.h> /* ITALIAN --- Per questo semplice esperimento collega un filo di qualche centimetro al connettore Y9. L'alta impedenza del campionatore A/D catturerá facilmente il segnale a 50Hz (o 60Hz) della rete e visualizzerá tutte le sue armoniche. Non vedrai un valore preciso della frequenza di rete, questa cambia continuamente con una massima fluttuazione di +/- 0.5Hz ENGLISH --- For this simple experiment, connect a few inches of wire to connector Y9. The high impedance of the A/D sampler will easily capture the network's 50Hz (or 60Hz) signal and display all its harmonics. You will not see a precise value of the mains frequency, this changes continuously with a maximum fluctuation of +/- 0.5Hz */ #define PEAKS 8 // Maximum number of peaks to detect #define SAMPLES 1024 // Number of sampled data #define SAMPLING 1000 // Smapling period as us #define FREQUENCY (1E6 / SAMPLING) // Sampling frequency F64 * vReal; // Real part for FFT F64 * vImag; // Imaginary part for FFT int emissionPeak[PEAKS]; // Emission peaks found int absorptionPeak[PEAKS]; // Absorption peaks found int nEmission; // Number of emission peaks found int nAbsorption; // Number of absorption peaks found otADS868x adc; // The ADC sampler otFFT fft; // FFT library // Peak detector int detect_peak( const double * data, // The data int data_count, // Row count of data int * emi_peaks, // Emission peaks will be put here int * num_emi_peaks, // Number of emission peaks found int max_emi_peaks, // Maximum number of emission peaks int * absop_peaks, // Absorption peaks will be put here int * num_absop_peaks, // Number of absorption peaks found int max_absop_peaks, // Maximum number of absorption peaks double delta, // Delta used for distinguishing peaks int emi_first // Should we search emission peak first of absorption peak first? ) { int i; double mx; double mn; int mx_pos = 0; int mn_pos = 0; int is_detecting_emi = emi_first; mx = data[0]; mn = data[0]; *num_emi_peaks = 0; *num_absop_peaks = 0; for(i = 1; i < data_count; ++i) { if(data[i] > mx) { mx_pos = i; mx = data[i]; } if(data[i] < mn) { mn_pos = i; mn = data[i]; } if(is_detecting_emi && data[i] < mx - delta) { if(*num_emi_peaks >= max_emi_peaks) // not enough spaces return 1; emi_peaks[*num_emi_peaks] = mx_pos; ++ (*num_emi_peaks); is_detecting_emi = 0; i = mx_pos - 1; mn = data[mx_pos]; mn_pos = mx_pos; } else if((!is_detecting_emi) && data[i] > mn + delta) { if(*num_absop_peaks >= max_absop_peaks) return 2; absop_peaks[*num_absop_peaks] = mn_pos; ++ (*num_absop_peaks); is_detecting_emi = 1; i = mn_pos - 1; mx = data[mn_pos]; mx_pos = mn_pos; } } return 0; } void setup() { UartEnableSignals(UART0); UartSetBaud(UART0, 115200); setStdout(4096, UART0); // printf output is now directed on UART0 TimerSetAsCounter(TIMER0); TimerEnable(TIMER0, true); DelayMs(1000); adc.init(); // Set ADC range adc.setRange(otADS868x::UNI_5V); vReal = (F64 *) _malloc(sizeof(F64) * SAMPLES); vImag = (F64 *) _malloc(sizeof(F64) * SAMPLES); fft.create(vReal, vImag, SAMPLES, FREQUENCY); printf("Started ...\n"); } void loop() { U32 i; F64 f, v; // Sample adc.read(vReal, SAMPLES, SAMPLING, TIMER0); fft.clearImaginary(); // Weigh data fft.windowing(otFFT::FFT_WIN_TYP_HAMMING, otFFT::FFT_FORWARD); fft.compute(otFFT::FFT_FORWARD); fft.complexToMagnitude(); i = fft.majorPeak(f, v); printf("F = %8.3lf Hz, Vpp = %8.3lf mV, Phase = %5.1lf\n", f, v / 2000.0, RAD_TO_DEG(atan2(vImag[i], vReal[i]))); detect_peak(vReal, SAMPLES, emissionPeak, &nEmission, PEAKS, absorptionPeak, &nAbsorption, PEAKS, 1000000, 1); if(nEmission > 2) // Not display f = 0 and fundamentals { for(int i = 2; i < nEmission; i++) printf("\tF(%d) = %8.3lf Hz\n", i, fft.frequency(emissionPeak[i])); } } /* PROGRAM OUTPUT ************************************************************** F = 50.168 Hz, Vpp = 4979.356 mV, Phase = -43.3 F(2) = 100.515 Hz F(3) = 150.641 Hz F(4) = 200.930 Hz F(5) = 251.163 Hz F(6) = 301.302 Hz F(7) = 401.805 Hz F = 50.167 Hz, Vpp = 4984.208 mV, Phase = -40.8 F(2) = 100.508 Hz F(3) = 150.640 Hz F(4) = 200.910 Hz F(5) = 251.170 Hz F(6) = 301.277 Hz F(7) = 401.783 Hz F = 50.169 Hz, Vpp = 4977.858 mV, Phase = -43.7 F(2) = 100.518 Hz F(3) = 150.643 Hz F(4) = 200.935 Hz F(5) = 251.172 Hz F(6) = 301.294 Hz F(7) = 401.803 Hz F = 50.180 Hz, Vpp = 4909.965 mV, Phase = -25.4 F(2) = 100.535 Hz F(3) = 150.664 Hz F(4) = 200.998 Hz F(5) = 251.200 Hz F(6) = 301.362 Hz F(7) = 401.862 Hz F = 50.182 Hz, Vpp = 4864.171 mV, Phase = 12.5 F(2) = 100.530 Hz F(3) = 150.662 Hz F(4) = 200.997 Hz F(5) = 251.199 Hz F(6) = 301.357 Hz F(7) = 401.856 Hz F = 50.166 Hz, Vpp = 4936.603 mV, Phase = 32.4 F(2) = 100.508 Hz F(3) = 150.635 Hz F(4) = 200.923 Hz F(5) = 251.157 Hz F(6) = 301.290 Hz F(7) = 401.789 Hz F = 50.185 Hz, Vpp = 4888.796 mV, Phase = 41.0 F(2) = 100.538 Hz F(3) = 150.676 Hz F(4) = 201.013 Hz F(5) = 251.220 Hz F(6) = 301.394 Hz F(7) = 401.897 Hz */