Smoothing problem

Hi
How to join orange line on serial plotter as red line drowned by hand?
Average is causing too much delay.

const int sensorIn = A1;
double Voltage = 0;

const int numReadings = 50;
int readings[numReadings];  // the readings from the analog input
int readIndex = 0;          // the index of the current reading
int total = 0;              // the running total
int average = 0;            // the average
int inputPin = A1;

void setup()
{
  Serial.begin(115200);
  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;
  }
}
void loop()
{

  Voltage = getVPP();

  total = total - readings[readIndex];
  readings[readIndex] = analogRead(inputPin);
  readings[readIndex] =   Voltage;
  total = total + readings[readIndex];
  readIndex = readIndex + 1;
  if (readIndex >= numReadings) {
    readIndex = 0;
  }
  average = total / numReadings;
 
  //Serial.print(" v = "); Serial.print(analog_value*5);
  Serial.print(" Amps RMS = "); Serial.print( Voltage);
 //  Serial.print("  average = "); Serial.print(average);

  Serial.println();
}
float getVPP()
{
  float result;
  int readValue;             //value read from the sensor
  int maxValue = 0;          // store max value here
  int minValue = 1024;          // store min value here, 4095.0
  //int minValue = 4095.0;

  uint32_t start_time = millis();
  while ((millis() - start_time) < 10)
    //while((millis()-start_time) < 100)  //sample for 1 Sec
  {
   
    readValue = analogRead(A1);
    

    if (readValue > maxValue)
    {
      maxValue = readValue;
    }
    if (readValue < minValue)
    {
      minValue = readValue;
    }
  }
  result = (maxValue - minValue);

  return result;
}

Any smoothing will always cause a delay. Unless you can measure in the future...

It appears you have a data problem, not a smoothing problem. Many readings are approximately zero, so averaging won't ever give the "red line" result.

If the near-zero data are erroneous, fix the problem. Or, ignore all readings below a threshold.

maybe envelope detection?

why are maxValue and minValue local to the function? If you make them global you might get a smooth update of peak-peak voltage without smoothing. What are you trying to measure?

yes, but using program not diode and capacitor

answer in post #7

OK, 1. have you biased the input voltage?
2. I think you're Algorithm in vpp gives a value close to zero when you have a value close to the top of the adc scale? Is this the intended behaviour? Could be wrong but I would like you do clarify.

The question was "what", not "how".
Leo..

Why bother wasting time with an analogRead if you're going to overwrite it?
Why lose precision writing a double value to an int?

Waste of time and code; they're already all zero.

1 Like

We are missing a LOT of information.
Which Arduino are you using? (LINK)
What is the source of your readings? (Schematic)

you are calculating the VPP and discarding the result

Basically you have made too many changes to your code; you need to start from square 1 and rewrite it.

can use leaky integration
avg += (samp - avg) * K K < 1
with a fast attack and very slow decay to capture close to the peak
K = 2 samp > avg
K = 100 samp > avg

What frequency are you expecting your code to work with?

I'm asking, because your code works well with an input frequency of around 1kHz.

For example, when I use a 1kHz sinewave, modulated at 1Hz with a staircase wave, like this:

Quite a complex looking waveform, but your code detects the staircase modulation nicely.

The problem you are having is due to your sampling time being inappropriate for the signal frequency you are observing.

while ((millis() - start_time) < 10)

The length of time that you are taking samples for in your function getVPP() needs to be longer than several periods of the input signal.

1 Like

red is fast/slow (1/10) attack filter
yellow simply ignores values that are zero

Yellow line this is what I need, can you post a code for that?

this is awk code i used to generate the data and post filter it

just use the previous value if current is zero

function zero (vec, dst, N) {
    printf "# smooth:\n"
    dst [0] = vec [0]

    for (n = 1; n < N; n++)  {
        if (0 == vec [n])
            dst [n] = dst [n-1]
        else
            dst [n] = vec [n]
    }
}

30 it is ok for shape of the line, but it is slowing down to much the loop.

And how to implement it to Arduino / my code?

yes

you can keep track of the lastValue and if set readValue to lastValue if readValue == 0

curious what you're measuring? looks like you're reading values as quickly as possibly for 10 msec. such things are typically done with a periodic sampling rate