3
\$\begingroup\$

I've set up high and low side MOSFETs, as shown in the top diagram below (modified from http://gammon.com.au ), which operate from a Raspberry Pi. I'm using a GPIO expander which provides 5V from the pins rather than the usual 3.3V from a GPIO pin.

The circuit worked as expected with one high-side and one low-side connected up to the Pi. However, with another high-side connected, it doesn't work as expected. When one high-side is off and one is on, the Drain of both the high-side MOSFETs incorrectly both provide 12V. When testing in Yenka, this works however (see bottom diagram).

I've checked the circuit thoroughly and swapped components etc. in case of anything being faulty, but still no joy.

Does anyone know what the reason could be?

enter image description here

enter image description here

\$\endgroup\$
6
  • 2
    \$\begingroup\$ as a matter of interest, what's the point of having a high AND a low side switch? \$\endgroup\$
    – danmcb
    Apr 15, 2022 at 12:52
  • \$\begingroup\$ @danmcb This provides a bit more background info - electronics.stackexchange.com/questions/609615/… \$\endgroup\$ Apr 15, 2022 at 12:57
  • \$\begingroup\$ On your real circuit, try connecting a 1K load resistor to GND onto your FET combined drains to draw the leakage current. Then measure the voltage at the drains. It should read zero volts on a DMM. \$\endgroup\$
    – TonyM
    Apr 15, 2022 at 13:03
  • \$\begingroup\$ Thanks - I tried both your suggestions regarding the resistors. The first one unfortunately didn't make a difference. For the second one, the voltage at the drains read 11.3V rather than 0V. \$\endgroup\$ Apr 15, 2022 at 13:10
  • \$\begingroup\$ You're welcome :-) My first suggestion can be ignored now I understand your question properly (drain, not source). The second suggests you've got a circuit fault. Try the 1K on just one FET at a time. If one doesn't measure 0 V with its FET off, measure voltages through the BJT/FET circuit to find the faulty part(s) or connections(s). \$\endgroup\$
    – TonyM
    Apr 15, 2022 at 13:42

2 Answers 2

2
\$\begingroup\$

You have two coils with a common. (+) goes to common then (-) goes to the other end of either coil. There's no singular "load" coil as you show. I won't investigate why the circuit may not work as you don't show any actual circuit diagrams of the assembled circuit, nor any pictures. So I have no idea what exactly did you do. I just assume it's all unnecessary anyway.

To drive the common, you can use a Sziklai pair as a top-side driver. No need for a MOSFET. Nothing wrong with MOSFETs, just that there is enough variety between the types that there's no common circuit that would work with all. Whereas with bipolar transistors, that's not a problem, and most any jellybean part rated at 300mA minimum will work just fine.

Two GPIOs per Segment

A low-side driver like a ULN2003 will do the job for set/reset as suggested in one of the comments to your other question.

The inputs will work fine from 3.3V outputs, so if you only used GPIO expanders to get 5V output - that is unnecessary.

schematic

simulate this circuit – Schematic created using CircuitLab

The circuit above simulates in real time. Click on any of the "⓪"/"①" input states to highlight them, then use Space to toggle them. The current meters will update to show which coil is energized.

To eliminate the high pulse currents, the segments should not be all switched at once. Operate only one segment at a time. The firmware should do as follows:

  1. For each digit:
    1. Enable the digit.
    2. For each segment.
      1. Strobe set or reset for T1.
      2. Wait T2.
    3. Disable the digit.
    4. Wait T3.

Implemented in Python, assuming no GPIO expanders, it'd look something like this:

import RPi.GPIO as GPIO
import time

ms = 0.001
T1 = 100*ms  # set/reset strobe
T2 = 10*ms   # inter-segment delay
T3 = 10*ms   # inter-digit delay

PIN_DIGIT = [1,2,3,4]
PIN_SEGMENT_SET = [5,6,7,8,9,10,11]
PIN_SEGMENT_RESET = [12,13,14,15,16,17,18]

FONT = {
 ' ': [0, 0, 0, 0, 0, 0, 0],
 '0': [1, 1, 1, 1, 1, 1, 0],
 '1': [0, 1, 1, 0, 0, 0, 0],
 '2': [1, 1, 0, 1, 1, 0, 1],
 '3': [1, 1, 1, 1, 0, 0, 1]
 # ...
}

def display_init():
  GPIO.setmode(GPIO.BOARD)
  for p in PIN_DIGIT + PIN_SEGMENT_SET + PIN_SEGMENT_RESET:
    GPIO.output(p, False)
    GPIO.setup(p, GPIO.OUT)

def display_update(text: str=""):
  N_digits = len(PIN_DIGIT)
  text = text.ljust(N_digits)

  for p_digit, char in zip(PIN_DIGIT, text):
    GPIO.output(p_digit, True)
    glyph = FONT.get(char, FONT[' '])
    for seg, p_set, p_reset in zip(glyph, PIN_SEGMENT_SET, PIN_SEGMENT_RESET):
      GPIO.output(seg and p_set or p_reset, True)
      time.sleep(T1)
      GPIO.output(p_set, False)
      GPIO.output(p_reset, False)
      time.sleep(T2)
    GPIO.output(p_digit, False)
    time.sleep(T3)

def display_shutdown():
  for p in PIN_DIGIT + PIN_SEGMENT_SET + PIN_SEGMENT_RESET:
    GPIO.setup(p, GPIO.IN)
  GPIO.cleanup()

if __name__=="__main__":
  display_init()
  display_update("4242")
  display_shutdown()

The GPIO expander will require modifications to pin access, but the general code flow would remain.

One GPIO per Segment

To save on GPIO pins, you can use a tri-state driver circuit, so that when the GPIO pin is switched to an input, neither SET nor RESET coils are driven.

You'll need only 4+7=11 GPIO outputs for the entire display that way. Given that transistors and resistors cost nothing compared to GPIO expanders, and GPIO expanders may be out of stock, the discrete driver is not the worst thing in the world :)

schematic

simulate this circuit

The circuit above simulates in real time. Click on any of the "⓪"/"①" input states to highlight them, then use Space to toggle them. Click on the switch SW1 to select it, then use space to toggle the GPIO direction. The current meters will update to show which coil is energized.

The firmware would then act as follows:

  1. For each digit:
    1. Enable the digit.
    2. For each segment.
      1. Set segment pin to output. Drive HI or LO as per segment status.
      2. Wait T1.
      3. Set segment pin to input to disable the segment driver.
      4. Wait T2.
    3. Disable the digit.
    4. Wait T3.

Implemented in Python, it'd look something like this:

import RPi.GPIO as GPIO
import time

ms = 0.001
T1 = 100*ms  # set/reset strobe
T2 = 10*ms   # inter-segment delay
T3 = 10*ms   # inter-digit delay

PIN_DIGIT = [1,2,3,4]
PIN_SEGMENT = [5,6,7,8,9,10,11]

FONT = {
 ' ': [0, 0, 0, 0, 0, 0, 0],
 '0': [1, 1, 1, 1, 1, 1, 0],
 '1': [0, 1, 1, 0, 0, 0, 0],
 '2': [1, 1, 0, 1, 1, 0, 1],
 '3': [1, 1, 1, 1, 0, 0, 1]
 # ...
}

def display_init():
  GPIO.setmode(GPIO.BOARD)
  for p in PIN_DIGIT:
    GPIO.output(p, False)
    GPIO.setup(p, GPIO.OUT)
  for p in PIN_SEGMENT:
    GPIO.setup(p, GPIO.IN)

