FIR Filtering

I have a program which allows me to modulate 700 kHz PWM, output PA7 by signal applied to PA6 as on the drawing. I need to remove yellow jumper and repleace it by filter program - red line.

PWM program

HardwareTimer pwmtimer3(3);

int inputPin = PA6;  // set input pin for the signal
int inputValue = PA6; // potentiometer input variable
int ledPin = PA7;     // set output pin for PA7


void setup() {
  pinMode(PA7, PWM);
  pwmtimer3.pause();
  pwmtimer3.setPrescaleFactor(1);       // Timer input clock Prescaler = 1 (= 72MHz input ?)
  pwmtimer3.setOverflow(100 - 1);          // PWM Period width for 720kHz ?
  pwmtimer3.setCompare(TIMER_CH2, 50);  // PWM High Pulse width is 50% duty (1:1)
  pwmtimer3.refresh();
  pwmtimer3.resume();


}

void loop() {
  // read the value from input pin
  inputValue = analogRead(inputPin);

  // send the square wave signal to PA7
  analogWrite(ledPin, inputValue / 4);
}

Filter code

#include <stdio.h>
#include <stdint.h>
 
//////////////////////////////////////////////////////////////
//  Filter Code Definitions
//////////////////////////////////////////////////////////////
 
// maximum number of inputs that can be handled
// in one function call
#define MAX_INPUT_LEN   80
// maximum length of filter than can be handled
#define MAX_FLT_LEN     63
// buffer to hold all of the input samples
#define BUFFER_LEN      (MAX_FLT_LEN - 1 + MAX_INPUT_LEN)
 
// array to hold input samples
double insamp[ BUFFER_LEN ];
 
// FIR init
void firFloatInit( void )
{
    memset( insamp, 0, sizeof( insamp ) );
}
 
// the FIR filter function
void firFloat( double *coeffs, double *input, double *output,
       int length, int filterLength )
{
    double acc;     // accumulator for MACs
    double *coeffp; // pointer to coefficients
    double *inputp; // pointer to input samples
    int n;
    int k;
 
    // put the new samples at the high end of the buffer
    memcpy( &insamp[filterLength - 1], input,
            length * sizeof(double) );
 
    // apply the filter to each input sample
    for ( n = 0; n < length; n++ ) {
        // calculate output n
        coeffp = coeffs;
        inputp = &insamp[filterLength - 1 + n];
        acc = 0;
        for ( k = 0; k < filterLength; k++ ) {
            acc += (*coeffp++) * (*inputp--);
        }
        output[n] = acc;
    }
    // shift input samples back in time for next time
    memmove( &insamp[0], &insamp[length],
            (filterLength - 1) * sizeof(double) );
 
}
 
//////////////////////////////////////////////////////////////
//  Test program
//////////////////////////////////////////////////////////////
 
// bandpass filter centred around 1000 Hz
// sampling rate = 8000 Hz
 
#define FILTER_LEN  63
double coeffs[ FILTER_LEN ] =
{
  -0.0448093,  0.0322875,   0.0181163,   0.0087615,   0.0056797,
   0.0086685,  0.0148049,   0.0187190,   0.0151019,   0.0027594,
  -0.0132676, -0.0232561,  -0.0187804,   0.0006382,   0.0250536,
   0.0387214,  0.0299817,   0.0002609,  -0.0345546,  -0.0525282,
  -0.0395620,  0.0000246,   0.0440998,   0.0651867,   0.0479110,
   0.0000135, -0.0508558,  -0.0736313,  -0.0529380,  -0.0000709,
   0.0540186,  0.0766746,   0.0540186,  -0.0000709,  -0.0529380,
  -0.0736313, -0.0508558,   0.0000135,   0.0479110,   0.0651867,
   0.0440998,  0.0000246,  -0.0395620,  -0.0525282,  -0.0345546,
   0.0002609,  0.0299817,   0.0387214,   0.0250536,   0.0006382,
  -0.0187804, -0.0232561,  -0.0132676,   0.0027594,   0.0151019,
   0.0187190,  0.0148049,   0.0086685,   0.0056797,   0.0087615,
   0.0181163,  0.0322875,  -0.0448093
};
 
void intToFloat( int16_t *input, double *output, int length )
{
    int i;
 
    for ( i = 0; i < length; i++ ) {
        output[i] = (double)input[i];
    }
}
 
