Skip to main content
Mod Removes Wiki by Voltage Spike
Even worst, the microcontroller will never run the filter at that speed
Source Link
jDAQ
  • 2.6k
  • 1
  • 10
  • 19

Also, if you are using the Arduino Uno you will not be able to do many floating point operations per cycle, someone got a figure of 9 us per operation (except division), so just the part where you calculate your output \$Y_i\$ would use 5 multiplications and 5 additions, taking 90 us. Your filter is designed for 20 kHzYour filter is designed for a sampling time Ts= 8e-6 seconds, so you would do that operation 20,000 times pernot be able to finish the first floating point multiplication before getting your second reading from the ADC, but:

$$20,000\cdot90 \,\mu\text{s} = 1.8 \, \text{s}$$and would have done 10 more readings before calculating the first output \$Y_i\$, long story short, the microcontroller will not be able to keep up and run that filter at that speed.

Also, if you are using the Arduino Uno you will not be able to do many floating point operations per cycle, someone got a figure of 9 us per operation (except division), so just the part where you calculate your output \$Y_i\$ would use 5 multiplications and 5 additions, taking 90 us. Your filter is designed for 20 kHz, so you would do that operation 20,000 times per second, but:

$$20,000\cdot90 \,\mu\text{s} = 1.8 \, \text{s}$$

Also, if you are using the Arduino Uno you will not be able to do many floating point operations per cycle, someone got a figure of 9 us per operation (except division), so just the part where you calculate your output \$Y_i\$ would use 5 multiplications and 5 additions, taking 90 us. Your filter is designed for a sampling time Ts= 8e-6 seconds, so you would not be able to finish the first floating point multiplication before getting your second reading from the ADC, and would have done 10 more readings before calculating the first output \$Y_i\$, long story short, the microcontroller will not be able to keep up and run that filter at that speed.

quick explanations that lead to a completely wrong "help", this filter will never work at 20kHz
Source Link
jDAQ
  • 2.6k
  • 1
  • 10
  • 19

Well, every iteration update your variables like this:

$$ U_{i-2} \leftarrow U_{i-1}$$ $$ U_{i-1} \leftarrow U_{i}$$ $$ U_{i} \leftarrow \text{curent ADC reading}$$ $$Y_{i-2} \leftarrow Y_{i-1}$$ $$Y_{i-1} \leftarrow Y_i$$ $$Y_i \leftarrow \text{calculate current output}$$

In you code you are using double variables for precision, but, for the Arduino Uno and other that use AVR architecture microcontrollers double is the same as float. If you intend on keep using double, notice you will not have the desired performanceprecision.

Also, if you are using the Arduino Uno you will not be able to do many floating point operations per cycle, someone got a figure of 9 us per operation (except division), so just the part where you calculate your output \$Y_i\$ would use 5 multiplications and 5 additions, taking 90 us. Your filter is designed for 20 kHz, so you would do that operation 20,000 times per second, but:

$$20,000\cdot90 \,\mu\text{s} = 1.8 \, \text{s}$$

So you are way over your budget in frequency, if you where doing only that calculation, you would be barely able to achieve a 10 kHz frequency.

Finally, you could improve your code in two ways, first

//you do not need all those values, 
//from your expression for the filter, you could use just this
//double Y_i[10] = {0,0,0,0,0,0,0,0,0,0};
//double U_i[10] = {0,0,0,0,0,0,0,0,0,0};
double Y_i[3] = {0,0,0};
double U_i[3] = {0,0,0};



//not needed, just load the values you want as initialization in the array above 
//double Y_i_1 = 0;
//double Y_i_2 = 0;
//double U_i_1 = 0;
//double U_i_2 = 0;

notice that

  • \$ U_{i-2}\$ = U_i[2]
  • \$ U_{i-1}\$ = U_i[1]
  • \$ U_{i}\$ = U_i[0]
  • \$Y_{i-2}\$ = Y_i[2]
  • \$Y_{i-1}\$ = Y_i[1]
  • \$Y_{i}\$ = Y_i[0]

