Noise on Voltage/Current analog read


Howard Dutton
 

On Wed, May 5, 2021 at 10:58 AM, <rad112g@...> wrote:
Works fine fine fine, i implemented it for both current and voltage, thanks for your time, congrats for your knowledge.
I will come back around to the OCS for a good once over, and when I do things like this will be built-in.


rad112g@...
 

Works fine fine fine, i implemented it for both current and voltage, thanks for your time, congrats for your knowledge.


Howard Dutton
 

On Wed, May 5, 2021 at 09:17 AM, Howard Dutton wrote:
...so it takes the analog sample in the main loop, averages, then drops it in a global variable.  The "(99 + 1) / 100" can be "(999 + 1) / 1000" or "(24 + 1) / 25", etc.  The depth of averaging gives the frequency response vs. noise tradeoff.  This is referred to as a rolling average and has the advantage of not requiring a massive array of values like a normal average does.
You could also bracket the analogRead() and averaging code so it runs at a fixed interval largely independent of the MCU frequency, etc.  Below is for 1 Hz samples in which case you would probably want the depth of averaging to be only 5 or 10 so it's fairly responsive to changes.

static unsigned long lastSampleTime = 0;
if ((long)(millis() - lastSampleTime) > 1000) {
  lastSampleTime = millis();
  // the code
}


Howard Dutton
 

To do this well you'd probably want to change some code from WebAjax:

#if STAT_DC_CURRENT_ANALOG != OFF
  f = toDCAmps(analogRead(STAT_DC_CURRENT_ANALOG));
  strcpy_P(temp1,htmlInnerStatusDCA);     dtostrf(f,6,1,ws1); strcat(ws1,"A"); if (f==invalid) strcpy(ws1,"Invalid"); sprintf(temp,temp1,ws1); client->print(temp);
#endif

...so it takes the analog sample in the main loop, averages, then drops it in a global variable.  The "(99 + 1) / 100" can be "(999 + 1) / 1000" or "(24 + 1) / 25", etc.  The depth of averaging gives the frequency response vs. noise tradeoff.  This is referred to as a rolling average and has the advantage of not requiring a massive array of values like a normal average does.

// global scope
float currentReading = 0.0;

// in the main loop somewhere
static int currentReadingRaw = 0;
currentReadingRaw = analogRead(STAT_DC_CURRENT_ANALOG);
currentReading = (currentReading*99.0 + currentReadingRaw) / 100.0;

........................

// new code for WebAjax.ino
#if STAT_DC_CURRENT_ANALOG != OFF

  f = toDCAmps(round(currentReading));
  strcpy_P(temp1,htmlInnerStatusDCA);     dtostrf(f,6,1,ws1); strcat(ws1,"A"); if (f==invalid) strcpy(ws1,"Invalid"); sprintf(temp,temp1,ws1); client->print(temp);
#endif


rad112g@...
 

Hello Howard, im getting very different values for voltage and current reading, im using 2k2 and 220 Ohm for voltage and ACS712 20A (0,1V/A), some instant measurements differs in about 1V/1A from others. Tried to install 1uF electrolitic or 0,1uF ceramic capacitors but didnt get any sustancial change, there are a lot of example codes for average analog read but dont know how to implement them in your OCS.
Could you give some code for average?