Moving Average Template class en een beetje assert

algemene C code
Gebruikers-avatar
Berichten: 5043
Geregistreerd: 13 Mei 2013, 20:57
Woonplaats: Heemskerk

Moving Average Template class en een beetje assert

Berichtdoor nicoverduin » 29 Aug 2016, 16:21

Getriggered door een moving average routine die op floats werkt EN ik had toch niets te doen :mrgreen: :mrgreen: De routine wat verder uitgewerkt. Reden hiervoor was dat je voor verschillende type getallen verschillende routines moet schrijven. Binnen C++ heb je echter templates. Voor heb die hier nog nooit van hebben gehoord, is een template een manier om een routine te schrijven zonder dat je weet of het een int, uint of float of double is etc. Op compileer tijd wordt bepaald of de routine nu als een float of int of int16_t of whatever wordt opgebouwd. De routine is nu als volgt:
cpp code
//
// adding assert checks
//
#define DEBUG_MODE // comment this line to avoid assert checks
#ifdef DEBUG_MODE

#define __ASSERT_USE_STDERR
#include <assert.h>
//
// handle diagnostic informations given by assertion and abort program execution:
//
void __assert(const char *__func, const char *__file, int __lineno, const char *__sexp) {
Serial.begin(9600);
// transmit diagnostic informations through serial link.
Serial.println(__func);
Serial.println(__file);
Serial.println(__lineno, DEC);
Serial.println(__sexp);
Serial.flush();
// abort program execution.
abort();
}
#endif

/**
* Moving Average Class as a template
*/
template<class T>
class MovingAverage {
private:
T *elements; // Type pointer elements in our array
T sum; // sum of elements in array
uint16_t _currentIndex; // current index
boolean _loopedThrough; // used to determine if we went through the whole array
uint16_t _numberOfElements; // number of elements in our array

public:
MovingAverage(uint16_t); // constructor
T CalculateMovingAverage(T); // Calculate new moving Average
};
/**
* @name MovingAverage Constructor
* @param numberOfElements number of elements in the array
* Creates dynamically an array of our type values and initializes the array
* and some local variables. There is no destructor as this is quite useless
* due to lack of garbage collection in Arduino
*/
template<class T>
MovingAverage<T>::MovingAverage(uint16_t numberOfelements) {
//
// allocate an array of size T
//
_numberOfElements = numberOfelements;
elements = (T *) malloc(_numberOfElements * sizeof(T));

#ifdef DEBUG_MODE
//
// verify enough memory
//
assert(elements != NULL);
#endif

for (uint8_t i = 0; i < _numberOfElements; i++) {
elements[i] = 0.0;
}
_loopedThrough = false; // this becomes true when the array is minially filled once
_currentIndex = 0; // start with index 0
sum = (T) 0;
}
/**
* @name CalculateMovingAverage
* @param newValue value to be added to array
* @returns T returns the new moving average.
* During the first filling of the elements array the moving average is determined on a less
* amount of entries. This function keeps track of this situation and calculates the correct
* average on the number of items listed.
*/

template<class T>
T MovingAverage<T>::CalculateMovingAverage(T newValue) {
//
// check if index is at our last entry in the array
//
if (_currentIndex >= _numberOfElements) {
_currentIndex = 0; // reset index
_loopedThrough = true; // we looped through at least once
}
//
// subtract our oldest and add latest value
//
sum = sum - elements[_currentIndex] + newValue;
elements[_currentIndex] = newValue;
//
// and increment index
_currentIndex++;
//
// return the correct moving average
//
if (_loopedThrough) {
return (T) (sum / _numberOfElements);
} else {
return (T) (sum / _currentIndex);
}
}

De compiler bepaalt dus wat de invulling voor T wordt. Dit kan ook betekenen dat er een aparte routine voor float komt en een voor int.

Daarnaast zit er een assert in. Ervaren developers kennen deze functie en stelt mij in staat dat als een conditie niet waar wordt een speciale routine wordt aangeroepen die wat informatie geeft over de test en waar deze plaatsvond.

cpp code
#ifdef DEBUG_MODE
//
// verify enough memory
//
assert(elements != NULL);
#endif


Vlak boven deze regels creer ik dynamisch een tabel van het aantal entries voor het MovingAvg. Echter als er niet genoeg RAM is dan gaat dat niet werken. malloc() geeft dan een NULL pointer terug. En dan wil je echt wel stoppen.

