I want to calculate an average value on my microcontroller with this formula:
uint16_t uAverage;
uint64_t counter;
uint16_t u;
uAverage = uAverage * (1 + 1 / counter) + u / counter;
But I had problems with those calculations in the past and this is also not working, because of the different types and also because of the division which should return a float value.
Can you please show me the best way how to cast in this formula.?
Edit: This is the whole source at the moment. This programm can measure an electrical power with the ADCs. If you have questions, please ask. microcontroller: ATmega2560
#include <avr/io.h>
#include <avr/interrupt.h>
#include <inttypes.h>
#include "LITECShieldDefinitions.h"
#include "ADC.h"
#include "Timer.h"
#include "HWTimer.h"
#include "LCD.h"
#include "USART.h"
volatile uint8_t setOffset = 0;
volatile uint8_t resetValues = 0;
volatile uint8_t resetSecondValues = 0;
volatile uint64_t counter = 1;
volatile uint64_t counterSecond = 1;
volatile uint16_t u = 0;
volatile uint16_t i = 0;
volatile int32_t p = 0;
volatile uint16_t uMin = 1023;
volatile uint16_t iMin = 1023;
volatile int32_t pMin = 1046529;
volatile uint16_t uMax = 0;
volatile uint16_t iMax = 0;
volatile int32_t pMax = 0;
volatile uint16_t uAverage = 0;
volatile uint16_t iAverage = 0;
volatile int32_t pAverage = 0;
volatile uint16_t uSecondAverage = 0;
volatile uint16_t iSecondAverage = 0;
volatile int32_t pSecondAverage = 0;
volatile uint16_t uOffset = 0;
volatile uint16_t iOffset = 0;
ISR(TIMER1_OVF_vect) {
TimerLoadValue(TIMER_1, 3000);
resetSecondValues = 1;
//TODO: print values to LCD
printf("u=%" PRIu16 "\n", u);
printf("i=%" PRIu16 "\n", i);
printf("p=%" PRId32 "\n", p);
printf("uMin=%" PRIu16 "\n", uMin);
printf("iMin=%" PRIu16 "\n", iMin);
printf("pMin=%" PRId32 "\n", pMin);
printf("uMax=%" PRIu16 "\n", uMax);
printf("iMax=%" PRIu16 "\n", iMax);
printf("pMax=%" PRId32 "\n", pMax);
printf("uAverage=%" PRIu16 "\n", uAverage);
printf("iAverage=%" PRIu16 "\n", iAverage);
printf("pAverage=%" PRId32 "\n", pAverage);
printf("uSecondAverage=%" PRIu16 "\n", uSecondAverage);
printf("iSecondAverage=%" PRIu16 "\n", iSecondAverage);
printf("pSecondAverage=%" PRId32 "\n", pSecondAverage);
printf("uOffset=%" PRIu16 "\n", uOffset);
printf("iOffset=%" PRIu16 "\n\n", iOffset);
}
ISR(USART0_RX_vect) {
char data = UDR0;
if (data == 'S') {
setOffset = 1;
printf("S\n");
} else if (data == 'R') {
resetValues = 1;
printf("R\n");
} else {
printf("S, R\n");
}
}
int main(void) {
DDRD = 0x00;
PORTD = 0xff;
LCDInit();
LCDClear();
LCDString(1, 1, "Wattmeter ");
USARTInit(0, 19200, 1, 1, 1, 0);
printf("Wattmeter\n");
sei();
TimerEnableOVFInt(TIMER_1);
TimerEnable(TIMER_1, PRE_DIV_256, TIMER_MODE0_NORMAL);
TimerLoadValue(TIMER_1, 3000);
ADCInit(ADC_VREF_TYPE_INTERNAL_AREF);
while(1) {
if (S1 || setOffset) {
setOffset = 0;
uOffset = u;
iOffset = i;
}
if (S0 || resetValues) {
resetValues = 0;
counter = 1;
counterSecond = 1;
u = 0;
i = 0;
p = 0;
uMin = 1023;
iMin = 1023;
pMin = 1046529;
uMax = 0;
iMax = 0;
pMax = 0;
uAverage = 0;
iAverage = 0;
pAverage = 0;
uSecondAverage = 0;
iSecondAverage = 0;
pSecondAverage = 0;
}
if (resetSecondValues) {
resetSecondValues = 0;
counterSecond = 1;
uSecondAverage = 0;
iSecondAverage = 0;
pSecondAverage = 0;
}
u = ADCReadChannel(0); //max. 10 bit value
i = ADCReadChannel(1);
int16_t uReal = u - uOffset;
int16_t iReal = i - iOffset;
p = (int32_t) uReal * iReal;
if (u < uMin) {
uMin = u;
}
if (i < iMin) {
iMin = i;
}
if (p < pMin) {
pMin = p;
}
if (u > uMax) {
uMax = u;
}
if (i > iMax) {
iMax = i;
}
if (p > pMax) {
pMax = p;
}
uAverage = uAverage * (1 - 1 / counter) + u / counter;
iAverage = iAverage * (1 - 1 / counter) + i / counter;
pAverage = pAverage * (1 - 1 / counter) + p / counter;
uSecondAverage = uSecondAverage * (1 - 1 / counterSecond) + u / counterSecond;
iSecondAverage = iSecondAverage * (1 - 1 / counterSecond) + i / counterSecond;
pSecondAverage = pSecondAverage * (1 - 1 / counterSecond) + p / counterSecond;
counter ++;
counterSecond ++;
}
}