RS-485 is best (you can buy some modules for this from Adafruit, Amazon, eBay, etc), but you can use the built-in hardware RS-232 serial UARTs from each on pins 0 and 1 so long as the baud rate is really really low. The lower the baud rate, the longer the range can be because lower baud rates reject noise better (and the longer the cable, the worse the noise, since the longer the cable the more it acts like an antenna and an inductor and a capacitor). Here are some rough estimates of how far you can transfer regular-logic-level unbalanced RS-232 signals:
If this trend continues, you should be able to get like 120m at 1200 bps (baud), 240m at 600 bps, 480m at 300 bps, etc. maybe even up to > 1000m at 50 bps. I don't think the trend will continue like that, and we are using 5V TTL logic (signal voltage) levels here instead of RS-232's +/- 12V or so, so our logic levels are much worse and will have less range, so just use
50 baud and give it a shot:
// do on each Arduino
Serial.begin(50); // 50 baud = 10 bytes/sec throughput rate; see below
Note that for 8-N-1 serial communication baud rate, which is the default on Arduino, there are 10 bits per byte sent over the wire. This is because there is "one start bit, the eight data bits, and the one stop bit" for every 8-bit byte sent. That's an effective throughput data rate of 80%. This means a baud rate of 50 bps (bits per second) only can transmit 50/10 = 5 bytes per second. That's it! That's suuuuuper slow, but if it's fast enough for your application, it's fast enough!
I hypothesize 5V TTL twisted quad RS-232 communication between two Arduinos would have a maximum range at
50 baud of about 1000m/(24V span for regular RS-232 / 5V span for 5V TTL logic RS-232) = 208m. Just a crude guestimate. Please report back any findings you get from your experiments. I'd like to hear about it.
Assuming that this all does work, it would also be useful to start increasing the baud rate on each device until the data starts getting corrupted. Back off on the baud rate a little, and that's your maximum baud rate. Take that maximum baud rate and divide by 2 or 3, and that's your maximum "safe" baud rate perhaps. If you need throughput that is as high as possible, then that's what I'd do. Ex: maybe in your case
50 baud works just fine, so you increase it. At
1000 baud you start seeing corrupted data, so you back off to
800. At that point you no longer see corrupted data. So, divide that by 2 or 3 and you get a maximum "safe" baud for your setup of perhaps 800/3 =
267 to 800/2 =
Try using a twisted quad cable (wires are twisted together in groups of 4) to reduce noise and increase range, and set the baud rates on each Arduino to like
50. You will need 3 wires connected between the Arduinos:
- GND to GND
- Tx to Rx
- Rx to Tx
Power them each separately with ungrounded power supplies.
Serial.read() (so long as
Serial.available() shows some data is available in the read buffer).
More on balanced vs unbalanced lines, and why I recommend "twisted quad" wire:
Normally, RS-232 is considered to be an unbalanced line transimission system. This means the impedance in the transmission wire is not equal to the impedance in the return wire, which would be a common ground between the sender and receiver, in conjunction with (in parallel with) an Earth ground through the building wiring and/or actually through the Earth...literally, the dirt you walk on. By powering each Arduino with an ungrounded power supply, such as a 2-prong power supply, however, which is common, there is no Earth ground connected to the Arduino. Furthermore, by only having a single transmission line active at any moment between two Arduinos, you have just balanced the transmission between them. Now, the out path is a single Tx signal from one Arduino to the other, and the return path has matching impedance, as it is your single, common GND wire between the two Arduinos. You now have balanced line RS-232 TTL logic level transmission between the two Arduinos. Balanced line transmission can have improved noise rejection and range by using a twisted pair between the two lines. In this case, however, there are 3 lines: Tx --> Rx, Rx --> Tx, and Gnd --> Gnd. So, you should use twisted quad wire, which means 4 wires at once are twisted together. Connect all 3 lines to the same twisted quad bundle. Again, remember, this assumes only one Arduino is transmitting at a time on one single wire in one single direction at a time (so as to not negate your return current through the GND line when transmitting on two lines, one in each direction, or double your return current through the GND line when transmitting on two lines each in the same direction [assuming you had multiple UARTS on each device]), thereby this usage creates a balanced line system since they also aren't truly grounded through a 3-prong grounded power supply. If these 2 requirements are met (1 Arduino transmits at a time, and at least one of them is not grounded to the building wiring), use twisted quad wire, as the system is balanced line communication. If it is not the case, because you are transmitting from each Arduino to the other at exactly the same time, or because both (not one) Arduinos are grounded to the building, thereby offering an alternative return path through the building ground wiring, then twisted quad cable will not benefit you, and you should use regular untwisted wiring.
Having said all that, experimentation is the real boss here. Try it out. if I didn't have twisted quad wire I'd try twisted pair, and if I didn't have twisted pair, I'd try untwisted wire.
Regarding your approach about using PWM to produce an analog output to be read by the receiving end:
Using PWM to produce an analog voltage to be read by the receiving end is an interesting approach. Without filtering, I think what you'd be doing is producing tremendous noise, however, literally producing electromagnetic radiation (think like low frequency radio or TV waves or something), where this huge 60m wire is your broadcasting antenna. If you put a 20k~50k resistor right at the sending end, however, and a 1uF capacitor right at the receiving end, however, to filter this PWM into an analog output immediately at the sending end, I think it would then eliminate your antenna effect where you are broadcasting something, and work much better, but still be highly susceptible to external noise influencing it. Give it a shot, but I suspect a simple set of digital pins to set HIGH or LOW on different pins to match different states would be much much much better than any analog signal at those lengths, with a 50 baud serial signal being the next best for signal-to-noise thereafter.
So, in order of best to worst signal-to-noise ratio (SNR):
- differential pair (referenced to each other) digital HIGH/LOW values to represent states, which you update very slowly
- RS-485 differential pair serial transmission
- Note: for all of the following really low-speed digital signal sending scenarios, you might try it with the low-pass filter shown in the schematic below too, as it may help reject noise.
- single-ended (referenced to GND) digital HIGH/LOW values to represent states, which you update very slowly
- super low-speed SPI (including bit-banging it); ie: declare any digital pin a
CLOCK_PIN, and any other digital pin a
DATA_PIN. Set a clock pin LOW, set a data pin HIGH, set the clock pin HIGH. The clock transition tells the receiver (you have to code this up) to read the data pin, so you just read a
1 bit. Set the data pin LOW, set the clock pin LOW. The clock transition tells the receiver to read the data pin, so you just read a
0 bit. Leave the data pin low, set the clock pin HIGH again. You just sent another
0 bit, etc etc. Send data like this really slowly. It will work at great lengths--even better than asynchronous serial since it's synchronous.
- asynchronous serial (+/- 12V true RS-232) at 100 baud
- asynchronous serial (+/- 12V true RS-232) at 50 baud
- asynchronous serial (5V TTL RS-232) at 50 baud
- asynchronous serial (3V TTL RS-232) at 50 baud
- analog value filtered with resistor and capacitor low-pass RC filter; update: I'd try this filtering layout for sending analog values via PWM (see schematic below, but use the higher resistor value I describe in my bullets underneath the schematic, rather than the lower value I show in the schematic); the filter may also be beneficial to help filter noise when doing low-speed digital communication too, so give it a shot in your 50-baud rate serial setup above too:
- Send with
analogWrite() (PWM); receive with
- Report back on this too please. I'm very curious if it would work.
- unfiltered PWM---square wave antenna broadcasting who knows what--could result in an interesting broadcasting system for you. Add a transistor and you could really amp up the power and broadcast some interesting signals out! Get some good high power going here (1W~10W+) and maybe even get the government to find out who's jamming GPS and cellular? I don't know: could be interesting!
Schematic of low-pass RC filter to reduce noise between the two Arduinos when sending really low-speed digital signals (better), or slowly-changing analog signals (worse) between the two sides:
simulate this circuit – Schematic created using CircuitLab
- For filtering the digital signals (ex: 5V TTL pseudo-RS232 serial at 50 to 100 baud):
- Use 470 Ohms for each resistor, as shown above.
- This results in a cutoff freq of 847 Hz, so stay below ~169 baud (
cutoff_freq/5 = 847Hz/5 = 169 or so) for digital signal sending through this filter.
- For filtering analog signals sent via
- Since most Arduino pins have a PWM Frequency of 490 Hz, we need a cutoff frequency of ~490Hz/10 = 49Hz or lower to cleanly filter out the PWM frequency and result in a true analog output.
- Using the calculator linked-to below, that means you should use R values of at least 10k each, which results in a cutoff freq. of 40 Hz. You can use 20k resistors each too, for a cutoff freq. of about 20 Hz.
- To increase cutoff frequency to allow higher baud rates, decrease either R or C or both.
- For a cutoff frequency calculator, see: https://electronicbase.net/low-pass-filter-calculator/#rc-low-pass-calculator --> "RC Low Pass Filter Calculator" --> enter, for example, 940 Ohms (470 x 2) as the resistor value and 0.2uF (0.1uF x 2) as the capacitor value to see that the resulting cutoff frequency for this low-pass filter is 846.57 Hz.
I'm no filter expert, but this is what I'd try. If someone sees some glaring errors in this filter or ways to improve it, please comment below the answer.
Here's the Bode plot for the above series filter I show except with a 1k resistor and 0.1uF (100nF) capacitor followed by the same thing again. The purple line is the voltage we care about. Source: godfreyl, here.
The cutoff frequency here is 398Hz, which is where the -3db drop occurs, which corresponds to the half power and 70.7% voltage attenuation point. (
sqrt(0.50) = 0.707, so
0.707^2 = 0.5)). You can read more about cutoff frequency here.
- Google search for "is rs232 balanced?"