Mijn testprogramma is devolgende:
cpp code
MovingAverage <float> test1(10);
MovingAverage <int> test2(10);

float tabelTest1[] = { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0 };
int tabelTest2[] = { 0,1,2,3,4,5,6,7,8,9 };

void setup()
{
Serial.begin(9600);
for (uint8_t j = 0; j < 2; j++) {
//
// test1
//
for (uint8_t i = 0; i < 10; i++) {
Serial.print(" value = ");
Serial.print(tabelTest1[i]);
Serial.print(" moving AVG = ");
Serial.println(test1.CalculateMovingAverage(tabelTest1[i]));
}
//
// test2
//
for (uint8_t i = 0; i < 10; i++) {
Serial.print(" value = ");
Serial.print(tabelTest2[i]);
Serial.print(" moving AVG = ");
Serial.println(test2.CalculateMovingAverage(tabelTest2[i]));
}
}
}

// The loop function is called in an endless loop
void loop()
{
}


En dan krijg je deze output
cpp code
value = 0.00 moving AVG = 0.00 
value = 1.00 moving AVG = 0.50
value = 2.00 moving AVG = 1.00
value = 3.00 moving AVG = 1.50
value = 4.00 moving AVG = 2.00
value = 5.00 moving AVG = 2.50
value = 6.00 moving AVG = 3.00
value = 7.00 moving AVG = 3.50
value = 8.00 moving AVG = 4.00
value = 9.00 moving AVG = 4.50
value = 0 moving AVG = 0
value = 1 moving AVG = 0
value = 2 moving AVG = 1
value = 3 moving AVG = 1
value = 4 moving AVG = 2
value = 5 moving AVG = 2
value = 6 moving AVG = 3
value = 7 moving AVG = 3
value = 8 moving AVG = 4
value = 9 moving AVG = 4
value = 0.00 moving AVG = 4.50
value = 1.00 moving AVG = 4.50
value = 2.00 moving AVG = 4.50
value = 3.00 moving AVG = 4.50
value = 4.00 moving AVG = 4.50
value = 5.00 moving AVG = 4.50
value = 6.00 moving AVG = 4.50
value = 7.00 moving AVG = 4.50
value = 8.00 moving AVG = 4.50
value = 9.00 moving AVG = 4.50
value = 0 moving AVG = 4
value = 1 moving AVG = 4
value = 2 moving AVG = 4
value = 3 moving AVG = 4
value = 4 moving AVG = 4
value = 5 moving AVG = 4
value = 6 moving AVG = 4
value = 7 moving AVG = 4
value = 8 moving AVG = 4
value = 9 moving AVG = 4


Zou je nu echter een te grote array willen maken (dus tabel vergroten naar 1000 x float(=4 bytes)) dan krijg je deze boodschap:
cpp code
MovingAverage
../MovingAvg.ino
61
elements != NULL


Dit kan wel ff moeilijk te behappen zijn maar wie weet loop je een keer ergens tegenaan......
Docent HBO Technische Informatica, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

Advertisement

Berichten: 163
Geregistreerd: 15 Dec 2012, 21:02
Woonplaats: Delfzijl

Re: Moving Average Template class en een beetje assert

Berichtdoor FPCUser » 29 Aug 2016, 16:42

Getriggered door een moving average routine die op floats werkt EN ik had toch niets te doen

Ik moest wel even op de kalender kijken. ;)
Nog drie dagen te gaan en dan pas is het september.
Of is dit een voorschot op de VUT?

In ieder geval: mooi werk en bedankt!

Gebruikers-avatar
Berichten: 5043
Geregistreerd: 13 Mei 2013, 20:57
Woonplaats: Heemskerk

Re: Moving Average Template class en een beetje assert

Berichtdoor nicoverduin » 29 Aug 2016, 17:09

Tja ik moet wat heh :mrgreen: :mrgreen:
Morgen is het weer mooi weer dus mot ik mee fietsen met de chef... En overmorgen ook al :x
En werk krijg ik toch niet meer. Na > duizend sollicitaties is die boodschap wel duidelijk.
Dus gaan we maar weer pogingen doen deze of gene iets bij te leren :mrgreen:
Docent HBO Technische Informatica, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

Gebruikers-avatar
Berichten: 2655
Geregistreerd: 06 Aug 2016, 01:03

Re: Moving Average Template class en een beetje assert

Berichtdoor Koepel » 29 Aug 2016, 23:00

