Zápisník experimentátora
Během přípravy pokračování článku o hodinách z NeoPixel Ring jsem napsal tento kód. Je to rychlá implementace plovoucího průměru, který se hodí na vyhlazování měření, které mírně oscilují okolo jedné hodnoty. Princip plovoucího průměru je jednoduchý. Zaznamenáváte si X hodnot dozadu a výsledek je suma hodnot / X. Podrobnosti o plovoucím průměru si můžete nastudovat na stránce na Wikipedii.
Plovoucí průměr si vysvětlíme na kódu, který využívá fotorezistor a analogový pin na Arduinu na měření intenzity světla. O měření intenzity přes fotorezistor si můžete přečíst podrobnosti v samostatném článku. Zde se budeme věnovat už jen samotnému procesu vyhlazování.
Jak zapojení využijme zapojení z obrázku vpravo. Vcc je tam připojeno na fotorezistor, což nám dodává výsledky v podobě:
Zajímavý je pro nás kód plovoucího průměru. Napsal jsem ho v podobě šablony, v níž nastavíte datový typ a počet záznamů v bufferu.
///
/// Moving average
///
/// Simple moving average with fast calculation.
/// typ - any type (int, float, ...)
/// sz - size of buffer
///
template<typename typ, int sz> class MovingAverage
{
typ data[sz]; // buffer
int pos; // actual position in buffer
typ sum; // precalculated sum
public:
MovingAverage()
: pos(0), sum(0)
{
memset(data,0,sizeof(data));
}
void Push(typ value)
{
sum-=data[pos];
sum+=value;
data[pos]=value;
pos++;
if(pos==sz)
pos=0;
}
typ MA()
{
return sum/sz;
}
};
MovingAverage<uint16_t,16> ma;
A použití v kódu je následující. Měříme analogové hodnoty, zasíláme je do bufferu a na další výpočty už používáme hodnotu vypočítaného plovoucího průměru.
void loop() {
uint16_t sv = analogRead(A0);
ma.Push(sv);
uint16_t sva = ma.MA();
int svc=constrain(sva,100,900);
int m=map(svc,100,900,0,255);
Serial.print(sv);
Serial.print(", ");
Serial.print(sva);
Serial.print(", ");
Serial.print(svc);
Serial.print(", ");
Serial.print(m);
Serial.println("");
delay(1000);
}
Toto je elementární implementace plovoucích průměrů, která ale splní všechny běžné požadavky. Můžete vyzkoušet i jiné implementace ze stránek Arduina.
15.06.2018