3
\$\begingroup\$

I understand Schmitt triggers are a great way to convert a floating or noisy signal to either HIGH or LOW depending on a threshold. It is mentioned in other threads that a Schmitt trigger can help with long SPI signals. In my case, I would like to transport a SPI signal over 1 meter, at a 10 MHz clock rate, with each SPI wire twisted with a ground wire, no differential signal, 33 Ohms terminations, 26 or 28AWG wires and the entire cable of wires shielded and connected to Earth. The SPI device is a BME680 temperature, pressure and humidity sensor.

However, why is a Schmitt trigger helpful for communicating with SPI, since the microprocessor already reads a signal as either HIGH or LOW depending on a threshold value? Or are Schmitt triggers only supposed to be integrated on the SPI device end, in my case, the BME680? If so, which SPI pins benefit from a Schmitt trigger?

\$\endgroup\$
4
  • \$\begingroup\$ Just converting a noisy signal to either high or low is something any old buffer can do. Schmitt triggers do a bit more. \$\endgroup\$
    – Hearth
    Commented May 17 at 21:52
  • \$\begingroup\$ Could you please describe their additional benefits? \$\endgroup\$
    – Tommy95
    Commented May 17 at 22:05
  • \$\begingroup\$ @Tommy95 It is beyond me why you would want to communicate at 10MHz. The sensors response times are in seconds. Wouldn't it be better to run at lower speed? \$\endgroup\$
    – kaosad
    Commented May 19 at 16:32
  • \$\begingroup\$ I wish I could, Kaosad, but at the moment I have a recurring timer interrupt routine occurring every 2 ms, which lasts 1 ms. I take sensor measurements every 2 seconds, so I have 2000 slots of 1ms processor time to collect sensor data but via spi I don’t know how to divide the task over these 2000 slots. Would you please have some insights on this? \$\endgroup\$
    – Tommy95
    Commented May 19 at 22:23

3 Answers 3

7
\$\begingroup\$

SPI is a synchronous bus, which means that the number of clock cycles generated by the controller needs to exactly match the number seen by the device.

Running a 20-MHz square wave over a meter of unbalanced cable can result in all kinds of signal integrity issues arising from random noise, internal reflections and crosstalk. If these effects occur on the rising or falling edge of the clock, the device might interpret them as extra clock cycles and get out of sync with the controller.

A Schmitt trigger is much more resistant to that kind of noise on rising and falling edges than an ordinary buffer. It'll basically reject anything that falls within its hysteresis "window". So the most important place for it is at the device end of the SPI clock signal. You might also use one on the MOSI signal to keep the delays more-or-less equalized.

As a side note, it doesn't seem like there's much point to running a temperature, etc. sensor at such a high clock rate to begin with. With long serial buses, lower speeds are advantageous.

\$\endgroup\$
7
  • \$\begingroup\$ Thanks for your answer, Dave. So, a schmitt trigger could be placed on SCK, MOSI and SS on the BME680 end? And on MISO on the other end? \$\endgroup\$
    – Tommy95
    Commented May 17 at 22:19
  • \$\begingroup\$ The reason for such a high clock rate is that my microprocessor has a recurring routine, and in it, there is only a few microseconds allocatable to fetching temperature, etc. information. \$\endgroup\$
    – Tommy95
    Commented May 17 at 22:21
  • \$\begingroup\$ @Tommy95 I don't think you can clock out all the sensor data in a few microseconds. Even at 10 MHz, you can transfer 10 bits in 1 microsecond. And you need to read several data registers to read all those values, and so reading one result byte takes 1.6us. And you can't have new data very often. For example, BSEC result updates every 3 seconds. \$\endgroup\$
    – Justme
    Commented May 17 at 22:32
  • \$\begingroup\$ I am triggering a measurement only every 2 seconds. I might increase it to 10 seconds. Believe it or not, at 15MHz, with a measurement every two seconds, the BME680 worked reliably over a 30cm cable. I might be able to work with 10MHz though, I edited the post \$\endgroup\$
    – Tommy95
    Commented May 17 at 22:34
  • 5
    \$\begingroup\$ @Tommy95 All micros can handle a decent number of periodic processes, with multitasking (preemptive or otherwise) letting them coexist. And this is literally all micros - even if it's not built into the hardware, using something like FreeRTOS will give you all the normal features you need. There's no reason to shoehorn this into a fast periodic function when you only need it to run every few seconds - just give yourself a 1s periodic task to run it from. And hence there's no reason to run SPI so fast. Classic XY problem. \$\endgroup\$
    – Graham
    Commented May 18 at 17:27
4
\$\begingroup\$

... why is a Schmitt trigger helpful for communicating with SPI, since the microprocessor already reads a signal as either HIGH or LOW depending on a threshold value?

That's the mistake in thinking any signas. The signal isn't just either HIGH or LOW with two digital states with nothing in between.

Every signal is analog and analog takes time to transition from HIGH to LOW state, and from LOW state to HIGH state.

All chips require the transition to happen in short enough time to prevent problems. The signal passing through a long cable will have slower transition times when it comes out of the cable, as the cable is a lossy medium, it has capacitance and resistance, so it limits bandwith of signals.

So even if the receiver input has sharp threshold, the slow signal spends too much time near the threshold, and any noise being addes to the signal may make it cross the threshold multiple times, so instead of one single nice sharp clock edge, a slow edge may be seen as several clock edges and extra clock edges will ruin the SPI transaction.