void floatToInt( double *input, int16_t *output, int length )
{
    int i;
 
    for ( i = 0; i < length; i++ ) {
        if ( input[i] > 32767.0 ) {
            input[i] = 32767.0;
        } else if ( input[i] < -32768.0 ) {
            input[i] = -32768.0;
        }
        // convert
        output[i] = (int16_t)input[i];
    }
}
 
// number of samples to read per loop
#define SAMPLES   80
 
int main( void )
{
    int size;
    int16_t input[SAMPLES];
    int16_t output[SAMPLES];
    double floatInput[SAMPLES];
    double floatOutput[SAMPLES];
    FILE   *in_fid;
    FILE   *out_fid;
 
    // open the input waveform file
    in_fid = fopen( "input.pcm", "rb" );
    if ( in_fid == 0 ) {
        printf("couldn't open input.pcm");
        return - 1;
    }
 
    // open the output waveform file
    out_fid = fopen( "outputFloat.pcm", "wb" );
    if ( out_fid == 0 ) {
        printf("couldn't open outputFloat.pcm");
        return -1;
    }
 
    // initialize the filter
    firFloatInit();
 
    // process all of the samples
    do {
        // read samples from file
        size = fread( input, sizeof(int16_t), SAMPLES, in_fid );
        // convert to doubles
        intToFloat( input, floatInput, size );
        // perform the filtering
        firFloat( coeffs, floatInput, floatOutput, size,
               FILTER_LEN );
        // convert to ints
        floatToInt( floatOutput, output, size );
        // write samples to file
        fwrite( output, sizeof(int16_t), size, out_fid );
    } while ( size != 0 );
 
    fclose( in_fid );
    fclose( out_fid );
 
    return 0;
}

red.jpg

red.jpg

I need to remove yellow jumper

Are you wearing a yellow jumper? In my country, people named Ted do not wear yellow jumpers. Red, pink, blue, green, yes. But not yellow. If you are wearing one, feel free to remove it.

Or, explain what yellow jumper you are talking about.

PA6 in program is connected to PWM modulator should be connected to input of the filter and output of the filter should be connected to PWM modulator.
The question is how to do it ?

Can you correct your post please?
I can't believe you typed all that in italics.

PA6 in program is connected to PWM modulator

OK.

should be connected to input of the filter

So, your "filter" is hardware? You can't connect a wire to software.

and output of the filter should be connected to PWM modulator.

OK.

The question is how to do it ?

And that is a programming question? How?

The filter is a software - filter code.

ted:
The filter is a software - filter code.

Then, any talk about moving wires is silly.

You have some input that you currently do nothing with/to before passing it to the output pin. You want to change that, so that what you pass to the output pin is not necessarily the same as the input.

   int inputVal = analogRead(PA6);
   int outputVal = firFilter(inputVal);
   analogWrite(PA7, outputVal);

Just write the firFilter() function, and you are done.

The results of my attempts and errors.
720_ok:59: error: ‘inputVal’ was not declared in this scope

int outputVal = firFilter(inputVal);

^

_720_ok:59: error: ‘firFilter’ was not declared in this scope

int outputVal = firFilter(inputVal);

^

_720_ok:62: error: redefinition of ‘int inputValue’

int inputValue = PA6; // potentiometer input variable

^

_720_ok:58: error: ‘int inputValue’ previously defined here

int inputValue = PA6; // potentiometer input variable

^

C:\Users\OWNER\Documents\Arduino_720_ok_720_ok.ino: In function ‘void loop()’:

_720_ok:181: error: ‘inputVal’ was not declared in this scope

outputVal = firFilter(inputVal);

^

_720_ok:181: error: ‘firFilter’ was not declared in this scope

outputVal = firFilter(inputVal);

^

exit status 1
‘inputVal’ was not declared in this scope

HardwareTimer pwmtimer3(3);
HardwareTimer pwmtimer2(2);
#include <stdio.h>
#include <stdint.h>
 
//////////////////////////////////////////////////////////////
//  Filter Code Definitions
//////////////////////////////////////////////////////////////
 
// maximum number of inputs that can be handled
// in one function call
#define MAX_INPUT_LEN   80
// maximum length of filter than can be handled
#define MAX_FLT_LEN     63
// buffer to hold all of the input samples
#define BUFFER_LEN      (MAX_FLT_LEN - 1 + MAX_INPUT_LEN)
 
// array to hold input samples
double insamp[ BUFFER_LEN ];
 
