Serial data arriving emulation

My sketch needs to put some data into serial reception buffer to emulate the serial arrival of data to be processed by another session of own sketch. Any idea how to do this? Are the serial buffers accessible?

As your topic does not relate directly to the installation or operation of the IDE it has been moved to the Programming category of the forum

I don't know why you need that (can't you use just two Arduinos connected via serial?), btw maybe a loopback test is what you need?

what do you mean by "session"?

if you want to test the processing of a command interpreter, why not just send "canned" msgs? otherwise, why not enter test thru the serial monitor?

to @docdoc & gcjr: I built a CNC machine controlled by an ESP32 (Home · bdring/Grbl_Esp32 Wiki · GitHub). I added a TFT touchscreen display to the hardware that needs to send some commands to the GRBL processor session, as if they were received via serial.

still don't know what you mean by "session"

come on gcjr... program session is simply a specific part of the program

"session" would typically mean some other task that might be connected to some server, not simply a sub-funciton of a program. sorry to waste your time

I think he just misspelled the word "session", meaning "section" aka "another portion of code". At least, it's what I interpreted here.

You just need to create your own "buffer" (like a char/byte array global variable) and fill it as needed: your serial data processing function should just read from the "buffer" if it isn't empty and do what you need.
It's harder to describe than to do, so if you post here your code (at least the function where you process serial incoming data) we could give you more specific tips.

loopback => connect Tx to Rx and have your code send stuff out.

It will be there for you to read when you check.

just make sure you don't push too much data as the buffer is not super large.

alternatively, create a fake Serial port class (a subclass of HardwareSerial) that just reads stuff from a file or hardcoded in flash when asked and use a #define at the start of your code to point to an instance of that fake UART instead of Serial

Yes. I would call that approach high rent.

As a hacker, I'd be more likely to succeed by finding that session in the code where reception occurred, and jumping in front of that to force feed some canned responses.

If the code isn't too badly organized and the serial input is not strewn about without care, there should only be one or a very few places where you would have to play that trick.

Post the sketch you are working with and let us see.

@J-M-L's idea makes it easy, I tell myself it would pay off handsomely if I just took some time and learned how to…

You could use a terminal emulator to make the inout you don't have. I think both PuTTY and CoolTerm allow for creating strings of characters that can be sent on command.

a7

on second thoughts you could just subclass Stream and the code is pretty short, here is an example for you to test

the idea is that instead of using directly Serial in your code, you use another name, like uart.

At the start of the code you decide if you want to fake the Serial input or not

#ifdef USING_FAKE_UART
FakeSerial uart;
#else
#define uart Serial
#endif

and thus depending on this line being commented out or not

#define USING_FAKE_UART // comment this out to use the real Serial UART

your uart variable then will either be the real Serial or an instance of my class FakeSerial

This class basically does what Serial would do when it comes to writing something out but if you ask to read from it, then you'll get the bytes that are stored in the buffer variable instead of going reading the real Serial line.

Test this out, start with the commented out #define, you'll see that whatever you type in the Serial monitor will get printed back at you (echo) - that's what the loop does. Then uncomment the #define and you'll see that the content of the buffer will get printed out without you having to touch anything.

class FakeSerial : public Stream {
  private:
    static constexpr const char buffer[] = "Hello, world!";
    size_t index;
    static constexpr size_t length = sizeof(buffer) - 1;

  public:
    FakeSerial() : index(0) {}
    void begin(unsigned long baud = 115200) {Serial.begin(baud);}
    int available() override                {return length - index;}
    int read() override                     {return (index < length) ? buffer[index++] : -1;}
    int peek() override                     {return (index < length) ? buffer[index] : -1;}
    void flush() override                   {Serial.flush();}
    size_t write(uint8_t c) override        {return Serial.write(c);}
    using Stream::write;
};

constexpr const char FakeSerial::buffer[];

// #define USING_FAKE_UART // comment this out to use the real Serial UART