And that filter expression with a bunch of if could be just

void loop() {

    U_i[2] = U_i[1];
    U_i[1] = U_i[0];
    U_i[i] = x;
    Y_i[2] = Y_i[1];
    Y_i[1] = Y_i[0];
    Y_i[0] = 0.144*U_i[0] + 0.2281*U_i[1] + 0.1441*U_i[2] + 0.6777*Y_i[1] - 0.254*Y_i[2];
    //send or store any of the values that you need, 
    //Y_i[0] will always have the latest update of the filter, and so on...


    //either put this filter in some non-critical interruption to execute it with the desired periodicity (best way) 
    //or use some precise delay here right after calculating the filter inside the loop
    delayMicroseconds(50);

}


Well, every iteration update your variables like this:

$$ U_{i-2} \leftarrow U_{i-1}$$ $$ U_{i-1} \leftarrow U_{i}$$ $$ U_{i} \leftarrow \text{curent ADC reading}$$ $$Y_{i-2} \leftarrow Y_{i-1}$$ $$Y_{i-1} \leftarrow Y_i$$ $$Y_i \leftarrow \text{calculate current output}$$

In you code you are using double variables for precision, but, for the Arduino Uno and other that use AVR architecture microcontrollers double is the same as float. If you intend on keep using double, notice you will not have the desired performance.

Also, if you are using the Arduino Uno you will not be able to do many floating point operations per cycle, someone got a figure of 9 us per operation (except division), so just the part where you calculate your output \$Y_i\$ would use 5 multiplications and 5 additions, taking 90 us. Your filter is designed for 20 kHz, so you would do that operation 20,000 times per second, but:

$$20,000\cdot90 \,\mu\text{s} = 1.8 \, \text{s}$$

So you are way over your budget in frequency, if you where doing only that calculation, you would be barely able to achieve a 10 kHz frequency.

Finally, you could improve your code in two ways, first

//you do not need all those values, 
//from your expression for the filter, you could use just this
//double Y_i[10] = {0,0,0,0,0,0,0,0,0,0};
//double U_i[10] = {0,0,0,0,0,0,0,0,0,0};
double Y_i[3] = {0,0,0};
double U_i[3] = {0,0,0};



//not needed, just load the values you want as initialization in the array above 
//double Y_i_1 = 0;
//double Y_i_2 = 0;
//double U_i_1 = 0;
//double U_i_2 = 0;

notice that

  • \$ U_{i-2}\$ = U_i[2]
  • \$ U_{i-1}\$ = U_i[1]
  • \$ U_{i}\$ = U_i[0]
  • \$Y_{i-2}\$ = Y_i[2]
  • \$Y_{i-1}\$ = Y_i[1]
  • \$Y_{i}\$ = Y_i[0]

And that filter expression with a bunch of if could be just

void loop() {

    U_i[2] = U_i[1];
    U_i[1] = U_i[0];
    U_i[i] = x;
    Y_i[2] = Y_i[1];
    Y_i[1] = Y_i[0];
    Y_i[0] = 0.144*U_i[0] + 0.2281*U_i[1] + 0.1441*U_i[2] + 0.6777*Y_i[1] - 0.254*Y_i[2];
    //send or store any of the values that you need, 
    //Y_i[0] will always have the latest update of the filter, and so on...


}


Well, every iteration update your variables like this:

$$ U_{i-2} \leftarrow U_{i-1}$$ $$ U_{i-1} \leftarrow U_{i}$$ $$ U_{i} \leftarrow \text{curent ADC reading}$$ $$Y_{i-2} \leftarrow Y_{i-1}$$ $$Y_{i-1} \leftarrow Y_i$$ $$Y_i \leftarrow \text{calculate current output}$$

In you code you are using double variables for precision, but, for the Arduino Uno and other that use AVR architecture microcontrollers double is the same as float. If you intend on keep using double, notice you will not have the desired precision.

