print to TFT and Serial without duplicating code

from a Mega 2560
i want to be able to print to a tft screen also putting the same to serial at the moment i am doing

Serial.println(F("[?] Print this menu"));
tft.println(F("[?] Print this menu"));

just to print one line of information to the screens
is there a single line of code i could use to do the same job?

serial come out to terminal and transmitted on RF
and tft on a 2.2 inch screen

Create a function that uses those two commands... and then callit each time you need to print on both media.

i'm still new to all this sketch but how would that work with something like this

        Serial.print(F("ADC = ")); Serial.print(adc); Serial.println(F(" mV"));
        tft.print(F("ADC = ")); tft.print(adc); tft.println(F(" mV"));

how would the function look

void printAll (){

not sure how to start

}

Maybe something like this? :-

void printAll(int adc)
{
  const char adcstring1[] PROGMEM = "ADC = ";
  const char adcstring2[] PROGMEM = " mV";
  Serial.print(adcstring1); Serial.print(adc); Serial.println(adcstring2);
  tft.print(adcstring1); tft.print(adc); tft.println(adcstring2);
}

Or even this? :-

void printAll(int adc)
{
  const char adcstring1[] PROGMEM = "ADC = ";
  const char adcstring2[] PROGMEM = " mV";
  char numbuf[6]; // upto 99999 mv
  itoa(adc, numbuf, 10);
  char line[15];
  strcpy(line, adcstring1);
  strcat(line, numbuf);
  strcat(line, adcstring2);
  Serial.println(line);
  tft.println(line);
}

Don't know if that's the kind of thing you were looking for.

Regards,

Graham

ghlawrence2000:
Maybe something like this? :-

void printAll(int adc)

{
  const char adcstring1[] PROGMEM = "ADC = ";
  const char adcstring2[] PROGMEM = " mV";
  Serial.print(adcstring1); Serial.print(adc); Serial.println(adcstring2);
  tft.print(adcstring1); tft.print(adc); tft.println(adcstring2);
}




Or even this? :-



void printAll(int adc)
{
  const char adcstring1[] PROGMEM = "ADC = ";
  const char adcstring2[] PROGMEM = " mV";
  char numbuf[6]; // upto 99999 mv
  itoa(adc, numbuf, 10);
  char line[15];
  strcpy(line, adcstring1);
  strcat(line, numbuf);
  strcat(line, adcstring2);
  Serial.println(line);
  tft.println(line);
}




Don't know if that's the kind of thing you were looking for.

Regards,

Graham

yes i can understand how that would work on that situation but its not really a solve all thing. i sorta understand how functions work and i just need one that will take for example the GSM FONA board there are plenty of menu items and each return different values

so for example and this is just a few lines i would want each print to serial to also print to tft

    case 'b': {
        // read the battery voltage and percentage
        uint16_t vbat;
        if (! fona.getBattVoltage(&vbat)) {
          Serial.println(F("Failed to read Batt"));
        } else {
          Serial.print(F("VBat = ")); Serial.print(vbat); Serial.println(F(" mV"));
        }
 

        if (! fona.getBattPercent(&vbat)) {
          Serial.println(F("Failed to read Batt"));
        } else {
          Serial.print(F("VPct = ")); Serial.print(vbat); Serial.println(F("%"));
        }
 
        break;
    }


    case 'C': {
        // read the CCID
        fona.getSIMCCID(replybuffer);  // make sure replybuffer is at least 21 bytes!
        Serial.print(F("SIM CCID = ")); Serial.println(replybuffer);
        break;
    }

    case 'i': {
        // read the RSSI
        uint8_t n = fona.getRSSI();
        int8_t r;
        
        Serial.print(F("RSSI = ")); Serial.print(n); Serial.print(": ");
        if (n == 0) r = -115;
        if (n == 1) r = -111;
        if (n == 31) r = -52;
        if ((n >= 2) && (n <= 30)) {
          r = map(n, 2, 30, -110, -54);
        }
        Serial.print(r); Serial.println(F(" dBm"));
       
        break;
    }

at the moment i am doing this

case 'i': {
        // read the RSSI
        uint8_t n = fona.getRSSI();
        int8_t r;
        
        Serial.print(F("RSSI = ")); Serial.print(n); Serial.print(": ");
        tft.print(F("RSSI = ")); tft.print(n); tft.print(": ");
        if (n == 0) r = -115;
        if (n == 1) r = -111;
        if (n == 31) r = -52;
        if ((n >= 2) && (n <= 30)) {
          r = map(n, 2, 30, -110, -54);
        }
        Serial.print(r); Serial.println(F(" dBm"));
        tft.print(r); tft.println(F(" dBm"));
       
        break;
    }

and so on etc now at the moment i have over 2000 lines of code and it is building up at first i was happy with just a serial print but then decided to go with a tft screen half way through the job.
so thats where i am at the moment just every time i see a serial.print line i copy it paste it underneath and replace serial with tft

hence looking for an easy way out .

Ah, I understand now and yes I see why my solution was no help.

Maybe this is better? :-

void both(char *s, ...)
{
  char buf[30];
  va_list arglist;
  va_start( arglist, s );
  vsprintf(buf, s, arglist);
  va_end( arglist );
  Serial.print(buf);
  tft.println(buf);
}

void setup() {
  Serial.begin(115200);
  int adc = 9989;
  int r = -111;
  int n = 1;
  both("Adc = %4d mV\n", adc);
  both("RSSI = %d : ", n);
  both("%4d dBm\n", r);
  both("RSSI = %d : %4d dBm\n", n, r);
}

Regards,

Graham

spot on i will try it out thanks

mikewitney:
is there a single line of code i could use to do the same job?

Yes providing you don't mind making a change to the TFT library... add the line:

Serial.print((char) c);

At the start of the write() function in the TFT library.

Then any call to TFT.print(...) or TFT.println(...) for example:

tft.println(F("[?] Print this menu"));

will also send the output to the screen and the serial port.

Of course this might not be convenient in your application for various reasons but it would result in compact and fast code.