Serial protocol - transmitting while receiving or vice versa

Hi forum.
I need some explanation about the serial protocol implemented into the Arduino board, I thing not fully understand.
First of all my request:
I need to test a simple external hardware circuit I have built (RS232 to RS485 <---LONG CABLE---> RS485 to RS232 transponder).
This circuit simply extends the 2lines RS232 link between two devices in a noisy environment.
For the test of the device I was thinking using the builtin serial interface in the Arduino UNO PIN 0 and PIN1 in a sort-of-loopback way.
I explain: instead of simply shorting the TX and RX of the UNO with a jumper cable, and sending chars from the serial terminal window and reading the response below I wanted to connect in between the external circuit.
And this way it works.
Now I wanted to implement it in a sketch that continuously sends and receives char and here I am stuck.
How can I send a command like Serial.println ("Hello") and simultaneously read the response inside the terminal windows- I should see two "Hello" - the One I have sent and the other I have received from the RX line?
I know maybe it's more easier than I think but... this overcomes my poor knowledge of the Arduino IDE.
Any help is appreciated.
Kind regards

Please take into account, that an UNO has only one serial line ( pin0/1 ) and this serial line is used for the connection to the serial Monitor in the IDE. You don't have an additional serial interface for a second device.
You must use SoftwareSerial for this purpose, ore use another Arduino board with a free serial line ( e.g. Leonardo or Mega ).

Thank You. Yes I have also tried it with serial software but how to code the fact that while one is transmitting the other port is simultaneous receiving??
Regards

There is an example for SoftwareSerial which shows transmitting from serial Monitor to SoftwareSerial line and vice versa ( in parallel ).

Thank You. will have a look right now

Received characters go into a buffer. This way you can do other things while receiving characters. Check with Serial.available() when characters are available and process them before the buffer overflows.

Sending characters also works with a buffer that contains all characters to be sent. If that buffer is full then further output is blocked until all characters are placed into the buffer.

All you have to do is checking for input before characters are lost. And do not try to block the controller by sending too many characters at once.

You will need to be careful with software serial, the standard softwareserial library is not capable of reliably sending and receiving simultaneously, so a loopback test will not work. I'm not sure if there are alternative libraries that will work. You could try sending on a software serial port while receiving on the hardware serial port.

The programs sends everything in BufferToSend and expects to receive it exactly the same.
The switch in the simulator is used to test error in receiving.

Make sure that nothing is connected to D0 (RX) & D1 (TX) when uploading the sketch to a physical Arduino.

You can try test the program

Here's the code:

const int bufferLength = 1200;
const unsigned long recvTimeOut = 1000;  // 1 sec
const unsigned long restartTimer = 10000;  // 10 sec

byte BufferToSend[bufferLength];
int sendIndex;
int receiveIndex;
enum progState {INITIALIZING, TXRX, TXCOMPLETE, REPORTING, FINISHED};
enum completeStatus {PERFECT, RECVMISMATCH, RECVTIMEOUT};
enum recvStatus {NOPROBLEM, FAIL, RECVCOMPLETE};
enum sendStatus {SENDCOMPLETE, SENDNOTFINISHED};
int progState = INITIALIZING;
int completeStatus;
unsigned long txComplateStart;
unsigned long completeStartTime;
int restartTimerDisplayed;

void setup() {
  Serial.begin(74880);
  for (int i = 0; i < bufferLength; i++) {
    BufferToSend[i] = i % 256;
  }
}

void loop() {
  switch (progState) {
    case INITIALIZING:
      chkReceive();
      chkReceive();
      sendIndex = 0;
      receiveIndex = 0;
      Serial.println(F("Please wait..."));
      Serial.flush();
      while (Serial.available() > 0) { //empty receive buffer
        Serial.read();
      }
      progState = TXRX;
      break;
    case TXRX:
      if (chkSend() == SENDCOMPLETE) {
        txComplateStart = millis();
        progState = TXCOMPLETE;
      } else if (chkReceive() == FAIL) {
        completeStatus = RECVMISMATCH;
        progState = REPORTING;
      }
      break;
    case TXCOMPLETE:
      if (millis() - txComplateStart > recvTimeOut) {
        completeStatus = RECVTIMEOUT;
        progState = REPORTING;
      }
      if (chkReceive() == RECVCOMPLETE) {
        completeStatus = PERFECT;
        progState = REPORTING;
      }
      break;
    case REPORTING:
      reporting();
      progState = FINISHED;
      completeStartTime = millis();
      restartTimerDisplayed = 0;
      break;
    case FINISHED:
      int restartIn = (restartTimer - millis() + completeStartTime) / 1000 + 1;
      if (restartIn < 0) {
        progState = INITIALIZING;
      } else if (restartIn != restartTimerDisplayed) {
        Serial.print(F("Restart in "));
        Serial.print(restartIn);
        if (restartIn > 1) {
          Serial.println(F(" secs."));
        } else {
          Serial.println(F(" sec."));
        }
        restartTimerDisplayed = restartIn;
      }
      break;
  } // end switch (progState) {
}

void reporting() {
  Serial.flush();
  Serial.println(F(""));
  Serial.println(F(""));
  Serial.print(F("Transmitted "));
  Serial.print(sendIndex);
  Serial.println(F(" byte(s)."));
  switch (completeStatus) {
    case PERFECT:
      Serial.println(F("Perfect! No Errors."));
      break;
    case RECVMISMATCH:
      Serial.print(F("Error in receiving in byte number "));
      Serial.println(receiveIndex);
      break;
    case RECVTIMEOUT:
      Serial.print(F("Incomplete data received. Only received "));
      Serial.print(receiveIndex);
      Serial.print(F(" bytes. Expected "));
      Serial.print(bufferLength);
      Serial.println(F(" bytes."));
      break;
  }
  Serial.println(F(""));
}


int chkReceive() {
  if (receiveIndex == bufferLength)
    return RECVCOMPLETE;
  if (Serial.available() > 0) {
    byte incomingByte = Serial.read();
    if (incomingByte != BufferToSend[receiveIndex]) {
      Serial.print(F("Error byte received 0x"));
      Serial.println(incomingByte, HEX);
      Serial.print(F("Expected byte 0x"));
      Serial.println(BufferToSend[receiveIndex], HEX);
      return FAIL;
    } else {
      receiveIndex++;
      return NOPROBLEM;
    }
  }
  return NOPROBLEM;
}

bool chkSend() {
  if (sendIndex < bufferLength) {
    if (Serial.availableForWrite() > 0) {
      Serial.write(BufferToSend[sendIndex]);
      sendIndex++;
    }
    return SENDNOTFINISHED;
  } else {
    return SENDCOMPLETE;
  }
}
1 Like

The sending and receiving happen in hardware. You don't have to do anything special to receive characters at the same time you are sending characters.

You might want to have a look at the AltSoftSerial library from PJRC which claims to be able to transmit and receive at the same time.

Really thank You all for the great help and support obtained.