I am now several days into trying to figure out how to split a working template class and related template functions out of a working .ino file and into a .cpp and .h, keeping the main code in the .ino. Could anyone spare the time to advise me on how to split this out. I seem to mess up the references to either the variables or to the functions each time I try. I cen’t imagine I’m the first fellow to struggle through this. Many thanks.
Here is the working code in one .ino file.
float measuredAltVolts = 12.5;
int measuredAltAmps = -5;
#define screen2PixelsPerChar 7
#define screen2RowVolt 1
#define screen2RowAmp 2
#define screen2ColAlt 6*screen2PixelsPerChar
#define screen2ColBat 13*screen2PixelsPerChar
#define screen2VoltErase 6*screen2PixelsPerChar
#define screen2AmpErase 8*screen2PixelsPerChar
#define screen2VoltFormat "%5s %5s"
#define screen2AmpFormat "%+3i %+3i"
//helper function
char *float2string(float v, uint8_t decimals) {
const int OUTPUT_BUFS = 7; // maximum number of floats in a single sprintf
const int MAX_OUTPUT = 13; // largest possible output string
float absV;
static char outputBuffers[OUTPUT_BUFS][MAX_OUTPUT + 1];
static uint8_t callCount;
char formatter[] = "%d.%0_d";
char *pos = outputBuffers[++callCount % OUTPUT_BUFS]; // Select buffer to use this time (Round-robben)
//__ return (dtostrf(v,MAX_OUTPUT , decimals, pos)); //<<-- This works GREAT, but is about 1.2K in code size larger then what is here.
formatter[5] = decimals + '0'; // create the number for the # of decimal characters we ultimatly want.
unsigned int mult = 1; // Calc multplier for fractional portion of number
uint8_t multleft = decimals;
while (multleft--) {
mult *= 10;
}
absV = v;
if (absV < 0)
absV *= -1;
snprintf(pos, MAX_OUTPUT, formatter,
(int)v, // Whole number, with its sign
(unsigned int) ((absV * mult)) % mult); // Fraction, w/o a sign.
return pos;
}
//Template Class
template <class T>
class LCDfield {
private:
T currentValue;
T lastValue = 0;
int column;
int row;
int eraseWidth;
String formatString;
int f2sDigits; //number of decimal places
public:
LCDfield(T currentValue, int column, int row, int eraseWidth, String formatString, int f2sDigits)
{
this->currentValue = currentValue;
this->column = column;
this->row = row;
this->eraseWidth = eraseWidth;
this->formatString = formatString;
this->f2sDigits = f2sDigits;
}
void Update();
}; // don't forget the semicolon at the end of the class
//Template Function
template <class T>
void LCDfield<T>::Update() {
#define lcdBuffSize 14
char lcdBuff[lcdBuffSize]; //for snprintf
if (currentValue != lastValue) {
lastValue += currentValue;
if (f2sDigits >= 0) {
snprintf(lcdBuff, lcdBuffSize, formatString.c_str(), float2string(currentValue, f2sDigits), float2string(lastValue, f2sDigits));
Serial.print("with float2string ");
Serial.println(lcdBuff);
}
else {
snprintf(lcdBuff, lcdBuffSize, formatString.c_str(), currentValue, lastValue);
Serial.print("withOUT float2string ");
Serial.println(lcdBuff);
}
currentValue++;
}
}
// create instances
LCDfield <float> LCDaltVolts(measuredAltVolts, screen2ColAlt, screen2RowVolt, screen2VoltErase, screen2VoltFormat, 2);
LCDfield <int> LCDaltAmps(measuredAltAmps, screen2ColAlt - 1, screen2RowAmp, screen2AmpErase, screen2AmpFormat, -1);
void setup() {
Serial.begin(115200);
Serial.println("Serial Out Started");
}
void loop() {
LCDaltVolts.Update();
LCDaltAmps.Update();
Serial.println("");
delay(1000);
}