I'm trying to learn on creating a library.
What i want to make is a function for averaging values read from a sensor.
Each time a sensor is read, the value should be passed and averaged with the previous values.
I have the skecth which i want to use for this, see below.
const int numAvr = 25;
int readings [numAvr];
int distance = 0;
int avr_distance = 0;
int readIndex = 0;
int average = 0;
int total = 0;
void setup() {
Serial.begin(230400);
}
void loop() {
distance = analogRead(A0);
total = total - readings[readIndex];
readings[readIndex] = distance;
total = total + distance;
readIndex = readIndex + 1;
if (readIndex >= numAvr) {
readIndex = 0;
}
avr_distance = total / numAvr;
Serial.print(distance);
Serial.print("\t");
Serial.println(avr_distance);
delay(10);
}
What I want to know is how to deal with the array containing the old data.
Do i keep (and update) this in the main sketch and pass it to the function that handles it or would it be possible to just pass one value to the function which then internally "logs" the old values?
if I have to update the array in the main sketch, most of the works is still done there (and a library with this function does not seem to make much sense).
Or maybe a total different route should be followed for such a averaging tool?
Exactly. You'll probably declare the array in the header file of your library (say KingBeeAverage.h) and it will present from the time your library class is instantiated in the main sketch ( KingBeeAverage myAverage ; ) and will not vanish (under normal circumstances) until your sketch ends.
The first thing you would do is modify your existing sketch to put the library stuff out into a separate .cpp and .h file. There's a couple of steps to doing this. The .h needs to contain declarations for any stuff that the user of your library will need, and the .cpp file is not pre-processed in the way that an .ino is, so it will have to explicitly include <Arduino.h>.
A library is simply that .cpp and .h file in a directory under 'libraries", with a library.properties file containing stuff like the library version and name.
I've got the basic concept working.
I do have some problem defining the array where all the measurements are stored.
I want to have an array with the size "range" which is a value passed to the class.
Results in a error however, unless i make it a fixed value (25 in .h file below), then all works fine.
/*
Library for averaging values.
11/6/2016
*/
#ifndef MBMath_h
#define MBMath_h
#include "Arduino.h"
class MBMath
{
public:
MBMath(int value, int range);
int mov_average(int value, int range);
private:
int _value;
int _range;
int readings [25];
int height_read;
int result;
int readIndex;
int total;
};
#endif
.ccp
/*
Library for averaging values.
11/6/2016
*/
#include "Arduino.h"
#include "MBMath.h"
MBMath::MBMath(int value, int range)
{
_value = value;
_range = range;
readings[_range]=0;
total =0;
readIndex=0;
result=0;
}
int MBMath::mov_average(int _value, int _range)
{
total = total - readings[readIndex];
readings[readIndex] = _value;
total = total + _value;
readIndex = readIndex + 1;
if (readIndex >= _range) {
readIndex = 0;
}
result = total / _range;
return result;
}
private:
static const int myRange = 25 ;
int readings[ myRange ] ;
. . .
. . .
But that is probably not exactly what you want. You want to specify via an argument to the constructor function, what the array dimensions should be. I'm curious to see what other answers you get, but I believe that it must be clear at compile time what the array dimensions should be.
Must admit I'm quite lost with your code (understand some, but clearly not all).
The template approach is new to me, so i'm tying to figure out what it exactly is.
Not sure how to use it either, how would i use this in a sketch file?
Template based code should be placed in an single header file not split per usual library of .h and .cpp files.
Compiled but not tested!
// FILE - MBMath.h
#ifndef MBMath_H
#define MBMath_H
// ... THE TEMPLATES 'RANGE' PARAMETER SPECIFIES THE LENGTH OF THE BUFF '_V' ...
// ... AT COMPILE TIME ...
template<const size_t RANGE>
class MBMath
{
const size_t kRANGE;
int _v[RANGE]; // ... AND IS USED TO SET THE BUFFERS LENGTH ...
int _index; // ... OUR RUNNING BUFFER INDEX ...
int _total; // ... OUR RUNNING TOTAL ...
public:
// Using templates and constructor initializaation list type constructors
// you can specify per instance buffers of specified size with the template
// parameter RANGE above
// <http://en.cppreference.com/w/cpp/language/initializer_list>
MBMath()
: kRANGE(RANGE) // ... CONSTANTS MUST BE INIT"D DIRST ...
, _index(0) // ... THEN INSTANCE VARIABLES ...
, _total(0)
{
// ... SET THE INITIAL BUFFER CONTENTS TO ZERO ...
memset(_v, 0, kRANGE); // CLEAR OUR BUFFER
}
int mov_average(int value)
{
// ... RESTATED VERSION OF YOUR MOVEING AVERAGE CODE ...
_total -= _v[_index];
_v[_index] = value;
_total += value;
// ... UPDATE INDEX TO USE NEXT SLOT IN BUFFER '_v' ...
_index = ((_index + 1) % kRANGE);
return _total / kRANGE;
}
};
#endif
// FILE - SomeSketch.ino
#include "MBMath.h"
#define BAUD_RATE (230400UL)
// Instance with internal buffer 10 int in length
MBMath<10> test;
void loop()
{
const int reading = analogRead(A0);
const int result = test.mov_average(reading);
Serial.print(reading);
Serial.print("\t");
Serial.println(result);
delay(10);
}
void setup()
{
Serial.begin(BAUD_RATE);
}