Smoothing incorrect

Hi
Why the values of average Ux and average Uy are wrong ?

//https://github.com/openenergymonitor/EmonLib/blob/master/examples/current_only/current_only.ino
#include "EmonLib.h"
EnergyMonitor emon1Ux;
EnergyMonitor emon1Uy;
//////////////

const int numReadingsx = 10;
const int numReadingsy = 10;
// Ux
int readingsx[numReadingsx];
int readIndexx = 0;
int totalx = 0;
int averagex = 0;

//Uy
int readingsy[numReadingsy];
int readIndexy = 0;
int totaly = 0;
int averagey = 0;
////////////////
float xn1; //
float yn1;
float xn1b;
float yn1b;

void setup()
{
  Serial.begin(115200);
  //////////////////
  //Ux
  for (int thisReadingx = 0; thisReadingx < numReadingsx; thisReadingx++) {
    readingsx[thisReadingx] = 0;
  }
  
//Uy
  for (int thisReadingy = 0; thisReadingy < numReadingsy; thisReadingy++) {
    readingsy[thisReadingy] = 0;
  }
  /////////////////
  emon1Ux.current(PA0, 1000);  // Ux green            // Current: input pin, calibration.
  emon1Uy.current(PA1, 1000); //Uy brawn

  pinMode(PA8, PWM);
  pinMode(PA9, PWM);
  
  TIMER1_BASE->CCER = (1 << 4) | (1 << 0); //cc1e/cc2e enable
  TIMER1_BASE->CCMR1 = (1 << 13) | (1 << 12) | (1 << 5) | (1 << 4); //toogle mode
  TIMER1_BASE->PSC = 0;
  //TIMER1_BASE->ARR=2879;
  TIMER1_BASE->ARR = 1181 * 2; // 15.2kHz
  TIMER1_BASE->CCR1 = 0 ;
  //TIMER1_BASE->CCR2=1439 ;//
  TIMER1_BASE->CCR2 = 1181 ;
  TIMER1_BASE->CR1 = 1;

}

void loop()
{
  double Ux = emon1Ux.calcIrms(1480); 
  double Uy = emon1Uy.calcIrms(1480);
  ///////////////////////

  float xn = Ux;
  float xnb = Uy;

  // compute filtered signal
  float yn = 0.969 * yn1 + 0.0155 * xn + 0.0155 * xn1 ;
  float ynb = 0.969 * yn1b + 0.0155 * xnb + 0.0155 * xn1b ;

  // store the previous vale
  xn1 = xn;
  yn1 = yn ;
  xn1b = xnb;
  yn1b = ynb ;

  // average Ux
  /////////////////////
  totalx = totalx - readingsx[readIndexx];
  //readingsx[readIndexx] = analogRead(inputPin);
  readingsx[readIndexx] = yn * 100;
  totalx = totalx + readingsx[readIndexx];
  readIndexx = readIndexx + 1;
  if (readIndexx >= numReadingsx) {
    readIndexx = 0;
  }
  // average Uy
  totaly = totaly - readingsy[readIndexy];
  //readings[readIndex] = analogRead(inputPin);
  readingsx[readIndexx] = ynb * 100;
  totaly = totaly + readingsy[readIndexy];
  readIndexy = readIndexy + 1;
  if (readIndexy >= numReadingsy) {
    readIndexy = 0;
  }

  ///////////
  averagex = totalx / numReadingsx;
  averagey = totaly / numReadingsy;

  Serial.print(" ynv =  ");
  Serial.print(yn * 100);                 // Ux after filter
  Serial.print(" ynb =  ");
  Serial.print(ynb * 100);                // Uy after filter

  Serial.print("   averagex =   ");
  Serial.print(averagex);                // average Ux
  Serial.print("   averagey =   ");
  Serial.print(averagey);                 // average Uy
  Serial.println();
 
}

I have no clue how you try to calculate average without a for loop ...
But, you are storing a float value into an integer value.
In Uno an int is only 16 bits, where the first bit holds the sign. It is very likely that it will overflow... you will also loose precision.

Calc of average:

int sum=0;
for (int i=0; i<10; i++) {
    sum=sum+val[i];
}
int average = sum/10;

And to help yourself: rename xn1 to prev_xn.

what should there correct values be?

