2

I plan on creating a system with multiple microcontrollers which need to communicate with one another.

All the microcontrollers will be placed inside a single enclosure, so no need for long distance solutions.

What I am looking for is full-duplex communication between a master device and multiple slaves. I call the communication full-duplex because I want the slaves to be able to send data to the master without a request from the master (the slaves should send data independently).

The number of microcontrollers I wish to connect is one master device and at least 16 slaves.

Ideally, I would like a robust solution which utilizes some kind of bus to connect to all the microcontrollers.

Among the potential solutions I found, the most applicable was the ICSC protocol along with an RS-485 bus, but I did not find any useful documentation on RS-485 with full duplex.

Do you have any recommendations? Is ISCS with RS-485 a good approach or should I resort to another solution?

EDIT

Further details to my question:

The slaves will be microcontrollers handling a subsystem. The subsystem is basically a physical input device with a feedback display which provides the user with the current state of the input.

Slaves send asynchronously data to the master whenever the user operates the input device. Slaves rarely send data at the same time.

The master can send data to the slaves at any time, changing a value in the subsystem controlled by the slave.

The functionalities to be implemented will be of the following type:

  • Master -> Slave void setValue(uint8_t value)
  • Slave -> Master uint8_t valueChanged() (returns new value)

All I need is a simple way, with as few wires as possible (and as few pins as possible on the master), which allows me to implement the functionalities above as efficiently as possible (with no unnecessary messages and requests on the communication lines).

Nicu Baciu
  • 57
  • 5
  • 1
    If you want any slave to be able to transmit at any given time regardless of other slaves being idle or transmitting, then to be able to receive simultaneously from 16 slaves then you need 16 receivers and have 16 point-to-point connections, so not a bus. If you want full-duplex RS-485, it usually means master can talk to all slaves simultaneously, but one slave at a time can send to master. And master can transmit and receive simultaneously. – Justme Sep 19 '22 at 13:30
  • 3
    The best solution would be simply an ethernet network. CAN can arrange similar functionality as a bus. – TQQQ Sep 19 '22 at 13:33
  • 2
    @TQQQ I'd suggest that for 17+ devices in a single enclosure, ethernet isn't a simple solution. – jonathanjo Sep 19 '22 at 13:48
  • 3
    Why exactly doesn't SPI with a master cyclically polling each slave work? It's the easiest and cheapest solution hardware-wise. Note that you can't have full duplex with 16 slaves using UART, unless the master tells each node when it is allowed to send - essentially the same thing as my SPI example, just with all the drawbacks of UART. – Lundin Sep 19 '22 at 13:48
  • 7
    Unless you have high bandwidth, I2C would be the way to go. CAN and RS-485 are overkill - they are meant for surviving out-of-the-box environments. I2C would require just two wires for the whole bus. – Smith Sep 19 '22 at 14:04
  • 1
    @Lundin Sometimes you want to create a "push" architecture vs a "polled" architecture. There are pros and cons to each, it's application/designer specific. – Aaron Sep 19 '22 at 14:27
  • @Smith You can use CAN as a protocol inside the box. You don't need to use CAN physical interface inside the box. Just like you can use UART without RS-485. – Justme Sep 19 '22 at 15:01
  • @jonathanjo you know, he needs a switch, but then it's a scalable solution. today it's 17, tomorrow 65. – TQQQ Sep 19 '22 at 15:22
  • @Smith true only if all devices are pretty close one to another within one board. If it's a 1 meter long application, even within one case, I2C is not his thing – TQQQ Sep 19 '22 at 15:23
  • Some kind of token ring system might be appropriate. – Ian Bland Sep 19 '22 at 15:24
  • Nicu, I did this over just a pair of shared wires. It's a 2 wire serial bus with negotiation. I connected up 16 devices. No problems. Similar idea to what's used with the Intel APIC bus used on motherboards supporting multiple cpus. I've written a white paper on the topic. Initiating communication is entirely asynchronous and handles collisions. – jonk Sep 19 '22 at 16:27
  • @jonk Could you please link the whitepaper you are referring to? – Nicu Baciu Sep 19 '22 at 17:35
  • 1
    @NicuBaciu It's a paper I wrote for a customer under contract. I'd need to re-write it here in my own words. There's quite a lot of detail (timing diagrams, calculations regarding uncertainties for collisions and what coding requirements exist to mitigate the problem, etc.) So whether I find time, or not, is another question. But if you study the Intel APIC bus details which arbitrates which of several CPUs gains access you will see much of what I'm talking about there. (Not the calculations or programming issues, though.) It was enjoyable to implement and see work! – jonk Sep 19 '22 at 17:45
  • @NicuBaciu Are you able to use (wire up directly together) just the I/O port structures of your MCUs with shared wires? Or is there some reason you need a specific physical layer? What I did was to just use the I/O port structure found on the PIC18F family. Also, how many bits are typically send/received and how often are these likely to be burst back and forth on the bus? (In the Intel APIC case, for example, only one of 4 CPUs are allowed to start up on a motherboard, giving time for software to start up the rest when ready. The 4 CPUs arbitrate to be the starting CPU.) – jonk Sep 20 '22 at 01:11
  • It's also worth mentioning that UART is dinosaur technology. Synching is awkward, error handling is poor, you need to manually implement CRC in software, and so on. It kind of went obsolete in the 1990s. – Lundin Sep 20 '22 at 06:34
  • I still don't see any reason why SPI wouldn't be suitable for this case, given the details in the question. Synchronous vs asynchronous is irrelevant and not a goal of its own, what matters is the real-time spec. How long should it take from an event to happen in a microcontroller until some actuator etc activates elsewhere? _That_ is all that matters. So write a proper specification then pick technology after that. Notably, pretty much _all_ mission-critical, real-time systems use cyclic intervals - just tweak the interval to suit your spec. You won't have longer latency than that. – Lundin Sep 20 '22 at 06:35

