Slow communication with a lot of cheap microcontrollers - Page 1
Forum section: electronics / projects

author: luky315
author_rank: Regular Contributor
timestamp: November 11, 2021, 09:04:24 am
content: I have a project with a lot of microcontrollers (up to 128, max. distance between them is 30cm) and I need to send data to them (2 bytes) and get their status information (voltage, temperature and touch info) once per second.The microcontroller (PSOC4000) that I'm using has no hardware UART, but that shouldn't be a problem with the relatively low speed. Or is there a better protocol than (LVTTL) UART for this use? The internal oscillator has a +-2% tolerance.Any suggestions?

author: daqq
author_rank: Super Contributor
timestamp: November 11, 2021, 09:32:40 am
content: Max distance between two of them or total length of the bus?If it is the later, this is the thing that I2C was designed for.QuoteYes it does. All of the PSoC 4000 have hardware USARTs/communication blocks.

author: luky315
author_rank: Regular Contributor
timestamp: November 11, 2021, 10:06:52 am
content: No, not all PSOC4000 have SCBs that are UART and SPI capable.30cm is the distance between devices. I have to use unshielded cables and need a more robust transmission than I2C.And there is the option of a galvanical isolation between groups of microcontrollers so I2C is a bit problematic....

author: voltsandjolts
author_rank: Unknown
timestamp: November 11, 2021, 10:19:30 am
content: Are all devices 30cm from the bus master like star, or is it like string 128 * 30cm long = 38 metres?

author: DavidAlfa
author_rank: Super Contributor
timestamp: November 11, 2021, 10:23:01 am
content: For isolation, some optocouplers should do it.I2c is ok, just use low speeds, ex. 10KHZ.You have a timer, you could make a software uart with it. It also support pwm.Also there's a systick timer...I would try to implement 2-wire rs485, there're isolated transceiver available

author: bingo600
author_rank: Super Contributor
timestamp: November 11, 2021, 01:06:48 pm
content: I was also having RS-485 popping up in my head, when i read the description.Make it a "Bus" , not a "Star" , then RS-485 will play really nice./Bingo

author: luky315
author_rank: Regular Contributor
timestamp: November 11, 2021, 01:40:01 pm
content: RS485 was also my first Idea, but it is a bit overkill for a low cost project. The 30cm are the maximum distance, normally the cables between the microcontrollers are much shorter and the overall length is a bit over 5m.It looks like it is a software-UART. Is there a "correct" way for implementing it in the most reliable way?Or could it be better to use a communication protocol with integrated syncronisation to minimize the clock variations? A slower, non certified LIN Bus with LVTTL levels for example?

author: DavidAlfa
author_rank: Super Contributor
timestamp: November 11, 2021, 01:44:47 pm
content: Rs485 is very similar as standard serial, but with addressing...I'd try i2c, just slow the speed down and use stronger pullups (ex. 1k)

author: luky315
author_rank: Regular Contributor
timestamp: November 11, 2021, 05:19:15 pm
content: What if I drop the PSoC controller and use ESP32 or similar low cost modules with capacitive touch?Has anyone experience with a lot of such things in close proximity?

author: tmadness
author_rank: Regular Contributor
timestamp: November 11, 2021, 05:32:43 pm
content: Using an esp will give you the ability to use mesh wifi:https://randomnerdtutorials.com/esp-mesh-esp32-esp8266-painlessmesh/Depends on the environment you are using, but wifi might be faster and more scalable

author: Siwastaja
author_rank: Super Contributor
timestamp: November 11, 2021, 06:07:33 pm
content: Is power/ground shared?If yes, GPIO push/pull output with series termination resistor, possibly a small capacitor at input, and some software signal conditioning (similar to what UART peripherals internally implement by sampling multiple times) is just fine unless this is a high interference environment. Definitely more robust than wireless on any ISM band.Differential signalling (RS422/485/CAN) becomes relevant when there are ground loops, or significant voltage drop on the ground wire due to the current consumption.Manchester encoding is great for such slow links. Why not faster, too, it just has 50% overhead which is why some don't like it. But with Manchester encoding, 2% clock tolerance is more than fine, and you can also AC couple it (through transformer or capacitor, for example).Software implementation of multi-sampling Manchester communication is trivial enough so left as exercise.