@nicoverduin, probeer 'j' eens 4 te maken en kijk wat er gebeurt.
Het is natuurlijk:
Code: Alles selecteren
elements[_currentIndex] = newValue;


Ik heb me altijd afgevraagd hoe een moving average goed kan gaan als er een 'sum' variable wordt gebruikt met floating point getallen. Dus eindelijk ga ik dat eens proberen, en heb de volgende test gedaan (na correctie van: = newValue).
Met Arduino.cc IDE 1.6.11 en een Arduino Uno.

Code: Alles selecteren
MovingAverage <float> test1(10);
 
float tabelTest1[] = {
  0.0,   1.0,   2.0,   3.0,   4.0,   5.0,   6.0,   7.0,   8.0,   9.0,
//  1E+10, 1E+10, 1E+10, 1E+10, 1E+10, 1E+10, 1E+10, 1E+10, 1E+10, 1E+10,
  1E+7,  1E+7,  1E+7,  1E+7,  1E+7,  1E+7,  1E+7,  1E+7,  1E+7,  1E+7,
//  1E-10, 1E-10, 1E-10, 1E-10, 1E-10, 1E-10, 1E-10, 1E-10, 1E-10, 1E-10,
  5,     5,     5,     5,     5,     5,     5,     5,     5,     5,
  5,     5,     5,     5,     5,     5,     5,     5,     5,     5,
  5,     5,     5,     5,     5,     5,     5,     5,     5,     5  };
 
void setup()
{
  Serial.begin(9600);
  Serial.println(F( "\nStarted"));
 
  for (uint8_t j = 0; j < 1; j++)
  {
    //
    // test1
    //
    for (uint8_t i = 0; i < sizeof(tabelTest1)/sizeof(float); i++)
    {
      Serial.print(" value = ");
      Serial.print(tabelTest1[i]);
      Serial.print(" moving AVG = ");
      Serial.println(test1.CalculateMovingAverage(tabelTest1[i]));
    }
  }
}
 
// The loop function is called in an endless loop
void loop()
{
}


Er kunnen rijen met getallen geselecteerd worden met of zonder de comment '//'. Met de rij van 10 miljoen blijft het gemiddelde op 5.40 steken in plaats op 5.00. Als 'j' er een paar keer meer doorheen gaat wordt het: 5.40, 6.20, 7.00, 7.80, enzovoorts. Het is dus inderdaad een constante ophoging van de sum.

Gebruikers-avatar
Berichten: 5043
Geregistreerd: 13 Mei 2013, 20:57
Woonplaats: Heemskerk

Re: Moving Average Template class en een beetje assert

Berichtdoor nicoverduin » 29 Aug 2016, 23:33

Dank voor het vinden van de fout.
Is aangepast en blijft nu gelijk. Alhoewel ik nog wel twijfel of het goed gaat met grote getallen. Immers float is maar iets van 5-6 cijfers en sum wordt dan al gauw groter en gaat precisie verliezen die groter wordt als je daarna weer getallen gaat aftrekken en optellen. Dat is de beperking van de Arduino. Of er moet iemand zijn met een echte double routine. Dacht niet dat ie in de compiler zat en anders waarschijnlijk een te groot beslag legt op het flash geheugen.
@edit: Je geeft het zelf al aan met de grotere getallen dat je dus die afwijkingen krijgt. Op zich bekend probleem. In de 70'er jaren kon je maar met 15 cijfers rekenen. Lijkt veel, maar als jij Crude Oil per ton moet uitrekenen van een van de grootste oliemaatschappijen ter wereld dan moet je nog goed nadenken hoe je de formule gaat oplossen... En floating point was niet van toepassing. Alles in packed decimal (IBM).
Eigenlijk zou je al een assert moeten doen dat er een afwijking kan ontstaan door een 'overflow' of 'accuracy loss'.
Docent HBO Technische Informatica, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

Gebruikers-avatar
Berichten: 2655
Geregistreerd: 06 Aug 2016, 01:03

Re: Moving Average Template class en een beetje assert

Berichtdoor Koepel » 29 Aug 2016, 23:46

Dat had ik getest. Met '5' en '10 miljoen' gaat het fout. Dan zou het gemiddelde gewoon iedere uitgerekend moeten worden, zonder de optimalisatie met de 'sum'.

Dat had ik hier al gedaan, omdat ik al vermoedde dat de 'sum' scheef zou kunnen gaan lopen, maar toen had ik het nog niet getest.
https://gist.github.com/Koepel/b70f81c71a52d8d6d3da86b9fe56d50e#file-bh1750-ino-L229

