Magnitude spectrum:

This sample implements a single-channel magnitude spectrum. The code is split into two tasks: a control task, which collects the discrete input signal of a hardware module, e.g. EL3632, and a CM task, which calculates the spectrum. The block diagram below shows the analysis chain implemented in the sample.

The source code for the sample is available for download from here:
MagnitudeSpectrum_Sample.zip

Block Diagram

Magnitude spectrum: 1:

Program parameters

The table below shows a list of important parameters for the configuration of the magnitude spectrum function block.

FFT-length

4096

Window size

3200

Buffer size

1600

Window type

eCM_HannWindow

Scaling type

eCM_ROOT_POWER_SUM

Scaling in decibels (dB)

FALSE

Global Constants

These parameters are defined as constants in the list of global variables.

VAR_GLOBAL CONSTANT
    cOversamples       : UDINT := 10;      // oversampling factor
    cBufferLength      : UDINT := 1600;    // size of buffer for spectrum
    cWindowLength      : UDINT := 3200;   // size of window
    cFFTResult         : UDINT := 2049;   // size of spectrum result
    cFFTLength         : UDINT := 4096;   // spectrum lines
END_VAR

Code for control task

The following code snippet shows the declaration in the MAIN program:

PROGRAM MAIN

VAR CONSTANT 
    cInitSource   : ST_MA_MultiArray_InitPars := ( eTypeCode := eMA_TypeCode_LREAL, nDims := 1, aDimSizes := [cBufferLength]);
END_VAR

VAR
     nInputSelection   : UDINT := 1; // Switch between hardware and function generator 
     nSample  : UDINT;
     aEl3632 AT %I*    : ARRAY[1..cOversamples] OF INT; // Input from hardware e.g. EL3632
     aBuffer  : ARRAY[1..cOversamples] OF LREAL; 

     fbSource      : FB_CMA_Source :=( stInitPars := cInitSource, nOwnID := eID_Source, aDestIDs := [eID_Spectrum]); // Initialize source buffers
     fbSink        : FB_CMA_Sink := (nOwnID := eID_Sink); 
     aSpectrumResult   : ARRAY[1..cFFTResult] OF LREAL; // Copy result        
END_VAR

Method calls MAIN program:

fbSource.Input1D(pDataIn := ADR(aBuffer),
               nDataInSize := SIZEOF(aBuffer), 
               eElementType := eMA_TypeCode_LREAL,
               nWorkDim := 0,
               pStartIndex := 0,
               nOptionPars := 0);

fbSink.Output1D(pDataOut := ADR(aSpectrumResult), 
               nDataOutSize := SIZEOF(aSpectrumResult), 
               eElementType := eMA_TypeCode_LREAL, 
               nWorkDim := 0,
               nElements := 0,
               pStartIndex := 0,
               nOptionPars := 0,
               bNewResult => bCalculate);

Code for CM Task

Declaration in MAIN_CM program:

PROGRAM MAIN_CM

VAR CONSTANT
     cInitSpectrum : ST_CM_MagnitudeSpectrum_InitPars := (nFFT_Length := cFFTLength, 
                                    nWindowLength := cWindowLength, 
                                    bTransformToDecibel:= FALSE, 
                                    eWindowType := eCM_HannWindow, 
                                    eScalingType := eCM_RMS);
END_VAR
VAR 
     fbSpectrum : FB_CMA_MagnitudeSpectrum :=(stInitPars := cInitSpectrum, 
                                   nOwnID := eID_Spectrum, 
                                   aDestIDs := [eID_Sink]);
END_VAR

Method calls in MAIN_CM program:

fbSpectrum.Call();

The result of the sample code can be checked for a sinusoidal signal of arbitrary amplitude and frequency as the input signal. The variable, fRmsValue above should be exactly equal to amplitude/SQRT(2).

Each frequency value can be assigned to the corresponding array index of the spectrum result. Calculation formula:
sample rate = oversampling factor / sampling task cycle time
index = frequency * (FFT length / sample rate)

Requirements

Development environment

Target system type

PLC libraries to include

TwinCAT v3.1.4013

PC or CX (x86, x64)

Tc3_CM, Tc3_CM_Base, Tc3_MultiArray