i tried testing the code on my laptop. i modified the code to use know values and simply the computation in order to verify the averaging and get the following

 yn =   100.0 totX =   100.0 numX =    10.0 avgX =    10.0 idxX =     1.0
 yn =   100.0 totX =   200.0 numX =    10.0 avgX =    20.0 idxX =     2.0
 yn =   100.0 totX =   300.0 numX =    10.0 avgX =    30.0 idxX =     3.0
 yn =   100.0 totX =   400.0 numX =    10.0 avgX =    40.0 idxX =     4.0
 yn =   100.0 totX =   500.0 numX =    10.0 avgX =    50.0 idxX =     5.0
 yn =   100.0 totX =   600.0 numX =    10.0 avgX =    60.0 idxX =     6.0
 yn =   100.0 totX =   700.0 numX =    10.0 avgX =    70.0 idxX =     7.0
 yn =   100.0 totX =   800.0 numX =    10.0 avgX =    80.0 idxX =     8.0
 yn =   100.0 totX =   900.0 numX =    10.0 avgX =    90.0 idxX =     9.0
 yn =   100.0 totX =  1000.0 numX =    10.0 avgX =   100.0 idxX =     0.0
 yn =   100.0 totX =  1000.0 numX =    10.0 avgX =   100.0 idxX =     1.0
 yn =   100.0 totX =  1000.0 numX =    10.0 avgX =   100.0 idxX =     2.0
 yn =   100.0 totX =  1000.0 numX =    10.0 avgX =   100.0 idxX =     3.0
 yn =   100.0 totX =  1000.0 numX =    10.0 avgX =   100.0 idxX =     4.0
 yn =   100.0 totX =  1000.0 numX =    10.0 avgX =   100.0 idxX =     5.0
 yn =   100.0 totX =  1000.0 numX =    10.0 avgX =   100.0 idxX =     6.0
 yn =   100.0 totX =  1000.0 numX =    10.0 avgX =   100.0 idxX =     7.0
 yn =   100.0 totX =  1000.0 numX =    10.0 avgX =   100.0 idxX =     8.0
 yn =   100.0 totX =  1000.0 numX =    10.0 avgX =   100.0 idxX =     9.0
 yn =   100.0 totX =  1000.0 numX =    10.0 avgX =   100.0 idxX =     0.0

code

#include <stdio.h>
#include <math.h>

struct Serial_s {
    void print (const char *s)    { printf ("%s", s); }
    void print (float f)          { printf ("%7.1f", f); }
    void println (void)           { printf ("\n"); }
} Serial;

struct EnergyMonitor {
    double calcIrms (int x) { return random () * 100. / RAND_MAX; }
};

// -----------------------------------------------------------------------------
EnergyMonitor emon1Ux;
EnergyMonitor emon1Uy;

const int numReadingsx = 10;
const int numReadingsy = 10;

// Ux
int readingsx[numReadingsx];
int readIndexx = 0;
int totalx = 0;
int averagex = 0;

//Uy
int readingsy[numReadingsy];
int readIndexy = 0;
int totaly = 0;
int averagey = 0;

float xn;
float xn1;
float yn1;

float xnb;
float xn1b;
float yn1b;

void loop ()
{
    double Ux = emon1Ux.calcIrms (1480);
    double Uy = emon1Uy.calcIrms (1480);

    xn  = Ux;
    xnb = Uy;

    // compute filtered signal
#if 0
    float yn  = 0.969 * yn1  + 0.0155 * xn  + 0.0155 * xn1 ;

#elif 1
#define K0  0.0
#define K1  1.0
#define K2  0
    xn = 1;
    float yn  = K0 * yn1  + K1 * xn  + K2 * xn1 ;
#else
#define K0  0.969 
#define K1  0.0155 
#define K2  0.0155 
    float yn  = K0 * yn1  + K1 * xn  + K2 * xn1 ;
#endif
    float ynb = 0.969 * yn1b + 0.0155 * xnb + 0.0155 * xn1b ;

    // store the previous vale
    xn1  = xn;
    yn1  = yn ;

    xn1b = xnb;
    yn1b = ynb ;

    // average Ux
    totalx = totalx - readingsx[readIndexx];

    //readingsx[readIndexx] = analogRead (inputPin);
    readingsx [readIndexx] = yn * 100;
    totalx                 = totalx + readingsx[readIndexx];
    readIndexx             = readIndexx + 1;
    if (readIndexx >= numReadingsx) {
        readIndexx = 0;
    }

    // average Uy
#if 0
    totaly = totaly - readingsy[readIndexy];

    //readings[readIndex] = analogRead (inputPin);
    readingsx [readIndexx] = ynb * 100;
    totaly                 = totaly + readingsy[readIndexy];
    readIndexy             = readIndexy + 1;
    if (readIndexy >= numReadingsy) {
        readIndexy = 0;
    }
#endif

    averagex = totalx / numReadingsx;
    averagey = totaly / numReadingsy;

    Serial.print (" yn = ");
    Serial.print (yn * 100);

    Serial.print (" totX = ");
    Serial.print (totalx);
    Serial.print (" numX = ");
    Serial.print (numReadingsx);
    Serial.print (" avgX = ");
    Serial.print (averagex);                // average Ux
    Serial.print (" idxX = ");
    Serial.print (readIndexx);

#if 0
    Serial.print (" ynb = ");
    Serial.print (ynb * 100);                // Uy after filter
    Serial.print ("   averagey =   ");
    Serial.print (averagey);                 // average Uy
#endif
    Serial.println ();
}