Een 'double' in de 8-bits AVR chips gaat niet lukken. De avr-gcc compiler vertaalt de getallen naar een 'float'. Daardoor is het bijvoorbeeld niet mogelijk om pi als constante in een 'double' berekening te gebruiken. Er is geen avr library voor 'double', maar er zijn wel libraries voor 'double' in gewoon 'c' source code, dus dat is het probleem niet.
Het probleem zit in die vertaalslag om alles als 'float' te zien. Zo'n vertaalslag heb ik nergens anders gezien.

Gebruikers-avatar
Berichten: 5043
Geregistreerd: 13 Mei 2013, 20:57
Woonplaats: Heemskerk

Re: Moving Average Template class en een beetje assert

Berichtdoor nicoverduin » 30 Aug 2016, 08:44

Het gaat natuurlijk net zo fout als je veel grote uint8_t's heb. Bijgaand de nieuwe code nu met alle bovenstaande aanpassingen als ook een check dat als het geen float of double is sum een uint32_t (unsigned long wordt).
cpp code
#include "Arduino.h"
//
// adding assert checks
//
#define DEBUG_MODE // comment this line to avoid assert checks
#ifdef DEBUG_MODE

#define __ASSERT_USE_STDERR
#include <assert.h>
//
// handle diagnostic informations given by assertion and abort program execution:
//
void __assert(const char *__func, const char *__file, int __lineno, const char *__sexp) {
Serial.begin(9600);
// transmit diagnostic informations through serial link.
Serial.println(__func);
Serial.println(__file);
Serial.println(__lineno, DEC);
Serial.println(__sexp);
Serial.flush();
// abort program execution.
abort();
}
#endif

/**
* Moving Average Class as a template
*/
template<class T>
class MovingAverage {
private:
T *elements; // Type pointer elements in our array
//
// reserve enough space for sum value
//
#if T == float
T sum; // sum of elements in array
#else
#if T == double
T sum;
#else
uint32_t sum;
#endif
#endif

uint16_t _currentIndex; // current index
boolean _loopedThrough; // used to determine if we went through the whole array
uint16_t _numberOfElements; // number of elements in our array

public:
MovingAverage(uint16_t); // constructor
T CalculateMovingAverage(T); // Calculate new moving Average
};
/**
* @name MovingAverage Constructor
* @param numberOfElements number of elements in the array
* Creates dynamically an array of our type values and initializes the array
* and some local variables. There is no destructor as this is quite useless
* due to lack of garbage collection in Arduino
*/
template<class T>
MovingAverage<T>::MovingAverage(uint16_t numberOfelements) {

//
// allocate an array of size T
//
_numberOfElements = numberOfelements;
elements = (T *) malloc(_numberOfElements * sizeof(T));

#ifdef DEBUG_MODE
//
// verify enough memory
//
assert(elements != NULL);
#endif

for (uint8_t i = 0; i < _numberOfElements; i++) {
elements[i] = 0.0;
}
_loopedThrough = false; // this becomes true when the array is minially filled once
_currentIndex = 0; // start with index 0
sum = (T) 0;
}
/**
* @name CalculateMovingAverage
* @param newValue value to be added to array
* @returns T returns the new moving average.
* During the first filling of the elements array the moving average is determined on a less
* amount of entries. This function keeps track of this situation and calculates the correct
* average on the number of items listed.
*/

template<class T>
T MovingAverage<T>::CalculateMovingAverage(T newValue) {
//
// check if index is at our last entry in the array
//
if (_currentIndex >= _numberOfElements) {
_currentIndex = 0; // reset index
_loopedThrough = true; // we looped through at least once
}
//
// subtract our oldest and add latest value
//
sum = sum - elements[_currentIndex] + newValue;
elements[_currentIndex] = newValue;
//
// and increment index
_currentIndex++;
//
// return the correct moving average
//
if (_loopedThrough) {
return (T) (sum / _numberOfElements);
} else {
return (T) (sum / _currentIndex);
}
}

MovingAverage <int> test2(10);
MovingAverage <float> test1(10);

float tabelTest1[] = { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0 };
int tabelTest2[] = { 0,1,2,3,4,5,6,7,8,9 };

