Averaging Integer Library

Hey guys,

I'm working on creating a library that averages integers. I'm running into a problem, though. When I try to compile my test code, the error states "invalid conversion from 'int' to 'int* (*)()'".

Here's the header file:

#ifndef Averaging_h
#define Averaging_h

#include "WProgram.h"

class AverageInteger
{
      public:
            AverageInteger(int (*functionInt()), unsigned int repeats);
            int averageInt();
            
            
      private:
            int (*executeInt());
};

#endif

Here's the CPP file:

#include "Averaging.h"


//Constructor:
AverageInteger::AverageInteger(int (*functionInt()), unsigned int repeats)
{
      executeInt() = functionInt();
      int returnedInt = 0;
      int answerInt = 0;
}

int AverageInteger::averageInt()
{
      for (unsigned int i = 0; i < repeats; i++)
      {
            returnedInt = executeInt();
            answerInt += returnedInt;
      }
      answerInt = (answerInt / repeats);
      return answerInt;
}

Here's the example code:

#include <Averaging.h>
#include <HM55B.h>
#include <SPI.h>

HM55B myCompass = HM55B(24,25,26);

AverageInteger myAverage = AverageInteger(myCompass.getValue(), 10);


void setup()
{
  Serial.begin(9600);
  Serial.println("Initializing HM55B");
  myCompass.begin();
  Serial.println("Initialized");
}

void loop()
{
  Serial.println(myAverage.averageInt(), DEC);
  
  //Serial.println(myCompass.getValue(), DEC);
}

The HM55B library can be found at: Google Code Archive - Long-term storage for Google Code Project Hosting.

I've looked around, and the closest example of what I'm trying to do can be found at: Arduino Playground - TimedAction Library

Thanks!

Chris

Here you are evaluating the function not passing a pointer to it

AverageInteger myAverage = AverageInteger(myCompass.getValue(), 10);

you need to get the address

AverageInteger myAverage = AverageInteger([glow]&[/glow]myCompass.getValue(), 10);

Really though since this is C++ you should just accept any object with the appropriate interface

Interesting construction, usefull for averaging multiple sensor readings. A few tips :

  • Use a long to add up all the returned Values ; this prevents overflows when many calls are made.
  • No need to declare returnInt and answerInt in the constructor, they are only used in the function AverageInt() for now.
  • The var repeats must be stored in a local var in the class. I wonder if it is a good choice to set repeats allready in the constructor.
  • A default value for repeats ?
  • Add a test to prevent divide by zero answer = repeats > 0? answer/repeats : 0;
  • Add extra vars + code for capturing the minimum and maximum value, and two additional functions to access them.

you might check my simple statistics class in the playground - Arduino Playground - Statistics

Thanks for the help guys. I've added a few of the tips, but I'll save the rest for after I get the core of library working. :slight_smile:

I've edited my library.

Averaging.h:

#ifndef Averaging_h
#define Averaging_h

#include "WProgram.h"

class Average
{
      public:
            Average(int* &functionInt(), unsigned int repeats);
            long averageReading();
            
            
      private:
            int (*executeInt());
};

#endif

Averaging.cpp:

#include "Averaging.h"


//Constructor:
Average::Average(int* &functionInt(), unsigned int repeats)
{
      executeInt() = &functionInt();
      // int returnedInt = 0;
      // int answerInt = 0;
      if (repeats <= 0)
      {
            repeats = 1;
      }
      else
      {
      }
}

long Average::averageReading()
{
      int returnedInt = 0;
      long answerLong = 0;
      for (unsigned int i = 0; i < repeats; i++)
      {
            returnedInt = executeInt();
            answerInt += returnedInt;
      }
      
      answerInt = (answerInt / repeats);
      return answerInt;
}

When I use this library, I get the error: "error: lvalue required as unary '&' operand"

I've tried googling that, and I got the forum result casting - How to cast a pointer in C++ - Stack Overflow but I still can't figure out how to fix the "unary '&' operand" error. What am I doing wrong?

Thanks again!

Chris

There are quite a few syntax errors in there I'm afraid but more than that there is a fundamental problem with the approach. By trying to pass the address of a class member function you need to scope it to the owning class in the declaration of the function pointer which means you will never be able to pass anything other than a member of whatever class myCompass belongs to.

You could get around this by using a regular C function pointer, or have the data supplying function in a single-member base class but what you really need is a functor. Google it, it's been implemented many times before in countless C++ libraries.

I wrote this sample sketch which does what you're looking for, and copes with overflow into 64 bits (as long as the number of, and size of, the samples don't exceed 32 bits). You may not understand this code right away but it's worth persisting because the techniques are useful.

template <class Functor>
class Average {
  public:
    long getAverage(long repeats,Functor f) {
      int64_t total=0;
      
      for(long i=0;i<repeats;i++)
        total+=f(i);
        
      return static_cast<long>(total/repeats);
    }
};  

struct DataSupplier {
  long operator()(long iteration) {
    return iteration;
  }
};

void setup() {
  Serial.begin(9600);
  
  Average<DataSupplier> av;
  DataSupplier dt;
  
  Serial.println(av.getAverage(100,dt));
}

void loop() {
}

The example functor just returns the interation count. In reality you would modify that to return your sample of data.

Andy,

Thanks for your reply (and the example code!). I'll look into functors as soon as I can. I don't know when I'll have this library done, because of school, etc, but I'll post a link to it if/when I finish it.

Thanks again!

Chris