avr: Improve the accuracy of pwr measurements and prevent an underflow condition in a boundary case by rounding down the multiplication constant. Thanks Mario!
This commit is contained in:
parent
8d1ccbc8fc
commit
fdc2e35e0f
|
@ -287,8 +287,18 @@ void send(uint8_t msg_type, const struct sensor *measurement, const struct state
|
||||||
pulse_count = aux->pulse_count_final;
|
pulse_count = aux->pulse_count_final;
|
||||||
sei();
|
sei();
|
||||||
|
|
||||||
MacU16X16to32(value, (uint16_t)(labs(rest)/65536), 242);
|
// Since the AVR has no dedicated floating-point hardware, we need
|
||||||
value /= 1024;
|
// to resort to fixed-point calculations for converting nWh/s to W.
|
||||||
|
// 1W = 10^6/3.6 nWh/s
|
||||||
|
// value[watt] = 3.6/10^6 * rest[nWh/s]
|
||||||
|
// value[watt] = 3.6/10^6 * 65536 * (rest[nWh/s] / 65536)
|
||||||
|
// value[watt] = 3.6/10^6 * 65536 * 262144 / 262144 * (rest[nWh/s] / 65536)
|
||||||
|
// value[watt] = 61847.53 / 262144 * (rest[nWh/s] / 65536)
|
||||||
|
// We round the constant down to 61847 to prevent 'underflow' in the
|
||||||
|
// consecutive else statement.
|
||||||
|
// The error introduced in the fixed-point rounding equals 8.6*10^-6.
|
||||||
|
MacU16X16to32(value, (uint16_t)(labs(rest)/65536), 61847);
|
||||||
|
value /= 262144;
|
||||||
|
|
||||||
if (rest >= 0)
|
if (rest >= 0)
|
||||||
value += pulse_count*3600;
|
value += pulse_count*3600;
|
||||||
|
|
Loading…
Reference in New Issue