// -----------------------------------------------------------------------------
int
main ()
{
    for (unsigned n = 0; n < 20; n++)  {
        loop ();
    }

    return 0;
}

Hi
Thanks for supporting, your code giving me error
++++++++++++++++++++++++++++
In file included from C:\Users\Galinka\Documents\Arduino\hardware\Arduino_STM32-master\STM32F1\cores\maple/wirish.h:72:0,
from C:\Users\Galinka\Documents\Arduino\hardware\Arduino_STM32-master\STM32F1\cores\maple/Arduino.h:30,
from sketch\filter_average.ino.cpp:1:
C:\Users\Galinka\Documents\Arduino\hardware\Arduino_STM32-master\STM32F1\cores\maple/usb_serial.h:96:22: error: 'Serial' has a previous declaration as 'USBSerial Serial'
extern USBSerial Serial;
^
C:\Users\Galinka\Documents\Arduino\filter_average\filter_average.ino: In member function 'double EnergyMonitor::calcIrms(int)':
filter_average:11:46: error: no matching function for call to 'random()'
double calcIrms (int x) { return random () * 100. / RAND_MAX; }
^
C:\Users\Galinka\Documents\Arduino\filter_average\filter_average.ino:11:46: note: candidates are:
In file included from C:\Users\Galinka\Documents\Arduino\hardware\Arduino_STM32-master\STM32F1\cores\maple/wirish.h:63:0,
from C:\Users\Galinka\Documents\Arduino\hardware\Arduino_STM32-master\STM32F1\cores\maple/Arduino.h:30,
from sketch\filter_average.ino.cpp:1:
C:\Users\Galinka\Documents\Arduino\hardware\Arduino_STM32-master\STM32F1\cores\maple/wirish_math.h:50:6: note: long int random(long int)
long random(long max);
^
C:\Users\Galinka\Documents\Arduino\hardware\Arduino_STM32-master\STM32F1\cores\maple/wirish_math.h:50:6: note: candidate expects 1 argument, 0 provided
C:\Users\Galinka\Documents\Arduino\hardware\Arduino_STM32-master\STM32F1\cores\maple/wirish_math.h:59:6: note: long int random(long int, long int)
long random(long min, long max);
^
C:\Users\Galinka\Documents\Arduino\hardware\Arduino_STM32-master\STM32F1\cores\maple/wirish_math.h:59:6: note: candidate expects 2 arguments, 0 provided
exit status 1
conflicting declaration 'Serial_s Serial'
+++++++++++++++++++++++++++++++++++++
here is the code to which I want to add average

//https://github.com/openenergymonitor/EmonLib/blob/master/examples/current_only/current_only.ino
#include "EmonLib.h"
EnergyMonitor emon1Ux;
EnergyMonitor emon1Uy;

float xn1;
float yn1;
float xn1b;
float yn1b;

void setup()
{
  Serial.begin(115200);

  emon1Ux.current(PA0, 1000);  // Ux green            // Current: input pin, calibration.
  emon1Uy.current(PA1, 1000); //Uy brawn
/*
  pinMode(PA8, PWM);
  pinMode(PA9, PWM);
  TIMER1_BASE->CCER = (1 << 4) | (1 << 0); //cc1e/cc2e enable
  TIMER1_BASE->CCMR1 = (1 << 13) | (1 << 12) | (1 << 5) | (1 << 4); //toogle mode
  TIMER1_BASE->PSC = 0;
  //TIMER1_BASE->ARR=2879;
  TIMER1_BASE->ARR = 1181 * 2; // 15.2kHz
  TIMER1_BASE->CCR1 = 0 ;
  //TIMER1_BASE->CCR2=1439 ;//
  TIMER1_BASE->CCR2 = 1181 ;
  TIMER1_BASE->CR1 = 1;
*/
}