#ifdef USING_FAKE_UART
FakeSerial uart;
#else
#define uart Serial
#endif

void setup() {
  uart.begin(115200);
}

void loop() {
  if (uart.available()) uart.write(uart.read()); // simple echo / loopback
}

of course it would not be super difficult to read from a file instead of reading from the buffer array.

1 Like

Bingo !!! Thank you J-M-L. It seams to be a good solution. I will try. Thanks again

Tested. It works as you suggested J-M-L but in my case would be much better if I can use both simultaneously, i.e, send data to FakeSerial and receive data from true Serial from one or other... Do you think is it possible ?

It’s possible but I wonder what’s the use case?

What would happen to the data sent to fakeSerial ?
If you don’t want it to go anywhere just don’t plug the Tx pin to anything

As shown in the figure below, the idea is to use the GRBL software (Home · bdring/Grbl_Esp32 Wiki · GitHub) installed on the ESP32 controller, without any changes and to have the possibility of sending commands from TFT display to the GRBL software transparently, as if they were arriving via serial. It would be very convenient to be able to interfere with the CNC in real time by changing parameters such as travel speed, cutter rotation, etc.

What you want to do is have two speakers on one serial port. Usually UART are one to one.
If you have two speakers then (even if you protect the lines) you’ll be in trouble if both speak at the same time

What you need to do is integrate the communication on the PC side before the data comes into the ESP32 - some sort of serial multiplexer.

There's no such thing as "simultaneously" in Arduino. You either put something (e.g. bytes or chars or string) on the "fake" serial or receive something from the "real" serial. You can't and shouldn't "mix" those things together.

But I still wonder why you can't do that in a simplest way. The first is using Serial loopback (see post #3), the next could be using a terminal emulator sending back to the sender everything receives from serial (the solution from @alto777 see last section of post #11). Hacking the "Serial" is a very interesting idea, technically intriguing, but it seems to me that it's an overly complex solution for this requirement, as if to hang a picture you wanna drill a hole in the wall and put in a bracket, instead of simply using a nail and a hammer.

To make my idea clear, let's assume you have this code where you need to receive a LF-terminated string (knowing nothing about your code as you haven't shown us, I use adapted portions of a similar solution I implemented in the past, so this code hasn't been tested, and shown just as an example):

...
// Serial buffer
#define MAXBUF 80
char serBuf[MAXBUF];
byte pBuf = 0;
// Line/command buffer (string)
char cmd[MAXBUF];
bool cmdReceived = false;
...
void loop() {
  // Serial input check
  if ( Serial.available() && ! cmdReceived) {
    char c = Serial.read();
    if ( c == '\n' || pBuf == MAXBUF) {
      strcpy(cmd, serBuf);
      pBuf = 0;
      cmdReceived = true;
    }
    else if (c != '\r') {
      inputBuf[pBuf++] = c;
      inputBuf[pBuf] = 0;
    }
  }
  // Was the command received (from either the Serial or the code)?
  if (cmdReceived) {
    // Clear the flag to let the program be ready for the next one
    cmdReceived = false;
    // Process data
... process here cmd[] string contents...
  }
...
  // Here we have some code that simulates receiving a command from 
  // the serial port
  strcpy(cmd, "COMMAND");
  cmdReceived = true;
...
}
...

By "simultaneous" I meant "interleaved"... But ok. I already have everything I need. Thank you very much !!!

I would take a man-in-the-middle (MiM) approach.

PC → MiM → ESP32

The PC sends data to the MiM, which relays it to the ESP32. If GRBL uses flow control (such as RTS/CTS or XON/XOFF), the MiM must handle it properly, passing it back to the PC for pausing and resuming transmission as needed to prevent data loss or buffer overflows.

The MiM would also manage the screen and user interface for additional commands, injecting them into the communication stream while still respecting GRBL’s flow control mechanisms.

This setup allows you to modify behavior without changing the software on either the PC or the ESP32. The MiM acts as an intermediary.