Analog smoothing of multiple inputs

Hello all

My project is coming along very well. Thanks in no small part to help from people here. Just a couple of things to go.

I have been trying to work out how to smooth the reads from multiple analog inputs. I can obviously find plenty of code for a single input, but not multiple inputs. And I am reluctant to have multiple almost identical code snippets if possible.

My project currently reads A0-A3 inclusive.

Any pointers to examples or references would be most helpful.

Regards

Fred

A pointer to your project would be helpful.

I don’t see your problem.
If you know how to do one, why not just repeat it for 4?

.

Repeating code was something I was attempting to avoid if I could. I'm already at 70% of device capacity and I still have wifi and website to add.

My code is becoming cumbersome to post here as it exceeds limits and I have to prune the daylights out of it to make it fit.

Regards

Fred

If you have multiple identical things, you put them in array.

const int NINPUTS = 4;

const byte inputPin[NINPUTS] = { A0, A4, A3, A5 };

int reading[NINPUTS];
float smoothedReading[NINPUTS];

void takeReadings() {
  for(int i = 0; i<NINPUTS; i++) {
    reading[i] = analogRead(inputPin[i]);
    smoothedReading[i] = smoothedReading[i] * .75 + reading[i] * .25;
  }
}

You can always Reply (not Quick Reply) and Attach your .ino file vs posting the code within code tags.

Can also bump up to a '1284P based card for 128K flash, 16K SRAM, more IO, dual serial ports.

Here's a Duemilanove style card I offer as one example: http://www.crossroadsfencing.com/BobuinoRev17/ |500x209

What smoothing technique do you use for 1 input? Averaging over a rolling window?

And I am reluctant to have multiple almost identical code snippets if possible.

That is what looping is all about:

for (int i = 0; i < 10; i++)
  {
  <get a reading>
  }
<take an average>

essentially you want to average the signal change over several samples.

You could do something like this to keep memory usage to a minimum Yn is the smoothed value at step n , Xn is the raw input value at step n

Yn = Yn-1 + (1/k * (Xn - Yn-1))

K Is a smoothing factor having it close to 0 or really high will influence the smoothing. having k < 1 will likely diverge.

Here is a quick table made with excel where I’m varying k from 1, 2, 3, …
You have samples taken on the left side and in the array what the smoothing value would be based on the smoothing factor k which is at the top of the column

To generate the samples I took some random noise around the value 50 (can range between 45 and 55)

this is what it looks like:

you can see the impact of the smoothing factor.

In this formula you only need the current value on input Xn and remembering the last smoothed value Yn-1.

If what you are asking for is obtaining only 1 number smoothing the combined signal from all the input then if all your analog inputs are in the same range and related then just sum your inputs and divide by the number of inputs (i.e. Average your input) to build Xn

If what you are asking for is getting multiple smoothed values, one per each input then

Loop for i varying between 0 and number of analog inputs - 1
     read analogInput[i] into an array currentInputValue[i] , 
     Keep an array of previousSmoothedOutput[i]
     compute in a another array currentSmoothedOutput[i] with the formula above (you can have an array of k[i] if smoothing factors need to be different for each input)

Do something with the currentSmoothedOutput array

Then move each currentSoothedOutput into previousSmoothedOutput

Go back to the loop

(Make sure all values are initialized to something meaningful the first time)

The good thing with this approach is that k can be changed in software so you can adjust the smoothing effect in software.

hope this helps

Hi all

Wow, so many answers. Maybe I should have been more clear about what exactly I wanted to achieve.

My project currently monitors 3 inputs. It displays the inputs to an LCD as well as writing the same to a data logger. The project will eventually monitor 4 inputs.

So what I was hoping to do was smooth/avaerage each individual input and still be able to display/write the result as I am now. I don’t want to avaerage all the inputs and get 1 result.

Now remember, I’m not a programmer. I have the sketch I have because of guys like you, Google, and a friend of mine who is a programmer.

Currently the sketch does what I require. I’m just hoping to make the result of the inouts a little more stable.

Still to do:
Add wifi shield go give the project a wireless web server. Display basic information.
Add MPPT control to the project. This will make it a charge controller
Add diversion control for the wind turbine.
Send the data log file to a network share after rollover for further processing.
Find an alternative for the SD card data logger as I am writing data to it twice per second. This is because the output of the wind turbine can change quickly, and I wish to capture as much data as practicle.

Ultimately I may need to move to a Raspberry Pi for coding, and use the UNO as a hardware interface only as I think I will run out of programming space on the UNO. I’ll probably use Firmata for that.

I have attached my current sketch.

Regards

Fred

MyWattmeter.ino (9.5 KB)

Raspberry Pi >:(

Use one of Crossroads 1284 boards.

.

PaulMurrayCbr:
If you have multiple identical things, you put them in array.

const int NINPUTS = 4;

const byte inputPin[NINPUTS] = { A0, A4, A3, A5 };

int reading[NINPUTS];
float smoothedReading[NINPUTS];

void takeReadings() {
  for(int i = 0; i<NINPUTS; i++) {
    reading[i] = analogRead(inputPin[i]);
    smoothedReading[i] = smoothedReading[i] * .75 + reading[i] * .25;
  }
}

Excuse my ignorance, but I’m not a coder and don’t fully understand what the code is doing. So I have a couple of questions.

  1. How many samples is the code as written taking?
  2. Can the number of samples be defined?
  3. How do I identify each smoothed reading to use later in my code?

Regards

Fred

  1. one, averaged with some previous samples
  2. yes, by changing the .25 and .75
  3. example: smoothedReading[i] or smoothedReading[0]

Awesome, I think I understand that.

So I went to put it into practice and I am having a problem.

As it is a function I have place all the code above loop setup(), but when I call a result “smoothedReading[1]” from within the void loop() the answer is zero.

const int NINPUTS = 4;

const byte inputPin[NINPUTS] = { A0, A4, A3, A5 };

int reading[NINPUTS];
float smoothedReading[NINPUTS];

void takeReadings() {
  for(int i = 0; i<NINPUTS; i++) {
    reading[i] = analogRead(inputPin[i]);
    smoothedReading[i] = smoothedReading[i] * .75 + reading[i] * .25;
  }
}

I’ve obviously done something wrong, but not being a programmer it’s not obvious to me.

I’ve attache mt code so you can see what I’ve done.

Your laughter at my blunder is expected, and your advice appreciated.

Regards

Fred

MyWattmeter.ino (11.2 KB)

Where do you ‘call’ takeReadings() ?

.

Line 232 Serial.println(smoothedReading[2]);

Is what I used to check the value of the reading.

Else line 235 should read VoltsIn = ((smoothedReading[2] * (Vcc / 1000)) / Res) / (R2 / (R1 + R2));

The smoothed readings need to be applied to the VoltsIn, TurbineIn, SolarIn, AmpsOut equations.

Regards

Fred

But you never 'call' the takeReadings() function to do the calculations.

.

Grin

added takeReadings(); to line 232

Vcc = result;

takeReadings(); Serial.println(smoothedReading[2]);

/* Calculate the battery voltage */ VoltsIn = ((smoothedReading[0] * (Vcc / 1000)) / Res) / (R2 / (R1 + R2));

Now its working.

Thanks heaps for your patience. Achieved what I wanted in a fraction of the code.

Regards

Fred