// FIR init
void firFloatInit( void )
{
    memset( insamp, 0, sizeof( insamp ) );
}
 
// the FIR filter function
void firFloat( double *coeffs, double *input, double *output,
       int length, int filterLength )
{
    double acc;     // accumulator for MACs
    double *coeffp; // pointer to coefficients
    double *inputp; // pointer to input samples
    int n;
    int k;
 
    // put the new samples at the high end of the buffer
    memcpy( &insamp[filterLength - 1], input,
            length * sizeof(double) );
 
    // apply the filter to each input sample
    for ( n = 0; n < length; n++ ) {
        // calculate output n
        coeffp = coeffs;
        inputp = &insamp[filterLength - 1 + n];
        acc = 0;
        for ( k = 0; k < filterLength; k++ ) {
            acc += (*coeffp++) * (*inputp--);
        }
        output[n] = acc;
    }
    // shift input samples back in time for next time
    memmove( &insamp[0], &insamp[length],
            (filterLength - 1) * sizeof(double) );
 
}
int input=analogRead(PA6);
int inputValue = PA6; // potentiometer input variable
int outputVal = firFilter(inputVal);
//analogWrite(PA7, outputVal);
int inputPin = PA6;  // set input pin for the potentiometer
int inputValue = PA6; // potentiometer input variable
int ledPin = PA7;     // set output pin for the LED


//  Test program
//////////////////////////////////////////////////////////////
 
// bandpass filter centred around 1000 Hz
// sampling rate = 8000 Hz
 
#define FILTER_LEN  63
double coeffs[ FILTER_LEN ] =
{
  -0.0448093,  0.0322875,   0.0181163,   0.0087615,   0.0056797,
   0.0086685,  0.0148049,   0.0187190,   0.0151019,   0.0027594,
  -0.0132676, -0.0232561,  -0.0187804,   0.0006382,   0.0250536,
   0.0387214,  0.0299817,   0.0002609,  -0.0345546,  -0.0525282,
  -0.0395620,  0.0000246,   0.0440998,   0.0651867,   0.0479110,
   0.0000135, -0.0508558,  -0.0736313,  -0.0529380,  -0.0000709,
   0.0540186,  0.0766746,   0.0540186,  -0.0000709,  -0.0529380,
  -0.0736313, -0.0508558,   0.0000135,   0.0479110,   0.0651867,
   0.0440998,  0.0000246,  -0.0395620,  -0.0525282,  -0.0345546,
   0.0002609,  0.0299817,   0.0387214,   0.0250536,   0.0006382,
  -0.0187804, -0.0232561,  -0.0132676,   0.0027594,   0.0151019,
   0.0187190,  0.0148049,   0.0086685,   0.0056797,   0.0087615,
   0.0181163,  0.0322875,  -0.0448093
};
 
void intToFloat( int16_t *input, double *output, int length )
{
    int i;
 
    for ( i = 0; i < length; i++ ) {
        output[i] = (double)input[i];
    }
}
 
void floatToInt( double *input, int16_t *output, int length )
{
    int i;
 
    for ( i = 0; i < length; i++ ) {
        if ( input[i] > 32767.0 ) {
            input[i] = 32767.0;
        } else if ( input[i] < -32768.0 ) {
            input[i] = -32768.0;
        }
        // convert
        output[i] = (int16_t)input[i];
    }
}
 
// number of samples to read per loop
#define SAMPLES   80
 
int main( void )
{
    int size;
    int16_t input[SAMPLES];
    int16_t output[SAMPLES];
    double floatInput[SAMPLES];
    double floatOutput[SAMPLES];
    FILE   *in_fid;
    FILE   *out_fid;
 
    // open the input waveform file
    in_fid = fopen( "input.pcm", "rb" );
    if ( in_fid == 0 ) {
        printf("couldn't open input.pcm");
        return -1;
    }
 
    // open the output waveform file
    out_fid = fopen( "outputFloat.pcm", "wb" );
    if ( out_fid == 0 ) {
        printf("couldn't open outputFloat.pcm");
        return -1;
    }
 
    // initialize the filter
    firFloatInit();
 
    // process all of the samples
    do {
        // read samples from file
        size = fread( input, sizeof(int16_t), SAMPLES, in_fid );
        // convert to doubles
        intToFloat( input, floatInput, size );
        // perform the filtering
        firFloat( coeffs, floatInput, floatOutput, size,
               FILTER_LEN );
        // convert to ints
        floatToInt( floatOutput, output, size );
        // write samples to file
        fwrite( output, sizeof(int16_t), size, out_fid );
    } while ( size != 0 );
 
    fclose( in_fid );
    fclose( out_fid );
 
    return 0;
}