author: SiliconWizard
author_rank: Super Contributor
timestamp: November 11, 2021, 06:35:49 pm
content: Quote from: luky315 on November 11, 2021, 10:06:52 amAnd you think that a simple asynchronous serial communication will be more robust than I2C? Yeah. To be seen. Maybe if you use higher voltages than 3.3V, for instance, which was common with RS232, for instance. Also don't forget that I2C can be used at any clock rate. You could use a much lower rate than the std 100 kHz if that makes things more robust (especially if there are that many devices on the bus...)Although I2C should be usable in this context, if you don't want to resort to using differential drivers and receivers (that might be too costly and/or overkill), I like the idea exposed by Siwastaja, Manchester encoding. For low speed, software encoding and decoding should pose zero problem even on modest MCUs. Of course you'll need to implement a protocol on top of it which handles addressing each MCU individually - and properly handle bus 'release' of the slave -> master direction.

author: Doctorandus_P
author_rank: Super Contributor
timestamp: November 12, 2021, 04:13:22 pm
content: 5 meter of wiring is quite a lot for I2C.And with so many devices you also add a lot of capacitance.RS485 can work with so many devicesSPI may also work option because it the combination of push pull outputs and cmos inputs.With 5 meters of length you have to handle transmission line effects in some way.But all together you may want to start thinking about splitting your bus into smaller sections.

author: byte
author_rank: Contributor
timestamp: November 12, 2021, 04:57:28 pm
content: SparkFun makes differential I2C Breakouts that extend the I2C distance to 100ft+https://www.sparkfun.com/products/16988https://www.sparkfun.com/products/18000https://www.sparkfun.com/products/17250

author: T3sl4co1l
author_rank: Super Contributor
timestamp: November 12, 2021, 05:23:54 pm
content: Very low baud (9600 or even less) and logic-level signaling will do, with RS-232 (or better) being preferable. Just filter it very well, use protection, and use schmitt trigger inputs, so that EMI and ESD don't cause problems.This allows you to bypass concerns of signal quality, transmission line effects, etc., but mind that it's fairly limited in scaling: if you choose a chain topology for example, you need to send and receive as much data as the total chain carries. 2 bytes * 128 devices = 256Bps minimum (roughly 2560 baud), for just sending; and then however many bytes they send back, and you may easily exhaust a 9600 baud COM port for example. (Which would then need a line bandwidth of >5kHz, say with RC or RLC filters at each port with Fc ~ 10kHz.)As mentioned, I2C can~kinda~be used this way, but I wouldn't recommend it. The sheer number of filters hanging off it, will make the whole bus much slower than the intended cutoff frequency to each node will be.There does happen to be a differential I2C, which wouldn't need such aggressive filtering; but again, it requires interfaces -- and also doesn't have nearly the common-mode range of RS-485 and friends, so still isn't great.Note that a chain topology may be more efficient than a parallel bus. For example, if every device receives, parses, and passes commands along the chain, it can tap off its own addressed command, and add its data in the respective slot of the return packet. That is, each device has two UARTs active, one facing the host, one facing the next device. For the most part, each device simply forwards host RX to device TX, but reads commands addressed to it (and these can be auto-addressed, like by decrementing the address as the packet passes through each node). Likewise, each device simply forwards device RX to host TX, except for stuffing its own data into the stream, in whatever fashion.A number of industrial protocols work like this (EtherCAT for example). In contrast, a parallel bus, offers random access; it's good when you don't know when you need to check a given node (or the polling rates differ), but when everything is sequential anyway, you're just doubling up on all the address commands, plus waiting for each response.CANbus is very reasonable for this sort of thing, low bandwidth information sharing with good EMI immunity; but you need interfaces of course, plus the code to manage it. It might also not scale so well to so many nodes, I'm not sure; but at least its differential design permits higher baud rates. Signaling is similar to RS-485, so it's no accident that both should be mentioned in this thread.(Point of clarification: RS-xxx don't make any statement about what data is on the line, or timing aside from min/max limits; they're only concerned with the signaling levels and rates, and stuff like recommended cable length. Connectors and protocols are up to you. Contrast this with standards that do include protocol (like CANbus), and others are protocols, independent of the signal layer (like Modbus, often done over RS-232, 485, or even tunneled over TCP/IP). Watch out for this, because sometimes "RS-232" is used loosely to also refer to the UART protocol commonly used with it; this isn't at all a guarantee, but they're used often enough together that we sometimes associate them in language. So, if you ever see "RS-232 TTL" or some abomination like that -- this is probably the sense in which it was meant.)Tim