void setup()
{
Serial.begin(9600);
for (uint8_t j = 0; j < 1; j++) {
//
// test1
//
for (uint8_t i = 0; i < 10; i++) {
Serial.print(" value = ");
Serial.print(tabelTest1[i]);
Serial.print(" moving AVG = ");
Serial.println(test1.CalculateMovingAverage(tabelTest1[i]));
}
//
// test2
//
for (uint8_t i = 0; i < 10; i++) {
Serial.print(" value = ");
Serial.print(tabelTest2[i]);
Serial.print(" moving AVG = ");
Serial.println(test2.CalculateMovingAverage(tabelTest2[i]));
}
}
}

// The loop function is called in an endless loop
void loop()
{
}
Docent HBO Technische Informatica, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

Gebruikers-avatar
Berichten: 5043
Geregistreerd: 13 Mei 2013, 20:57
Woonplaats: Heemskerk

Re: Moving Average Template class en een beetje assert

Berichtdoor nicoverduin » 30 Aug 2016, 11:01

Leuk geprobeerd.... Maar die #if's werken niet.... Back to the drawing board.....
Docent HBO Technische Informatica, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

Gebruikers-avatar
Berichten: 5043
Geregistreerd: 13 Mei 2013, 20:57
Woonplaats: Heemskerk

Re: Moving Average Template class en een beetje assert

Berichtdoor nicoverduin » 30 Aug 2016, 17:37

De aanhouder wint :). Wel een stukje lastigere code geworden (tijd voor een library .....).
De code lijkt vrij robuust binnen de beperkingen van de arduino.
@Johan: als jij er nog eens een kritische blik tegen mijn programmeurs blindheid wil werpen op de code...

cpp code
#include "Arduino.h"

//
// adding assert checks
//
#define DEBUG_MODE // comment this line to avoid assert checks
#ifdef DEBUG_MODE

#define __ASSERT_USE_STDERR
#include <assert.h>
//
// handle diagnostic informations given by assertion and abort program execution:
//
void __assert(const char *__func, const char *__file, int __lineno, const char *__sexp) {
Serial.begin(9600);
// transmit diagnostic informations through serial link.
Serial.println(__func);
Serial.println(__file);
Serial.println(__lineno, DEC);
Serial.println(__sexp);
Serial.flush();
// abort program execution.
abort();
}
#endif
//
// Generic catch-all implementation for determining type of variable
// with thanks to http://arduino.stackexchange.com/questi ... a-variable
//
template <typename T_ty> struct TypeInfo { static const char * name; };
template <typename T_ty> const char * TypeInfo<T_ty>::name = "unknown";
//
// Handy macro to make querying stuff easier.
//
#define TYPE_NAME(var) TypeInfo< typeof(var) >::name
//
// Handy macro to make defining stuff easier.
//
#define MAKE_TYPE_INFO(type) template <> const char * TypeInfo<type>::name = #type;
//
// Type-specific implementations. Only float and double need to be tested
//
MAKE_TYPE_INFO( float )
MAKE_TYPE_INFO( double )

/**
* Moving Average Class as a template
*/
template<class T>
class MovingAverage {
private:
T *elements; // Type pointer elements in our array
uint16_t _currentIndex; // current index
T _sum; // sum for floats and double
uint32_t _sum_32; // sum for rest
boolean _loopedThrough; // used to determine if we went through the whole array
uint16_t _numberOfElements; // number of elements in our array

public:
MovingAverage(uint16_t); // constructor
T CalculateMovingAverage(T); // Calculate new moving Average
};
/**
* @name MovingAverage Constructor
* @param numberOfElements number of elements in the array
* Creates dynamically an array of our type values and initializes the array
* and some local variables. There is no destructor as this is quite useless
* due to lack of garbage collection in Arduino
*/
template<class T>
MovingAverage<T>::MovingAverage(uint16_t numberOfelements) {

//
// allocate an array of size T
//
_numberOfElements = numberOfelements;
elements = (T *) malloc(_numberOfElements * sizeof(T));

#ifdef DEBUG_MODE
//
// verify enough memory
//
assert(elements != NULL);
#endif

for (uint8_t i = 0; i < _numberOfElements; i++) {
elements[i] = 0.0;
}
_loopedThrough = false; // this becomes true when the array is minimally filled once
_currentIndex = 0; // start with index 0

if ((strcmp(TYPE_NAME(T), "float") != 0) && (strcmp(TYPE_NAME(T), "double") != 0) ){
_sum_32 = 0;
} else {
_sum = 0.0;
}
}
/**
* @name CalculateMovingAverage
* @param newValue value to be added to array
* @returns T returns the new moving average.
* During the first filling of the elements array the moving average is determined on a less
* amount of entries. This function keeps track of this situation and calculates the correct
* average on the number of items listed.
*/

