Raspberry Pi – Driving a Relay using GPIO

There’s something exciting about crossing the boundary between the abstract world of software and the physical ‘real world’, and a relay driven from a GPIO pin seemed like a good example of this. Although a simple project, I still learned some new things about the Raspberry Pi while doing it.

There are only four components required, and the cost for these is around 70p, so it would be a good candidate for a classroom exercise. Even a cheap relay like the Omron G5LA-1 5DC can switch loads of 10A at 240V.

A word of caution: don’t tinker with mains voltages unless you’re really (really) sure about what you’re doing. A mechanical relay allows a safe learning environment, since you can switch any load with it (e.g. a 9V DC battery/bulb circuit for testing), and the concept of a mechanical switch is very easy to grasp. A more efficient alternative to switch an AC load would be to use a solid-state relay (e.g. opto-coupled Triac), but it’s quite easy to make a wrong assumption and blow everything up with a loud bang and a big spark. I recommend sticking with mechanical relays until you’re entirely sure about what you’re doing. Tip: you can buy plug-in low-voltage AC power-supplies if you want to play with triacs.

The Circuit

There are four components to this circuit. A relay (5V DC coil), a BC337 NPN transistor, a diode, and 1K resistor. Essentially, the transistor is used to energise the relay’s coil with the required voltage and current.

A relay will often have 3 significant voltage/current ratings specified; coil, AC load, and DC load. The most important to our circuit is the coil rating, which is the current at a specified voltage required to energise the coil (activate the switch), sometimes expressed as milliwatts (mW).

The AC and DC load ratings relate to the switch-contacts, and state the maximum load current (e.g. for your lamp, motor, etc.) that can be carried at the given AC and DC voltages. DC loads are rated lower because they arc (spark) more, which eventually wears the contacts to the point of failure. In general, large loads need heavier contacts, which in turn need bigger coils to switch them, and bigger coils need more power from your circuit.

Relays sometimes don’t fit easily onto a breadboard, so you might want to build the circuit on veroboard instead, or just mount the relay on veroboard and add two pins for the coil contacts (allowing you to breadboard it). Don’t ever put AC mains into your breadboard!

Schematic for a relay via GPIO on the Raspberry Pi

 

The GPIO pin used in the example code is GPIO_17, which appears on pin 11 of the Raspberry Pi’s 26-pin expansion header (opposite GPIO_18 (PCM_CLK) and beside GPIO_21 (PCM_DOUT)). The choice of GPIO 17 was simply because I considered it less likely to conflict with other peripherals likely to be in use.

Although the pin is marked 3.3V on the schematic, don’t confuse this with the 3V3 pin – I labelled it with the voltage to highlight that a 3.3V GPIO pin is driving a 5V load – it could also drive a 24V coil, for example, if an appropriate DC power supply is used rather than the Raspi’s 5V line.

Essentially, to activate the relay, all the circuit does is send a few milliamps at 3.3V from the GPIO pin, through a 1K resistor (you may choose to increase this to 1.2K if you want to be strictly below 3mA). This current is enough to saturate the BC337 transistor, causing current to flow on the 5V rail through the transistor, and therefore also through the relay’s coil.

Most general purpose NPN transistors with an minimum hFE of say 50 to 100 could be used in place of the BC337 – it will depend on a) how much current you’re willing to draw from the GPIO pin, b) how much current is required to energise the relay’s coil, c) the actual hFE of the transistor in your hand, since they vary wildly and the current gain could easily be significantly more than the stated minimum.

The diode in the circuit is there to conduct the current generated by the de-energising coil back across the coil (e.g. when switched off), allowing the power to dissipate more gradually, avoiding a voltage spike.

Take care to orient the diode correctly, or you’ll short 5V to ground via the transistor when the GPIO is high. Similarly, take care to correctly identify the collector, base, and emitter pins on your transistor. The pin ordering varies by type, so check the datasheet. I’d recommend you double check these two components before powering up.

The breadboard photo shows it wired up. The pin numbering on my IDC plug should be though of from above the connector, to make it correspond with the 26-pin header numbering. Blue is 5V, and brown is Ground. The green wire connects from GPIO 17 (pin 11 on the Raspi’s 26-pin header) to the transistor base via resistor R1.

You can test that the relay is working by disconnecting the wire from GPIO 17 (pin 11 of the 26-pin header) and touching it to 3V3 (pin 1). You should hear a click as you connect/disconnect 3V3. Make sure you keep the resistor in the circuit (e.g. don’t just take a wire from 3V3 to the transistor’s base pin).

Note that the circuit assumes the GPIO pin will be configured as an output. If it’s likely to also spend some time as an input, then a resistor (10K would do) between the base and ground would ensure the transistor is fully off, rather than having a floating voltage applied.

Using the relay via the ‘/sys’ filesystem

Enable GPIO 17 access via the Kernel on path ‘/sys/class/gpio/’, and configure it as an output pin: -

echo "17" > /sys/class/gpio/export
echo "out" > /sys/class/gpio/gpio17/direction

View the current state of GPIO 17: -

cat /sys/class/gpio/gpio17/value

Set the state of GPIO 17 by writing “1″ for high (relay on) and “0″ for low (relay off): -

echo "1" > /sys/class/gpio/gpio17/value
echo "0" > /sys/class/gpio/gpio17/value

Finally, to use the C code instead, remove the pin from the control of the Kernel driver: -

echo "17" > /sys/class/gpio/unexport

The C Code Alternative

The C source code below shows how to drive the relay using the GPIO peripheral’s hardware registers. It’s all in one file for simplicity and for clarity, though there’s not much to it.