void loop()
{
  double Ux = emon1Ux.calcIrms(1480);  // Calculate Irms only
  double Uy = emon1Uy.calcIrms(1480);
  ///////////////////////

  float xn = Ux;
  float xnb = Uy;

  // compute filtered signal
  float yn = 0.969 * yn1 + 0.0155 * xn + 0.0155 * xn1 ;
  float ynb = 0.969 * yn1b + 0.0155 * xnb + 0.0155 * xn1b ;

  // store the previous vale
  xn1 = xn;
  yn1 = yn ;
  xn1b = xnb;
  yn1b = ynb ;


  
  Serial.print(" ynv =   ");
  Serial.print(yn);  //Ux after filter
  Serial.print(" ynb =  ");
  Serial.print(ynb);  //Uy after filter
  Serial.println();

}

and this is the program which I am trying to use for that


const int numReadings = 10;

int readings[numReadings];     
int readIndex = 0;             
int total = 0;                  
int average = 0;                

int inputPin = PA0;

void setup() {

  Serial.begin(115200);

  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;
  }
}

void loop() {

  total = total - readings[readIndex];
  readings[readIndex] = analogRead(inputPin);
  total = total + readings[readIndex];
  readIndex = readIndex + 1;
  if (readIndex >= numReadings) {
    readIndex = 0;
  }
  average = total / numReadings;
  Serial.println(average);

}

The first column is Ux, average of it is a third column, so average should be 790 instead of -1090 and for Uy ( the second column ) average should be 835 instead of 0

I did that way

//https://github.com/openenergymonitor/EmonLib/blob/master/examples/current_only/current_only.ino
#include "EmonLib.h"
EnergyMonitor emon1Ux;
EnergyMonitor emon1Uy;

float xn1;
float yn1;
float xn1b;
float yn1b;
//////////////
int i;
int sum = 0;
int  val[i] = yn;
////////////
void setup()
{
  Serial.begin(115200);

  emon1Ux.current(PA0, 1000);  // Ux green            // Current: input pin, calibration.
  emon1Uy.current(PA1, 1000); //Uy brawn
  ////////
  for (int i = 0; i < 10; i++) {
    sum = sum + val[i];
  //////////////////
  }

  /*
    pinMode(PA8, PWM);
    pinMode(PA9, PWM);
    TIMER1_BASE->CCER = (1 << 4) | (1 << 0); //cc1e/cc2e enable
    TIMER1_BASE->CCMR1 = (1 << 13) | (1 << 12) | (1 << 5) | (1 << 4); //toogle mode
    TIMER1_BASE->PSC = 0;
    //TIMER1_BASE->ARR=2879;
    TIMER1_BASE->ARR = 1181 * 2; // 15.2kHz
    TIMER1_BASE->CCR1 = 0 ;
    //TIMER1_BASE->CCR2=1439 ;//
    TIMER1_BASE->CCR2 = 1181 ;
    TIMER1_BASE->CR1 = 1;
  */
}

void loop()
{
  double Ux = emon1Ux.calcIrms(1480);  // Calculate Irms only
  double Uy = emon1Uy.calcIrms(1480);
  ///////////////////////

  float xn = Ux;
  float xnb = Uy;

  // compute filtered signal
  float yn = 0.969 * yn1 + 0.0155 * xn + 0.0155 * xn1 ;
  float ynb = 0.969 * yn1b + 0.0155 * xnb + 0.0155 * xn1b ;

  // store the previous vale
  xn1 = xn;
  yn1 = yn ;
  xn1b = xnb;
  yn1b = ynb ;

  int average = sum / 10;

  Serial.print(" average =   ");
  Serial.print(average);  //Ux after filter

  Serial.print(" ynv =   ");
  Serial.print(yn);  //Ux after filter
  Serial.print(" ynb =  ");
  Serial.print(ynb);  //Uy after filter
  Serial.println();

}

but I have a error
average_sum:13:13: error: array bound is not an integer constant before ']' token
float val[i] = yn;
^
C:\Users\Galinka\Documents\Arduino\average_sum\average_sum.ino: In function 'void setup()':
average_sum:23:17: error: 'val' was not declared in this scope
sum = sum + val[i];
^
exit status 1
array bound is not an integer constant before ']' token

Remove the keyword "float", as that declares a new variable.

You are supposed to fill val[] first with values read from your analogRead...
Usually that is not done in setup.

As you might be looking for a smoothing function, you might also like:

\\before setup:
int smoothed=0;

\\in your loop:
smoothed = (15*smoothed + analogRead(somePin) + 8)/16;

What do you expect this to do?

You already have an IIR filter here, why add another moving average filter instead of tuning the existing filter?

The one you have now has a pretty strange frequency response, how did you design it?

It looks finally someone (@PieterP ) understands that you have built a smoothing filter with this:

  float yn = 0.969 * yn1 + 0.0155 * xn + 0.0155 * xn1 ;
  float ynb = 0.969 * yn1b + 0.0155 * xnb + 0.0155 * xn1b ;