Also, if you are using the Arduino Uno you will not be able to do many floating point operations per cycle, someone got a figure of 9 us per operation (except division), so just the part where you calculate your output \$Y_i\$ would use 5 multiplications and 5 additions, taking 90 us. Your filter is designed for 20 kHz, so you would do that operation 20,000 times per second, but:

$$20,000\cdot90 \,\mu\text{s} = 1.8 \, \text{s}$$

So you are way over your budget in frequency, if you where doing only that calculation, you would be barely able to achieve a 10 kHz frequency.

Finally, you could improve your code in two ways, first

//you do not need all those values, 
//from your expression for the filter, you could use just this
//double Y_i[10] = {0,0,0,0,0,0,0,0,0,0};
//double U_i[10] = {0,0,0,0,0,0,0,0,0,0};
double Y_i[3] = {0,0,0};
double U_i[3] = {0,0,0};



//not needed, just load the values you want as initialization in the array above 
//double Y_i_1 = 0;
//double Y_i_2 = 0;
//double U_i_1 = 0;
//double U_i_2 = 0;

notice that

  • \$ U_{i-2}\$ = U_i[2]
  • \$ U_{i-1}\$ = U_i[1]
  • \$ U_{i}\$ = U_i[0]
  • \$Y_{i-2}\$ = Y_i[2]
  • \$Y_{i-1}\$ = Y_i[1]
  • \$Y_{i}\$ = Y_i[0]

And that filter expression with a bunch of if could be just

void loop() {

    U_i[2] = U_i[1];
    U_i[1] = U_i[0];
    U_i[i] = x;
    Y_i[2] = Y_i[1];
    Y_i[1] = Y_i[0];
    Y_i[0] = 0.144*U_i[0] + 0.2281*U_i[1] + 0.1441*U_i[2] + 0.6777*Y_i[1] - 0.254*Y_i[2];
    //send or store any of the values that you need, 
    //Y_i[0] will always have the latest update of the filter, and so on...


    //either put this filter in some non-critical interruption to execute it with the desired periodicity (best way) 
    //or use some precise delay here right after calculating the filter inside the loop
    delayMicroseconds(50);

}


quick explanations that lead to a completely wrong "help", this filter will never work at 20kHz
Source Link
jDAQ
  • 2.6k
  • 1
  • 10
  • 19

Well, every iteration update your variables like this:

$$ U_{i-2} \leftarrow U_{i-1}$$ $$ U_{i-1} \leftarrow U_{i}$$ $$ U_{i} \leftarrow \text{curent ADC reading}$$ $$Y_{i-2} \leftarrow Y_{i-1}$$ $$Y_{i-1} \leftarrow Y_i$$ $$Y_i \leftarrow \text{calculate current output}$$

In you code you are using double variables for precision, but, for the Arduino Uno and other that use AVR architecture microcontrollers double is the same as float. If you intend on keep using double, notice you will not have the desired performance.

Also, if you are using the Arduino Uno you will not be able to do many floating point operations per cycle, someone got a figure of 9 us per operation (except division), so just the part where you calculate your output \$Y_i\$ would use 5 multiplications and 5 additions, taking 90 us. Your filter is designed for 20 kHz, so you would do that operation 20,000 times per second, but:

$$20,000\cdot90 \,\mu\text{s} = 1.8 \, \text{s}$$

So you are way over your budget in frequency, if you where doing only that calculation, you would be barely able to achieve a 10 kHz frequency.

Finally, you could improve your code in two ways, first

//you do not need all those values, 
//from your expression for the filter, you could use just this
//double Y_i[10] = {0,0,0,0,0,0,0,0,0,0};
//double U_i[10] = {0,0,0,0,0,0,0,0,0,0};
double Y_i[3] = {0,0,0};
double U_i[3] = {0,0,0};



//not needed, just load the values you want as initialization in the array above 
//double Y_i_1 = 0;
//double Y_i_2 = 0;
//double U_i_1 = 0;
//double U_i_2 = 0;

