Basic Serial and SoftwareSerial Questions

Thanks in advance to anyone who has the patience to read all of this and help me learn. I’ve highlighted specific questions and pleas for help in red :slight_smile:

I’m attempting to learn about serial communications, particularly how to use SoftwareSerial on a Sparkfun Redboard (Arduino Uno). However I’m having some trouble understanding the basics, even after going through some of the easy examples I found online.

I’ve seen a couple examples very similar to the one below (originally seen in this discussion, https://forum.arduino.cc/index.php?topic=161151.0), but I can’t get it to work. From my understanding, I should be able to connect by USB to the Arduino, load this sketch, and then whatever I type in the Arduino IDE serial monitor should get echoed back to me. (Additionally, if I had a device hooked up that was sending responses, this sketch would display the responses to the serial monitor, but I’m not doing that yet.)

I attempted to comment on the sketch below to illustrate how I understand the statements, but please correct my comments if I’ve misunderstood a concept.

#include<SoftwareSerial.h> //Include the SoftwareSerial library

//Setup the mySerial object. We will transmit to the object using Pin 3 and receive
//from the object using Pin 2
SoftwareSerial mySerial(2,3);

void setup()
{
mySerial.begin(9600); //Open the mySerial port for communication
Serial.begin(9600); //Open the serial port for communication
}

void loop()
{
if (mySerial.available()) //Has the mySerial object received something? (i.e. have we
//typed something into the serial monitor and transmitted
//it to the object using Pin 3?)
Serial.write(mySerial.read()); //If yes, read the data going to the object and
//display it to the serial monitor. Basically we are
//echoing what we sent.
if (Serial.available()) //Is there data waiting in the receive buffer of the serial port?
//(i.e. has the object transmitted something that was received
//on Pin 2 which is now waiting in the serial port receive
//buffer?)
mySerial.write(Serial.read()); //If yes, read what is in the serial buffer, and
//transmit it back to the object. I have particular
//trouble understanding this line. If mySerial sent me
//something and it’s sitting in the serial receive
//buffer, why wouldn’t we display it to the serial
//monitor? Instead it looks like we’re sending it right
//back to the mySerial object.
}

Thanks!
Travis

tex792: From my understanding, I should be able to connect by USB to the Arduino, load this sketch, and then whatever I type in the Arduino IDE serial monitor should get echoed back to me.

If you want to be able to see what SoftwareSerial write()s then you need something connecting pins 2 and 3 to another USB port on your PC - for example a USB-TTL cable. And you also need another terminal program running on your PC to see what comes in on the second USB cable.

When you communicate with the Arduino using the regular USB connection the serial data uses Pins 0 and 1.

The purpose of SoftwareSerial is to create a second completely separate serial port using another pair of pins - for example to communicate with a GPS module or a Bluetooth module while still being able to communicate with the PC over the regular USB cable.

...R

If you want to be able to see what SoftwareSerial write()s then you need something connecting pins 2 and 3 to another USB port on your PC - for example a USB-TTL cable.

I saw another example here which uses similar code, https://www.arduino.cc/en/Tutorial/SoftwareSerialExample, and it says:

“There is no circuit for this example. Make sure that your Arduino or Genuino board is attached to your computer via USB to enable serial communication through the serial monitor window of the Arduino Software (IDE).”

That makes it sounds like I don’t need anything connected on the other end. The code from that example is copied below:

#include <SoftwareSerial.h>

SoftwareSerial mySerial(10, 11); // RX, TX

void setup() {
// Open serial communications and wait for port to open:
Serial.begin(57600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}

Serial.println(“Goodnight moon!”);

// set the data rate for the SoftwareSerial port
mySerial.begin(4800);
mySerial.println(“Hello, world?”);
}

void loop() { // run over and over
if (mySerial.available()) {
Serial.write(mySerial.read());
}
if (Serial.available()) {
mySerial.write(Serial.read());
}
}

These are the critical lines from your link

In the example below, digital pins 10 and 11 on your Arduino or Genuino boards are used as virtual RX and TX serial lines. The virtual RX pin is set up to listen for anything coming in on via the main serial line, and to then echo that data out the virtual TX line. Conversely, anything received on the virtual RX is sent out over the hardware TX.

I agree that it could be stated more clearly - but it is intended to convey the idea that pins 10 and 11 connect to some other device thereby enabling you to use the Serial Monitor to send data to that other device and to display data coming from that device.

For the future please post your code between [code] [/code] tags so your code looks like thisand is easy to copy to a text editor. See How to use the Forum

...R

void loop() { if (mySerial.available()) //Has mySerial received something?

Serial.write(mySerial.read()); //If yes, send it to Serial, i.e. the serial monitor.

if (Serial.available()) //Has Serial received something?

mySerial.write(Serial.read()); //If yes, send it to mySerial.

Thanks R and Nick. I went back to an XBee tutorial that used similar code (see bottom of post). This seemed to help drive the point home for me.

One question I still have though for the bit of code in the loop. The way it is written, it looks like it would be a never ending loop. It seems if Serial receives something and sends to mySerial, then mySerial has received something and it would be sent to Serial…and so on and so on forever. What keeps this from happening? Again, I’m just trying to get an intuitive grasp of what’s happening here.

Sketch from XBee Shield Hookup Guide, https://learn.sparkfun.com/tutorials/xbee-shield-hookup-guide:

/*****************************************************************
XBee_Serial_Passthrough.ino

Set up a software serial port to pass data between an XBee Shield
and the serial monitor.

Hardware Hookup:
  The XBee Shield makes all of the connections you'll need
  between Arduino and XBee. If you have the shield make
  sure the SWITCH IS IN THE "DLINE" POSITION. That will connect
  the XBee's DOUT and DIN pins to Arduino pins 2 and 3.

*****************************************************************/
// We'll use SoftwareSerial to communicate with the XBee:
#include <SoftwareSerial.h>
// XBee's DOUT (TX) is connected to pin 2 (Arduino's Software RX)
// XBee's DIN (RX) is connected to pin 3 (Arduino's Software TX)
SoftwareSerial XBee(2, 3); // RX, TX

void setup()
{
  // Set up both ports at 9600 baud. This value is most important
  // for the XBee. Make sure the baud rate matches the config
  // setting of your XBee.
  XBee.begin(9600);
  Serial.begin(9600);
}

void loop()
{
  if (Serial.available())
  { // If data comes in from serial monitor, send it out to XBee
    XBee.write(Serial.read());
  }
  if (XBee.available())
  { // If data comes in from XBee, send it out to serial monitor
    Serial.write(XBee.read());
  }
}

It seems if Serial receives something and sends to mySerial, then mySerial has received something and it would be sent to Serial...and so on and so on forever.

Correct.

If that doesn't work properly, something is wrong with either the wiring, the baud rate, the devices or the power supplies.

tex792: and it would be sent to Serial...and so on and so on forever.

I'm not clear from your question if you are satisfied with that behaviour or if you are wondering how to make it work differently?

These examples are very basic. In many projects you will want the Arduino to do something based on the data it receives and not just act as a dumb intermediary. For that situation have a look at Serial Input Basics

...R

tex792: One question I still have though for the bit of code in the loop. The way it is written, it looks like it would be a never ending loop. It seems if Serial receives something and sends to mySerial, then mySerial has received something and it would be sent to Serial...and so on and so on forever. What keeps this from happening? Again, I'm just trying to get an intuitive grasp of what's happening here.

This program stands between two friends. Alice says "Hello" The program hears this and says "Hello" to Bob. Bob then says "Good morning Alice!" so the program says "Good morning Alice!" to Alice. There's no endless echo.

Robin2:
I’m not clear from your question if you are satisfied with that behaviour or if you are wondering how to make it work differently?

Robin, I’m satisfied with how the code operates (posted below again). And just to clarify my setup, I have one XBee connected by a shield to an Arduino which is connected to my computer by USB. I use the Arduino serial monitor to view that one. The other XBee is connected to an XBee Explorer which is connected by USB to the same computer and monitored through XCTU. When I type something in the serial monitor, it shows up in XCTU, and when I type something in XCTU, it shows up in the serial monitor, and in that regard, it seems to be working as expected. So yay! I drew it out on a whiteboard to help me understand how the “available, read, and write” statements make the system operate.

To follow this drawing, start at “Hello” on the serial monitor side and follow it to XCTU. Then go from “Bye” on the XCTU side and follow it back to the serial monitor.
(not sure if the image embedded correctly here, so I also uploaded it to this post as an attachment)

/*****************************************************************
XBee_Serial_Passthrough.ino

Set up a software serial port to pass data between an XBee Shield
and the serial monitor.

Hardware Hookup:
  The XBee Shield makes all of the connections you'll need
  between Arduino and XBee. If you have the shield make
  sure the SWITCH IS IN THE "DLINE" POSITION. That will connect
  the XBee's DOUT and DIN pins to Arduino pins 2 and 3.

*****************************************************************/
// We'll use SoftwareSerial to communicate with the XBee:
#include <SoftwareSerial.h>
// XBee's DOUT (TX) is connected to pin 2 (Arduino's Software RX)
// XBee's DIN (RX) is connected to pin 3 (Arduino's Software TX)
SoftwareSerial XBee(2, 3); // RX, TX

void setup()
{
  // Set up both ports at 9600 baud. This value is most important
  // for the XBee. Make sure the baud rate matches the config
  // setting of your XBee.
  XBee.begin(9600);
  Serial.begin(9600);
}

void loop()
{
  if (Serial.available())
  { // If data comes in from serial monitor, send it out to XBee
    XBee.write(Serial.read());
  }
  if (XBee.available())
  { // If data comes in from XBee, send it out to serial monitor
    Serial.write(XBee.read());
  }
}

Image from Reply #9 so we don’t have to download it. See this Image Guide

1375fb953c0692e8c86c62f5b4529917474d5815.jpg

…R

Robin2: Image from Reply #9 so we don't have to download it.

Thanks Robin, I updated my post so the picture shows up now.