When I send data to an Arduino Uno via the serial monitor, the serial data goes down the same USB cable used to program the Arduino. So there must be a device on the Arduino board like a FTDI or USB-capable AVR that drives the RXD
pin of the Arduino. So my question is: When I want two Arduino boards to communicate with each other over serial, many tutorials say just connect RX and TX on one Arduino to TX to RX on the other. So how come the device on the board that normally drives the RXD
pin doesn't "fight" the other Arduino that is also now driving the RXD
line?
3 Answers
The Atmega16U2 that does the USB communications is connected to Rx and Tx via 1k resistors, so when communicating with another Arduino it "overpowers" the USB interface. See image:
By the way, note that the Tx and Rx LEDs are connected to the Atmega16U2, not the Atmega328P, so they do not light when doing Arduino-to-Arduino communications.
Measuring with an empty sketch on my Uno, the current between Tx and Gnd was 0.14 mA, not 5 mA. So that suggests that the Atmega16U2 sets the pins to high-impedance when not actually receiving data from the USB interface.
It's logical it would do that, because the 5 mA you mention (in a comment) could be a nuisance if you wanted to use that pin for something else.
-
Awesome, thanks! You were both very quick. So does this mean that it is safe to power the Arduinos via the USB even when they are wired for serial communications with another Arduino? And that the ATmega16U2 and the other Arduino will fight, but only with ~5mA? Sep 24 at 4:10
-
1Yes, I think that's done all the time. However, and this is important, because the Arduino-to-Arduino connection will overpower the USB interface, you will have trouble programming it (the one you are trying to program) while they are connected.– Nick Gammon ♦Sep 24 at 4:30
-
1It's also possible, although I'm not certain, that the USB chip would set the pins to high-impedance when not actually in use. In fact, I just measured on my Uno, the current between Tx and Gnd was 0.14 mA, not 5 mA. It's logical it would do that, because the 5 mA you mention could be a nuisance if you wanted to use that pin for something else.– Nick Gammon ♦Sep 24 at 4:41
-
@NeilStockbridge So those 1k resistors are probably there as a precaution against you trying to reprogram the chip while it is connected to something else.– Nick Gammon ♦Sep 24 at 4:43
If we take a look at this portion of the Arduino Uno schematic (whole schematic is located here):
... we see there are two 1K Ohm (1,000 Ohms) resistors (labeled RN4A and RN4B) between the USB to serial conversion chip on the left to the Atmel processor at center right. These allow the Rx (Receive) and Tx (Transmit) pins to be back driven by an externally connected device.
-
-
-
That must be an old schematic, as the Uno now has a Atmega328P not an Atmega8. However the principle is the same.– Nick Gammon ♦Sep 24 at 3:51
-
Hmmm, it came right off of arduino.cc's web site. Oooh, that's what they meant by "Reference Design".– st2000Sep 24 at 3:53
-
1Mine has "Rev 3" on it, so you must have found an earlier revision. It's still a reference design though.– Nick Gammon ♦Sep 24 at 3:55
Another way to do serial communication between Arduinos is to use the SoftwareSerial library using (digital) pins of your choosing for serial communication between the Arduinos. Incidentally, it avoids interference from your computer under simple serial communication,
The SoftwareSerial library allows serial communication on other digital pins of an Arduino board, using software to replicate the functionality (hence the name "SoftwareSerial"). It is possible to have multiple software serial ports with speeds up to 115200 bps. A parameter enables inverted signaling for devices which require that protocol.
https://docs.arduino.cc/learn/built-in-libraries/software-serial
It takes just a little preparation and understanding, but not much.
#include <SoftwareSerial.h>
#define rxPin 10
#define txPin 11
// Set up a new SoftwareSerial object
SoftwareSerial mySerial = SoftwareSerial(rxPin, txPin);
void setup() {
// Define pin modes for TX and RX
pinMode(rxPin, INPUT);
pinMode(txPin, OUTPUT);
// Set the baud rate for the SoftwareSerial object
mySerial.begin(9600);
}
void loop() {
if (mySerial.available() > 0) {
mySerial.read();
}
}
In this example (copied from the above/linked article), you would use the mySerial
variable to do your Arduino to Arduino communication in the same way as you use the standard serial connection. You would also need to wire the RX
and TX
pins of one Arduino to the TX
and RX
pin of the other Arduino, respectively.
One of the benefits of learning how to use the SoftwareSerial library is that there are many communication devices that use serial connection, such as Bluetooth modules (HC-05, HC-06, and HM-10 for example), that you can now use with ease. In this case, you can replace the wires I had you add with a Bluetooth module and communication between the 2 Arduinos wirelessly. Or you can instead communicate with a mobile device with the Bluetooth module.
https://www.instructables.com/Tutorial-Using-HC06-Bluetooth-to-Serial-Wireless-U-1/
Or you could access the internet with a WiFi module over SoftwareSerial.
https://www.taintedbits.com/2017/07/21/arduino-uno-esp8266-software-serial/
-
the question doesn't ask how to avoid interference. it asks why there isn't one.– Juraj ♦Sep 26 at 4:47