author: Siwastaja
author_rank: Super Contributor
timestamp: November 12, 2021, 05:35:55 pm
content: Chain sidesteps signal integrity and bus arbitration issues easily; OTOH, in a chain, any single point of failure causes a system-wide communication blackout. Also, last nodes need to relay the data generated by all other nodes, limiting throughput (average speed).But 128 devices on single shared bus is not trivial! And even on a bus, a dead node can bring the whole bus down unless this is taken care of in design. As a comparison, when chained, 128 is not a problem at all, except for latency and throughput, but those don't always matter.And, sometimes you just need all nodes to be responsive - i.e., if one fails, the system failsanyway, even if you managed to get all the other readings through. In such case, designing a system which can deal with one dead node is waste of time.A good compromise might be just using multiple chains to ease the latency/throughput issues. Like max 64 devices per chain divided in up to 4 chains. Then it's also easier to guarantee that each node-to-node link is of maximum certain physical length; if that length is exceeded anywhere, just make it another chain! Then, you can use better signalling schemes for the end nodes in chain, for example run the same logical ones and zeroes through RS422 transceivers. This way, you save the cost of extra wires and the transceivers inmostof the nodes, yet get the robustness exactly where you need it.The "master" device that connects to said 4 chains can then implement the same bitbanged communication but with the difference that it accesses four GPIO pins at once. Especially easy to do if you route them to the same physical IO port on the MCU.

author: DavidAlfa
author_rank: Super Contributor
timestamp: November 12, 2021, 07:04:57 pm
content: I think that anyone should have at least tried the available options before discarding them so easily.I2c is the only hardware interface you have, provides exactly what you need: Addressing, dedicated hardware offload, simple bus design...So take 5m of shielded wire, few resistors and test it out!Ifnit fails, then start trying other Vodoo/Black magic stuff.You have i2c - canbus tranceivers, which might be the perfect solution.Might worth reading:https://hackaday.com/2017/02/08/taking-the-leap-off-board-an-introduction-to-i2c-over-long-wires/

author: T3sl4co1l
author_rank: Super Contributor
timestamp: November 12, 2021, 07:34:23 pm
content: By the way -- the catch with all of this is, in a quiet environment, absolutely, you can get away with anything and everything -- I2C on tinsel wire, Ethernet on coathangers, orADSL over (salty) wet string. But the instant some noise appears in the environment, you get intermittent dips, denial of service, corrupted data -- the works. The challenge is always to get a reliable connection, in the presence of such interference -- where "reliable" is a design parameter and measured quantity!If your application can tolerate unreliable data, maybe you add checksums to deal with data corruption, maybe you don't really need fresh samples every pass, etc., and maybe that does well enough in whatever environment you're using it in. If this is a one-off household sort of thing, yeah, you can get away with that -- though, do be careful every time you bring in new hardware, all it might take is one noisy Chinese phone charger to stuff up the whole system. And woe is you if your neighbor decides to take up CB radio or something. But that's probably pretty far-out too, so, yeah?The ADSL case above, is a fantastic example of a tolerant protocol; it works by dividing the channel into frequency bands (IIRC), and basically handling them independently, as if each one has its own radio transceiver; a given band might have utterly abysmal reception (giving a weak, noisy signal that can't be changed too often i.e. carries low bandwidth), but in total, it can still operate, and often surprisingly well at that, because of all the redundancy and compensation. The downside is it's devilishly hard to write or build such a system (all that functionality is packed into an IC or two, with good reason!). I certainly wouldn't expect you to use something so complex, but there is a huge range of options between "nothing" and "okay with wet string", something is likely doable.Tim

author: Siwastaja
author_rank: Super Contributor
timestamp: November 13, 2021, 07:50:02 am
content: Quote from: DavidAlfa on November 12, 2021, 07:04:57 pmThis is horrible advice. I2C just is totally unsuitable for such use. It's not designed for this.Yet if you do as you suggest, you likely find out it seemingly "works" on the lab table. No "Vodoo" needed, you think.Except then it fails in real world, randomly every now and then, when you least expect it, and you are wondering why, and need to start from scratch.Proper design is not "Vodoo".Instead, if you want to "save time" by not understanding everything, pick some standard solution usually used in that domain.CAN or RS485 would be obvious choices, depending on which gives you more comfortable (less work) high-level interface. I kind of like the CAN packet structure and priority "addressing" (really content description IDs) but it isn't a perfect fit in every project.For more adventurous, you can of course use I2C but then you get into quite some serious signal integrity work to prove it is even remotely reliable, because it isn't originally supposed to used this way. Requires a lot of expertise.

