One-Way SPI to multiple devices on long ribbon cable - Page 1
Forum section: electronics / projects

author: zacaj
author_rank: Contributor
timestamp: January 30, 2021, 08:39:53 pm
content: I'm trying to set up a system to drive a bunch of ST7735S LCD displays from a Raspberry Pi. Works fine with one display at up to around 80MHz. But what I want to have is ~10 displays spaced over 10-15ft. I've been doing some testing and I can get it working up to at least 3 displays over 4ft (with a 30ohm series resistor on the clock pin at the rpi), but I have to drop the speed down to 10MHz, and I'm sure it'd get worse when I go longer. Since I have a bunch of boards in between though, it feels like I should be able to make these into 'repeaters' to strengthen the signal and cut down on noise/etc, so I'm looking for any advice on that front.My basic thinking was to put some sort of buffer chip at each display's output to extend the signal down the line to the next display, with each buffer chip having its own source termination, is there any obvious issue with that? Any more stuff I can do to help? I've been doing a bunch of reading and seen a lot of mention of other resistors and caps one one end of the line or the other, but not enough specifics for me to go on. Also saw a recommendation to use a ground wire between each signal on the ribbon cable, so I'll do that too. Anything else?Can anyone help with the formulas/calculations for the resistors/caps? I think you want the source termination to = impedance of the line - output impedance of the driver. I've seen some people saying ribbon cables tend to be ~100-150ohm impedance, but no mention of what length that is or anything, or how they got that number. Was thinking about using a 74HC541 for the buffer chip (would a different chip or technology (cmos/ttl, etc) be better?), and I think it has between 50-100ohm impedance on the outputs (0.30-0.6V/6mA on their output specs of the datasheet), which seems to recommend between 50-100ohm source termination. Through trial and error that seems too high (hence the 30ohm I'm currently using), but not sure if I messed anything up either

author: ledtester
author_rank: Super Contributor
timestamp: February 01, 2021, 06:08:08 pm
content: Here's an overview of RS232, RS422 and RS485 which you may find helpful:https://pdfserv.maximintegrated.com/en/an/AN3884.pdfAnother idea is SPI over LVDS. From this discussion in the TI support forum:https://e2e.ti.com/support/interface/f/138/t/701058?SPI-LVDS-over-20-meters-or-more-Quote

