Hey @StefanL38, I took some time to read up on SafeString
and it does not appear to solve my problem. It seems to help with string manipulation, which I do not have trouble with. It also does not appear to support the IPAddress data type, nor a string in PROGMEM.
To be clear, I print a variety of character types to an LCD using the LiquidCrystal_I2C
library. Sometimes, it is a string in PROGMEM, sometimes it is a char array in memory, sometimes it is an IPAddress. The LiquidCrystal_I2C::print()
function can handle all these data types with no issue.
The problem arises when I try to define a function that will abstract away the verbosity of the LiquidCrystal_I2C function calls. I am looking for an Interface for this function signature that will allow me to accept all the different data types without duplicating the function code.
This is an example of what the original code looks like:
#include <LiquidCrystal_I2C.h>
#include <IPAddress.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);
void setup() {
lcd.init();
lcd.backlight();
lcd.clear();
char line1[21] = "Line One";
IPAddress ip(192, 168, 1, 1);
lcd.setCursor(0, 0);
lcd.print(F("Line Zero"));
lcd.setCursor(0, 1);
lcd.print(line1);
lcd.setCursor(0, 2);
lcd.print("Line Two");
lcd.setCursor(0, 3);
lcd.print(ip);
}
void loop() {
}
This a working example of how it looks with an overloaded display()
function. While this may appear lengthier, it makes the code both more concise and readable each time I have to print to the LCD. Note how each of the display()
functions hold identical code, varying only in the function signature.
#include <LiquidCrystal_I2C.h>
#include <IPAddress.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);
void display(const byte row, const char* line) {
lcd.setCursor(0, row);
lcd.print(line);
}
void display(const byte row, const __FlashStringHelper *line) {
lcd.setCursor(0, row);
lcd.print(line);
}
void display(const byte row, const IPAddress line) {
lcd.setCursor(0, row);
lcd.print(line);
}
void setup() {
lcd.init();
lcd.backlight();
lcd.clear();
char line1[21] = "Line One";
IPAddress ip(192, 168, 1, 1);
display(0, F("Line Zero"));
display(1, line1);
display(2, "Line Two");
display(3, ip);
}
void loop() {
}
The solution I am looking for, if it exists, is a way to use the Printable
, or some similar interface to get this code below to work:
#include <LiquidCrystal_I2C.h>
#include <IPAddress.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);
void display(const byte row, <**WHAT CAN I USE HERE?**> line) {
lcd.setCursor(0, row);
lcd.print(line);
}
void setup() {
lcd.init();
lcd.backlight();
lcd.clear();
char line1[21] = "Line One";
IPAddress ip(192, 168, 1, 1);
display(0, F("Line Zero"));
display(1, line1);
display(2, "Line Two");
display(3, ip);
}
void loop() {
}
If that were possible, I would then be able to refine the function further to make each instance of displaying something to the LCD even more concise, like so:
#include <LiquidCrystal_I2C.h>
#include <IPAddress.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);
void display(
<**WHAT CAN I USE HERE?**> line0 = "",
<**WHAT CAN I USE HERE?**> line1 = "",
<**WHAT CAN I USE HERE?**> line2 = "",
<**WHAT CAN I USE HERE?**> line3 = "") {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(line0);
lcd.setCursor(0, 1);
lcd.print(line1);
lcd.setCursor(0, 2);
lcd.print(line2);
lcd.setCursor(0, 3);
lcd.print(line3);
}
void setup() {
lcd.init();
lcd.backlight();
char line1[21] = "Line One";
IPAddress ip(192, 168, 1, 1);
display(F("Line Zero"), line1, "Line Two", ip);
}
void loop() {
}
Sorry for the wall of text, but I hope there is now no ambiguity as to what I am trying to achieve. If you still believe this can be done with SafeString or some interface, I'd really appreciate a code example to demonstrate this. Thank you!