Syncronizing multiple arduinos modules using IO pins

Hey everyone,

I'm trying to find the most efficient way to sync multiple arduinos to prevent them from performing a specific task at the same time (I don't need to completely guarantee that this does not happen, but want to reduce the probability as much as possible). Each arduino (Atmega 328 8Mhz) is in a module with other electronics and has two connectors to connect to the previous and next modules. So they are connected in a chain, and can be up to 15-20 modules (they are close together though, 10-15cm cables between each).

The base idea was that they all have the same pin connected together, set to INPUT by default, with a pulldown on one end of the chain. When one of them wants to do the task, changes to OUTPUT and sets the value to HIGH, so the others know they have to wait. I use port manipulation instead of the digitalRead and digitalWrite functions so this is done eficientlly. Still, it's possible that two modules read the pin at the same time, are are both set as outputs together.

So I considered putting 100Ohm resistors between the pins to avoid shorting them (to keep the current below 50mA on a 3.3V atmega) . But since I have many modules connected together I'm afraid this can make the signal noisy. Should I use a lower resistor, or not use one at all, since even if multiple pins are set as as outputs, they will all be HIGH and never change?

Apart from the multiple outputs problem, I'm not sure if a single pin will have the power to send a proper signal to all the others without any interferences.

Any thoughts on this? Or am I over complicating and maybe there's a simpler way?

Thank you in advance for any comments on this.

Hi, Welcome to the forum.

Please read the first post in any forum entitled how to use this forum. http://forum.arduino.cc/index.php/topic,148850.0.html .

You can look at it from the other end. You have one UNO as master and it controls when each other UNO does the task.

What is the application, and why so many UNO so close together, can't one UNO do all the tasks?

Thanks.. Tom... :)

Interesting question.

A single Arduino board or one Master, as TomGeorge wrote, solves all problems. If you tell about your project, maybe some of use have a few good ideas.

For example with a serial bus and each Arduino board gets a number. Then the Master can send out the numbers.

How often is a Arduino board active and for how long ?

The common way for a signal used by multiple Arduino boards, is to use a pullup resistor and every Arduino board can pull it down.

Your pulldown resistor determines the impedance of the signal. How low it should be depends on how many inductive loads or motors or mains wires or welding devices are nearby. The rule of thumb is 10k for a signal that is on the same pcb board, 4k7 for something that is attached to the Arduino board, and down to 1k for long shielded Cat5 wires. So if you choose 470 Ω, then it should work in a normal situation.

Keep the maximum I/O pin current for the ATmega328P below 20 mA. Don't go near the maximum shortcut current of 40 mA. Therefor 100 Ω is too low.

Why do you think that there will be a shortcut ? Suppose you use a pullup resistor for the signal, then you can change a pin between "input" and "output low", and there will never be a shortcut. When a pin is still INPUT, it can be preset as LOW. That will disable the internal pullup resistor. After that the pin is set as OUTPUT and there is no shortcut.

I see a lot of problems: When one board claims the signal, then the others might be waiting for the signal. As soon as the signal is released then all the others jump in and claim the signal ?

Proper synchronization is not easy, requires retries in case of collissions. All that should be handled in hardware on an I2C bus, and certainly if a master queries the other I2C slaves every now and then.

Years ago industry created a "token ring" network to solve your problem. You can do something similar.

Paul

tarquinio: The base idea was that they all have the same pin connected together, set to INPUT by default, with a pulldown on one end of the chain.

More common is a pull-up. Also avoids problems with slight differences in the 3.3V levels of the boards; unless all powered from the same power source; grounds are normally shared so the same for all boards. No need for extra resistors between the boards in that case, just make sure you never set them to OUTPUT, HIGH.

There may be a simpler way, but need to know more about your project for that.

tarquinio: When one of them wants to do the task, changes to OUTPUT and sets the value to HIGH, so the others know they have to wait.

Suppose the master pulls the line HIGH and then LOW again after a short interval (maybe 1 millisec) and each of the slaves starts a timer as soon as it detects the transition to HIGH. Each slave on the chain has a slightly longer time period before it tries to transmit so no two of them will try at the same time. If it wants to transmit it pulls the line HIGH and sends its message (presumably on a different line). If the other slaves detect a second HIGH before its own interval expires they turn their timers off and wait for the next HIGH from the master.

...R

Hi,

Sorry if I was a bit vague in the description of the project. I wasn't trying to be lazy or secretive. I made the questions in a more generic way because I have interest in knowing the feasibility and problems of this particular solution (using a shared single pin to sync multiple arduinos) for other future projects. The current project I'm working on is already functional. This idea was just an optimization, and a way for me learn some new stuff.

Here is a more complete description os this particular project:

