I am using a microcontroller to multiplex 6x 7-segment displays. Segments are driven by 2N3906’s and displays by a ULN2003. Average segment current is around 9mA, so instantaneous LED current pulses are around 53mA per segment.

My code is currently setup to do the following:

1) Display n is on for 1.9ms

2) When 1.9ms has elapsed, switch off all segments

3) Reset timer

4) Select Display n+1

5) Turn On correct segments for Display n+1

The delay between switching on and off (step 2 & 5) is around 150usec. The code works perfectly fine, but my issue is noise. I’m using an ADC to measure an input voltage and the reference isn’t even close to stable despite filtering and separate grounds due to the massive switching currents. This is compounded by the fact that I am switching the segments completely off, then completely on when switching displays, but this is the only way I have found to prevent bleedover between displays (similarly described in this post: Multiplexing two 7-Segment displays (Ghosting issues)) … if I keep the segments on, then switch displays, there is a bleedover of the previous digit into the next digit. The reverse is true if I switch displays first. The scope traces look somewhat better (significantly fewer spikes) if I don’t switch segments completely off first.

Does anyone have any suggestions on how I might reduce this bleedover in the code without having to completely turn segments on/off?

With regard to the noise, this is currently being done on a breadboard so ground separation isn’t great, but different strips are used for switching and chip/reference power. I’m also considering switching to MOSFETs as opposed to the 2N3906’s to reduce uC port switching currents a bit.


Display Drive Schematic (there are only 2x 2200uF caps total) enter image description here

ADC Reference Schematic, Reference is just TL431A enter image description here

Reference Output with Microcontroller Disconnected enter image description here

Reference Output with Segments Switched On-Off enter image description here

While I didn't post the reference out with segments switched on-off vs on all the time, there actually isn't a significant difference between them. The real difference seems to be that the large spikes are slightly lower in amplitude, but not significant. However it can be clearly seen that the reference out is extremely noisy. The spikes are located at about 310kHz, 2x the DC-DC converter frequency (generating the 5.3V).

Any other tips to improve the noise behavior? Would MOSFETs like BSS84 replacing the 2N3906s help?

  • 1
    \$\begingroup\$ Any schematic available? The tool built-in on the editor toolbar is pretty good and easy to use. \$\endgroup\$
    – Transistor
    Commented Nov 6, 2017 at 17:10
  • 1
    \$\begingroup\$ 150 us seems a bit large for bleedover latency...optimized code should be able to reduce this considerably, provided you're not clocking the microcontroller slowly. \$\endgroup\$
    – glen_geek
    Commented Nov 6, 2017 at 17:53
  • 2
    \$\begingroup\$ How about arranging to do the entire conversion during one of your blanking periods? Most converters in UPs can go at above 10khz so you should be able to do the whole conversion during the blanking interval. Push comes to shove leave everything off for a ms or so at the end of the cycle and do the conversion there. Other then that, layout, decoupling, reference voltage connection points, the usual. \$\endgroup\$
    – Dan Mills
    Commented Nov 6, 2017 at 23:05
  • \$\begingroup\$ @Glen_geek: The 150usec off time is coincidental (this is how long it takes to run the routines called between turn-off and turn-on) but also intentional, in that I wanted these routines there as the longer off time seemed to result in a smoother looking display appearance with less bleed-over. \$\endgroup\$
    – User7251
    Commented Nov 7, 2017 at 23:51
  • \$\begingroup\$ @DanMills: I like that idea ... will have to give it a shot. Right now I'm running the ADC every 25ms, then averaging the values for display after 125ms (no interrupts, just non-blocking). The measured ADC conv time takes 100us, I may be able to put that in there while the displays are turned off \$\endgroup\$
    – User7251
    Commented Nov 7, 2017 at 23:51

2 Answers 2


You can reduce the off time to maybe 1-2 usec most likely, assuming you have push-pull drive of the PNP transistors.

For dealing with noise, make sure the ground of your ULN2003 is separate from the ground reference of the ADC (probably the ground pin of your micro) and make sure the applied voltage is with reference to the latter.

The ULN2003 will switch a peak current of 53*7 = 371mA, which is problematic, especially on a breadboard.

  • \$\begingroup\$ The 150usec off time is coincidental (this is how long it takes to run the routines called between turn-off and turn-on) but also intentional, in that I wanted these routines there as the longer off time seemed to result in a smoother looking display appearance with less bleed-over. Would minimizing this help to minimize the voltage fluctuation on ground? The chip and ULN2003 have different ground strips on breadboard currently, spaced across the board from each other. And yeah, it's a large current, one display uses the decimal point as well so it's even higher than that. \$\endgroup\$
    – User7251
    Commented Nov 7, 2017 at 23:45
  • \$\begingroup\$ 150us between port writes for an AVR is excessive - more like 150ns. If you are using Arduino, then 150us is easily explained, but we’re talking C++ not C. You can simply write to the port register and avoid the long delay. The usual technique for muxing is to use a timer tick and update one digit each tick. For a 1ms tick the whole display is updated many times per second. \$\endgroup\$
    – Kartman
    Commented Aug 11, 2022 at 5:19

The segment current loop must be isolated and separated from the rest of the circuit.

Here's how I'd do it:


simulate this circuit – Schematic created using CircuitLab

The rather fast edges generated by the MCU on its digital outputs are shunted locally by C3 and C4. The loop area traced from VCC pin, to each GPIO pin, through its associated series resistor and 1nF filter capacitor, back to the GND pin, should be kept minimal. Even on a bread board.

The R1 and R2 act as an additional layer of filtering, decreasing the common mode currents flowing between the display and MCU supplies. R3 could be an inductor instead, shunted by anti-parallel Schottky diodes:


simulate this circuit

The breadboard layout is important, although solderless breadboards are not the best for such designs. I'd start with something like the below:

An example layout of the circuit on a solderless breadboard

  • \$\begingroup\$ There is no R1 in the schematic presented, and R2 is the base resistor integrated into the Darlington array: what does it have to do with common mode currents flowing between the display and MCU supplies? \$\endgroup\$
    – greybeard
    Commented Aug 9, 2023 at 14:37

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.