5 Answers5

6

Terminology: "Full duplex" really means "transmit in both directions simultaneously"; you mean something more like "masterless bus" or "unsolicited asynchronous transmissions".

RS-485 would work fine, but doesn't add very much as your system is physically small, and the 17 extra chips seems like a lot of overhead.

Idea 1: Open Collector Single Wire Asynchronous Serial

enter image description here

I'd suggest something like an open-collector single-wire bus, with a single-pull-up; each device can pull it down. You'll need some kind of contention handling, but what you do on top depends on what kind of messages need to be sent. (I might suggest you expand on this in your question.)

I've used this kind of thing for busses with low utilisation: Data-collecting slaves listen momentarily for a quiet line, and then just broadcast very short messages with checksums whenever they want to, single listener throws away bad checksum messages and logs the others. (Low utilisation: a few percent; very short messages: about 10 bytes.) The mechanism was inspired by ethernet's CSMA/CD algorithm. Perhaps your application is similar.

You could send packets such as a single byte of address, then the value, then a 16-bit CRC; you could do the framing the way SLIP does it RFC 1055.

(Following edit saying messages are single bytes.)

Idea 2: Circular Shift Register (with/without clock)

enter image description here

You might also consider putting the master and slaves in a shift register ring, where the master clocks everything around. As your messages appear to be very short (8 bits) you can do this pretty simply. You use some kind of bit- or byte-stuffing to keep them all in sync. If you don't want a dedicated clock, you could manchester-encode the data bits; then you're down to two wires.

Idea 2b: Revisit i2c

Most CPUs have a lot of hardware to help with i2c. You might find it does everything you want with considerably less "master" overhead than you're imagining. Unless you're using manchester encoding, idea 2 is really pretty close to i2c.

jonathanjo
  • 12,049
  • 3
  • 27
  • 60
  • In idea 1, as I understand, I have to implement some kind of addressing protocol in order to communicate something to a specific slave. Am I right? I am thinking about something like an ID as a first byte to transmit followed by the actual data byte. – Nicu Baciu Sep 19 '22 at 16:17
  • (Added an edit about addressing and framing for idea 1, if that helps.) – jonathanjo Sep 19 '22 at 16:23
3

solution which utilizes some kind of bus to connect

Any kind of bus will have contention,

If you need full duplex you need indivudual channels.

In a small enclosure there's no need for fancy drivers, CCTalk (which is used inside poker machines etc.) uses TTL level UART signals. open collector with send and receive on the same wire (it is therefore half duplex but is shared between all the devices, )

if you add interrupt line (one per device) you can use a serial bus like SPI or I2C (or even cctalk) and not have the host busy waiting for a device to be ready to send.

  • 1
    I think CAN would be probably the best, it is simplex but at a very fast baud it should suffice. It gives you CSMANDA (Carrier Sense, Multiple Access, Non Destructive Arbitration), It is a bus standard and no hub or switch is required. The controller will buffer some of the data for the processor and more important messages will go first. The micro controllers can be interrupted when a CAN message comes through (there are also filters) and not be busy determining and decoding messages. It should only add a few $ to each node and it removes a lot of software overhead. – Gil Sep 19 '22 at 14:34
2

You could implement a ring of UARTs if response time is not very important.

schematic

simulate this circuit – Schematic created using CircuitLab

  • Any MCU may be the logical master
  • Each MCU forwards each packet, that is not meant for it, or just all, for simplicity.
  • There is no collision possible.
  • Each MCU may insert a packet after completion of the last received.
  • An MCU can have a bypass resistor attached (here U5). If it enters sleep mode and disables TX output, the ring still is closed.