I had no clue what was going on there...
So, maybe forget my suggestions, or throw away this more complicated filter and replace it with my suggestions...
Both at the same time seems not a good idea...

I doubt anyone does, or that it does anything useful. That is the standard form for a simple FIR filter, but the coefficients are very strange.

the results are not so good, smoothing is in too large steps

I copied from it youtube

I have a noisy signal 12 Hz, the filter it is removing it nicely but still have not smooth signal after filtration.

What filter? The code is an incomprehensible mishmash.

Please post links to where you found the little bits and pieces you threw together.

Often a bad idea.

That's because the filter doesn't remove it nicely. It might attenuate it a little bit, but it is a poor filter for the job. You'll have to understand the characteristics of the noise you're dealing with and design the filter based on that knowledge.

The moving average “smoothing” you're trying to add is just another filter with a specific frequency response:

It is an easy filter to understand intuitively, but it's often not the right choice if you want a low-pass filter.

The filter is from here
https://www.youtube.com/watch?v=eM4VHtettGg

I almost did ,too much delay

//https://github.com/openenergymonitor/EmonLib/blob/master/examples/current_only/current_only.ino
#include "EmonLib.h"
EnergyMonitor emon1Ux;
EnergyMonitor emon1Uy;

const int numReadings = 20;
int readings[numReadings], readIndex = 0, total = 0, average = 0;
////////////////

////////////////////
float xn1;
float yn1;
float xn1b;
float yn1b;

void setup()
{
  Serial.begin(115200);

  emon1Ux.current(PA0, 1000);  // Ux green            // Current: input pin, calibration.
  emon1Uy.current(PA1, 1000); //Uy brawn

  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;
  }

  pinMode(PA8, PWM);
  pinMode(PA9, PWM);
  TIMER1_BASE->CCER = (1 << 4) | (1 << 0); //cc1e/cc2e enable
  TIMER1_BASE->CCMR1 = (1 << 13) | (1 << 12) | (1 << 5) | (1 << 4); //toogle mode
  TIMER1_BASE->PSC = 0;
  //TIMER1_BASE->ARR=2879;
  TIMER1_BASE->ARR = 1181 * 2; // 15.2kHz
  TIMER1_BASE->CCR1 = 0 ;
  //TIMER1_BASE->CCR2=1439 ;//
  TIMER1_BASE->CCR2 = 1181 ;
  TIMER1_BASE->CR1 = 1;

}

void loop()
{
  double Ux = emon1Ux.calcIrms(1480);  // Calculate Irms only
  double Uy = emon1Uy.calcIrms(1480);
  ///////////////////////

  float xn = Ux;
  float xnb = Uy;

  // compute filtered signal
  float yn = 0.969 * yn1 + 0.0155 * xn + 0.0155 * xn1 ;
  float ynb = 0.969 * yn1b + 0.0155 * xnb + 0.0155 * xn1b ;

  // store the previous vale
  xn1 = xn;
  yn1 = yn ;
  xn1b = xnb;
  yn1b = ynb ;
  //////////////
  total = total - readings[readIndex];
 // readings[readIndex] = analogRead(PA0);
   readings[readIndex] = yn*100;
  total = total + readings[readIndex];
  readIndex = readIndex + 1;
  if (readIndex >= numReadings) {
    readIndex = 0;
  }
  average = total / numReadings;
  //average = (total / numReadings) * 5;
  Serial.print( " average =  ");
  Serial.print(average );
  ////////////////


  Serial.print(" ynv =   ");
  Serial.print(yn*100);  //Ux after filter
 // Serial.print(" ynb =  ");
 // Serial.print(ynb);  //Uy after filter
  Serial.println();

}

I need a better low pass filter which give me green line without additional smoothing

It's a simple first-order IIR filter, with a cut-off frequency of 5 Hz and a sampling rate of 1 kHz (or a normalized frequency of 0.01 half-cycles/sample).
You need to decide if this order is high enough and if the cut-off frequency is appropriate for your application. There is no magic one-size-fits-all low-pass filter.

At the very least, you should make sure that your sampling rate is constant, e.g. by using a timer using micros().

You can find an example here: Arduino Filters: Butterworth.ino

If you use the following settings, you'll get the same filter you had before:

// Sampling frequency
const double f_s = 1000; // Hz
// Cut-off frequency (-3 dB)
const double f_c = 5; // Hz
// Normalized cut-off frequency
const double f_n = 2 * f_c / f_s;
// First-order Butterworth filter
auto filter = butter<1>(f_n);

You'll have to explain that more clearly (and quantitatively).