Noise on Voltage/Current analog read


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?


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


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
}


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 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.