The usleep(1) call has been used to create a short delay before reading the LEVn register to feed back the pin status. This is because the rise time for a GPIO pin (the time for the voltage on the pin to rise to a level that’s considered ‘high’) is around 100ns to 3V. The ‘high’ threshold is probably less than half that, but even if it’s 30ns, that’s 21 ARM clock cycles at 700MHz, and is enough time to read the LEVn register before it has transitioned.

/*
  * gpio_relay.c - example of driving a relay using the GPIO peripheral on a BCM2835 (Raspberry Pi)
  *
  * Copyright 2012 Kevin Sangeelee.
  * Released as GPLv2, see <http://www.gnu.org/licenses/>
  *
  * This is intended as an example of using Raspberry Pi hardware registers to drive a relay using GPIO. Use at your own
   * risk or not at all. As far as possible, I've omitted anything that doesn't relate to the Raspi registers. There are more
  * conventional ways of doing this using kernel drivers.
  */
#include <stdio.h>
#include <fcntl.h>
#include <sys/mman.h>

#define IOBASE   0x20000000

#define GPIO_BASE (IOBASE + 0x200000)

#define GPFSEL0    *(gpio.addr + 0)
#define GPFSEL1    *(gpio.addr + 1)
#define GPFSEL2    *(gpio.addr + 2)
#define GPFSEL3    *(gpio.addr + 3)
#define GPFSEL4    *(gpio.addr + 4)
#define GPFSEL5    *(gpio.addr + 5)
// Reserved @ word offset 6
#define GPSET0    *(gpio.addr + 7)
#define GPSET1    *(gpio.addr + 8)
// Reserved @ word offset 9
#define GPCLR0    *(gpio.addr + 10)
#define GPCLR1    *(gpio.addr + 11)
// Reserved @ word offset 12
#define GPLEV0    *(gpio.addr + 13)
#define GPLEV1    *(gpio.addr + 14)

#define BIT_17 (1 << 17)

#define PAGESIZE 4096
#define BLOCK_SIZE 4096

struct bcm2835_peripheral {
    unsigned long addr_p;
    int mem_fd;
    void *map;
    volatile unsigned int *addr;
};

struct bcm2835_peripheral gpio = {GPIO_BASE};

// Some forward declarations...
int map_peripheral(struct bcm2835_peripheral *p);
void unmap_peripheral(struct bcm2835_peripheral *p);

int gpio_state = -1;

////////////////
//  main()
////////////////
int main(int argc, char *argv[]) {

    if(argc == 2) {
        if(!strcmp(argv[1], "on"))
            gpio_state = 1;
        if(!strcmp(argv[1], "off"))
            gpio_state = 0;
    }

    if(map_peripheral(&gpio) == -1) {
        printf("Failed to map the physical GPIO registers into the virtual memory space.\n");
        return -1;
    }

    /* Set GPIO 17 as an output pin */
    GPFSEL1 &= ~(7 << 21); // Mask out bits 23-21 of GPFSEL1 (i.e. force to zero)
    GPFSEL1 |= (1 << 21);  // Set bits 23-21 of GPFSEL1 to binary '001'

    if(gpio_state == 0)
        GPCLR0 = BIT_17;
    else if(gpio_state == 1)
        GPSET0 = BIT_17;

    usleep(1);    // Delay to allow any change in state to be reflected in the LEVn, register bit.

    printf("GPIO 17 is %s\n", (GPLEV0 & BIT_17) ? "high" : "low");

    unmap_peripheral(&gpio);

    // Done!
}

