From fdc2e35e0f4be9efc8837b1968520a6930af3283 Mon Sep 17 00:00:00 2001 From: Bart Van Der Meerssche Date: Wed, 8 Sep 2010 17:53:57 +0200 Subject: [PATCH] avr: Improve the accuracy of pwr measurements and prevent an underflow condition in a boundary case by rounding down the multiplication constant. Thanks Mario! --- mote/v1/avr/main.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/mote/v1/avr/main.c b/mote/v1/avr/main.c index 8114edb..63dca9b 100644 --- a/mote/v1/avr/main.c +++ b/mote/v1/avr/main.c @@ -287,8 +287,18 @@ void send(uint8_t msg_type, const struct sensor *measurement, const struct state pulse_count = aux->pulse_count_final; sei(); - MacU16X16to32(value, (uint16_t)(labs(rest)/65536), 242); - value /= 1024; + // Since the AVR has no dedicated floating-point hardware, we need + // 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) value += pulse_count*3600;