Electronic – Unwanted “memory effect” on a bus with optocouplers

busopto-isolator

I'm working on a microcontroller driver for an equipment which can have up to 64 optically isolated digital inputs. The hardware was designed with an 8-bit bus in mind, so we have up to eight rows of 8 optocouplers arranged like this (TCMD4000 is a quad optocoupler chip with darlington transistor outputs):

Figure 1:

schematic

simulate this circuit – Schematic created using CircuitLab

The idea was to sequentially assert the control lines L1 to L8 low so the bus (bits or columns B1 to B8) can be read as a whole byte. While a Lx line is asserted low all the others should be held high so we guarantee no other opto row will interfere with the bus, for their transistors would theoretically be cut (Vc=Ve or Vc < Ve). That way a logic one on an outside input would turn the corresponding LED on and drive the bit on the bus low for the current selected row, with the bus logic level being inverted again by a 74LV240 between the resistors and the microcontroller (that way a logic "one" on the LEDs side is also perceived as a logic "one" at the microcontroller data port reading from the bus).

To make it easier to follow, consider just 1 bit; it is enough for the problem to show up:

Figure 2:

schematic

simulate this circuit

Using a frequency of 1kHz to change the asserted lines low (L1 to L8) we would reread the state of the same row at 125Hz. Initially I was asserting L1 low, read the row state and right away would assert L1 high again (this takes up only a few usec), so on the next 1kHz timer interrupt L2 would be asserted low and so on, but I was surprised to see that, when either opto on the same column is turned on, the voltage on B1 goes to 0.6V while the LED is on (low level, as expected) but instead of coming back to high (3.3V) it gets stuck forever at 1V when the LED is turned off and a Lx line is driven low (for simplicity I was using just two lines on my tests, L1 and L2). Note I said "forever" because the voltage at B1 never comes back high, even though no LED is ever turned on again, like a flip-flop that changed state (see figure below, where the yellow trace is the voltage at B1 and the green is the L1 line; the waveform underneath is the same but zoomed to show detail of B1 voltage waveform):

Figure 3:
"memory effect" in action: even after the 1st opto goes off, <code>B1</code> keeps at 1V although the 2nd opto was never turned on

Figure 4:
zoomed waveform, to show detail of voltage at <code>B1</code>

The only solution for that bit to go back high is to disconnect one of the involved transistors' collectors from the bus, which then restores the voltage B1 to 3.3V, with a time constant dictated by the 10K resistor, like shown below:

Figure 5:
<code>B1</code> voltage rising up after LED turned off, with only one opto on the column

Note however that while we switch the Lx lines high and low the time constant is many times greater than if L1 line is always held low (~320ms vs. 5ms):

Figure 6: opto response time with LED on and then off, with L1 always low:
opto response time with LED on and then off, with <code>L1</code> always low

That behaviour suggested me that by leaving the Lx lines asserted low until the next line time (1ms instead of the few usec required just for the state read) would give more time for the voltage at B1 to recover, and indeed it worked, with B1 not staying stuck at 1V after the LED was off. Nevertheless, I still don't understand completely these two things:

1 – why when an opto is "disabled" by pulling its emitter high it behaves like "freezing" the voltage at the level it was until the next opto is enabled by pulling its Lx line low (please refer back to figure 5, where it is noticeable this causes the time constant "expansion" if you compare with the case where you never take the Lx line high)

2 – why the "memory effect" happened (B1 staying halfway between low and high everytime L1 or L2 were asserted low, even though there was no more LED turned on anymore)

I hope I could make it a little clearer now! Sorry for the lack of information before, it was really hard to explain without these waveforms.

Best Answer

You don't show what the optos are connected to, but some logic devices (not 74LSxx devices) include "bus-keeper" circuits which behave as weak pull-ups when an input is high, and weak pull-downs when it is low. Such circuitry is often useful, but may cause difficulties when interfacing with logic which doesn't drive very strongly. Still, I would expect that a 10K pull-up should win against a bus keeper.

If the signals from the optos are connected to microcontroller I/O pins, I would suggest that between rows you release all the L1, L2, etc. wires, set the pins to outputs driven "high", then set the pins back to inputs and then drive the proper Lx pin. That approach should let you scan much faster than would otherwise be possible, whether there are bus-keeper circuits or not.

To clarify my later point, pins which are high tend to stay high, and vice versa (due to parasitic capacitance if not bus keepers). The time required for a pin to switch depends how hard it's driven. I would expect that an opto which is "on" would drive a pin low relatively strongly, while a 10K pull-up drives comparatively weakly. If one can disable the optos (e.g. by releasing all the Lx pins high) and use something to unconditionally strongly drive the column pins high (e.g. an I/O port configured as output), it will take almost no time to switch those pins high. If that high drive is then disabled and one Lx pin is driven low, it should be able to quickly switch the appropriate port pin. By contrast, if one simply changed which Lx pin was enabled without precharging the column, it might many many microseconds for the resistor to switch the pin high.

Since you don't have the columns connected to microcontroller I/O pins, you probably don't have a means of pre-charging them. If the only things that can pull the columns high are resistors, the speed at which the columns pull high will be controlled by the resistance. The lower the resistance, the faster the action, but if the resistors are too low the optos won't be able to sink enough current to yield a clean "low". If you want faster action, you could use diodes to connect a port pin to the bus pins such that when the pin is high it pulls all the bus pins high via the diodes.