Wednesday, September 19, 2012

GPIO Input Circuit

After holidays and many other distractions, I am finally able to get back to work on my Raspberry Pi interface.

Here is the GPIO input circuit that I came up with using an opto-coupler for protection. The opto-coupler that I chose is the LTV-847 (Jameco part number 878286) which provides 4 opto-couplers in a 16-pin DIP format.

Power applied to the anode and cathode will cause the internal LED to emit light.  This is detected by the internal photocell which controls the output.  Because there is no electrical connection between the input and output sides, opto-couplers are handy for connecting between very different voltage levels.  They are also excellent at preventing the introduction of electrical noise into a system.  For this application, the isolation will provide electrical protection to the Raspberry Pi.

The complete circuit for using this is shown below.  The 1KΩ resistor on the input is for limiting the current that can flow through the LED.  The 10KΩ pull-up resistor is internal to the Raspberry  Pi.  Be sure to set the pull-up option when you set the pin to input mode.  Using a separate 5V power supply for the interface provides greater protection than powering this all from the 5V line on the GPIO header.  If that line gets shorted to ground, or even if it just draws too much current, it can cause the Pi to suddenly reboot.

When the input is open, no current will flow through the detector and the Raspberry Pi will see the pin hi due to the pull-up resistor.  When the the input is connected to ground, current will flow and the Pi will see the the pin  as low, since it is effectively connected to ground now.


  1. Could this same schematic be used for detecting +12V inputs instead of 5V ?

  2. Yes. You would just need to use an optocoupler that is rated for 12V.

  3. Hi Ted,

    Well, I've been some days surfing on the net and looking for the best option to connect my RPi GPIO port through an isolated interface. I've found a lot of options, that under my judgement are very bad or poor designs (for example, connecting the RPi ground with your external ground produces a non isolated coupling).
    My doubs are about the 10k pull-up internal resistor you draw. Are you sure about that resistor? Why you don't connect the collector to the GPIO pin to an extrnal resistor to limit the current flowing out the pin?

    1. Yes I am sure. I am not sure what the GPIO devices default to on power up, but when you set them to input, there is the option to configure a pull up or pull down resistor that is internal to the RasPi. You can add another one externally if you like, but that would be in parallel and would change the resistance.

  4. Hi again,
    I'm reading my post and I notice that may be I sound so critical. Of course I'm not critical with your design. Your interface with an optocoupler is one of the bests I've found, but I still have doubts about the optimal design to interface the RPi with the external world.
    I was thinking in to use the optocoupler 4n25, with the cathode to the external ground and the anode to a resistor 470 ohm and the TTL input to this resistor. On the side of the transistor: the emiter to a ground, the collector to a 270 ohm resistor, and this resistor to the 3.3V of the RPi. Then the input of the GPIO to the collector. I'm not sure if we need to connect a pull down resistor between the input and the Rpi ground.
    All the comments are welcome. Of course I'm interested too in your design to interface the serial port. My interest is in connect a serial modem to the Rpi and do an automatic phone call if there are some conditions on the sensors connected to the GPIO.

    Thanks a lot.

    1. I am not an Electrical Engineer, just a hobbyist with a lot of experience. (Thirteen years working as a programmer for a firm that built custom hardware for NASA Langley taught me a lot.) I am open to all feedback, both positive and negative. If you can improve on my design, please do. That is what community collaboration is all about.

  5. Suppose your software accidentally set up gpio pin as output instead of input.
    What happens when you connect your circuit input to the ground ? Won't it take too much current from gpio pin when set to high state ?
    I've just found more info about this problem:

    1. Yes. You can prevent this by placing a 1K ohm resistor in-line with the GPIO pin. That will limit the current.

  6. You example LTV-847 you are dropping the input voltage by 1v? V = IR, So .010*1000 = 1v? What is mA you expect? I am struggling to under stand you input resistance choice. I am sure the issue is my understanding, maybe you would explain where I am in error? I am using a different isolator TLP521-4, but don't understand how close or far apart the LTV-847 and the TLP521-4 are in behavior? Also, not all GPIO pins are pull-ups capable? Or are they all?

  7. I don't know where you get the 1v drop from.
    V=IR so I=V/R V=5 and R=1000 so I=0.005A or 5mA.
    This is done to protect the LED internal to the OptoIsolator.
    If you don't do this, you WILL destroy the LED.
    I found this out very quickly.
    I chose that resistance simply because it is common and I have hundreds of them.

    The datasheet for the TLP521 can be found here:

    It recommends a typical LED forward current of 16mA with a max of 25mA.
    So, R=V/I = 5/0.016 = 312.5ohms. A common resistor value is 330ohms, so that is what I would recommend. Don't go less that 200ohms.
    This is all assuming that you will be using 5V. You will need to adjust if you use 3.3V instead.

  8. Ted, reading the spec sheet for the TLP521 the typical test was noted as 4v with 10mA, that is where I was getting the 1v drop, thinking the original source was 5v and the LTV-847 was similar to the TLP-521 but there are quite different.

    Thanks for the explanation above. Appreciate it. Yes, I to realized fast, I had the resistance off, and toasted one of my TLP521 ICs. The maximum voltage is 5v at source, but the voltage is split, and given the line distance of my circuit (signal travels over several feet via a CAT6 pair), so the typical voltage load will never be above 5v but usually is about 3v. Spending some quality time with a multimeter validated this voltage range.

    So just before optoisolator, R=V/I, 3.3/.016=206 ohms, and I just happen to have a ton of 220 ohms resistors. Thanks again for the assistance.

  9. hai. i want to ask you a bit about gpio because im doing my university project now. if you dont mind, can i have your email address ? or you can email me first, then i will reply my questions to you. i really need help asap and hope you can help me :( thank you.
    email address :

  10. Ted: Just an FYI: When you calculate the resistance used needed for an LED, you need to figure in the voltage drop. The Lite-on version of that chip specifies an LED voltage of 1.2 volts. Since the LED is a constant current device, it exhibits a (roughly) constant voltage drop, so the correct calculations would be for 5V - 1.2V = 3.8, or with 3.3V - 1.2V = 2.1volts. If you are using a 12 volt source, the difference is much less (as a percentage) than if you are using a 3.3 volt source (as you can see). So correcting the value you state above, of 5 ma, it is actually 3.8ma. and the example you give using a 330 ohm give you 11.5ma, not 16. However, opto's in general that are designed for digital interfacing (as opposed to analog values) are designed to be sensitive to a wide input range, in this case, it you only need 1ma to get a minimum of 50ma of current (and possibly as much as 600ma) of output current, so your circuit should work. That figure is a multiplier however, (see Current transfer ratio in the data sheet), so if you have 2 ma, then your minimum current becomes 100ma, and the high end becomes 1200ma assuming the package can handle it. More to the point, the fall time of the signal would be faster, and/or you can use a smaller pullup to make the rise time faster for higher speed. However, at 3.8ma, a long wire could drop your voltage pretty quickly to a marginal state of the threshold of your opto. A 240 ohm resistor would put you right at 16ma (assuming whatever is driving the LED can handle it), and really turn that transistor on, so higher speeds could be achieved.

  11. i want to ask you a bit about gpio because im doing my university project now. if you dont mind, can i have your email address ? or you can email me first, then i will reply my questions to you. i really need help asap and hope you can help me :( thank you.
    email address

  12. Thanks for making this available. Based upon your circuit I made a small PCB for 4 opto-isolated input signals.

    Please see at

  13. i m using GPIO input as pull-up internally , along with it i also connected external pull up configuration using resistor for pushbutton event detection but than also i am get a floating value in inputs , due to which the functions in program gets called without even button press.

    Can someone give a proper solution to solve this issue

    1. Having both internal and external pull-up resistors will reduce the effective pull-up resistance. Two 10K resistors in parallel result in an actual resistance of 5K. This should still be enough to hold the gpio line high, but it would be best if you eliminated one of the pull-ups.

      The other thing to be sure of is that you are executing the function when the gpio line goes low. If you are using interrupts, then execute on the falling edge.

      That is all the help I can give without more information on your circuit and application.

  14. thanks a lot for your precious comment sir. i will remove the external pull configuration and try it again

    i am using the button press event (raising or falling edge detection using callback) .

    1. If you are using rising OR falling edge then realize that you will get two events per button press - one when you press the button and one when you release.

      Actually, if you have not made an effort to debounce the circuit, then you will likely get several events from one button press.

      See this post for more information:

  15. Ted, can you help me?
    I need to connect 2 analog sensors and 1 switching sensor to the raspberry inputs (raspberry will read the signal).
    the analog sensors range from 0 to 24v, while the switching sensor is 0 or 24v.
    I know that I need a/d conversion. But apart from using the MCP3008 a/d converter, what else do I need?
    I know the switching sensor will be ok with the circuit you posted here, because it's only 24v or 0v.
    But what about the analog sensors? The output varies, it may be 15v or 4v at a time. The voltage needs to be lowered but it must keep the range.

    1. The simple solution is to use a voltage divider. Here is a good explanation:

      Use a 4K and a 1K resistor and the 0-24V will become 0-4.8V
      Do this with the analog and the sensing inputs. I would just use the sensing input like is was analog then you don't need an opto-coupler.

      Hope that makes sense.

  16. This comment has been removed by the author.

  17. This comment has been removed by the author.

  18. Apologize in advanced for my ignorance..
    I'm looking to do exactly what you have listed above.
    When looking at the diagram it says INPUT with the resistor. Based on how the Optocoupler digram is rotated from the LTV847 top diagram it shows the input going into the cathode pin.. is that correct?
    If I have a 5v power source.. where does the +(POS) and -(NEG) get connected too?

    1. Anode is positive, cathode is negative. 5V goes to anode (pine 1,3,5, or 7) and the input goes to cathode (2,4,6 or 8)
      Then if the input is connected to ground, current flows and the optical sensor then triggers the internal transistor. This allows a GPIO pin connected as shown to be pulled low.

  19. I’m just Getting back to a project I was working on and had a couple questions to ensure I’m doing this correctly.
    I’m trying to monitor when a 5v voltage comes on and off.
    I have a 5vdc coming into the optocoupler as you show in your design.
    I have the Collector pin connected with a 1k resistor inline to the GPIO port 13
    And the emitter connected back to the Ground on the PI.

    Below is the script I’m attempting to work with this .. I suspect I’m doing something wrong.(or missing something)
    Any thoughts/direction would be great

    import RPi.GPIO as GPIO
    import time

    # Time when Optocoupler on GPIO13 is closed
    closes = []

    # set up the GPIO pins to register the presses and control the LED,
    GPIO.setup(12, GPIO.OUT)
    GPIO.setup(13, GPIO.IN, pull_up_down=GPIO.PUD_UP)

    # turn LED off initially
    GPIO.output(12, False)
    file = open(“closes.txt”,”a+”)
    while True:
    # wait for input to go 'low'
    input_value = GPIO.input(13)
    if not input_value:
    # log start time and light the LED
    start_time = time.time()
    GPIO.output(12, True)
    # wait for input to go high again
    while not input_value:
    input_value = GPIO.input(13)
    # log the time the coupler is closed, and extinguish LED
    end_time = time.time()
    GPIO.output(12, False)

  20. Works great as designed on Raspberry Pi...great job!

  21. Are you still seeing and responding to comments on this post?