我想用这个公式计算我的微控制器的平均值:
uint16_t uAverage;
uint64_t counter;
uint16_t u;
uAverage = uAverage * (1 + 1 / counter) + u / counter;
但是我在过去的那些计算中遇到了问题,这也是行不通的,因为它们的类型不同,而且因为除法应该返回浮点值。
请告诉我如何使用这个公式的最佳方法。
编辑: 这是目前的全部来源。该程序可以使用ADC测量电功率。如果您有任何疑问,请询问。微控制器: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 ++;
}
}
答案 0 :(得分:1)
是否需要非浮点答案:
执行一个整数除法。在分割之前添加counter/2
来获得一个舍入商。
通过缩放uAverage
,可以根据变量的允许范围提高精度。
uint16_t uAverage;
uint64_t counter;
uint16_t u;
// uAverage = uAverage * (1 + 1 / counter) + u / counter;
// uAverage = uAverage + uAverage / counter + u / counter;
// uAverage = (uAverage*counter + uAverage + u) / counter;
uAverage = (uAverage*counter + uAverage + u + counter/2) / counter;
// or
const unsigned Scale = 16; // Largest value that does not overflow computations.
uScAverage = (uScAverage*counter + uScAverage + scale*(u + counter/2)) / counter;
uAverage = (uScAverage + Scale/2)/Scale;
答案 1 :(得分:0)
将整数除以整数会返回整数。
以1 / counter
为例:
counter > 1
,则返回0 counter == 1
,则会返回1 counter == 0
,则会生成异常所以你基本上应该把至少一个操作数转换为float
或double
。
话虽如此,这是您尝试执行的计算的解决方案:
uAverage += (double)(uAverage+u)/counter;
答案 2 :(得分:0)
这有效:
注意计算中的修正:你的1和2给出结果2.5 ......
float uAverage=0;
int counter=0;
int u=0;
while(scanf("%d",&u)) {//can type any no numeric to quit...
counter++;
uAverage = uAverage * (1.0 - 1.0 / counter) + (float)u / counter;
printf("%f\n",uAverage);
}