Arduino Asked by user1420303 on September 25, 2021
Problem: I need to send small integer numbers (single-digit numbers suffices) between two arduinos located approximately 50-60m away from each other.
The connection must be made through cables. I have read that the mentioned distance is too long for using serial communication. I do not care if the method is not fast, delays up to one or two seconds are ok for this. If it helps: the devices (Arduino UNO or similar) will run not yet written codes for a simple alarm system (with no cameras/images).
Question: What is a good way to this?
My efforts: I thought a couple of alternatives to solve this problem. Both involve the use of PWM signals sent from a device A to another B.
I’m a novice in this field so I do not known if there is something wrong with my approach. I would also appreciate if a better alternative is proposed.
Thanks in advance.
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:
Source:
https://www.tldp.org/HOWTO/Remote-Serial-Console-HOWTO/serial-distance.html
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 = 400
.
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:
Power them each separately with ungrounded power supplies.
Communicate via Serial.write()
and Serial.read()
(so long as Serial.available()
shows some data is available in the read buffer).
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.
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):
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.analogWrite()
(PWM); receive with analogRead()
.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
cutoff_freq/5 = 847Hz/5 = 169
or so) for digital signal sending through this filter.analogWrite()
:
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.
Correct answer by Gabriel Staples on September 25, 2021
It appears the easiest would be to use a simple CAN transceiver on each end, one set to transmit and the other to receive. You did not mention bidirectional communications although both Physical layers suggested below will support that quite easily. The electrical characteristics of the CAN bus cable restrict the cable length according to the selected bit rate. You can use cabling up to 250 meters with the baud rate of 250 kbit/s. The maximum bus length with a bit rate of 10 kbit/s is 1 km, and the shortest with 1 Mbit/s is 40 meters. Another approach would be to used RS485. RS485 is popular for inexpensive local networks, multidrop communication links and long haul data transfer over distances of up to 4,000 feet. The use of a balanced line means RS485 has excellent noise rejection and is ideal for industrial and commercial applications. Note these typically are driven with Async signals from a uart or similar device. Software serial would work great and leave the onboard serial port for debugging. the Async communications does the syncing automatically, nothing for you to do, just keep the baud rates the same.
Answered by Gil on September 25, 2021
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP