3

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

jsotola
  • 2,497
  • 2
  • 12
  • 21
user2878409
  • 111
  • 6
  • 2
    as a matter of interest, what's the point of having a high AND a low side switch? – danmcb Apr 15 '22 at 12:52
  • @danmcb This provides a bit more background info - https://electronics.stackexchange.com/questions/609615/controlling-flip-vane-clock-digits – user2878409 Apr 15 '22 at 12:57
  • 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. – TonyM Apr 15 '22 at 13:03
  • 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. – user2878409 Apr 15 '22 at 13:10
  • 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). – TonyM Apr 15 '22 at 13:42
  • What GPIO expander are you using? Be precise. Assume we'd like to write code for that thing. – Kuba hasn't forgotten Monica Apr 15 '22 at 14:04

2 Answers2

2

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()
  • 1
    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. – user2878409 Apr 15 '22 at 18:10
  • PS. Does C1 have to be an electrolytic capacitor? – user2878409 Apr 15 '22 at 21:38
  • 1
    No, it doesn't have to be electrolytic, but you'll pay way more money for 470uF in tantalums or ceramics, probably. – Kuba hasn't forgotten Monica Apr 16 '22 at 03:12
  • 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? https://www.youtube.com/watch?v=2RvvwcioQHw i.e. the segments change on one digit, then the next digit, etc... ? Thanks. – user2878409 May 12 '22 at 19:13
  • In other words, can anything be modified so that all the coils in a single digit (set/reset) could be turned on at once? – user2878409 May 12 '22 at 21:54
0

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.

Andy aka
  • 434,556
  • 28
  • 351
  • 777
  • Sorry, I did indeed mean Drain. – user2878409 Apr 15 '22 at 12:53
  • 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. – user2878409 Apr 15 '22 at 12:54
  • 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. – Andy aka Apr 15 '22 at 12:59
  • 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. – user2878409 Apr 15 '22 at 13:12
  • Then, I believe, you may have a faulty MOSFET and it has gone short circuit. – Andy aka Apr 15 '22 at 13:20