author: T3sl4co1l
author_rank: Super Contributor
timestamp: February 01, 2021, 06:40:55 pm
content: To use them in a bus configuration, you must have an end-terminated bus, not (just) source. This will reduce signal levels and draw extra supply current, so it needs interface devices -- drivers with stronger outputs, and receivers with more precise thresholds.RS-422/485 only goes up to 20MHz or so (at least, I don't recall seeing any at 50+ MHz?). Traditional logic (74AC, 74LVC) is capable of the speed and drive, but I'm not sure about receive (74HC7014 is well suited to this sort of application, except that it may be too slow for that much clock rate; and I don't think a version was ever made in other logic families).So that kind of leaves LVDS, which is fine. Beware that the signal strength, and receiver common mode voltage range, are lower, so it's not nearly as robust as RS-422 is. It is preferably used on-board, and must leave the board in shielded cables (PCIe, HDMI, SATA, and USB High Speed, are popular examples).As for other topologies, you could use a hub configuration, where links are always point-to-point (so can be source terminated when acceptable), and buffers fan out to additional point-to-point links as needed. Maybe a bit intensive on transceivers and cables? I don't know.Edit: a note, this is all easy enough just using converters -- you need three or more pairs per target, so it's a bit annoying to wire up (thank goodness for ribbon cables), but it is Just That Easy. Convert each logic signal to diff pair, then convert back. The above mentioned method, using a serdes (serializer-deserializer, un/packs a parallel bus into speedy serial packets), is basically just as easy, using a suitable pair of devices (and only needs one or more pairs per target).Tim

author: penfold
author_rank: Frequent Contributor
timestamp: February 01, 2021, 06:51:58 pm
content: Just a word of advice... keep your clock line well separated on the ribbon cable with with a couple of grounded wires in-between it and the data lines... I'd be afraid to admit how long I was scratching my head chasing a glitch that looked like it was causing itself!

author: ledtester
author_rank: Super Contributor
timestamp: February 01, 2021, 06:56:10 pm
content: QuoteI would use shielded twisted pair.

author: nctnico
author_rank: Super Contributor
timestamp: February 01, 2021, 10:26:02 pm
content: Quote from: zacaj on January 30, 2021, 08:39:53 pmLike others said: use differential signalling using RS485 or LVDS drivers. Twisted pair ribbon cable does exist so you can have a signal pair, ground pair, signal pair, etc for improved noisy immunity. You'll need to terminate the end of the bus in any case. An easy way is to have receivers on each display board and two plugs (in & out if you want) to daisy chain the display boards. The display board with also need termination jumpers so the bus can be terminated at the last display board in the chain.You might want to consider updating the displays continuously. If the communication gets messed up then the display contents will be corrected quickly.

author: magic
author_rank: Super Contributor
timestamp: February 02, 2021, 11:32:16 am
content: Use a scope to see what goes wrong.I wonder if it would work on ribbon with some 74LVC drivers (maybe a paralleled pair) and AC coupled end termination and no source termination to maintain full swing. Ground must be included between each SPI signal and on both edges of the ribbon. Straight bus, no branching.

author: PeteH
author_rank: Unknown
timestamp: February 02, 2021, 12:46:12 pm
content: LTC1686 or 87... Or any other one like it should be able to handle this. (52Mbps RS-422 compatible transceivers)Propagation delays and skew needs to check out... May need to buffer at certain points in the chain, maybe 2-3 times. Probably even better parts on the market which have tighter delay specs.

author: Siwastaja
author_rank: Super Contributor
timestamp: February 02, 2021, 01:43:13 pm
content: SPI is really designed for physically small (several inches) on-board buses. Multi-board may be acceptable if the wiring is short, for example between a main PCB and a control panel within the same casing.You can kinda (ab)use SPI for a longer link by adding source termination aka series termination (as you have done with your clock signal already), but thenthe only point where the signal is valid is at the end of the transmission line, necessitating max 1 device per bus. (Sometimes a clump of several devices at the end of the line with short stubs is OK.) Even then, 80 Mbit/s is pushing it.Your bus topology really needsparalleltermination, this is the way you can have valid signal levels at any point within the bus. But parallel termination halves the voltage level so you need driver ICs, complicating away the inherent simplicity of SPI.You likely need something else.Also consider running a separate link for each display.

author: zacaj
author_rank: Contributor
timestamp: February 02, 2021, 03:31:08 pm
content: Quote from: Siwastaja on February 02, 2021, 01:43:13 pmCan you explain more on why that is? I was definitely seeing that (the more displays I added to my bus, the more issues the *earlier* displays would have) but I don't quite get why. Is it just because the isn't any room for the signal to bounce back and conflict with itself?Quote from: Siwastaja on February 02, 2021, 01:43:13 pmI can technically do that as a backup, but I was really hoping this chained approach would work, since it means I can add more displays to the end of the chain as needed (within some limits) and theoretically requires one simplier board per display (custom boards being cheap in bulk) vs one larger custom board at the source with a bunch of repeat circuitry to feed all the linesQuote from: nctnico on February 01, 2021, 10:26:02 pmMy current design is using the "two plugs" approach like that.... Would you still need the termination jumpers on the last display if there's a driver chip on each board between the in and out?Quote from: ledtester on February 01, 2021, 06:08:08 pmThanks. I'm still learning about differential signals, RS422, etc. I've got some chips on hand to play around with and get a feel for it all but I haven't worked with it at all yet... Was hoping that for hops of at most a foot or two between each display I could avoid needing to go that far

author: T3sl4co1l
author_rank: Super Contributor
timestamp: February 02, 2021, 04:25:33 pm
content: Quote from: zacaj on February 02, 2021, 03:31:08 pmYes!Consider the voltage on the transmission line.The instant the transmitter transitions, it sends a current into the line. The current is set by the source termination resistor, and the line impedance. Let's say both are 100 ohms.Thus, at the transmitter port, we have a voltage divider, say it's transitioning from 0 to 3.3V, then the pin voltage (assuming an ideal transmitter; it's not, but we can lump in its internal resistance with the source termination resistor, so this is fine) goes from 0 to 1.65V,and that 1.65V wavefront propagates down the line.Some time later, a lone device at the far end, receives the 1.65V wavefront. The line is open (unterminated) at this end, so the wave reflects in phase, and at nearly full amplitude. At the end, the wave doubles up on itself and a clean 3.3V is received. Later, the wave returns to the source, adding its 1.65V level to the initial 1.65V level, setting the full line to 3.3V.In effect, the transmitter tried to set the line to 3.3V, and at the speed of light (in the medium), that event is communicated over the length of the line. The transmitter must deliver current during this transition, to drive that event. It's not for free of course, there's energy stored in the line.In practice, there is some loss and phase shift due to the transmission line itself, and the receiver pin capacitance. They act to round off the edge, or cause a little ringing. Likewise, the source end won't be perfectly terminated, so a little wave will reflect back off it, and so on and so forth; but as long as the double reflection is small (say, less than 20%), we aren't very interested in it. (Why 20%? This is about how much range a CMOS receiver considers a "valid" logic level.)Now add a receiver midway along the line. What does it see? First nothing, then 1.65V, then 3.3V -- an indeterminate level is read for the duration of twice the distance to the far (unterminated) end. This perfectly describes the failure you observed, which is fortunate I guess, in that it failed exactly as one should expect!Also, note that, if the line is longer than the pulse width being driven into it, then the transmitted and reflected wavefronts will both be in transit at the same time -- even stranger combinations (i.e. runt pulses) appear midway along the line.If we load or double terminate the line instead, then the transmitter drives 3.3V into the line, and either 1.65V (source terminated) or 3.3V (unterminated) launches down the line, and at the far end, the wavefront is simply absorbed, leaving 1.65 or 3.3V along the line.There is no double-time penalty for a reflected wave.Likewise, any receiver placed midway along the line, sees the same single wavefront -- and there is no problem with multiple wavefronts travelling on the line at the same time, so long as they're synchronized in time and direction.Of course, for the double-terminated case, we need a receiver that can read a 1.65V threshold, likely not a plain old CMOS receiver.And for the LVDS case, everything still applies, and we can ignore common mode propagation as long as everything is well behaved (but, be aware that it is still there, and will make you pay attention to it if you forget about it too much!). The differential signal is simply smaller (100s mV), and appropriate drivers and receivers are used to handle it.(To a first degree approximation, differential pair PCB traces can be treated as individual transmission lines. So, you simply have whatever signal is travelling on each one, independently. Termination is one resistor per trace, and the differential termination is... simply the equivalent of both in series. We define common mode as the average voltage between the two lines, and differential as the difference. This is actually not a terrible approximation, on board -- not much coupling occurs between edge-adjacent traces. The coupling is more important in twisted pair cable for instance, and the calculations may change.)Tim

author: nctnico
author_rank: Super Contributor
timestamp: February 02, 2021, 04:57:48 pm
content: Quote from: Siwastaja on February 02, 2021, 01:43:13 pmNo. The signal is valid all along a transmission line. Look at the original ethernet which uses a single coax cable (terminated at the beginning and end) with tap points to receive / transmit data. Other examples are CAN and typical RS485 busses. It is perfectly possible to use SPI over longer distances (between boards) for not so critical applications as displays but it will require differential signalling and filtering of the clock and select lines to prevent false edges.Quote from: zacaj on February 02, 2021, 03:31:08 pmIn that case no.

author: magic
author_rank: Super Contributor
timestamp: February 03, 2021, 08:54:21 am
content: With source termination and open circuit end, the end is the only point where you will ever see the transmitted signal intact.That's why I would test end termination instead. Might work on not too long distancesQuote from: Siwastaja on February 02, 2021, 01:43:13 pmThis, however, is wrong. Series (source) termination halves signal level, parallel (end) termination loads the driver. So you need a driver, but for different reason, and as I said, two paralleled 74 series gates on each line could drive 100Ω.

author: zacaj
author_rank: Contributor
timestamp: February 04, 2021, 12:49:26 am
content: Quote from: magic on February 03, 2021, 08:54:21 amIf I put a driver between each display, with source termination on each driver, would that mean that every display is technically at the "end" of the circuit, and thus will get the signals properly? or am I at risk of the drivers in the middle of the chain somehow propagating the reflected signal/etc?

author: T3sl4co1l
author_rank: Super Contributor
timestamp: February 04, 2021, 07:07:24 am
content: Quote from: zacaj on February 04, 2021, 12:49:26 amYes, buffering -- adding repeaters -- maintains signal quality. Indeed they act to sharpen the signal, making up for line losses. (This happens to be how undersea telephone cables were built: an amplifier every km or few, with frequency compensation to account for line characteristics. After some hundreds of amplifier stages, they ended up within a few dB over the desired passband -- damn fine work!)The downside is, the delays of each buffer won't be perfectly matched, and eventually the signals will skew apart (violating setup/hold times, and corrupt data results). Cables don't have perfect matching, either. This shouldn't be too bad for single chip buffers and a dozen displays, but it will limit scale at some point. (Skew can also be avoided, with synchronization -- adding D flip-flops every once in a while. Note this will increase clock count, so it's not a transparent solution. Or -- using a single channel, again, a serdes pair joined with LVDS or whatever.)Tim

author: magic
author_rank: Super Contributor
timestamp: February 04, 2021, 08:59:40 am
content: IIRC this was a decent explanation of basic transmission line effects:https://www.eevblog.com/forum/projects/super-simple-_fast-edge_-pulse-generator-for-scope-based-basic-tdr/Quote from: zacaj on February 04, 2021, 12:49:26 amProbably yes, though my first thought was to use 100Ω "parallel" termination at the end and a driver capable of driving 100Ω at the source. This should be trivial to retrofit into whatever setup you have now, without modifying the display boards. It will be more susceptible to losses in the cable, though, and I don't know how good or bad those cables are. But I suspect on a distance of a few meters you will only see some "rounding" of the corners of the waveform. Heck, USB2.0 runs on shitty-ass cables at 480Mb/s.Whatever you do, it is a good idea to have ground on each side of each signal on the ribbon.

author: zacaj
author_rank: Contributor
timestamp: February 04, 2021, 02:39:46 pm
content: Quote from: T3sl4co1l on February 04, 2021, 07:07:24 amYou mean, the delay between each pin on one buffer chip aren't perfectly matched? Or the delays between different buffer chips? I don't think the latter should matter in my case, since the communication is all one way? As long as all signals are delayed the same amount it should still workQuote from: magic on February 04, 2021, 08:59:40 amTo be clear, you mean, put a 100ohm resistor from each signal line to ground? How would I tell how much my driver can "drive"?I didn't have the ground on each signal in the ribbon before, but I'll definitely try that on my next revision. No brainer for sure

author: T3sl4co1l
author_rank: Super Contributor
timestamp: February 04, 2021, 03:48:20 pm
content: Yes, between buffers within a given chip. The difference will be small (under a ns?), just that it will add up eventually (so, probably nothing to worry about for 10 displays, but 100, good luck?).Huh, I wonder if in a given multi-gate chip, there's any fab difference, say part A has a longer internal connection somewhere, or something. Probably of a similar (small) magnitude.Tim

author: perieanuo
author_rank: Frequent Contributor
timestamp: February 04, 2021, 04:30:44 pm
content: hi,I don't get the specs, you need 80MHz for driving several displays?? Are you sure?

author: zacaj
author_rank: Contributor
timestamp: February 04, 2021, 09:09:07 pm
content: Quote from: perieanuo on February 04, 2021, 04:30:44 pmEach display is 160x128x16bpp = 327680 bits per frame. I'd like to have them updating in under 10ms, so that's ~11MHz for one display. If I want to drive 8+ displays....Worse, my current timings show that I'm missing something there, and it's actually even slower than that. I think I'm currently getting around 90ms real world timing for one display at 10MHz (the max I can drive my chain of displays at currently)Unless I'm completely messing something up here?

author: gnuarm
author_rank: Super Contributor
timestamp: February 05, 2021, 04:59:46 am
content: Quote from: zacaj on February 04, 2021, 09:09:07 pmYeah, I don't get the same numbers as you. Your bits per frame right, but to achieve 10 ms refresh time means 32.768 MHz bit rate for one display. To achieve that requires a separate run for each display from the source. i guess I initially though you were sending the same video to each display.Now you know why monitors have special interfaces. They have to haul a LOT of data every frame.How are you generating this much data? I don't think there is any way a Raspberry Pi can do the job for separate displays. Can it?What is the source of your data?

author: Siwastaja
author_rank: Super Contributor
timestamp: February 05, 2021, 07:01:29 am
content: The intended use case for such SPI displays is one display per bus, on the front panel of the product with ashortcable.I'd seriously consider "one cheap MCU per display" approach; instead of raw pixel data, share the data required to generate the display content, for example CAN bus would be well suited for such use.

author: zacaj
author_rank: Contributor
timestamp: February 05, 2021, 03:06:53 pm
content: Quote from: gnuarm on February 05, 2021, 04:59:46 amNow that I'm looking at it I don't know where that 11MHz number came from either, weird.. Anyway, my hope was that, since these displays are so small, they don't need that much special treatment. Most of this data is just various image files being streamed off the filesystem, with some of them having custom text layered on top. The RPi is running a tcp server that receives commands for what to show on each display. It's not continually updating (most of these images will be static) but it needs a fast response time.

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: February 05, 2021, 04:39:57 pm
content: Definitely LVDS for maximum distance/speed. Maybe RS485 but data rate will be significantly limited, and you may get skew issues.

author: zacaj
author_rank: Contributor
timestamp: February 09, 2021, 12:28:27 am
content: Got some new boards in today which incorporate source termination resistors and a SN74HC367N buffer chip between each display... Was able to reliably drive 5 (I don't have the rest wired up to test yet) at 30MHz, but if I up the frequency any more the screens at the end of the chain start having issues (as opposed to the ones at the beginning). If I lessen the amount of screens I can increase the Hz more. So there's still something that's getting lost over the distance despite having repeaters every foot or so

author: T3sl4co1l
author_rank: Super Contributor
timestamp: February 09, 2021, 12:33:53 am
content: How are you wiring between each buffer and display?Tim

author: nctnico
author_rank: Super Contributor
timestamp: February 09, 2021, 12:51:08 am
content: Quote from: zacaj on February 09, 2021, 12:28:27 amI'd measure the signals using an oscilloscope. See if the timing is still OK.

author: zacaj
author_rank: Contributor
timestamp: February 09, 2021, 03:27:02 am
content: Quote from: T3sl4co1l on February 09, 2021, 12:33:53 amI've hand-crimped some small wiring harnesses (each display's mounting position is unique)

author: gnuarm
author_rank: Super Contributor
timestamp: February 09, 2021, 04:26:15 am
content: Quote from: zacaj on February 09, 2021, 12:28:27 amI don't know that so many buffers are a good thing. The signal needs to be restored. Buffer chips can have an asymmetrical drive that changes the duty cycle of the clock. If your pulses are 15 ns wide and you lose a ns on each one they don't need to be buffered very many times before the pulse gets too thin to work well.