I'm helping a friend build a modular music sequencer. There are different modules with buttons, knobs, leds, etc... There is a server module that processes everything, all the other modules are connected in a chain. The communication is being done using serial. The modules have different ID's. When the server sends a message, all modules listen. When one of the inputs on any of the modules changes, it sends a message to the server. As we can't have all the TX connected together, each module has a 2 channel mux. When not transmitting, each module sends to the server what is coming from the next module. When a module wants to transmit, it toggles the mux while transmitting so it sends to the server it's own data. The only problem here is when two modules transmit at the same time, only the one closer to the server would get through. I know the typical ways to deal with this using software, like time division multiplexing, or the server pooling the different modules one by one. Since in these modules, the most usual situation would be only one of them transmiting at a single time, I didn't like these solutions. I opted for each module just sending the message asap, reducing the lag, then resend the message if an ACK is not received from the server within a timeout period, standard stuff. This way most messages arrive fast, and only a few collide but are also re-sent eventually.

Tbh the system probablly works well enough as it is now. As I mentioned, the next idea is an optimization but most important for me is a way to explore some things I'm less confident about (I'm a programmer and used to some low-level programming, but less confident about electronic stuff like impedances, electric noise, dimensioning the components, if we should use a pull-up or pull-down, that sort of stuff). Some of the answers posted here already gave me some good tips about some of these things.

So my idea was to have a "BUSY" pin so that all the modules would know if the transmission line was busy or not. While there is still the possibility of a colision, the chances are much lower like this. They would have to try and transmit within a couple clock cycles of each other right? When they want to transmit but see the line is busy, they don't hang and just wait for the line to be free, they will do other stuff and come back to check the line later. Since they are doing these verifications out of sync, I think the probability of a collision will be really low.

So from the answers you guys provided: - I should use a pull-up and not a pull-down. - It's OK to have multiple pins as outputs connected together as long as they are all set as low before changing from input to output. (when I mentioned I was afraid of a possible short was because I wasn't sure doing this was safe). - In this case I don't need resistors between every pin in the chain.

I just have a question now about the pull-up resistor.

Koepel: Your pulldown resistor determines the impedance of the signal. How low it should be depends on how many inductive loads or motors or mains wires or welding devices are nearby. The rule of thumb is 10k for a signal that is on the same pcb board, 4k7 for something that is attached to the Arduino board, and down to 1k for long shielded Cat5 wires. So if you choose 470 Ω, then it should work in a normal situation.

So in the first like you're saying that the value should be lower the more interference is around, if I understood correctly. You confused me with the values though, since you mentioned "down to 1k" for long wires but then you suggest a value even lower. Is this because I don't have shielded cables? Or because I will have multiple small cables between boards instead of a big one?

Thank you for all the tips and suggestions so far. :)

There is another protocol you have missed, based on a open-collector bus with a pull-up.

Using an asynchronous serial system, a slave sends firstly its own address. As it does so, it monitors the line during HIGH bits and if it sees the line pulled LOW, it immediately quits. This means that one gets priority without a fatal collision, so not wasting time.

(I forget which protocol this actually is!)

tarquinio: You confused me with the values though, since you mentioned "down to 1k" for long wires but then you suggest a value even lower.

Sometimes a certain "bus" is used, or the signal has to meet certain specifications. The ATmega328P can push/pull 20mA and this is your own signal, so why not 470 Ω ? Something between 250 Ω and 10k is 470 ;)

Koepel: The ATmega328P can push/pull 20mA and this is your own signal, so why not 470 Ω ? Something between 250 Ω and 10k is 470 ;)

Ok so if go this right, if i'm making my own protocol and want to get the best signal possible, i should have the resistor value as low as possible. And that value is one that makes the current be close the the max current the pin can source/sink. And this is the same if I have 1 or 20 slaves on the line. Is this correct?

Correct.

Just remember: one resistor total, not one per slave.

Great! I think I know all I need now. Thanks everyone for your help and comments. :slight_smile:

Bus systems are either tri-state with a slave sending only when enabled, or "open collector" where each node can pull a line low, but not high - high is implemented by a common pullup resistor at either end of the line. Neither system is supported by an Arduino, all digital pins are either inputs or outputs, never tri-state nor open collector. With the only exception of the I2C pins, which are open collector on demand. But with some bitfiddling one can switch a pin to either input (tri state or open) or low output (active low with pullup).

In addition to star networks, with all nodes sharing the same lines, there exist daisy chain networks as rings (SPI) or linear with nearest node having highest precedence. Provided that the amount of data can ever be transported throug a network of any topology, it's sufficient in a linear network that each node buffers input from lower precedence nodes, for later transmission towards the root node (master). In the opposite direction everything sent by the root node is echoed to the next lower priority node.

Kind of a star network can be implemented by RS-485 transmitters, if only one node is allowed to send at any time. Here the transceivers implement tri-state lines. This IMO is the only way to use Serial (UART) for communication with more than one partner, else I2C is the better solution (short range).