Average Analog data

Hello!

I am trying to take the first 100 values of analog data from pin A0 and average it! Then, for all of the incoming data after the first 100 values, I want to subtract the average from it and take the absolute value.

I know it seems strange, but its for the project I am working on and I am just having some coding issues.

Take a looks

  const int analogPin = A0;

  void setup(){

    pinMode(A0, INPUT_PULLUP);

    Serial.begin(9600);

  }

  void loop(){
    const double values[100] = {(analogRead(A0))};

    double sum = 0;

    for (int i = 0; i < 100; i++){
      sum += values[i]*100;   
  }
      Serial.println(abs(analogPin - sum/100));
      
}

Feel free to make changes/ suggestions. Thanks.

Walking through it, a couple of things at a time:

You establish a constant analogPin, here:

 const int analogPin = A0;

but you never use that value in the sketch. What's its purpose?

Why do you select INPUT_PULLUP as the mode for pin A0, here:

   pinMode(A0, INPUT_PULLUP);

Is there something about your analog source that makes you want a pullup resistor?

I'm not familiar with this construction:

   const double values[100] = {(analogRead(A0))};

What do you think it does?

  1. I thought I was storing the first 100 values as an array by making the character type const int. I guess I could use analogPin here:
 const double values[100] = {(analogRead(analogPin))};
  1. I'm using INPUT_PULLUP because it seemed to correct the graph when view the code in serial plotter, however maybe I should switch back to...?
 pinMode(A0, INPUT);
  1. Ah, here I was trying to make an array but I was also experimenting with different data types. Let's forget the const for now. So I am declaring a variable called an array called values
double values

and I want the first 100 digits of the data

 double values[100]

, however until like an array with given values, I want the values to come from analog pin A0

 double values[100] = {(analogRead(A0))};

I hope that helps to clarify.

I am trying to take the first 100 values of analog data from pin A0 and average it! Then, for all of the incoming data after the first 100 values, I want to subtract the average from it and take the absolute value.

You have not said which Arduino you are using, but with a microprocessor like the ATmega 328 memory is limited, and you need to pay attention to memory issues and write efficient code.

You do not need to store all the first 100 values in an array. Just add them together and divide to find the average. Do this operation in set up if you only want to do it once. It also does not make sense to use floating point math with the integer values of analogRead(). The abs() function can produce incorrect results when other functions, like analogRead(), are used inside the braces, so create a variable for it to work with.

I’d do something like this

unsigned long sum;
const byte analogPin = A0;

void setup() {
  Serial.begin(9600);
  for (byte  i = 0; i < 100; i++)
  {
    sum += analogRead(analogPin);
  }

  Serial.println(sum);
  sum = sum / 100;
  Serial.println(sum);
}

void loop() {
  int val = analogRead(analogPin) - sum;
  Serial.println(abs(val));
  //Serial.println(abs(analogRead(analogPin)-sum));
  delay(1000);

cattledog:

Thank you for the clear response. I am working with an Arduino Mega 2560. I'll give it a shot tomorrow when I'm back in my lab!

adbc22:

  1. I thought I was storing the first 100 values as an array by making the character type const int. I guess I could use analogPin here:
 const double values[100] = {(analogRead(analogPin))};

So, it looks like you defined the constant analogPin to be A0, and then didn't use it for anything. That's OK with me, it doesn't hurt anything to have an extra constant defined in the sketch.

  1. I'm using INPUT_PULLUP because it seemed to correct the graph when view the code in serial plotter, however maybe I should switch back to...?
 pinMode(A0, INPUT);

I can't see the graph, and you haven't described it, so I can't comment on it. I can say, though, that setting the pin's mode to INPUT_PULLUP connects a resistor of maybe 35K between the pin and 5V. That can have an impact on the analog values that you read, depending on the stiffness of the voltage source connected to the analog pin. You don't say anything about what you're measuring, so I can't tell if that creates a problem, or if it's what you intended. It sounds like you decided to do that by trial and error. For most conditions, it would probably be wrong, and the mode you'd really want would be INPUT.

  1. Ah, here I was trying to make an array ..., however until like an array with given values, I want the values to come from analog pin A0
 double values[100] = {(analogRead(A0))};

I don't think that code does what you think it does. If you want to try an experiment to see what really happens, connect analog input A0 to the 3.3V supply, use that code to initialize the array, and print its values. The analog reading corresponding to 3.3V on a 5V Arduino is
1024 * 3.3 / 5 =~ 675.8
So, if the code were to actually initialize each element of the array by reading an analog value, the array elements would all be in the neighborhood of 676. Print the values, and see what you got. Is it what you expected?

The code does nothing useful. At best, it stores one analog data point as the first element of the array and sets the rest of the array to 0.

The only way to do this correctly would be to do

static const byte analogPin = A0;
static const int MaxCount = 100;
int currentCount = 0;
long sum = 0;

void loop()
    {
     if(currentCount < MaxCount)
       {
         currentCount++;
         sum += analogRead(analogPin);
        }
      else
         {
           int avg = sum / MaxCount;
           int sample = analogRead(analogPin);
           int delta = sample - avg;
           // ... do something with delta here
          }
   // other stuff
   delay(sometimevalue);
   } // loop

The use of a for-loop to read the values in setup can make sense only if there is a delay() in the loop so that you do not read the first 100 samples within a millisecond, and this will delay getting into your loop() until all the samples are read. For example, if you want to read once a second, then loop() will be inactive for 1:40 (one minute, forty seconds) which may be completely unacceptable.

Note that if you want to use the delta to compute the statistical standard deviation around the mean, there is a simple transformation of the standard deviation computation that requires only three scalar variables, and can start working immediately, not after 100 samples. Since my stat book is in my office, and I am not, I can’t give it to you right now, but if that’s what you need, your delta computation will be inadequate. Let me know, and I’ll post it here for all to see.

Note also the comment about INPUT_PULLUP. That is just wrong. It just guaranttes that the first reading is skewed high (perhaps all the way to 1023), which will give you an “average” of 1023/100=10. This will change your delta-graph from being 0-based to 10-based.

Note the use of the long. 100 reads of 1023 would be 102,300, which exceeds the size of an int (32767). However, if you use the three-variable version, you will have to use two float values, because even a long is too small. Or, you could use ‘long long’, which is neither a Chinese pianist nor a panda, but a 64-bit integer. A float is somewhat slower but takes up less space. For very large sample numbers, a float can lose significances. If you don’t know what that means, ask.
joe

adbc22:
I am trying to take the first 100 values of analog data from pin A0 and average it! Then, for all of the incoming data after the first 100 values, I want to subtract the average from it and take the absolute value.

When?

Just once, when the sketch starts up? Put it in setup.

On occasion, when some condition happens (a button press, a new series of readings)? Test for the condition in the loop(), take your average when it happens.

BTW: there’s probably no point in taking 100 readings if they are all microseconds apart. Add a delay between each reading, or wait for the average to “settle” (eg, by taking a running standard deviation).