author: DavidAlfa
author_rank: Super Contributor
timestamp: November 13, 2021, 09:43:27 am
content: I don't completely agree.1-wire is very similar, uses a pullup for the whole bus, no differential signaling, yet it's able to run 20 devices over 100m.There's nothing special, the protocol uses checksum and they recommend cat7 wire for long distances.For an i2c all you need is to make it more tought against errors.Slowing it down, adding checksum and i2c resetting timeouts should make it a lot better.It's 5m, not 5km... Of course you must know the environment and design it for the worst condition.

author: Siwastaja
author_rank: Super Contributor
timestamp: November 13, 2021, 09:47:47 am
content: Quote from: DavidAlfa on November 13, 2021, 09:43:27 am... in a hobby setting where it's completely irrelevant if it actually works or not, or if some measurements are lost, because you get new readings a second later. Protocol uses CRC so it can discard faulty data.The OP didn't specify if availability of data (i.e., packet loss) is important or not. They didn't specify if reliability is important. So I assume they are important. Not "pacemaker" or "moon rocket" important, but still something where outages and packet loss could be undesirable. I.e., something where normal consumer level approaches are required.But of course OP can specify further if they can accept unreliable communication. If this is the case, cheap ISM radios are also one possibility.

author: David Hess
author_rank: Super Contributor
timestamp: November 14, 2021, 08:52:21 pm
content: Quote from: Doctorandus_P on November 12, 2021, 04:13:22 pmAnd that gets down to the core problem. Unlike RS-485, I2C was not intended to operate into a terminated transmission line, so total line capacitance which limits rise and fall times has to be considered. Ignoring common mode problems, if I2C was used with a terminated transmission line, then it would be fine at high speeds over longer distances. Essentially it ends up being a single ended version of RS-485, but there are difficulties because the I2C interface was not intended for this.SPI could work more easily because nothing prevents implementing an SPI interface to handle two separate terminated transmission lines for transmit and receive, unlike I2C which only uses one line for both.There is an additional complication with the above, which points out why RS-485 is the way it is. If the transmission line is double terminated, then logic levels along the transmission line are halved, which common logic receivers are going to complain about. Either some type of line receiver to translate the levels is needed, which is how RS-485 works, or parallel termination needs to be used to preserve the logic levels. but then the transmitter side has to drive the entire transmission line resistance which will be quite low.Why not just ignore termination and go slow with I2C? That could work, but there is a limit to line length because if the rise and fall times are too slow, then I2C may not work no matter how slow the data rate is. Check the datasheet for *maximum* rise and fall time specifications at the receiver.

