I'm working on an Arduino project where I have a main block and multiple sub-blocks connected via I2C. Each sub-block has its own unique function, and I need to identify the physical order in which these sub-blocks are connected to the main block.
Currently, I'm using I2C for communication between the main block and sub-blocks, and I am looking for a solution that helps determine the order of the sub-blocks' connection (i.e., which one is connected first, second, etc.).
I have considered using EEPROM or additional GPIO pins to store and identify each sub-block's ID, but I was wondering if there are better or more efficient methods. Would using technologies like CAN bus or 1-Wire make more sense for determining the connection order? Or is there a clever I2C-based solution that I could implement?
I'd appreciate any suggestions or advice from the community, especially if you've faced a similar challenge!
It depends on what your requirements are and the context. Some questions come to mind:
1: As per @Wawa's comment above, is this supposed to be hot-swappable? I.e. will the master need to detect new blocks and changes in block order while everything is running? If it needs to be hot-swappable, to what extent is it acceptable that an interruption of functioning of either the sub-block(s) and/or the master block occurs?
2: If you only connect 'sub blocks' together, do they need to be able to do anything autonomously?
3: As per @jremington's question above - what are these blocks? What kind of hardware and software/firmware do they consist of?
4: How many blocks will there be to a series? Is it always 3 or, can it be 1 through.....how many?
5: Are the sub blocks self-powered or do they rely on a connection to the master for their power supply?
6: When connecting blocks to the master, will there always be ONE sub-block being connected to the master, then ONE sub-block to that first block, then ONE sub to the second, etc? Or is it possible that the user connects a couple of sub-blocks together and then connects that string/array to a master block?
I probably forgot a few more, but this should get us going in terms of figuring out some use cases.
Thanks, Leo. You're right; I am trying to determine the physical connection order of the sub-blocks. I understand I2C isn’t inherently hot-pluggable, but I’m looking for any workaround or additional methods to achieve this.
The "blocks" are individual modules, each with its own unique function, like sensors or actuators, connected to the main Arduino via I2C. My goal is to determine the order in which these sub-blocks are physically connected.
Thanks for the detailed questions, rsmls. Let me provide some context:
The system doesn't necessarily need to be hot-swappable, though being able to detect changes in the block configuration after power cycling would be useful. Minimal disruptions are acceptable if blocks are added/removed.
The sub-blocks don’t need to act autonomously; they rely on the master for coordination.
The blocks are hardware modules like sensors and actuators, each with basic functionality managed by the main Arduino.
The number of sub-blocks can vary—typically between 1 and 10.
The sub-blocks rely on power from the master block.
The connection order is flexible; users could connect a few sub-blocks to each other and then connect that chain to the master.
Each sub-block will have 4 magnetic connectors that provide the connections, allowing for modular and easy assembly.
Hope this helps clarify the use case. I'm open to further suggestions or approaches based on this setup.
I know of no way to detect connection "order". The data and clock wires may be considered to be zero-length, for your purposes. Actually physically extending the I2C bus far enough that one might be able to measure, for example, propagation time, would be extending the I2C bus far beyond it's capabilities.
What you require is a bus arrangement where at least one signal passes through, and can be blocked by, each device. Therein lies a mechanism that can be used to determine order.
Thanks for the concise responses; this is very helpful.
I'm aware that I'm skipping a few steps in suggesting this, but the first solution that comes to mind would be to use an additional conductor to detect the order of connection of the blocks, and then use something faster (I'd suggest CAN) for actual communication.
The additional conductor would in fact be two nets on the sub-blocks: an "ID-in" and an "ID-out" net. You could have the sub-blocks iteratively detect each other by having each sub-block communicate a list of sub-blocks behind it to its 'parent' block. You could use something like OneWire for this, but UART may work, too (in this case I'd use two conductors so that you can benefit from bidirectional communication, making the detection process more robust).
For the communication part, CAN would be robust and relatively simple to implement. I believe you can even hot-swap CAN with suitable transceivers. I2C in practice can often be hot-swapped, but it's not designed to do so, so it's not recommended. Either I2C or CAN would work fine if it's OK to power-cycle after changing the block configuration. Personally, I'd go with something hot-swappable if this is feasible for you in terms of coding, because...well, it'd be awesome, wouldn't it?
You could do all this using a 5-pin connector carrying supply GND + Vcc, CAN +/- and one (optionally two) ID pin(s). Maybe you could even be creative and 'abuse' either of the CAN lines for the detection process during startup and then reconnect/reconfigure it back to CAN once the order detection is done. However, if you can spare the extra conductor(s), the overall system will end up being simpler to implement and probably more robust.
I'm aware there are several electrical and software details that would need to be worked out. But I hope the conceptual design is clear.
I'm also sure there are other and probably better ways to do this, so hold on for more people chiming in.
I think the only (feasible) way is if the sub-blocks are 'smart' and can talk to each other throughout the chain.
Is that part of the normal I2C implementation? Or are we talking about making every I2C device smarter now? The OP talks of sensors doing this, but we'd need to interpose some form of MCU between the sensor and the bus for this to work.
I'm not talking about I2C at all, really. I'd not recommend it for this purpose.
Yes, each sub-block would require a small MCU for detection and communications purposes. Something from the ATtiny range, for instance, or STM32F1xx. It could be selected also depending on what kind of work it needs to do. Communication with the master block could then be reduced to a standard protocol that suits all purposes, which makes the master firmware less complex. Of course at the cost of increased complexity of the sub blocks, but there's always a compromise.
Note that departure from I2C is not necessarily a problem since some of the blocks aren't necessarily tied to I2C to begin with; think of motor controllers etc.
Use one or more I2C multiplexers; each slave will connect to one of the outputs.
Set the multiplexer to channel 0, scan I2C addresses and the address of the slave connected to that channel will be found.
Set the multiplexer to channel 1, scan I2C addresses again and the address of the slave connected to that channel will be found.
I have difficulty visualizing how this works in a serial/daisy-chained setup. Isn't your proposal more suitable for a parallel/star setup in which every sub-block connects directly with the master block?
OK, thanks for clarifying; I thought I might have missed something.
I'm under the impression that the daisy-chain concept is a critical part of the system, also given the N=1...10 sub-blocks that might be connected. @araffakh can you confirm that you intend the system to work as you drew in #1, or is it also permissible if all blocks somehow connect directly to the master block?
@rsmls Thanks for following up. Yes, you're correct—the daisy-chain concept is indeed a critical part of the system. The sub-blocks are meant to be connected in sequence, with each sub-block connecting to the one before and after it. This design is important to maintain the flexibility in the number of sub-blocks, ranging from 1 to 10, and to ensure easy assembly and modularity.
To provide more context, the system consists of a main block (controller) and multiple sub-blocks. The sub-blocks are connected in a daisy-chain configuration, meaning that each one connects to the one before and after it, forming a sequential chain. Each sub-block has its own unique ID and a value determined by a variable resistor(to make it easy). The value is unique for each sub-block, and the goal is to have the main block recognize both the order of the connected sub-blocks and their values.
The connection order can change, and the system must be capable of dynamically identifying the new sequence and values when the blocks are rearranged. This flexibility is crucial, as it allows users to configure the system differently based on their needs without manually reprogramming the setup.
Direct connection of all sub-blocks to the master block wouldn't meet the requirements, as I want to maintain a simple, linear daisy-chain where each block can easily identify its predecessor and successor.
I appreciate your input and hope this helps clarify the intended architecture.