notice that

  • \$ U_{i-2}\$ = U_i[2]
  • \$ U_{i-1}\$ = U_i[1]
  • \$ U_{i}\$ = U_i[0]
  • \$Y_{i-2}\$ = Y_i[2]
  • \$Y_{i-1}\$ = Y_i[1]
  • \$Y_{i}\$ = Y_i[0]

And that filter expression with a bunch of if could be just

void loop() {

    U_i[2] = U_i[1];
    U_i[1] = U_i[0];
    U_i[i] = x;
    Y_i[2] = Y_i[1];
    Y_i[1] = Y_i[0];
    Y_i[0] = 0.144*U_i[0] + 0.2281*U_i[1] + 0.1441*U_i[2] + 0.6777*Y_i[1] - 0.254*Y_i[2];
    //send or store any of the values that you need, 
    //Y_i[0] will always have the latest update of the filter, and so on...


}


Well, every iteration update your variables like this:

$$ U_{i-2} \leftarrow U_{i-1}$$ $$ U_{i-1} \leftarrow U_{i}$$ $$ U_{i} \leftarrow \text{curent ADC reading}$$ $$Y_{i-2} \leftarrow Y_{i-1}$$ $$Y_{i-1} \leftarrow Y_i$$ $$Y_i \leftarrow \text{calculate current output}$$

Well, every iteration update your variables like this:

$$ U_{i-2} \leftarrow U_{i-1}$$ $$ U_{i-1} \leftarrow U_{i}$$ $$ U_{i} \leftarrow \text{curent ADC reading}$$ $$Y_{i-2} \leftarrow Y_{i-1}$$ $$Y_{i-1} \leftarrow Y_i$$ $$Y_i \leftarrow \text{calculate current output}$$

In you code you are using double variables for precision, but, for the Arduino Uno and other that use AVR architecture microcontrollers double is the same as float. If you intend on keep using double, notice you will not have the desired performance.

Also, if you are using the Arduino Uno you will not be able to do many floating point operations per cycle, someone got a figure of 9 us per operation (except division), so just the part where you calculate your output \$Y_i\$ would use 5 multiplications and 5 additions, taking 90 us. Your filter is designed for 20 kHz, so you would do that operation 20,000 times per second, but:

$$20,000\cdot90 \,\mu\text{s} = 1.8 \, \text{s}$$

So you are way over your budget in frequency, if you where doing only that calculation, you would be barely able to achieve a 10 kHz frequency.

Finally, you could improve your code in two ways, first

//you do not need all those values, 
//from your expression for the filter, you could use just this
//double Y_i[10] = {0,0,0,0,0,0,0,0,0,0};
//double U_i[10] = {0,0,0,0,0,0,0,0,0,0};
double Y_i[3] = {0,0,0};
double U_i[3] = {0,0,0};



//not needed, just load the values you want as initialization in the array above 
//double Y_i_1 = 0;
//double Y_i_2 = 0;
//double U_i_1 = 0;
//double U_i_2 = 0;

notice that

  • \$ U_{i-2}\$ = U_i[2]
  • \$ U_{i-1}\$ = U_i[1]
  • \$ U_{i}\$ = U_i[0]
  • \$Y_{i-2}\$ = Y_i[2]
  • \$Y_{i-1}\$ = Y_i[1]
  • \$Y_{i}\$ = Y_i[0]

And that filter expression with a bunch of if could be just

void loop() {

    U_i[2] = U_i[1];
    U_i[1] = U_i[0];
    U_i[i] = x;
    Y_i[2] = Y_i[1];
    Y_i[1] = Y_i[0];
    Y_i[0] = 0.144*U_i[0] + 0.2281*U_i[1] + 0.1441*U_i[2] + 0.6777*Y_i[1] - 0.254*Y_i[2];
    //send or store any of the values that you need, 
    //Y_i[0] will always have the latest update of the filter, and so on...


}


Source Link
jDAQ
  • 2.6k
  • 1
  • 10
  • 19
Loading
Post Made Community Wiki by jDAQ