Code:
static const int BUFFER_SIZE = 40;
static const unsigned MAX_COUNTER = 100;
static unsigned int display_counter = MAX_COUNTER;
// prevent compiler from optimizing sprintf test
volatile float ten = 10.0f;
// Convert a floating point number to a string with a %<m>.<n>f format. Not all
// versions of sprintf support floating point, so on the first call test to see
// if it works, and if we don't get the expected result, do the conversion in
// an alternate fashion. This function is optimized for the range of values we
// expect to see with the power meter.
//
// On the Teensy, if you optimize for space, a smaller library is used that
// does not do have %f, %g, etc. formats.
char *
float_to_string (float number, char *buffer, int fract)
{
static bool first_time = true;
static bool sprintf_works;
if (first_time) {
first_time = false;
strcpy (buffer, "no results");
sprintf (buffer, "%6.3f", ten);
sprintf_works = (strcmp (buffer, "10.000") == 0);
if (!sprintf_works)
Serial.printf ("sprintf does not work for floating point, '%s'\n", buffer);
}
if (sprintf_works)
sprintf (buffer, "%*.*f", fract + 3, fract, number);
else {
bool negative = (number < 0.0f);
float number2 = fabs (number);
if (fract == 0) {
number2 += 0.5f;
sprintf (buffer, "%2d.", (int) (negative ? -number2 : number2));
} else if (fract == 1) {
int number_x10 = (int) ((number2 * 10.0f) + 0.5f);
int number_main = number_x10 / 10;
int number_fract = number_x10 % 10;
sprintf (buffer,
"%2d.%c",
negative ? -number_main : number_main,
number_fract + '0');
} else if (fract == 2) {
int number_x100 = (int) ((fabsf (number) * 100.0f) + 0.5f);
int number_main = number_x100 / 100L;
int number_fract = number_x100 % 100L;
sprintf (buffer,
"%2d.%c%c",
negative ? -number_main : number_main,
((number_fract / 10) % 10) + '0',
((number_fract / 1) % 10) + '0');
} else {
int number_x1000 = (int) ((fabsf (number) * 1000.0f) + 0.5f);
int number_main = number_x1000 / 1000L;
int number_fract = number_x1000 % 1000L;
sprintf (buffer,
"%2d.%c%c%c",
negative ? -number_main : number_main,
((number_fract / 100) % 10) + '0',
((number_fract / 10) % 10) + '0',
((number_fract / 1) % 10) + '0');
}
}
return buffer;
}
// Get power values each time, but only update the display every so often
void
update_power_display (void)
{
// Read voltage and current from INA219.
float shuntvoltage = ina219.getShuntVoltage_mV () / 1000.0f;
float busvoltage = ina219.getBusVoltage_V ();
float amps = ina219.getCurrent_mA () / 1000.0f;
// Compute load voltage, power, and milliamp-hours.
float volts = busvoltage + shuntvoltage;
float watts = volts * amps;
max_volts = fmaxf (volts, max_volts);
max_amps = fmaxf (amps, max_amps);
max_watts = fmaxf (watts, max_watts);
// Only update the display every 1/2 second
if (++display_counter >= MAX_COUNTER) {
display_counter = 0;
char volts_output [BUFFER_SIZE];
char amps_output [BUFFER_SIZE];
char watts_output [BUFFER_SIZE];
char float_buffer1[BUFFER_SIZE];
char float_buffer2[BUFFER_SIZE];
sprintf (volts_output,
"V: %s max: %s",
float_to_string (volts, float_buffer1, 3),
float_to_string (max_volts, float_buffer2, 3));
sprintf (amps_output,
"A: %s max: %s",
float_to_string (amps, float_buffer1, 3),
float_to_string (max_amps, float_buffer2, 3));
sprintf (watts_output,
"W: %s max: %s",
float_to_string (watts, float_buffer1, 3),
float_to_string (max_watts, float_buffer2, 3));
Serial.printf ("%s, %s, %s\n",
volts_output,
amps_output,
watts_output);
display.clearDisplay ();
display.setCursor (0, 0);
display.println (volts_output);
display.println (amps_output);
display.print (watts_output);
display.display ();
}
}