So as the signal must have quick and sharp transition so it quickly goes far from the threshold so added noise isn't a problem, you can use a Schmitt trigger to receive slow signal edges and it will reshape them into quick strong signal edges for your SPI chip.

How it helps is that there is no single threshold, but two, which are used for hysteresis. The output does not transition high until input has gone high enough to reach the high threshold, and the output does not transition low until input has gone low enough to reach the low threshold. Therefore it does not matter how slowly the signal rises or falls between the two thresholds, or how much added noise there is, as long as it is not large enough to cross both thresholds.

Also it does not make much sense to use 20 MHz SPI bus over 1 meter cable, for many reasons.

The BME680 sensor first of all supports only 10 MHz.

Also most of the changes the sensor detects happen so slowy that maybe reading data once per second is enough.

If you want 1 meter cable, it can more easily be done via I2C.

\$\endgroup\$
6
  • \$\begingroup\$ Thanks Justme. The sensor will be triggered only once every two seconds, but the data exchange time with the device must be just a couple of microseconds since my microprocessor has another recurrent routine. I have tested the BME680 at 15MHz over 30cm and it works reliably, despite the datasheet mentioning 10MHz maximum. I would now like to extend it to 1m. Unfortunately, I2C is not a solution, the microprocessor environment I am using is known to dysfuntion with I2C. \$\endgroup\$
    – Tommy95
    Commented May 17 at 22:32
  • \$\begingroup\$ @Tommy95 But you are making it more complex than it needs to be. You have whole 2 seconds to transfer new batch of data out from chip, so you don't need 20 MHz. And you should not overclock the bus over the 10 MHz maximum, and you don't need to. 1 MHz would be fine to spend the 2 seconds reading data out. Which processor environment with a dysfunctional I2C you are using? I.e. MCU make/model/type? \$\endgroup\$
    – Justme
    Commented May 17 at 22:35
  • \$\begingroup\$ Thanks for your generous use of time on my case, Justme. Imagine I have a routine using a timer interrupt happening every 2000us and which lasts 1000us. Every two seconds, I decide to dedicate the 1000us left to collect this environmental data, and to trigger its next measurement. If you have a better way to do it, please share it, I couldn't find anything better. \$\endgroup\$
    – Tommy95
    Commented May 17 at 22:43
  • \$\begingroup\$ @Tommy95 I don't know enough why your systems works like that and what the timer interrupt spends doing for 1ms and what the main code is doing for 1ms, but you have effectively 2000 slots of 1ms, or 50% of the CPU time free to handle fetching data from sensors, right? \$\endgroup\$
    – Justme
    Commented May 17 at 22:49
  • 1
    \$\begingroup\$ The timer isr should just set a flag or keep a count of ticks like Arduino does. You can then schedule and execute co-operative functions to do your various tasks. Since you don’t tie up the interrupts for extended periods, you can use interrupts for uart, spi, I2C etc as is normally done. Each task runs to completion and must complete within 1ms. Learn about finite state machines to implement code that do this and not lose track of where it was. I2C has bus lockup as a design feature. Implement timeouts to recover as all good I2C implementations should do. \$\endgroup\$
    – Kartman
    Commented May 19 at 3:31
1
\$\begingroup\$

Without knowing the likely impedance of your cabling it's hard to say.

Schmitt triggers will mask the effect of reflections to a degree, so they can help mitigate poorly designed termination, but only so far.

In your case you can measure the signal at the end of your proposed wiring with a fast scope (probably 200MHz scope will give you a good enough idea). Then tune that 33R series termination until the rising and falling edges are clean. You might find you need anywhere between 10R and 100R ... just guessing.

Now if there aren't horrible noise sources you will be able to use any fast enough gate or even just the receiving sensor input pins. If there are noise sources then you will benefit from Schmitt triggers just to avoid the noise causing accidental edges on the CS or CLK signals. The data signals are less likely to be a problem but they are not immune.

Edit: if you are using cat 5e or similar then the cable impedance for a single ended signal then I would guess 50R impedance.

\$\endgroup\$
3
  • \$\begingroup\$ Thanks Robin. In the end I put Schmitt triggers on CLK, SS, MOSI and MISO on both sides, so that's 8 buffers. I used an online calculator for the termination resistor value, for 28AWG, 1 meter, it gave me 100 Ohms. I am wondering if this configuration is correct: "Master" microprocessor SCK pin -> Schmitt trigger -> 100 Ohms termination resistor -> ESD diode -> D-SUB connector pin. Is this the correct placement for the termination resistor? \$\endgroup\$
    – Tommy95
    Commented May 19 at 13:32
  • 1
    \$\begingroup\$ The esd diode should be as close to connector as possible. The series termination should be as close to the driver output pin as possible. So for sck, cs and mosi that's at the driver gates that are next to MCU. For MISO the series termination should be at the device end (again as close to the driver gate output as possible). \$\endgroup\$ Commented May 19 at 18:07
  • 1
    \$\begingroup\$ P.s I would still be tempted to measure it with a scope at the receiving end once you have it built. You should see a clean rising and falling edge. You should set your spi clock to 100Khz or so,.then look for any transitions that happening between clock edges,.these being caused by reflections and thus incorrect termination. \$\endgroup\$ Commented May 19 at 18:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.