A variation for faster response time is the immediate forwarding of each received byte. A sync gap between packets allows packet insertion for all MCUs. This can only work if a significant part of the bandwith is available at all times.

Jens
  • 5,598
  • 2
  • 7
  • 28
  • Response time is somewhat important. I would like a response time of around 50ms. And if the number of MCUs increases, the response time increases as well. But just for my curiosity: what "stop condition" would the messages have in such a ring? How would a node know not to forward a message to avoid creating an infinite loop? – Nicu Baciu Sep 19 '22 at 23:50
  • 1
    @NicuBaciu Each device has an address and then the packet contains a token to indicate start of packet; sender addr; destination addr; length; CRC. You pass along until you are the recipient. If you send a "general call" message, then to pass along until the sender is yourself. To assign the address, you can self promote to a master or specify a master. The "master" says to the next node you are "1" using special message. Slave 1 sends the message saying next is 2 and so on until reaching the master. – Mishyoshi Sep 20 '22 at 01:47
  • 1
    @NicuBaciu If a slave doesn't receive a message within "x" ms, it may even chirp a special message saying that slave "n" didn't receive anything from "n-1", which other nodes may use to indicate that the ring is broken somewhere/a slave is stuck. – Mishyoshi Sep 20 '22 at 01:48
  • Yikes, token ring... Why use UART for this instead of daisy-chain SPI? With SPI you have the advantage that you can easily integrate "dumb" nodes in the chain, such as shift registers. – Lundin Sep 20 '22 at 06:40
  • @Lundin Using UART is a personal preference. I like the advantage, that a node can send an arbitrary amount of byte without waiting for a clock from a master and I need just one wire. – Jens Sep 20 '22 at 13:23
1

As @Smith says in the comments. I2C fits the bill with the information provided in the OP. Here is a good explanation of how I2C works including

  • SINGLE MASTER WITH MULTIPLE SLAVES
  • MULTIPLE MASTERS WITH MULTIPLE SLAVES
Aaron
  • 7,274
  • 16
  • 30
1

You cannot have full duplex communication unless you want to send data to receive on a bi directional bus which requires two to four wires. In a bi directional bus, you send a byte to receive a byte at the same time.Have you tried one wire bus which is perhaps cheaper to implement for 16 slaves? One wire bus works with upto 50 slaves. It is not duplex though. You generally dont need duplex communication in a multi master or multi-slave type MCU interfacing architecture. Some more details of your setup may be necessary. You haven't indicated the rate at which the master would communicate with the slaves and at what intervals. If you are collecting data every one minute from each slave,lot of simple communication protocols work. Rs-485 is suitable for long distances like 10 to 50m.You may want to look at CSMA/CA type bus architecture. This works well in multi-master and multi-slave setups.

Please specify some more of your system requirements such as:

Baud rate of the bus.

Send/receive data intervals ( in milliseconds or seconds) per slave.

Would you send or receive data synchronously (in regular intervals) or asynchronously (in irregular intervals)?

Data size ( payload size in bytes or Kilobytes) for each communication of master with a slave.

If I'm not mistaken, nobody sets up 16 slaves with a MCU master to have a high speed duplex communication bus.

Edit: After looking at your additional requirements, it seems like your setup seems interrupt driven. It means that when a slave sends a message, there would be a interrupt in the master which does some processing and sends a message back to the slave. It seems like your setup is multi-master rather than multi-slave. You seem like not polling the slaves to check if they have a message for the master. Slaves usually respond when they have a command from the master. Its how master-slave communication works in MCU interfacing. I dont know if the MCU you are planning to use supports a protocol which allows slave initiating data. Can you post the MCU part number or datasheet of your system?

A bus protocol like CAN works well in this scenario.

Amit M
  • 394
  • 1
  • 11
  • I am currently in the design phase so I have not chosen an MCU yet. I want to decide on what to use based on the requirements of the system and the particularities of the communication. For the MCU I only need 3 IO pins to control the components of the subsystem and all I need in addition to that are communication pins. – Nicu Baciu Sep 19 '22 at 15:49
  • You said that the slaves sends data to the master based on user key press and after that the master would change its behavior. Does the master control the slave by sending data to the slaves to display something in the UI? It seems the device initiating data would be a master so in your setup, so each slave would be a master.. This can change in a bus protocol like Ethernet or etherCAT which has greater than 1 Mbps baudrate and it can just poll each slave. See this link: https://electronics.stackexchange.com/questions/456057/can-rs485-be-considered-a-multi-master-bus – Amit M Sep 19 '22 at 15:58
  • UART is also possible as jens pointed out. Most MCUs have UARTs so it shouldnt be a problem. You need not have the highest or fastest protocol such as RS-485 for it. Your main requirement seems like each node should be a master in a multi master bus. – Amit M Sep 19 '22 at 21:23