Write to both Serial and File at the same time

Hi! Is there a class with which you can write to both serial and file at the same time?

Serial_mod.println(...) --> Serial.println() + file.println()

Or is it possible to forward the serial data stream to a file at the same time?

Thanks!

Just put one after the other.

If you have a LOT of spare time you could write an object class derived from Print that would act similar to the Serial and File objects but write to both.

If you have a LOT of spare time you could write an object class derived from Print that would act similar to the Serial and File objects but write to both.

Or you could just write a 2 line function to do it

class DualSerial: public Print
{
private:
    File myFile;
public:
    DualSerial();

    virtual size_t write(uint8_t c) 
    {
      if (use_Serial) Serial.write(c);
      if (use_SD) myFile.print(c); 
      return 1;
    }

    bool use_Serial;
    bool use_SD;

    using Print::write;
};

Hello, I found this solution. Unfortunately, I don't know whether the overwriting is OK or whether something is still missing. I am C novice. Letters and numbers come out correctly with the serial, but in the SD file there are not the letters but the ordinal numbers of the letters (e.g. 8054737163 ...). You can cast the uint8_t on char but then the digits are not correct. Does anyone know which virtuals I have to overwrite and how?

It works for me after adding the required constructor. Could you show the problem you are having in an actual sketch?

#include <SD.h>


class DualSerial: public Print
{
  private:
    File myFile;
  public:
    DualSerial();


    virtual size_t write(uint8_t c)
    {
      if (use_Serial) Serial.write(c);
      if (use_SD) myFile.print(c);
      return 1;
    }


    bool use_Serial;
    bool use_SD;


    using Print::write;
};


DualSerial::DualSerial()
{
  use_Serial = false;
  use_SD = false;
}


DualSerial myDS;


const char *abc = "ABC";


void setup()
{
  Serial.begin(115200);
  myDS.use_Serial = true;


  myDS.print("This is a test of .print()");
  myDS.println("This is a test of .println()");
  myDS.print('A');
  myDS.print('B');
  myDS.println('C');
  myDS.print(1);
  myDS.print(2);
  myDS.println(3);
  myDS.println(8675309l);
  myDS.println(8675309l, HEX);
  myDS.println(65000);
  myDS.println(56000, HEX);
}


void loop() {}

rsardu:

class DualSerial: public Print

{
private:
   File myFile;
public:
   DualSerial();

virtual size_t write(uint8_t c)
   {
     if (use_Serial) Serial.write(c);
     if (use_SD) myFile.print(c); <<<<<<<<<<<<< use write, not print.
     return 1;
   }

bool use_Serial;
   bool use_SD;

using Print::write;
};




Hello, I found this solution. Unfortunately, I don't know whether the overwriting is OK or whether something is still missing. I am C novice. Letters and numbers come out correctly with the serial, but in the SD file there are not the letters but the ordinal numbers of the letters (e.g. 8054737163 ...). You can cast the uint8_t on char but then the digits are not correct. Does anyone know which virtuals I have to overwrite and how?
#include <SD.h>
#define PIN_SPI_CS   10  //CS=SS

class DualSerial: public Print
{
  private:
  public:
    File myFile;
  public:
    DualSerial();
    virtual size_t write(uint8_t c)
    {
      if (use_Serial) Serial.write(c);
      if (use_SD) myFile.write(c);
      return 1;
    }
    bool use_Serial;
    bool use_SD;
    using Print::write;
};

DualSerial::DualSerial()
{
  use_Serial = false;
  use_SD = false;

  if (!SD.begin(PIN_SPI_CS))  {
    Serial.println(F("Card failed, or not present"));
    //return 
  }

  SD.remove("gps.txt");

  myFile = SD.open(F("gps.txt"), FILE_WRITE);
  if (!myFile)  {
    Serial.println(F("Error opening SD file"));
  }
  
}

void DumpFile()
{
  File dataFile = SD.open("gps.txt");
  if (dataFile) {
    while (dataFile.available()) {
      Serial.write(dataFile.read());
    }
    dataFile.close();
  }
  else {
    Serial.println("error opening");
  }
}

DualSerial myDS;

const char *abc = "ABC";

void setup()
{
  Serial.begin(9600);
  
  myDS.use_Serial = true;
  myDS.use_SD = true;

  Serial.println("---Prints to Serial and SD---");
  
  myDS.print("This is a test of .print()");
  myDS.println("This is a test of .println()");
  myDS.print('A');
  myDS.print('B');
  myDS.println('C');
  myDS.print(1);
  myDS.print(2);
  myDS.println(3);
  myDS.println(8675309l);
  myDS.println(8675309l, HEX);
  myDS.println(65000);
  myDS.println(56000, HEX);

  myDS.myFile.close();  

  Serial.println("---Dump SD file---");
  DumpFile();
}
16:44:18.326 -> This is a test of .print()This is a test of .println()
16:44:18.394 -> ABC
16:44:18.394 -> 123
16:44:18.394 -> 8675309
16:44:18.427 -> 845FED
16:44:18.427 -> 65000
16:44:18.427 -> DAC0
16:44:18.427 -> ---Dump SD file---
16:44:18.461 -> This is a test of .print()This is a test of .println()
16:44:18.529 -> ABC
16:44:18.529 -> 123
16:44:18.529 -> 8675309
16:44:18.529 -> 845FED
16:44:18.529 -> 65000
16:44:18.529 -> DAC0

Thanks to all! “Write” does the trick!

And you understand the difference between write and print now?
The print class drives calls to write() with raw characters which are then passed down
to the stream implementation, so you just redirect the write calls in a "tee" with this class.

MarkT:
And you understand the difference between write and print now?
The print class drives calls to write() with raw characters which are then passed down
to the stream implementation, so you just redirect the write calls in a "tee" with this class.

Yep. Thanks!