template<class T>
T MovingAverage<T>::CalculateMovingAverage(T newValue) {
//
// check if index is at our last entry in the array
//
if (_currentIndex >= _numberOfElements) {
_currentIndex = 0; // reset index
_loopedThrough = true; // we looped through at least once
}
//
// subtract our oldest and add latest value
//
if ((strcmp(TYPE_NAME(T), "float") != 0) && (strcmp(TYPE_NAME(T), "double") != 0) ){
//
// non floating point
//
_sum_32 = _sum_32 - elements[_currentIndex] + newValue;
} else {
//
// floating point
//
_sum = _sum - elements[_currentIndex] + newValue;
}
elements[_currentIndex] = newValue;
//
// and increment index
//
_currentIndex++;

//
// return the correct moving average
//
if ((strcmp(TYPE_NAME(T), "float") != 0) && (strcmp(TYPE_NAME(T), "double") != 0) ){
//
// non floating point
//
if (_loopedThrough) {
return (T) (_sum_32 / _numberOfElements);
} else {
return (T) (_sum_32 / _currentIndex);
}
} else {
//
// non floating point
//
if (_loopedThrough) {
return (T) (_sum / _numberOfElements);
} else {
return (T) (_sum / _currentIndex);
}
}
}

MovingAverage <uint32_t> test2(10);
MovingAverage <float> test1(5);

float tabelTest1[] = { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0 };
uint32_t tabelTest2[] = { 0,25500, 205500,35500,46600,57770,60000,7,8000,9999 };

void setup()
{
Serial.begin(9600);
for (uint8_t j = 0; j < 2; j++) {
//
// test1
//
for (uint8_t i = 0; i < 10; i++) {
Serial.print(" value = ");
Serial.print(tabelTest1[i]);
Serial.print(" moving AVG = ");
Serial.println(test1.CalculateMovingAverage(tabelTest1[i]));
}
//
// test2
//
for (uint8_t i = 0; i < 10; i++) {
Serial.print(" value = ");
Serial.print(tabelTest2[i]);
Serial.print(" moving AVG = ");
Serial.println(test2.CalculateMovingAverage(tabelTest2[i]));
}
}
}

// The loop function is called in an endless loop
void loop()
{
}
Docent HBO Technische Informatica, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

Gebruikers-avatar
Berichten: 2655
Geregistreerd: 06 Aug 2016, 01:03

Re: Moving Average Template class en een beetje assert

Berichtdoor Koepel » 31 Aug 2016, 03:05

Het is voor mij te ingewikkeld. Ik heb zelf nog nooit een template gemaakt :roll:
Je probeert alles te vangen met een enkele class + template ? Maar dan wordt het wel ingewikkelder met de strcmp().
Het lijkt wel Pokemon Go ("Gotta Catch 'Em All").

Ik heb dit gemaakt:
Code: Alles selecteren
#define R10(a) a;a;a;a;a;a;a;a;a;a
#define R100(a) R10(a);R10(a);R10(a);R10(a);R10(a);R10(a);R10(a);R10(a);R10(a);R10(a)
#define R1000(a) R100(a);R100(a);R100(a);R100(a);R100(a);R100(a);R100(a);R100(a);R100(a);R100(a)

...
    unsigned long t1 = micros();
    R1000( test1.CalculateMovingAverage( 7.77));
    unsigned long t2 = micros();
    Serial.print(" tijd=");
    Serial.println( (t2 - t1)/1000);


Getest op Arduino Uno met Arduino.cc IDE 1.6.11.
Nieuwe manier, integer: 45 us
Nieuwe manier, float: 56 us
Oude manier, integer 45 us
Oude manier, float: 56 us
Dat begrijp ik niet, gaat de compiler tijdens het compileren al de strcmp doen ?
Als dat zo is, dan is er geen nadeel voor de tijd.

De tijden zijn best snel. Een float vermenigvuldiging kost 8 us en een float deling kost 80 us.
Dat is dus het voordeel van de 'sum'.

Er is geen ~MovingAverage, om het geheugen vrij te geven met free().

Volgende

Terug naar C code

Wie is er online?

Gebruikers in dit forum: Geen geregistreerde gebruikers en 9 gasten