Dynamic variables for functions

I want to make a simple averaging function for a project I'm working on. What I want to do is to specify a variable and a number of data points to collect:

int average(int variable, int n)

And the function will take n samples of variable, sum them, and divide by n. What I want to know is how I can specify a variable (which will be an analog or digital reading that is constantly changing) and use that. Do I need pointers?

Thanks.
baum

Well, the typical way to do this would be to collect your samples all up into an array first, using whatever method you like to take the samples, and then calculate the average of the array based on that.

But is there a way in which I can specify a variable to collect values from over a period of time instead of the values themselves?

baum:
But is there a way in which I can specify a variable to collect values from over a period of time instead of the values themselves?

The challenge is, how will the function operate "over time"? A function executes immediately, and then returns control back to the caller. If the function ITSELF could take the readings, then it could just block until it had collected enough readings, but then it wouldn't really be an 'average' function, it would be a 'take the readings and average them' function.

True. Is there a way to run my polling code in the background?

using interrupt, maybe

How bout this:

use a timer interrupt (how?) to poll input every x milliseconds, send this to function. So how do I use timer interrupts?

Search for the MsTimer2 library. Pretty good for this sort of thing.

Then yeah if you had a timer updating your variable, and you were willing to let the average function block the main loop, you would pass in a pointer, e.g.

uint8_t average_over_time(uint8_t* value, int num_readings, unsigned long delay_between_readings)
{
 uint16_t total = 0;
 int remaining_readings = num_readings;
 while (remaining_readings--)
 {
   total += *value;
   delay(delay_between_readings);
 }
 return (total/num_readings);
}

Great! I'll try that out. What delay should I use for msTimer2? 1 Ms? 2Ms? What do you think would be best?

Thanks!

why use interrupt on time when you can use interrupt on pin change?
that way i read PPM and i have great precision (error < 100microsec)

#define MASKPCINT0 (1<<2)
#define MASKPCINT1 (1<<4)
#define MASKPCINT2 (1<<5)
#define MASKPCINT3 (1<<6)

InputPin::InputPin(){
  pinMode(2, INPUT); // 3 is used for esc
  pinMode(4, INPUT);
  pinMode(5, INPUT);
  pinMode(6, INPUT);
  // interrupt on pin change FROM PCINT16 to PCINT23
  PCICR |= (1 << PCIE2);

  PCMSK2 = (1 << PCINT18) | // digital pin2
  (1 << PCINT20) | // digital pin4
  (1 << PCINT21) | // digital pin5
  (1 << PCINT22); // digital pin6
}

//declaration is here because interrupt function doesn't want it in .h
unsigned long _startIn[4];
unsigned long _rawIn[4];
unsigned long _time;
byte _oldbit=0, _newbit, _changed;
volatile boolean _hasChanged=false;

ISR(PCINT2_vect) {
  _time=micros();
  
  _newbit=PIND;
  _changed=_newbit^_oldbit;
  
  if (_changed&MASKPCINT0){//if digital PIN2 has changed

    if (_newbit&MASKPCINT0) { //if PIN2 now is high
      _startIn[0]=_time;
    }else{
      _rawIn[0]=_time-_startIn[0];
    }
    _hasChanged=true;
  }

  if (_changed&MASKPCINT1){//if digital PIN4 has changed
    if (_newbit&MASKPCINT1) 
      _startIn[1]=_time;
    else 
      _rawIn[1]=_time-_startIn[1];
    _hasChanged=true;
  }
  
  if (_changed&MASKPCINT2){//if digital PIN5 has changed
    if (_newbit&MASKPCINT2) 
      _startIn[2]=_time;
    else 
      _rawIn[2]=_time-_startIn[2];
    _hasChanged=true;
  }

  if (_changed&MASKPCINT3){//if digital PIN6 has changed
    if (_newbit&MASKPCINT3) 
      _startIn[3]=_time;
    else 
      _rawIn[3]=_time-_startIn[3];
  }
  _oldbit=_newbit;
}

I don't get it... can you sort of summarize it for me?

Thanks.

I'm not good in English but I try :slight_smile:

This code is from a class of mine. Ah, an it work on atmega <=328

InputPin::InputPin() is the constructor, the code is executed when the class is instantiated.
I set the pin I need as input (digital pin 2, 4, 5, 6)
then i activate the interrupt on this PIN. PCIE2 is for interrupt fro pin from PCINT16 to PCINT23, PCIE1 for interrupt from PCINT8 to PCINT15 and PCIE0 from PCINT0 to PCINT8 (crystal pin cannot be used). To understand witch digital/analog pin is PCINT look here: http://arduino.cc/en/Hacking/PinMapping168
// interrupt on pin change FROM PCINT16 to PCINT23
PCICR |= (1 << PCIE2);

now that gereral interrupt is ok, we unmask the input pin per pin
PCMSK2 = (1 << PCINT18) | // digital pin2
(1 << PCINT20) | // digital pin4
(1 << PCINT21) | // digital pin5
(1 << PCINT22); // digital pin6

ISR(PCINT2_vect) is the function called by the interrupt on PCINT2: it cannot be called from code
here inside I use just some Arduino Reference - Arduino Reference