def display_update(text: str=""):
  N_digits = len(PIN_DIGIT)
  text = text.ljust(N_digits)

  for p_digit, char in zip(PIN_DIGIT, text):
    GPIO.output(p_digit, True)
    glyph = FONT.get(char, FONT[' '])
    for seg, p_seg in zip(glyph, PIN_SEGMENT):
      GPIO.setup(p_seg, GPIO.OUT)
      GPIO.output(p_seg, seg)
      time.sleep(T1)
      GPIO.setup(p_seg, GPIO.IN)
      time.sleep(T2)
    GPIO.output(p_digit, False)
    time.sleep(T3)

def display_shutdown():
  for p in PIN_DIGIT:
    GPIO.setup(p, GPIO.IN)
  GPIO.cleanup()

if __name__=="__main__":
  display_init()
  display_update("4242")
  display_shutdown()
\$\endgroup\$
5
  • 1
    \$\begingroup\$ Thanks for this which I'll look into further - very useful. I should've said in my original question that the coils run on 12V. My "-12V" reference should've really read "gnd". I was a bit confused by some of the other suggestions people made but the MOSFET one made most sense to me, so I pursued it. However your clear diagram and code makes sense! The expander uses the MCP23017 port expander. Thanks again. \$\endgroup\$ Apr 15, 2022 at 18:10
  • \$\begingroup\$ PS. Does C1 have to be an electrolytic capacitor? \$\endgroup\$ Apr 15, 2022 at 21:38
  • 1
    \$\begingroup\$ No, it doesn't have to be electrolytic, but you'll pay way more money for 470uF in tantalums or ceramics, probably. \$\endgroup\$ Apr 16, 2022 at 3:12
  • \$\begingroup\$ I'm pleased to say I managed to get this working and wired up! Looking at the code, I was wondering - is there a way to modify it so the clock behaves like the one in this video when the digits change? youtube.com/watch?v=2RvvwcioQHw i.e. the segments change on one digit, then the next digit, etc... ? Thanks. \$\endgroup\$ May 12, 2022 at 19:13
  • \$\begingroup\$ In other words, can anything be modified so that all the coils in a single digit (set/reset) could be turned on at once? \$\endgroup\$ May 12, 2022 at 21:54
0
\$\begingroup\$

You said this: -

When one high-side's off and on's on, the Source of both the high-side MOSFETs incorrectly both provide 12V.

And it doesn't make sense because the sources are always connected to 12 volts. I think you may have meant to say "drain" instead: -

When one high-side's off and on's on, the DRAIN of both the high-side MOSFETs incorrectly both provide 12V.

If this is indeed what you meant then, if the low-side MOSFET is deactivated, the electromagnet load on the activated high-side MOSFET will pass 12 volts through to the drain of the deactivated low-side MOSFET and then, the 2nd electromagnet load will pass that 12 volts through to the other high-side MOSFET.

\$\endgroup\$
5
  • \$\begingroup\$ Sorry, I did indeed mean Drain. \$\endgroup\$ Apr 15, 2022 at 12:53
  • \$\begingroup\$ I initially tested the circuit with the electromagnet loads attached, but then removed them and just monitored the Drain voltages with a multimeter - and the same happened. \$\endgroup\$ Apr 15, 2022 at 12:54
  • \$\begingroup\$ An unloaded MOSFET drain will have leakage current to its source that makes it look like it is at the same voltage as its source. If you measured with a multimeter (10 Mohm input impedance) it will still probably indicate about 12 volts. \$\endgroup\$
    – Andy aka
    Apr 15, 2022 at 12:59
  • \$\begingroup\$ Thanks for your suggestions. In your original answer, is there any way this could be avoided? I note you say about that happening when the low-side MOSFET is deactivated, but I've kept the low-side one activated and still have the issue. \$\endgroup\$ Apr 15, 2022 at 13:12
  • \$\begingroup\$ Then, I believe, you may have a faulty MOSFET and it has gone short circuit. \$\endgroup\$
    – Andy aka
    Apr 15, 2022 at 13:20

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.