void setup() {
  pinMode(PA7, PWM);
  pwmtimer3.pause();
  pwmtimer3.setPrescaleFactor(1);       // Timer input clock Prescaler = 1 (= 72MHz input ?)
  pwmtimer3.setOverflow(100 - 1);          // PWM Period width for 720kHz ?
  pwmtimer3.setCompare(TIMER_CH2, 50);  // PWM High Pulse width is 50% duty (1:1)
  pwmtimer3.refresh();
  pwmtimer3.resume();


}

void loop() {
  // read the value from the potentiometer:
  inputValue = analogRead(inputPin);
  outputVal = firFilter(inputVal);
analogWrite(PA7, outputVal);
  // send the square wave signal to the LED:
  //analogWrite(ledPin, inputValue / 4);



}

That code is a train wreck. All you did was mash together a program (written in standard C) that filters pre-recorded data stored in a file system with an Arduino sketch that reads data from an input pin one value at a time and writes it out a different pin.

I don’ see any hope of getting that to work. At best, someone could study the filter algorithm and figure out how to adapt it for streaming data. Better to learn how to implement a digital filter (volumes have been written) or find example code (written as an Arduino sketch) that works for streaming data.

a train wreck - I agree.
Better to learn - I Am doing that but progress is slow, it is hard to find similar applications for filter above 1 kHz, this is the only the one which I have find but no input and output pins in it.

Don't know anything about this library, but it was the first hit when Googling "arduino FIR filter":

A place to start anyway.

So I change the method, adding recommended by post #7 step by step I mark them as adding: #1, #2, on beginning and #3, #4 at the end.

I have only one error.

sawn_filter_orginal:14: error: ‘firFilter’ was not declared in this scope

int outputVal = firFilter(inputVal);

^

exit status 1
‘firFilter’ was not declared in this scope

#include <stdio.h>
#include <stdint.h>
 /*to be added
    int inputVal = analogRead(PA6);
   int outputVal = firFilter(inputVal);
   analogWrite(PA7, outputVal);
  */
  
// adding #1
int inputPin = PA6;  // set input pin for the signal
int inputValue = PA6; // potentiometer input variable
int ledPin = PA7;     // set output pin for PA7


//adding#2
   int inputVal = analogRead(PA6);
   int outputVal = firFilter(inputVal);

//////////////////////////////////////////////////////////////
//  Filter Code Definitions
//////////////////////////////////////////////////////////////
 
// maximum number of inputs that can be handled
// in one function call
#define MAX_INPUT_LEN   80
// maximum length of filter than can be handled
#define MAX_FLT_LEN     63
// buffer to hold all of the input samples
#define BUFFER_LEN      (MAX_FLT_LEN - 1 + MAX_INPUT_LEN)
 
// array to hold input samples
double insamp[ BUFFER_LEN ];
 
// FIR init
void firFloatInit( void )
{
    memset( insamp, 0, sizeof( insamp ) );
}
 
// the FIR filter function
void firFloat( double *coeffs, double *input, double *output,
       int length, int filterLength )
{
    double acc;     // accumulator for MACs
    double *coeffp; // pointer to coefficients
    double *inputp; // pointer to input samples
    int n;
    int k;
 
    // put the new samples at the high end of the buffer
    memcpy( &insamp[filterLength - 1], input,
            length * sizeof(double) );
 
    // apply the filter to each input sample
    for ( n = 0; n < length; n++ ) {
        // calculate output n
        coeffp = coeffs;
        inputp = &insamp[filterLength - 1 + n];
        acc = 0;
        for ( k = 0; k < filterLength; k++ ) {
            acc += (*coeffp++) * (*inputp--);
        }
        output[n] = acc;
    }
    // shift input samples back in time for next time
    memmove( &insamp[0], &insamp[length],
            (filterLength - 1) * sizeof(double) );
 
}
 
//////////////////////////////////////////////////////////////
//  Test program
//////////////////////////////////////////////////////////////
 
// bandpass filter centred around 1000 Hz
// sampling rate = 8000 Hz
 