author: T3sl4co1l
author_rank: Super Contributor
timestamp: November 14, 2021, 09:44:33 pm
content: Quote from: David Hess on November 14, 2021, 08:52:21 pmThe biggest problem is the impedance mismatch. If I2C drivers were designed to drive pullups as low as Zo / 2, it could be double-terminated just fine. Where Zo is some reasonable line impedance, say 50 (coax) to 100Ω (alternate-ground ribbon cable), sometimes a bit higher (specialty cables).Alternately, the line could be made in high-Z media, but this is rather impractical; single lines above 200 ohm already have very ponderous geometry (huge ratio of signal to shield diameters, or conductor over ground plane if it's not coaxial -- but that would be tremendously noise sensitive, basically a wire in free space!). Special techniques can be used to increase the impedance (inductive loading) but this increases the cost even further, and was basically only ever done for specific applications (mid-era Tektronix scopes used such means for delay lines; the step response wasn't quite perfect, with some pre-ringing visible, but it was an alright compromise between fidelity, bandwidth, and cost or size).So, for all practical purposes, there is no case where we can:a. take existing chips and terminate them into any reasonable medium, orb. construct a medium which can be terminated into standard pull-ups.The interfaces also have relatively high loading capacitance per pin, which is just another part of the slow risetime in normal use, but would severely limit the performance of a high-Z line. Reason being, we can increase Z two ways: increase Lo, and decrease Co, of the line (that is, its inductance and capacitance per unit length).Finally, the act of increasing Lo (inductive loading) greatly reduces its velocity factor, so that a 5m network goes from being, essentially possible aside from noise issues, to effectively looking like a some-100s m network having real issues with propagation delay between nodes!QuoteYup, I'm fond of putting SPI into cables -- when I have to, that is -- using RS-422 transmitters and receivers. Takes up relatively a lot of pins (3 or more pairs, plus power and grounds), so it's likely going in a 10 or 16-pin ribbon -- but it's an easy solution, where you can be reasonably sure the signal quality and noise immunity will meet expectations.QuoteTo refine this point a bit -- RS-422/485 transmitters typically have quite low output impedance, enough to drive a good couple volts onto the line. If the line is fairly short, the logic levels at any receiver can be expected to be quite strong as well -- and the same will be true of logic-level transmitters used in a similar manner (like I2C versus its relatively large pullups, or TTL outputs versus asymmetrical termination resistors*). The catch is, if the source impedance isn't so low, or the line is long (so its resistance is substantial), that level isn't going to be nearly as strong. And this is why RS-422/485 input thresholds are so narrow (some 100s mV, usually with a slight positive bias so a dead-line condition reads low).Typical I2C receivers, with TTL, LVCMOS or CMOS thresholds (V_IL(max) ca. 0.8-1.5V), will not read a lossy condition so well (that is, V_OL being above V_IL(max), for sizable (low value) pullups, or long line lengths).*A common solution back in the day: a TTL pin driving a ribbon cable (every other wire grounded). Terminated into something like 390 pullup and 150Ω pulldown, the Thevenin equivalent termination resistance matches, while the logic level still meets TTL limits (V_IL < 0.8V, V_IH > 2V). TTL output-high drive rather sucks (~50Ω equivalent?) but pulldown is quite strong, and this combined with the similarly off-center input threshold means it performs pretty well.This does NOT work with CMOS devices, unfortunately, as their input thresholds are typically quite wide and supply-referenced (30/70% VDD). No combination of termination resistors will terminate a typical line impedance and still meet input thresholds. Special receivers can be used, however (like the 74HC7014 precision Schmitt buffer, with ~60%VDD input thresholds).And, as mentioned, there are differential I2C interfaces -- these use low resistance terminations; the environment is comparable to RS-485 / CAN. They implement the same wired-OR arbitration, too. So they're not bad for going the distance.Tim

author: luky315
author_rank: Regular Contributor
timestamp: November 15, 2021, 06:37:30 am
content: I found something that sounds very nice: Unfortunately it's in german:https://ctlabwiki.thoralt.de/wiki/index.php/OptobusThe only problem that I see with this solution is that every node is a single point of failure. But it has a galvanic isolation whoch could be helpful.My application isn't important or high rel, its just a bunch of touch buttons so if its not working it is "only" anoying, but it has to work for a long time so I would prefer a stable solution where I don't habe to trubleshoot a lot

author: mjs
author_rank: Regular Contributor
timestamp: November 15, 2021, 09:56:59 am
content: DALI bus used in lighting is quite robust, but slow. It uses 250mA current source and pull down/short circuit to signal bits - devices can also extract some power from the bus.Following that, bit banged slower 'I2C' with separate higher current open collector and something like 50 mA current source pulling SDA and SCL up might work and be really cheap ?(That's the cheap option, otherwise I'd use RS485 or CAN)

author: David Hess
author_rank: Super Contributor
timestamp: November 16, 2021, 03:52:24 am
content: Quote from: mjs on November 15, 2021, 09:56:59 amThat could work, but here is the problem. The transmission line needs to be terminated to get high speed operation like I described above, (1) but it also needs to achieve a sufficient logic threshold. I2C requires 50% Vcc so at 5 volts with a 100 ohm transmission line, so that is 50 milliamps per termination or 100 milliamps, and double that for 50 ohms, which I suspect shows why the DALI bus uses 250 milliamps.That is completely feasible to do if you can get an I2C driver which can sink that much, but it also shows why RS-485 becomes desirable for longer lengths. Does anybody make something like a multidrop V.35 interface?(1) It isn't the data rate which is the problem, but the minimum edge rate.

author: DavidAlfa
author_rank: Super Contributor
timestamp: November 16, 2021, 06:27:18 am
content: Check the PCA9615...