2-wire comms acting very strange

Hey Everyone,
I'm new to Arduinos but old to code. To start myself off, I thought it would be interesting to get two Arduino (MEGA 2560 R3) boards talking.

In an effort to start simple, I thought I'd just see if each one could read a 'high' line from the other.

On one Arduino, I have used pins 14 and 21, and I have those connected to pin 21 and 14 on the other.

Here's a sorry attempt at ascii art, trying to show that the cables "cross"

14 14
X
21 21

The idea is, pin 14 goes HIGH, a digitalRead takes place on 21 (which should be HIGH)
if the HIGH is detected, turn on a status light, and unset some values so if the cables are unplugged, the light goes off. Should be very simple.

The problem is I'm seeing all kinds of erratic behavior. I have 3 Arduinos here, all of them react to the code below differently. One of them just shows the "Link Light" as on, always, unless I ground pin21. Another two will somehow pass the link-light back and forth, so if one has it shown, the one it's connected to will power up, and then the light turns off on the first one and turns on on the second one.

The underpinning assumption of this code is that these states are persistent unless manually changed - but that doesn't seem to be the case?

void setup() {
  pinMode(14, OUTPUT); //Rx
  pinMode(21, INPUT);    //Tx
  pinMode(11, OUTPUT); //Link Light
}

void loop() {
int Link = 0;

    digitalWrite(14, HIGH);  //send ON
    Link = digitalRead(21);  //pin21 is connected to pin14 on the other arduino

    if(Link == HIGH){         //if pin21 was read as HIGH, link is good
    Link = 0;                    //unset Handshake variable
    digitalWrite(11, HIGH);  //set handshake light
    }
}

I've found in some cases simply picking up an Arduino and rotating it to certain positions will cause the link-light to go on or off. The natural assumption is "bad solder job on the led" or "loose cables". Neither are the case - the connections are firm and the led board is very thoroughly tested - I don't know what more could be done there.

Is there some incredibly obvious sin of Arduino programming I've committed?

I don't see where you are turning off pin 14, so the LED will always be on.
Also, if the cable is unplugged, the input is indeterminate. Sometimes high sometimes low. Put a 10K pulldown resistor on the input.

This code is like...Version 8621, I can see in a previous "sketch" of this, I had a line in my if statement to set pin 14 low - but good catch, I'll add that back in.

As for the 10K input resistor...that's interesting. Why does that help?

volumetricsteve:
This code is like...Version 8621, I can see in a previous "sketch" of this, I had a line in my if statement to set pin 14 low - but good catch, I'll add that back in.

As for the 10K input resistor...that's interesting. Why does that help?

it is not meant as input-resistor as IO-input-pin-------10k-resistor-----other-IO-pin
it is meant as IO-input-pin----X---10k-resistor----GND

The other Arduino will be connected at the "X".

The input-resistoance of an IO-pin with pinMode "INPUT" is so high that even a two inch long wire is enough to catch up electromagnetic noise to make the input switch randomly between HIGH and LOW.

A 10 kohm-resistor connected to ground like shown above "pulls-down the IO-pin to LOW. That's why it is called pulldown-resistor. If the connected IO-pin of the second Arduino goes high a current of 5V / 10.000 Ohm = 0,5 mA
is flowing from the OUTPUT-O-pin towards ground. 0,5 mA is pretty tiny and does not overload the OUTPUT-pin.
All the voltage is dropping across the pulldown-resistor which means the INPUT-pin will detect a HIGH.

If you want to tinker with any kind of microcoontroller and add hardware it will be very good to have a basic knowledge about electronics. In the micro-controller-world things are NOT super-standardised as with USB-devices.
Some addtional parts work on 3,3V and would be damaged if you give them a HIGH-signal on 5V.
With buses like SPI who work on high frequencies 1-4 MHz, your wiring becomes relevant to good or bad function.

You can ask for help here on any aspect. You should have a digital multimeter as a minimum measurement-equipment.
If an error is caused by hardware (bad soldering, wire-brake) you should be able to check this with the digital multimeter.
I don't know if this DMM is available in your conutry.

beyond the standard things voltage, current, resistance it offers diode-testing, frequency, PWM-duty-cycle, capacitor
Very good compromise between price and versatility.
If you want to go with the most cheapest maybe as a second for voltage measuring
https://www.banggood.com/search/digital-multimeter.html?from=nav&pfrom=1&pto=10
best regards Stefan

(deleted)

Why not use the in-bulit I2C and the Wire library. Have a look at this I2C Tutorial

On a Mega I2C uses pins 20 sda and 21 scl and you do NOT cross the connections.

...R

By enabling the internal pull-up resistor you can eliminate the need for an external resistor. The pull-up will keep the input HIGH if not connected so the sender must pull the input LOW to signal a connection.

const byte RX_DIPin = 21;
const byte TX_DOPin = 14;
const byte LinkLight_DOPin = 11;


void setup()
{
  digitalWrite(TX_DOPin, LOW);
  pinMode(TX_DOPin, OUTPUT); // TX (LOW to signal connection)


  pinMode(RX_DIPin, INPUT_PULLUP);    // RX (HIGH if not connected)


  pinMode(LinkLight_DOPin, OUTPUT);  //Link Light
}


void loop()
{
  digitalWrite(LinkLight_DOPin, !digitalRead(RX_DIPin));  //set handshake light
}

Be sure to connect the Ground pins between the two Arduinos.

Wow, a lot to reply to! Thanks everyone.

@StefanL38
Thank you for all the information.
You said:

The input-resistoance of an IO-pin with pinMode "INPUT" is so high that even a two inch long wire is enough to catch up electromagnetic noise to make the input switch randomly between HIGH and LOW.

This explains the other-worldly poltergeist type behavior I was seeing, but did you mean resistance or resonance? I assume resistance.

I have a Fluke 87V Multimeter so I think I'm good there unless there are other things that would be specifically good or somehow better for Arduino work.

@spycatcher2k
You said:

Do you have the grounds connecter between the Arduinos?

I don't know what you mean. If I ground my data lines, they'll just....ground, right?

@Robin2
You asked why I'm not using I2C and, not be dismissive, that's just not what I'm doing. I may do I2C things in the future, but not at the moment.

@johnwasser
This is excellent. Using an internal resistor would save me a round of part purchasing too...and help keep things manageable.

I'm unsure of what code here specifically invokes use of this internal ground pin. Is the magic in simply setting the pinMode on TX_DOPin, etc? or the const byte part?

I see you also mentioned:

Be sure to connect the Ground pins between the two Arduinos.

I'm not sure what this means. To literally connect ground pins between both Arduinos implies there's some 3rd in-between place to ground them. I assume you're not being literal but then I'm not sure what lines you're grounding and/or where you're grounding them.

Thanks again

Spycatcher means as well as the two data pins you have a common ground pin between each device:
14 14 GND
X |
21 21 GND

If not then the 0v at either end could be at different potentials relative to each other.

Edit: Just link a third wire between the provided 0v/GND pins on both boards. There is no need to user a 3rd data pin. That would probably work if they were both outputs and both LOW, but it would be a highly unusual way of providing a signal ground. I wouldn’t recommend it.

That makes sense, Thank you!