#define FILTER_LEN  63
double coeffs[ FILTER_LEN ] =
{
  -0.0448093,  0.0322875,   0.0181163,   0.0087615,   0.0056797,
   0.0086685,  0.0148049,   0.0187190,   0.0151019,   0.0027594,
  -0.0132676, -0.0232561,  -0.0187804,   0.0006382,   0.0250536,
   0.0387214,  0.0299817,   0.0002609,  -0.0345546,  -0.0525282,
  -0.0395620,  0.0000246,   0.0440998,   0.0651867,   0.0479110,
   0.0000135, -0.0508558,  -0.0736313,  -0.0529380,  -0.0000709,
   0.0540186,  0.0766746,   0.0540186,  -0.0000709,  -0.0529380,
  -0.0736313, -0.0508558,   0.0000135,   0.0479110,   0.0651867,
   0.0440998,  0.0000246,  -0.0395620,  -0.0525282,  -0.0345546,
   0.0002609,  0.0299817,   0.0387214,   0.0250536,   0.0006382,
  -0.0187804, -0.0232561,  -0.0132676,   0.0027594,   0.0151019,
   0.0187190,  0.0148049,   0.0086685,   0.0056797,   0.0087615,
   0.0181163,  0.0322875,  -0.0448093
};
 
void intToFloat( int16_t *input, double *output, int length )
{
    int i;
 
    for ( i = 0; i < length; i++ ) {
        output[i] = (double)input[i];
    }
}
 
void floatToInt( double *input, int16_t *output, int length )
{
    int i;
 
    for ( i = 0; i < length; i++ ) {
        if ( input[i] > 32767.0 ) {
            input[i] = 32767.0;
        } else if ( input[i] < -32768.0 ) {
            input[i] = -32768.0;
        }
        // convert
        output[i] = (int16_t)input[i];
    }
}
 
// number of samples to read per loop
#define SAMPLES   80
 
int main( void )
{
    int size;
    int16_t input[SAMPLES];
    int16_t output[SAMPLES];
    double floatInput[SAMPLES];
    double floatOutput[SAMPLES];
    FILE   *in_fid;
    FILE   *out_fid;
 
    // open the input waveform file
    in_fid = fopen( "input.pcm", "rb" );
    if ( in_fid == 0 ) {
        printf("couldn't open input.pcm");
        return -1;
    }
 
    // open the output waveform file
    out_fid = fopen( "outputFloat.pcm", "wb" );
    if ( out_fid == 0 ) {
        printf("couldn't open outputFloat.pcm");
        return -1;
    }
 
    // initialize the filter
    firFloatInit();
 
    // process all of the samples
    do {
        // read samples from file
        size = fread( input, sizeof(int16_t), SAMPLES, in_fid );
        // convert to doubles
        intToFloat( input, floatInput, size );
        // perform the filtering
        firFloat( coeffs, floatInput, floatOutput, size,
               FILTER_LEN );
        // convert to ints
        floatToInt( floatOutput, output, size );
        // write samples to file
        fwrite( output, sizeof(int16_t), size, out_fid );
    } while ( size != 0 );
 
    fclose( in_fid );
    fclose( out_fid );
 
    return 0;
}


//adding#3
void loop() {
  // read the value from input pin
  inputValue = analogRead(inputPin);

  // send the square wave signal to PA7
  analogWrite(ledPin, inputValue / 4);

  
  //adding #4
   analogWrite(PA7, outputVal);
   
   
}

Thanks, I am studying the link, but I am afraid that is for very low frequencies limited by default arduino PWM frequency ~490 Hz, my first program post#0 has 720 kHz.

You are confused.

A digital filter is simply a mathematical function that reads numbers in and spits numbers out. The tap coefficients are derived from the required filtering characteristics relative to the assumed data sampling rate. It has absolutely nothing to do with the PWM frequency.

The code you have is not going to work. It's never going to work. Arduino sketches don't have an explicit main() function. Plus, as I pointed out in Reply #9, this code takes its input from and sends its output to a file system. Unless your data is stored on an SD card, your Arduino doesn't have a file system.

To get anywhere you're going to need to implement a digital filter that takes one input sample at a time, processes it, and gives you one output sample. You might be able to adapt the guts of the firFloat() function that you got from somewhere to do this. Or, use the library I linked in Reply #11. Or, find a different Arduino filter library. But, the path you're currently on is just a waste of time.

#9 - I still there
#11 = #10 , no pins for input or output.
Or, find a different Arduino filter library = I have already done a lot of searching so far no luck.