// Exposes the physical address defined in the passed structure using mmap on /dev/mem
int map_peripheral(struct bcm2835_peripheral *p)
{
   // Open /dev/mem
   if ((p->mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) {
      printf("Failed to open /dev/mem, try checking permissions.\n");
      return -1;
   }

   p->map = mmap(
      NULL,
      BLOCK_SIZE,
      PROT_READ|PROT_WRITE,
      MAP_SHARED,
      p->mem_fd,  // File descriptor to physical memory virtual file '/dev/mem'
      p->addr_p      // Address in physical map that we want this memory block to expose
   );

   if (p->map == MAP_FAILED) {
        perror("mmap");
        return -1;
   }

   p->addr = (volatile unsigned int *)p->map;

   return 0;
}

void unmap_peripheral(struct bcm2835_peripheral *p) {

    munmap(p->map, BLOCK_SIZE);
    close(p->mem_fd);
}

The code can be compiled and run with

root@pi:~# gcc -o gpio_relay gpio_relay.c
root@pi:~# ./gpio_relay on
GPIO 17 is high
root@pi:~# ./gpio_relay off
GPIO 17 is low

Note: there was an error in the original example code, where it was initialising GPFSEL0 rather than GPFSEL1. If the pin fails to go high, maybe you’ve got the original code.

References

114 thoughts on “Raspberry Pi – Driving a Relay using GPIO

  1. Great post. Knocked one of these up last night – works a treat. I was impatient and only had Maplin to hand so I used N18AW relay, a cheap diode, a cheap 1.2Kohm resistor and a 2N3904 transistor. Was just over £3 in total. All mounted on some stripboard.

    Plan to make a Raspi controlled beer o’clock alarm for the office :D

      1. As a complete beginner on the Pi , I have looked at this as a way of controlling the remote for a radio controlled car. I would need to use four relays : forward, back, turn right and turn left. Will I have a problem if I create four circuits like yours given that I will need to switch two relays on at the same time? Will this drain too much current form the Pi?

        1. No, not from the Pi, since current from the Pi is only used to drive the transistors. It may, however, drain too much current from the Pi’s power supply, and that depends on how much spare power your supply can deliver.

          Regardless, you might consider using reed-relays for this instead – they’re typically much lighter, with contacts designed for low currents, and therefore require less power to switch.

    1. The diode happened to be a 1N4004, but most diodes would do (voltage and current conducted aren’t high when a 5V coil’s field collapses). I just used what was handy at the time.

  2. Loved this post, I am making a build notification tool (lava lamp & buzzer alertion system ;)

    The parts I used to build this, I got from Maplin:

    QR40T – 2N3904 transistor
    RP68Y – 6V 10A PCB Relay
    QL76H – 1N4004S diode
    M1K2 – 1K2 Metal Film 0.6W Resistor

    Hope this helps anyone else :)

  3. Relay modules for Arduino coat about $1 per relay on eBay, they look like they will do the job. You can get from 1 to 16 relays. Google for “Relay Module Switch Board For Arduino”

    Mike

    1. Thanks Mike – yes, it’s worth pointing out that if you just need relay control and aren’t interested in learning how to do the electronics stuff yourself, then there are numerous cheap options available – in fact, any board that accepts 3.3V as a ‘high’ signal will work directly with the Raspberry Pi’s GPIO outputs. The power requirement of the relay coils would need to be known, and a separate power source provided if they exceed, in total, the power available from the Pi.

    2. Every “Relay Module Switch Board For Arduino” I am able to find on ebay says “5v”. But the output from rpi GPIO digital output port is only 3.3V, right? Is it enough to activate/control the relay?

      1. I expect that the board’s input pin will accept 3.3V as ‘high/on’. The relay itself will most probably still need a 5V supply, the Raspberry Pi should be able to provide this if your 5V supply can deliver the 100mA or so that a relay might draw.

        1. Thank you very much Kevin.

          So far I have found:
          [5V-2-Channel-Relay-Module-Board-Shield-With-optocoup-For-Arduino-PIC-MCU]
          I read that every relay need 15-20mA driver current at 5V.
          Thus the real limit on the number of relays to be activated at the same time is that the total current is less or equal the current that the rpi is able to output at 5V.
          Do you know how much is it?

          Latching relays like this one:
          http://www.ebay.co.uk/itm/Latching-Bistable-Relay-Board-5V-AVR-PIC-Arduino-from-EU-/180912202423?pt=LH_DefaultDomain_0&hash=item2a1f3522b7
          apart from the higher price, can be used with a rpi aswell?

          Thank you! This post is bookmarked and will be so useful for me.
          Michele

          1. Hi, the relay on the board you mentioned on eBay has a nominal coil current of 70mA (see http://www.songle.com/en/pdf/20084141716341001.pdf), two of which could draw twice that. In fact, there is usually a surge of current, and then the holding current is a bit lower, but nowhere as low as ~10mA per relay. I removed the link to avoid anyone else being misled.

            That said, it would still work fine with the Raspberry Pi – there are countless 5V relay boards available on eBay etc, but I’d recommend you find a seller who at least knows what they’re selling.

            A latching relay is a good way to minimise power consumption – the one you linked to should work with the Raspberry Pi, it may even be possible to drive S and R directly from 3V3 the GPIO, but you’d need to check the docs to be sure.

  4. Hi!
    Nice word…
    Just a quick question…
    Is there a way to check the status of the gpio line using C language?
    I’m a total noob in C (but a great programmer in Delphi/Lazarus :P)

  5. I’m wondering if all this will work with a darlington array, such as uln2803 (which is basically the same thing, in an IC)

    it’s a bit of a risk to see if the uln2803 will work at 3.3V though.. we’ll see :P

    1. I’ve not used that chip, but a darlington array should be ok, and would reduce the current requirement from the GPIO pins. Regardless, they can provide enough current to drive most general purpose transistors for switching relay coils.

        1. Good news. As you’ll be aware, you can drive motors and coils directly from the IC, without even the need of a relay, but bear in mind that a line-driver will only switch DC loads.

          1. yes, I’m planning to use the relays on home appliances and lighting (AC, obviously), so they are necessary. DC stuff (LEDs, motors, etc) already work nicely, and at whatever voltage i choose to input to the IC

  6. Hi Kevin
    I am attempting to use my Pi and this circuit to switch a garage door opener (GDO) with a 30V DC coil relay. The GDO provides a Common (ground) and Relay (30V) connectors which when connected trigger the AC motor to open the door. When I connect this/your circuit but provide 30V from the Relay (instead of 5V from the Pi) it does not want to work. I have also tried a test of a 12V and no luck. I have been using a SY-4080 SS Relay as a test relay (before connecting to the GDO) as it accepts 3V-32VDC – but will only trigger when I supply 5V.
    Your advise please.

    Richard.

    1. Hi Richard,

      I don’t want to give advice on switching mains level voltages, but in terms of energising a DC coil as per the post, you need to ensure that your transistor can switch the load required of the coil (given either as ohms, mW, or mA – convert between them using Ohm’s Law). Also, the C-E voltage rating must be greater than the requirement of your coil.

      Also, your DC power-supply grounds must be connected. If you have a 40V DC supply to energise a 30V DC coil, then the ground of this supply would need to be connected to the ground of the Raspberry Pi’s supply.

      However, I suspect that you’ve confused the contact rating (the switch) with the coil rating (the bit that flicks the switch) – a 30V DC coil would be very unusual, whereas 30V DC contact rating would be very common. A mistake or misunderstanding on this, when using mains AC voltage, could easily kill your Raspberry Pi (and quite possibly even yourself).

      I’d recommend you find a 12V DC power-supply, buy a relay with a 12V coil, and make that audibly click before moving on to anything else (and certainly before trying to control any domestic mains circuits).

      1. Hi Kevin

        Thanks for your reply. Yes, I would think that I am trying to connect to (switch on) a 30V DC ‘contact’ as it is currently activating the relay/switch (inside the GDO) when the common and relay are briefly touched. I measured the voltage and current across the contacts (using a multimeter) and is it reads 30VDC and draws 76mA.

        I now believe I need a mechanical relay that has a 5V coil (powered from the Pi and energized with the BC337 NPN transistor) that will allow me to switch this 30V DC contact load briefly (via GPIO on/off commands from my Pi program).

        Rest assured I am going no where near any AC mains level voltages. All that is contained inside the GDO.

        Thanks for your help. I am learning lots … but feel free to comment if I still don’t seem to get it. :-) Your site is very enlightening.

        Richard.

        1. If I understand correctly, connecting ‘relay’ (R) and ‘common’ (C) results in an internal relay energising. The voltage across R->C is 30V, and the current through R->C is 76mA. If so, then connecting R to the transistor’s collector, C to the emitter and to the Raspberry Pi’s Ground should be enough to drive the internal relay coil.

          I’d try it first without the Raspberry Pi – just find a 3V3 or 5V supply, connect a resistor to the transistor’s base and then connect the other leg of the resistor alternately between +ve and ground of your supply. Don’t forget to join your ‘common’ and ground too. You’re essentially doing what the GPIO pin does when it goes high and low, so if it works, then it should work fine with the Pi.

          1. Hi Kevin

            Yes, it is working now using the Pi and the (R) and (C) connections as you advised. Thanks for your help. Regards Richard.

  7. Hi Kevin

    Yes, that is my way forward. Away on a ski holiday at present so apologies for the delayed reply. Will let you know how I get on in a week or so.

    Richard

  8. Hi,
    I’m a total noob, sorry if this is a stupid question, but:
    why is the transistor required? Can’t you just switch a (3V) relay with the 3.3V output from the GPIO pin?

    1. It’s a perfectly reasonable question – the answer is that you can drive directly from a GPIO pin if you can find a relay that will energise with the current that the GPIO pins can supply (e.g. a lot less than 25mA). Most small relays require between 50mA to 150mA to energise.

      The transistor conducts a relatively large current when a relatively small current is applied to the base pin – small enough to be driven by a GPIO pin on the Raspberry Pi, which is why the transistor is required.

      You might find a reed-relay that can energise with a low enough current, but then the contact rating will be much lower.

  9. Great outline, thank you. Can you explain or (give some overview?) how one would customize this for each GPIOx. As best I can tell there can be 17 to 21+ GPIO’s available in the new 2.0 512M boards.

    1. More of the same really. For the C code, it’s just a matter of setting the appropriate GPFSELn bits to ’001′ (so the corresponding pin functions as an output), and using GPSETn and GPCLRn bits to set and clear the bits that relate to the pins you want to control.

      The Bash approach makes it even more obvious – just replace 17 with the GPIO that you want to control. As long as you know which physical pin on the Pi is connected to the GPIO you’re using, then you should be able to control it. You might try connecting the transistor to a different pin, then you’ll understand what’s required.

      1. Thanks for this post Kevin ( most detailed one I saw on this topic anywhere online). I plan to try out switching a simple led with a 5v relay before moving on to switching on AC circuits at home, over the next couple of weeks.
        Can all the pins on the RPi be used – 17-21 like David says above? Most forums seem to indicate that only 5 odd are GPIO pins, others are I2C, PWM and other types ( I have yet to understand what these are).
        In short, it would be awesome if you can post a detailed tutorial like this one on driving a 16 channel 5V 10A relays using the RPi – something like http://www.youtube.com/watch?v=8X6PgYaegz0 .

        1. Hi Vinod, most of the pins on the P1 header can be used for GPIO (some on other headers can be used too). The GPIO function select registers determine what peripherals (I2C, SPI, PWM, etc.) are is connected to (is active on) a pin. For our application, we configure the required pin as a GPIO Output. I believe that the default state for any pin, other than the UART, is GPIO Input. Certain kernel drivers will reconfigure pins if loaded, and if so you might need to prevent them loading (e.g. blacklist them).

          As a starting point, read the datasheet to understand how the function-select bits work for each pin. The I2C and SPI peripherals are just for serial communications, PWM (Pulse Width Modulation) peripherals generate high/low pulses of a specified width, and at a specified frequency – commonly used to generate a variable average voltage or to drive servos.

          A 16 channel driver is really just more of the same as what’s here (and written elsewhere), so it’s more of an ‘exercise for the reader’ ;-) Between the datasheet, the schematic and the code, all the information you need is there to extend this. An enhancement might be a darlington array chip to provide multiple high-gain transistors in a single package – neater than 16 x 3-pin transistors. The power supply would, of course, need to be capable of energising 16 relays simultaneously, unless you take steps in software to stagger them.

          1. Thanks for the detailed reply Kevin – was most useful, and helped me be a little more confident as I wired up a led today ( without worrying about using/messing up a wrong pin).
            I got the led on/off via GPIO working today, and thanks to webiopi, through a web interface – in about 30 minutes flat.
            Wrote about it at http://saranga2000.wordpress.com/2012/12/07/raspberry-pi-hello-gpio/
            - only as a thankyou to all the Giants (including you) on whose shoulders I stood today.

  10. With respect to the C code above would it be possible to alter the code to take a variable input into the command line, for example so that is might work like ./gpio_relay 17 on ie ./gpio_relay x on where x is the particular pin being controlled?

    1. Hi David, yes it’s easy to get at parameters from the command line – define main with ‘int argc’ and ‘char *argv[]‘ parameters (for reference, the RTC post has source-code that uses these), which contain the ‘count’ and ‘values’ of parameters respectively. You can use the printf() function to display the parameters if you want to experiment a bit.

  11. Hi Kevin, Ive been trying to get a circuit like above ( controlling a relay with the GPIO) to work. I wired up the exact same circuit but with different parts ( using what I had with me). I used
    1. BC547B transistor
    2. 1N4007 diode
    3. a local relay I got in a kit – that seems to indicate its a 6v relay ( pic attached).

    Circuit and Relay spec pics are here:
    http://kannvin.freeshell.net/wiki/doku.php?id=personal:journal:2012-12-12-144621

    I don’t get the clicking sound with the base connected through a 1K ohm resistor to the 3.3V pin.

    I did some debugging and saw that:
    1. I am able to light up a LED through the same circuit, removing the diode, and passing the 5v through a 470ohm resistor through led
    2. the relay itself is working – i get a clicking sound if I connect the 5v pin and ground directly to the leads of the relay.

    What am I doing wrong – the only thing I can think of is the BC547B is not able to power up sufficiently to turn on the 6V relay. Is this it? Or am I doing something else wrong? If former, what should I do different to drive the relay.
    Please help.

    1. You can try using a lower value resistor to the base, to make sure that the transistor is reaching saturation – you could use your 470R instead. You might also try a another transistor, since the actual gain varies wildly, even among transistors of the same type.

      Note your link returns ‘permission denied’.

    1. There’s a symmetry in an NPN transistor, but not a perfect symmetry. So it will work similarly when connected in reverse like you did, just not so well (hence a small current flows, enough to drive an LED but not enough to drive a relay). A higher current through the base may actually drive it to saturation. To understand more you need to read about doping of diodes, and consider that a bipolar transistor is made from two diodes – there are plenty of sources on the net that will explain the details better than I could.

      Glad you figured it out.

  12. Thanks for posting this! Great place to start for a noob like me. Can you please explain the purpose of the diode in this configuration? Would the diode still be required if a darlington array were used?

    Cheers!

    1. This is nicely explained in the “Tutorial on Relays” (linked in the References) – “Current flowing through a relay coil creates a magnetic field which collapses suddenly when the current is switched off. The sudden collapse of the magnetic field induces a brief high voltage across the relay coil which is very likely to damage transistors and ICs. The protection diode allows the induced voltage to drive a brief current through the coil (and diode) so the magnetic field dies away quickly rather than instantly. This prevents the induced voltage becoming high enough to cause damage to transistors and ICs.”

      It’s still required for a darlington pair, because there’s still a transistor driving the relay’s coil.

  13. Hi,

    Some very useful information in here which is appreciated.
    It doesn’t however quite answer a problem I have. I have a manual shutter release which I made for my Canon 1000D camera. Plenty of examples on the net on how to do this. What I want to do now is use my Pi to trigger the camera rather than a manual button.
    I’m sure this should be straight forward but i’m worried about power. The current manual system doesn’t provide any power to the camera, if I hook up a transistor in place of the manual switch and set gpio pin ‘x’ to high would i be sending power through the transistor to the camera? Hope that makes sense !
    Thank you.

    1. When the GPIO is high, current would flow from the GPIO pin through the transistor base-emitter to ground. If saturated, then the collector is effectively connected to ground, and the current will flow from some point in the camera (e.g. via your manual switch) to ground. So you’re not feeding the camera from the Raspberry Pi (though their grounds will need to be connected).

      You should be able to automate this with either an NPN or a PNP transistor, depending on whether the camera’s input is normally high and pulled low to activate (NPN) or normally low and pulled high to activate (PNP). You’d really need to figure this out based on what you can learn about your camera.

      Alternatively, if the manual shutter release is simply a momentary push-button, then perhaps a relay might be more an equivalent solution. You could substitute (or augment) the existing switch without needing to concern yourself about the switch circuit in the camera. A reed-relay is small and will consume very little power.

      1. Kevin,

        Many thanks for your rapid response, I’ll work out which transistor type I will need, PNP or NPN. I understand that the GPIO will feed 3.3v, is that correct? How do I work out what rating of transistor I would need, possibly even a resistor in there before the transistor. Your help is much appreciated.

        Thank You.

        1. Yes, the GPIO will provide 3.3V. I think any common transistor would do for your purpose, since it’s probably switching a tiny load. See the references for a good explanation of transistors to learn how to figure out the resistor value. The central variables are the load that’s driven by the transistor, and the gain (Hfe) of the transistor.

          You might start by measuring the voltage from each pin on your manual switch to ground. Also measure the voltage across the switch pins. Make a note of these with the switch both open and closed. You could also measure the current through the switch (your multimeter will effectively be closing the switch when you touch the probes across the pins).

          However, if your project is more about getting something working than about learning the electronics, then I’d recommend you use a relay instead – it’s much simpler to figure out.

  14. Many thanks again, I do have a desire to learn as much as possible. I’m impressed by your responses, very sincere and useful, for which i thank you. I will endeavor to complete my project and forward the result. Again, many thanks – I am impressed and thankful.

    Adrian.

    1. Hi Huub, good stuff, I hope I didn’t turn your TV off in the middle of Christmas viewing! An enhancement that comes to mind regarding your code would be to show the states on the same page as the form (e.g. either in a div above, or individually beside each button). Then an action page (e.g. ‘do_action.php?gpio=24&state=1′) would process the request and then redirect back to the form. An HTTP 302, or 303/307 response can be used to direct the browser back to an originating page.

      1. Thanks Kevin, will put something up when complete, need to make a box for it all as it will be externally sited. Will keep int touch…

        Regards.

  15. I’m baffled. I put this circuit together with a set of transistors and relays I’ve used for projects in the past. And the behavior I’m seeing is REVERSED!
    2n3904 transistor
    aleph sd1a05awj relay
    1N4148 diode
    1.2KOhm resistor

    I can put my meter on the pi’s pins 17 and ground and set it to “output” and “write 1″ to it I see the voltage turn on. When I “write 0″ out, no voltage. So I’m confident I’m controlling the output pin properly. But when I hook up the circuit the relay “closes” when I “write 0″ and opens when I “write 1″. I can hear the reed relay click as it opens and closes and measure the resistance across the contacts as continuity opens and closes. So I know the relay is functioning.

    I’ve reviewed my circuit and compared it to the picture and diagram in this article and it all appears correct. I’ve triple checked the polarity on the diode and transistor.

    Something is saturating the transistor when Pin 17 is off and somehow dropping it when Pin 17 is on.

    I’m open to any suggestions as I’m still fairly new at this.
    Thanks in advance,
    Ben

    1. That does sound strange. The first thing I’d do set use a multimeter to measure the current between (more accurately, through) the GPIO and the 1.2K resistor, and then again between, for example +V and the coil.

      Do this for both GPIO = 0 and GPIO = 1. I’d also repeat after adding a pull-down resistor between the transistor’s base and ground (~10K).

      1. Ok, well this is embarrassing. I got my 2N3904′s mixed in with my 2N3906′s and guest what the difference is . .. PNP vs NPN. So the circuit was behaving exactly as I implemented it, i.e. a “normally open” transistor that closed with current was applied. Sigh . ..

        Ok, I got my REAL 3904 transistor in place and I could hear the relay “tink” quietly when I turned it off :-). However, the odd thing is, that I had to reduce my resistor drastically to saturate the transistor enough to get a solid open on my relay. I ended up needing to use a 390 ohm instead of 1.2K. I reduced the resistor step by step until the relay would open and pass 5v to to light an LED.

        Thanks for the troubleshooting tips and this great article.
        Ben

        1. Looking at the 3904 datasheet, the gain parameter (hFE) for this transistor is quite low, and also seems to be vary wildly on a narrow range of collector currents, so I’d guess that this is the reason you need a much lower value resistor between the pin and base.

          On the other hand, your relay, with a 500ohm coil (I think), should only require 10mA to energise at 5V, and this is the ‘ideal’ for maximum hFE according to the datasheet. Measuring actual current through certain points in the circuit would allow you to do the sums to confirm all is within spec (and if you do, please post us your data).

          Are you sure the collector and the emitter are the right way round?

          1. I measure exactly 10mA current through the coil when it is active. I measure almost 10mA to the base of the transistor as well from the GPIO pin. This seems high compared to your 3mA suggestion in your post. The current on the emitter leg of the transistor is 20mA. I think that makes sense as it is passing both the base and collector’s current to ground.

            I am a little concerned about the 10mA to the base, but if I am reading the GPIO specs right, I should be able to handle up to 15mA’s on a given pin. So while I’m at 3.3 times your recommended mA it seems like I’m still in spec. Am I understanding this correctly? Also, I will be driving two of these circuits from pin 17 and 22 respectively. 20mA off of that P1 block still is below the 50mA limit. Do you see any trouble here?

            I have quintuple checked both the cathode/anode orientation of my diode and the collector/emitter orientation of my transistor. Beyond that, if I understand the nature of the transistor (polarized) I don’t believe it would work properly if either were reversed.

            It seems to work reliably now and I’m getting ready to move it off of my breadboard and onto onto the protoboard, but I’ll wait a bit to see if you see any gaping holes in my logic. Wouldn’t want to melt down my Pi. Thanks for your suggestions and hints along the way!
            Ben

            1. As long as you’re not exceeding the maximum B-E current, then it should all be ok. Regardless though, something seems wrong if the transistor needs 10mA B-E to drive 10mA C-E. What are the current measurements with the 1K or higher resistors? Have you tried a different NPN transistor (even of the same type)?

              I think that if the emitter and the collector are reversed, it will still work as an NPN, but less effectively due to the different amounts of doping between the two N channels – that is, a higher base current will be required to saturate. My knowledge on transistors is a bit superficial, I should add!

              1. Ok, looks like your understanding of the transistor (much deeper than mine) provided the final clue. Of course I would have to overdrive the base if it was backwards! I had been looking at a datasheet for a different 3904 package. Yes, the collector and emitter were reversed! Ok, back to using a 1.2K resistor and only drawing 2mA to saturate it and open the relay. I can only hope that some other beginner can learn from my mistakes. I appreciate you patience and hints along the way. Warming up the soldering iron and getting out the proto-board.

    1. The user that runs the program needs to have write-permission on the file ‘/dev/mem’. There are various approaches – search around chmod, chgrp or chown, /etc/group, udev configuration.

      Alternatively, use the ‘/sys/class/gpio’ files – you can use from bash, but they can also be used from C with fopen(), fputs(), etc. This also requires a user with appropriate permissions (e.g. group read & write), but limits access to only the GPIO pins.

  16. I am thinking about controlling 120V (<300W) by following this post. I am going to get parts from Adafruit. May I ask whether I can use the diode and transistor for my project:
    - PN2222 Transistor: https://www.adafruit.com/products/756
    - 1N4001 Diode: https://www.adafruit.com/products/755

    The diode seems to be ok since it is supposed to protect only 3.3V. But due to my poor understanding of transistor, I am not sure if the one above would work.

    Thanks for your great post!

    1. Both should be fine – other transistors may need lower resistor values, depending on the gain. Probably not in this instance. However, I’d encourage you to learn about how transistors work in this example by confirming for yourself that the transistor would work. hFE and the relay coil current are the two variables you need to focus on.

  17. Hello,

    I just came here yesterday as I am interested in how to deal with a relay as well and simply have to say that this article is supreme for a beginner like me.
    After reading the article, shopping at an electronics store nearby (i had to use a different relay), reading data-sheets and coping with the characteristics of the requirements, I gave everything a try and it just works. Guess I will try to use the relay with some testing equipment (as I am a beginner, guess i shouldn’t and mustn’t deal with regular 230V-currents right now ;-)). Anyhow…THANKS!

    Greeting from Germany
    Norman

    1. You might consider buying a cheap low-voltage lighting transformer and bulb, and switch the low voltage (e.g. 12V AC) using the relay. You can scale up when you are confident that you know what you are doing.

  18. Hi Kevin,

    First of all I got to tell you that the electrical drawing with the relay and more, works just fine, even up here in Sweden… :P
    Ive soldered it together on a board and it works fine, Iam using it for switching on/off heating in our summerhouse, depending on how hot/cold it is from our 1-wire DS18S20 net.

    But now I would like to have a feedback that tells me if the Relay has been switched, when I login remote.

    Its working so fine, I wounder if you could put together a version 1.1 of the drawing and the C code.
    So my plans is to use another transistor and a gpio for input, at the side of the relay (NC and C). That is possible right?

    Once again, thanx for a great tut!

    //Regards Mats

    1. The state of the GPIO pin will tell you the state of the relay, so perhaps this is the simplest approach? If you really need true feedback from the relay then…

      I’d advise against doing anything on the contact-side of the relay – if you’re switching an AC load, then you risk high voltage going into the GPIO pin used for feedback. It can be done of course, but not without rectification, isolation, limiting current, etc.

      You could possibly choose a relay with two completely independent sets of contacts (double-pole) switched from the coil – one pole could be used for 3.3V GPIO feedback (perhaps opto-isolated), the other for the AC load – but keep the AC and DC wiring safely separated.

      1. Hi and thanx for fast reply,

        You are right about the state of the GPIO pin is telling me the status, but I need some more status check.
        During winter time it can can be about -10 Celsius around some certain electronics inside, so I am worried about some electronic stuffs malfunction in this cold weather conditions.
        To get a quick way of controlling my on/off for heating in the summerhouse, instead of learning how to build my own php script handle this in a the apache website.
        I downloaded “WebIOPi” and with this installed and running I cant use the echo “0″ or “1″ command to view it.
        Although, if I find a php script witch makes me controll it in the webinterface instead of WebIOPi. I would go with that first, and see how this turns out.

        Speaking about your advise, I forgot to write this.
        I am driving through the “5v relay NO-C” 24vAC to a contactor who handle the switching of 240vAC.

        My plan were to add, diod to get 24vDC to switch another trasistor, and that will lead 3,3v/5v from-to GPIO to have the input. That would fit in the board where this all is soldered up at today (and this little change will be a possible chance to make it in this going on season). Changing to another relay (doule-pole) would not be an option cause it cant fit at the board, so i´d need to make a new one. And that would at this time of the year not be a possible project. Perhaps next winter season.

        But I guess the best way during this ongoing season is for me to figure it out how to learn programming php to get this work.

        Sincerely
        Mats

  19. First of all, I’m fairly new to electronics and have already learned so much. Thanks for sharing so much information. It has been invaluable in my quest!

    Ok- so initially, I tried to connect a GPIO directly to a relay. I purchased a 3V relay, thinking that’s all I needed. It didn’t work. As far as I (now) understand, the GPIO pins only push 40mA, and the relay I bought requires 120mA to switch. Dang- seems I need more mA.

    I tested the 3V3 pin on the PI with a multimeter, and it pushes nearly 300mA. So as a quick test, I hooked up my relay directly to the 3V3 pin, and the relay does work (I hear the click).

    So I found your page and tried to follow it (using the 3V3 instead of 5V to power my relay). I went to Fry’s and purchased a transistor and a diode, and I guess I got the wrong ones. I spent quite a bit of time researching these components, but I guess I still fail to understand what I need. What are the important factors for these components?

    Here’s what I bought:
    1. General Purpose Diode – NTE110A (http://www.nteinc.com/specs/100to199/pdf/nte110a.pdf)
    2. NPN Transistor – NTE2361 (http://www.nteinc.com/specs/2300to2399/pdf/nte2361.pdf)
    3. Relay – Philmore 86-103 (http://www.philmore-datak.com/mc/Page%20266.pdf)

    I believe I got everything wired up correctly and verified the diode direction and transistor ECB pins were correct… but the relay does not switch. Any thoughts? Thanks in advance.

    crazy888s

    1. I FIGURED IT OUT! I just had my transistor the wrong way *face palm*

      The spec sheet I linked too made me think the pins go ECB when the trapezoid was facing me…. a multimeter showed I had it backwards though.

      Thanks for the guide. Add this to your success stories. Cheers!

      1. I don’t think that would work. With a resistance of 60 ohms, the coil could feasibly draw 55mA from the GPIO pin which is way above the rating. Quite a nice little low power relay though – just don’t try driving it directly.

  20. Pingback: Me and my ideas?
  21. I have a few questions (Well, maybe more than a few). My ultimate goal is to control six 12V bilge pumps with my Raspberry Pi.
    Would that require six relays?
    What type of relay would I need?
    Would that require six transistors?
    Could I use the relay you mentioned in your article?
    How many diodes would I need?
    Lastly, would a 1N4148 diode work?

    Thanks.

    1. Hi, you’d just need to replicate the circuit six times, each connected to a different GPIO. You might find it easier to buy a pre-built relay board that switches on 3V3, eBay among others has plenty of these. Any general purpose relay would likely do, as long as the contacts can accommodate your device (volts/amps rating). A 1N4148 would work.

        1. Probably yes – on both questions. As long as your 5V line can deliver enough power to drive 6 x relays, you should be ok.

    1. In the circuit above, the load that you switch with the relay contacts is already isolated from the Raspberry Pi (because the coil in a relay is already isolated from the contact that it switches).

      Isolation would therefore relate to the circuit driving the relay coil. You might choose to do this for safety reasons if, for example, the transistor is driving a much higher voltage, or perhaps just to eliminate noise from one circuit or the other, or to have separate grounds in each circuit. The list goes on…

      Isolation isn’t applicable or necessary in the example above – I’d say that, if you don’t know you need isolation, then you probably don’t.

  22. hey

    great tutorial..is there a way i can drive the relay using python? it works fine with the /sys/ filesystem and i already tried it with a little python script but with no result. i used the RPi.GPIO library and tried to set the pin to ‘high’ and ‘low’ but it won’t work. does somebody know a solution to my problem maybe?

    greetings, luci

    1. Hi, I don’t know much about Python libraries. You could try using the /sys filesystem with standard file-handling functions. This seems to be a good place to start before looking into why the library isn’t working. You could also try running the library-based Python code as root (e.g. sudo) to make sure it’s not a simple permissions issue.

  23. If you want to play with Triacs… a good low voltage AC power supply to use is sprinkler system power supplies.. eg Rainbird. They run at 24VAC.

    Triacs are nice to use, cheaper, quicker, and more efficient than relays.

    1. Thanks for the tip – another option is a 12VAC low-voltage lighting transformer, which can be bought for a few pounds.

  24. Excellent Thread, this saves me lot of time; before build on breadboard test it on CircuitLab.

    Im using a relay MD-5T, just needing 12 v to open a door usign a REST service.

  25. Hi, thanks for the excellent article. I am just starting out with this whole hobby electronics thing, and I was able to understand and build your relay, and it even worked the first try! Unfortunately, I’m still a bit ignorant about programming. I need the gpio_relay.c program to control GPIO 25 (pin 22). I tried replacing all the occurrences of “17″ with “25″ in your program, but it does not work as it should. Any suggestions? (Should note that I was able to build it and it worked fine on GPIO 17). Thanks!!

    1. You probably need to set the appropriate GPFSELn bits for GPIO25 rather than GPIO17 – by default these pins are be configured as inputs. It’s worth the effort figuring out on paper how bits are manipulated to configure GPFSEL registers. There’s doubtless lots written on this elsewhere, but come back to me if you get stuck…

      1. I’m not going to lie, most of what you said might as well have been in Latin, lol!! The purpose of driving my relay is really really simple, and I’m able to make it work 100% of the time by just putting the ‘echo “1″‘ and ‘echo “0″‘ commands in the shell script. Thanks for taking the time to reply to my comment, though. This is really a wonderful tutorial and solution!!!

        1. Much better to use a solution you’re confident with, unless there’s a need for more. For the record: -

          GPFSEL2 &= ~(7 < < 15);
          GPFSEL2 |= (1 << 15);

          would set GPIO-25 to output mode. Note GPFSEL2, rather than GPFSEL1 holds the function select bits for GPIO-25.

  26. how can i control 4 solid state relays using my raspberry pi ???
    how i connect the solid state relays with raspberry pi and how i control them via the ‘/sys’ filesystem ??

    1. The answer is beyond the scope of a blog comment – in principle, the control side of the SSR could be driven by a GPIO pin and a resistor, but the details would depend on the relay. Most common SSRs switch AC loads, and so you’d have to experiment on low-voltage circuits to be safe. There are almost certainly more appropriate tutorials elsewhere on the net.

  27. You might want to look into small MOSFETS like the 2n7000. If you use a MOSFET you don’t need a current limiting resistor, and the current draw on the RasPI’s GPIO pin is virtually unmeasurable.

    1. I’d argue that it’s usually good practice to include a current limiting resistor – particularly when learning. It’s easy to confuse the pins on transistors, or refer to the wrong data-sheet for pin assignment, etc. There’s also the possibility that a part will fail, creating a short to ground.

    1. Sure, feel free to use the diagram. Ideally, the link text would be something like ‘Courtesy of…’ or ‘Image by…’ in the image title, but it’s up to you. Nice project.

      Had a look at the KNX link you mentioned – their website has almost no useful information. No studies should be tied to such a closed organisation, so well done for ditching them and learning stuff ‘from the wires up’.

      1. Thanks for the permission, will add a caption to show that it’s from you. Really like your site and can’t wait to have a look more into your raspberry pi power controller after exams.
        Cheers,
        Ryan

  28. Hi Kevin, thanks for the tutorial.

    I have problem here,
    i can switch on the relay, but i cannot switch off.

    looklike the problem is from transistor BC337, i already try change the 1K resistor with 10K but still have the problem.
    the strange things is, when i touch the resitor pin, i can switch on the relay and it will be switch on forever. ( it’s just like SCR)
    and when i disconect the Resistor R1 from GPIO9 pin, the relay is still on.

    My component is:
    Transistor Q1 = BC337
    Resistor R1 = 1K or 10K
    Relay = HFS5 (5volt relay)
    Dioda D1 = IN4002

    I use 5 volt (+) from Pin 2 and Ground from Pin 6
    And using GPIO 9 from Pin 21

    1. Hi, it looks like you’re using a solid state relay which requires an AC load in order for it to ever switch off (which it does as the AC load voltage crosses 0V). Try it on a low-voltage AC load to see if it makes a difference.

        1. The problem with a coil relay is that it draws current when energised, quite a lot relative to most USB devices. If you just need a reset function, then I suppose a relay with normally-closed contacts might do the job.

          A latching relay helps avoid the need for continuous current in the coil, but they are typically more complex to drive, requiring an H bridge circuit. Some small signal latching relays could be driven by GPIO pins, if you don’t mind going a little out of spec – the coil may draw more than the usual 25mA per pin, but only for a short amount of time.

          So, a transistor is possibly the best option – as long as it has a low resistance when fully saturated/on, and it can carry loads of 500mA or so (as per USB specification, check your device won’t draw more).

          1. Hi Kevin,

            Thanks for the Reply,
            i check “BAFO USB to Serial” only need 100mA, so as you suggest, with transistor i can Switch on/off this “BAFO USB to Serial” Devices.
            Thanks for the help, now i will search the best transistor for it, or do you have a sugestion ?

            1. Check the comments for the power controller post elsewhere on this blog – Alex from MSL Digital Solutions uses a IRFU5305 for his power controller that would meet your needs. You will likely need to drive its gate with another transistor.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>