void calculate_power(volatile struct state_struct *pstate) { int32_t rest, power = 0; uint8_t pulse_count; cli(); rest = pstate->nano_end - pstate->nano_start; pulse_count = pstate->pulse_count_final; sei(); // 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 // power[watt] = 3.6/10^6 * rest[nWh/s] // power[watt] = 3.6/10^6 * 65536 * (rest[nWh/s] / 65536) // power[watt] = 3.6/10^6 * 65536 * 262144 / 262144 * (rest[nWh/s] / 65536) // power[watt] = 61847.53 / 262144 * (rest[nWh/s] / 65536) // We have to correct for only using 666 samples iso 2000/3, so: // power[watt] = 61847.53 * 1/666 * 2000/3 / 262144 * (rest[nWh/s] / 65536) // power[watt] = 61909.44 / 262144 * (rest[nWh/s] / 65536) // We round the constant down to 61909 to prevent 'underflow' in the // consecutive else statement. // The error introduced in the fixed-point rounding equals 7.1*10^-6. MacU16X16to32(power, (uint16_t)(labs(rest)/65536), 61909); power /= 262144; if (rest >= 0) { power += pulse_count*3600; } else { power = pulse_count*3600 - power; } pstate->power = power; }
void send(uint8_t msg_type, const struct sensor *measurement, const struct state *aux) { uint8_t i; uint32_t value = 0; uint32_t ms = 0; int32_t rest; uint8_t pulse_count; char message[60]; switch (msg_type) { case PULSE: // blink the green LED PORTB |= (1<<PB7);//DONE _delay_ms(20); PORTB &= ~(1<<PB7);//DONE cli(); value = measurement->value; ms = aux->time; sei(); strcpy(message, "pls "); break; case POWER: cli(); rest = aux->nano_end - aux->nano_start; pulse_count = aux->pulse_count_final; sei(); // 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; else value = pulse_count*3600 - value; strcpy(message, "pwr "); break; } strcpy(&message[4], measurement->id); strcpy(&message[36], ":0000000000\n"); i = 46; do { // generate digits in reverse order message[i--] = '0' + value % 10; // get next digit } while ((value /= 10) > 0); // delete it if ((msg_type == PULSE) && ms) { strcpy(&message[47], ":0000000000\n"); i = 57; do { // generate digits in reverse order message[i--] = '0' + ms % 10; // get next digit } while ((ms /= 10) > 0); // delete it } printString(message); // printString("\r"); }