Arduino: Switching High Voltages Using a Transistor

Arduinos are fairly limited when it comes to connecting things to them. Anything that needs more than 5V (or 3.3V depending on the board) is a no no. And it’s not just voltage you need to worry about. Even if the voltage is OK you still need to care about the amount of current the device requires. Luckily there are ways for an Arduino to control higher voltage / higher current devices.

There are various devices that can be used to help the Arduino switch high voltages. relays, solid state relays, transistors, mosfets, Darlington transistors, SCRs, IGBs, Diacs, Triacs …..

Picking a suitable device depends on a few different factors but mainly comes down to the voltage & current being switched, the voltage & current of the control signal, and how quick things need to happen.

I want to control a 12v Shako solenoid valve rated at 4.6W. 4.6W means it requires (4.6W/12V) around 0.3833 amps or 383 mA of current. How do I know it is rated for 4.6 Watts? It’s printed on the coil ;-)

Watts = Amps x Voltage. Which also means

  • Amps = Watts ÷ Voltage, and
  • Volts = Watts ÷ Amps

12v at 383mA is low enough that we do not need any real special considerations except to check that the transistor we want to use can handle these values.

There are many kinds of transistor and one of the most common the Small Signal, Bipolar Junction Transistor (or BJT). Of these, there are 2 types, NPN type and PNP type.
Both NPN and PNP work in a similar way, except, the polarities are reversed and, when used as switches, NPNs are best used on the LOW side of a circuit and PNPs on the HIGH side.

NPNs are the more common and are probably easier to use. I cover how bipolar junction transistors work in another post so I will jump into using them as switches.

How Transistors Work

In simple terms, when a small current is applied to the Base pin, a larger current is allowed to flow between Collector and Emitter. The amount of current flow between Collector and Emitter is directly related to the current on the Base pin. More current at Base, up to a point, results in more current being allowed between Collector and Emitter. After a point, things stop working.

Because the current between Collector and Emitter is larger (sometimes much much larger) than the current on Base, the transistor is said to amplify the current.

The amount that the current through Collector and Emitter increases based on the current on the Base pin is call the gain, sometimes referred to as HFe or β (Beta). More on this later.

BJTs have three pins; Base, Emitter, Collector.

Although EBC is a common pin configuration, it is not standard. There are many many different BJTs and not all have the same pin outs. Check the data sheet before using.

I am using the transistor in the common emitter configuration. This is where the control signal goes to the base pin, the high voltage goes to solenoid valve and then to the Collector, and the Emitter goes to ground. This is often called the common emitter configuration and/or Low Side.

Low Side / High Side

When the transistor is connected to the GND side of the circuit it is said to be on the LOW side. When the transistor is connected to the VCC side it is said to be on the HIGH side.

I want to use the transistor on the LOW SIDE so I will use a NPN transistor. PNP transistors are normally better suited to High side circuits.

Transistors have 4 states, fully open, closed a bit/open a bit, fully closed, and broken :-( These 4 states are also know as

  • cutoff
  • active or linear
  • saturation
  • breakdown

Cutoff Region

When no current (or very very little current) is applied to the Base pin, the transistor is in the cutoff region. While in the cutoff region no current flows through Collector and Emitter and the transistor can be considered as off or fully open.

Active or Linear Region

When applying current to the Base pin, as the current increases, at a certain point the transistor will move from the cutoff region to the active region. In the active region the transistor starts to allow current to flow through Collector and Emitter. At first it allows just a little bit of current but as the current on the Base pin further increases, more and more current is allowed through the Collector. The amount of current at Collector is a multiple of the current at Base.

Saturation Region

When the current on the Base pin gets to a certain level, the transistor moves from the active region into the saturation region. In the saturation region the transistor allows the maximum current to flow through Collector and Emitter and can be considered as fully closed or fully on. When in the saturation region, adding more current to the Base has no effect on the current through Collector, the

Breakdown Region

Too much voltage on the Collector pin sends the transistor in to the Breakdown Region. As the name may suggest, this is where normal operations break down and the Collector current increases rapidly and can create a run-away current situation. This is not a good place to be so make sure you are using a transistor that can handle the voltage and remember to leave some padding. You should not use an silicon device at its maximum ratings.

Each transistor has different specifications and to determine when a transistor moves between the different regions and to know how much current is required for it to enter the saturation region you need to look at the data sheet and maybe get out a calculator.

Transistor as a Switch

When using a transistor as a switch we are only interested in the on and off states or more correctly the Cutoff and Saturation regions. We are not really interested in the Active region. By using the transistor in only the cutoff region (open) and the saturation region (closed) the transistor is either fully open or fully closed (ie off or on).

We use the transistor as a switch by applying a control signal/current to the Base pin which allows current to flow through Collector and Emitter which turns on and off whatever is connected to the Emitter pin. As long as we supply enough current to the Base to put the transistor in to the Saturation region, the switch will be fully closed. Ideally what we want, is the sweet spot, where we have just the right amount of current on Base and just the right amount of current through Collector-Emitter.

When a transistor is used as a switch, aim to put it fully in the Saturation region to ensure it is fully closed.

I have a small bag of 2N2222A transistors that I think may be suitable. These are NPN type BJTs.

2N2222

There are 4 main models of 2N2222 to consider:
– 2N2222
– 2N2222A
– PN2222
– PN2222A

2N22222N2222APN2222PN2222A
Maximum Collector-Emitter Voltage (VCEO)30V40V30V40V
Emitter-Base Voltage (VEBO)5V6V5V6V
Maximum Collector Current (IC)0.8A/800mA0.6A/600mA0.6A/600mA1A/1000mA
Maximum DC Current Gain (hFE)300300300300
PackageTO-18TO-92TO-92TO-92

The PN2222A is the better choice but I only have the 2N2222A so that is what I am using.

Confirm the 2N2222A Is Suitable

When looking for a transistor there are a couple of things to consider first,

  • the maximum voltage the transistor can handle
  • the maximum current the transistor can switch
  • the gain.

Maximum Voltage and Current

I am controlling a solenoid valve that uses 12V and is rated for 4.6W. Divide the watts by voltage to get current, 4.6W/12V = 0.3833. which I am rounding up to 0.385. So 0.385 or 385mA.
The 2N2222A can handle up to 40V at up to 600mA so, initially at least, it seems OK. Remember these figures are the maximum and the transistor should not be used at these levels.

Gain

Even though a transistor may be able to handle the desired voltage and current, if the gain is low and the control signal on Base is not large enough, the transistor may not fully close. In this case the transistor is not a good choice.

Transistor Current Gain (HFe or β)

The current gain is the amount of amplification and is a ratio based on the amount of current on Base.

For regular BJTs it is common practice to simply use a gain of 100, however, the gain is not uniform across all currents and voltages (or temperatures) so it is always worth checking the data sheet. There is normally a chart that shows the gain but an educated guess may still be required for some situations.

This chart is taken from the Semtech Electronics 2N2222/2N2222A data sheet, top of page 3, and shows the Collector current across the bottom and the amount of gain vertically.
Divide the Collector current by the gain to find out what current is required on the Base.

To make things a little clearer I have coloured the line for 10V at 25° with yellow.


Using the 10V at 25° line (closest to my 12V), you can see that at 385mA the gain is around 180.
You can also see that at 10V and 25° the gain starts at around 100 and remains above 100 right until around 500mA. This is why many people simply use a gain of 100.

You may be able to see that the 2N2222 has peak performance when switching currents around 100mA (the top of the curve) but after this performance weakens slightly. So, while using a 2N2222 to switch my solenoid works it may not be the very best choice for other devices.
Based on the chart, at 25° and 10V the gain is around 180 so more than enough for my requirements and means I could use a gain of 100 just like everybody else if I so wished

Using the chart to determine the gain will give you the point where the transistor goes from the active region to the saturation region. Ideally you need to be above this point to ensure the transistor fully goes into saturation so, although the chart tells me the gain is around 180 by using a lower gain, such as 100, I can be sure the transistor is fully saturated and therefore, fully on.

As long as you give yourself plenty of margin of error, using the chart can be useful. However, the charts can sometimes be hard to read due to poor quality type and thick lines.


Some data sheets also provide a summary of the gain at specific currents.

The table taken from the data sheet, top of page 2.

The last two entries are of interest to me. These shows the Min. and Max. gain for 10V at 150 mA and 500mA. My solenoid requires 385mA so it is somewhere in the middle but more towards 500mA (closer to 40 than 30).
Using the gain for 500mA can be overkill but it would ensure the transistor is most definitely saturated. I would consider this the very safe but wasteful option. As long as the device providing the control signal, in my case a 5V Arduino, can provide the required current to the Base pin, using a gain of 40 will ensure the transistor is fully saturated for any current up to 500mA. Using a gain of 40 I absolutely know the transistor is saturated. remember, 40 is the minimum.

Basically we have 3 values; 180, 100, 40.
180 at the top end. This is likely to be the boundary between saturation and active.
100 in the middle. The default rule of thumb for many people.
40 at the bottom. Absolutely 100% puts the transistor in to saturation but maybe a little wasteful.

Base Resistor

BJTs are current driven devices and require a current limiting resistor in series with the Base pin. Without a resistor the transistor will try to draw as much current as possible until it destroys itself and quite possibly the Arduino as well.

What Value Base Resistor?

Picking the resistor to use on the Base pin is like a balancing act. We want a resistor that will allow enough current on the Base so that enough current flows at Collector-Emitter to drive the solenoid valve but we also shouldn’t let too much current through. When using the transistor for switching we want to aim for a bit more current than the bare minimum required and for most applications the actual value doesn’t need to be that precise.

To calculate the resistor value to use on the Base pin various pieces of information are required:
– The required current through Collector and Emitter (VCEO)
– The transistor current gain (HFe or β (Beta)).
– Voltage on Base
– The voltage drop through Base and Emitter

Current through Collector and Emitter (VCEO)

This is the current required by the solenoid valve and is 0.385A (or 385mA).

The transistor current gain (HFe or β (Beta)).

Based on the chart, the gain at 385mA is around 180 (remember this is the point where thew transistor enters the saturation region but is not fully saturated). Also from the data sheet, the gain at 500mA is 40. Common practice is too use a gain of 100. Which one to use?

  • A gain 180 will be at the boundary between the active region and the saturation region. This is not where I want to be. I want to be well inside the saturated region.
  • A gain of 100 is very likely in the saturated region.
  • A gain of 40 will be well inside the saturated region.

I can dismiss the gain of 180 and use either 100 or 40. I will do the calculations for both and see which one I am more comfortable with.

Voltage on Base

Since I am connecting the Base pin to a 5V Arduino Nano the voltage on Base is 5V (could be a little less but not enough to worry about).

Voltage drop through Base and Emitter

Silicon transistors have an intrinsic voltage drop of about 0.7V across the Base and Emitter. This needs to be taken in to account when calculating the resistor value.

Base Resistor Calculation

The Base resistor value is calculated using good old Ohms law.

  1. I need to allow at least 0.385A through the Collector and Emitter.
  2. The gain is either 100 or 40 or somewhere between.

Using a gain of 100

Using a gain of 100 I will need 0.385A ÷ 100 or 0.00385A on the Base pin.

We can use Ohm’s law to calculate the resistor value ( I=V ÷ R, or Current = Volts ÷ Ohms ). By rearranging the formula we have Voltage ÷ Amps = Ohms.

Remembering to include the voltage drop, we have

((5V – 0.7V ) ÷ 0.00385A) = 1116 ohms.


The closest I have are 1000 ohms (1KΩ) and 2000 ohms (2KΩ).
1000 ohms will allow a little more current through.
2000 ohms will allow a little less current through.

I can double check what current these will allow by again using ohms law:

1000 ohm resistor: current = 4.3 ÷ 1000. Which comes out at 0.0043A
2000 ohm resistor: current = 4.3 ÷ 2000. Which comes out at 0.00215A

I need at least 0.00385A so the 1000 ohms it is.

A typical 5V Arduino can safely delver up to 20mA (0.020A) from a single pin so 0.0043A is well within limits.

Using a gain of 40

Using a gain of 40 tells me I need 0.385A ÷ 40 or 0.009625A at Base.
Using Ohm’s law to calculate the resistor value (remember to include the voltage drop) we have

((5V – 0.7V ) ÷ 0.009625A) = 446 ohms.

I don’t have a 446 ohm resistor. I have 330 ohm and 510 ohm though.

330 ohm resistor: current = 4.3 ÷ 330 Which comes out at 0.0130A
510 ohm resistor: current = 4.3 ÷ 510 Which comes out at 0.0084A

I need at least 0.009625A so the 330 ohms it is.

Which Gain Value to Use?

Since both are within limits it comes down to how much current you want to draw from the Arduino, how much you want to ensure the transistor goes into the Saturation region and how sure you are the numbers you got from the charts are correct. In my case, using a gain of 100 is safe and will put the transistor into the Saturation region (remember, the chart told me the actual gain is likely to be around 180). A gain of 40 definitely puts the transistor well into Saturation so both can be used.
I am using mains power so I do not need to care too much about efficiency. If this were a battery powered project I would use a higher resistor and reduce the current taken from the Arduino. This would result in better battery life.

Using a gain of 100 with a 1000Ω resistor is the better option. Less current draw is normally better. A gain of 40 is at the extreme end and although this definitely puts the transistor into the saturation region is not as efficient.

Now I know what resistor to use I can start actually building things.

Circuit

For the value of R1 see above.

Depending on the device you are driving you may need a series resistor between the 12V and the device. For solenoids the resistor is not required.

On the right hand-side I have an RCA connector for the solenoid valve and a barrel socket (DC005) for the 12V power in.

The green LED will flash at the same rate as the valve turns on and off and is used to indicate when the valve is/should be open. In my case this is not actually required as the solenoid on the valve has a built in LED. The valve you are using may not have an LED though.

Note: I am using the same breadboard for mixed voltages. The Arduino side is 5V and the solenoid side is 12V. The GNDs are connected but not the +voltages. Do not connect the Arduino directly to 12V.

My breadboard has a gap on the power rails and it is fine for me to have 5V on one side and 12V on the other. Many breadboards do not have the gap. Double check before putting mixed voltages on the same breadboard power rail.

Flyback Diode

The astute amongst you will have noticed the diode connected to the RCA socket. This is a flyback diode. Also known as many other names including, snubber diode, commutating diode, freewheeling diode, suppressor diode, clamp diode, and even catch diode (thanks wikipedia).

If you look closely at the diode you may think, it could be connected backwards. However, it is connected correctly. The diode is used to feed any back flow of pesky electrons back into themselves without causing harm (not really).

When you remove power from a solenoid, or any other electromagnet, the magnetic field collapses and creates a current as it collapses (the coil is an inductive load). This current can be very high and can be powerful enough to kill an Arduino. To stop this happening, it is good practice to add a flyback diode. The diode allows current to move in one direction only and safely dissipates the current created by the collapsing magnetic field. This can slow the decay slightly and thus slow how fast the valve closes but for use with solenoids this is not noticeable. Solenoid valves are fairly slow anyway.

Example 1: Blink With Added Solenoid Valve

The first example is fairly basic. I am using a variation of the Arduino Blink example to turn on and turn of the valve at regular intervals. I am using this as a test to make sure the valve switches before attempting more complex things.

Circuit

This example uses the same circuit as above. R1 is 1K ohms.

Very simple sketch to get started with. The Solenoid valve and LED are turned on for 1 second and then turns off for one second. This repeats indefinitely.

Sketch: Switching high voltages with an Arduino using a transistor 01

//  Sketch: Switching high voltages with an Arduino using a transistor 01
// www.martyncurrey.com
 
const byte LED_PIN = 10;
byte const TRANSISTOR_PIN = 4;
 
void setup() 
{
    pinMode(LED_PIN, OUTPUT);
    pinMode(TRANSISTOR_PIN, OUTPUT);
}
 
void loop() 
{
  digitalWrite(LED_PIN, HIGH);   
  digitalWrite(TRANSISTOR_PIN, HIGH); 
  delay(1000);       
 
  digitalWrite(LED_PIN, LOW);  
  digitalWrite(TRANSISTOR_PIN, LOW);     
  delay(1000);                       
}

Hopefully the code should be fairly clear. The solenoid valve and LED are turned on with

  digitalWrite(LED_PIN, HIGH);   
  digitalWrite(TRANSISTOR_PIN, HIGH); 

and turned off with

  digitalWrite(LED_PIN, LOW);  
  digitalWrite(TRANSISTOR_PIN, LOW);     

the delay() statement causes the Arduino to wait for the specified number of milliseconds. 1000ms is 1 second. So 1 second on and 1 second off.

Example 2: Turn on a solenoid valve using a toggle switch

Using the code featured in Switching Things On And Off With An Arduino: Toggle Switch we can add a toggle switch. Press for ON, press again for OFF.

Circuit

Same circuit as used in the previous example except there is now an added button switch on pin D2.

Sketch: Switching High Voltages With An Arduino – Use a toggle switch to turn a solenoid valve on and off

//  Sketch: Switching High Voltages With An Arduino - Use a toggle switch to turn a solenoid valve on and off
// www.martyncurrey.com
//
//  An  example of using a button switch as a toggle switch to turn a solenoid valve on or off
//
//  Pins
//  D10 to resistor and LED
//  D4 to resistor and transistor
//  D2 to push button switch
 
 
// Define the pins being used
const int PIN_LED = 10;
const int PIN_TRANSISTOR = 4;
const int PIN_SWITCH = 2;
 
// variables to hold the new and old switch states
boolean oldSwitchState = LOW;
boolean newSwitchState1 = LOW;
boolean newSwitchState2 = LOW;
boolean newSwitchState3 = LOW;
 
boolean valveStatus = LOW;
 
 
void setup() 
{
    Serial.begin(9600);
    Serial.print("Sketch:   ");   Serial.println(__FILE__);
    Serial.print("Uploaded: ");   Serial.println(__DATE__);
    Serial.println(" ");
 
    pinMode(PIN_LED, OUTPUT);        digitalWrite(PIN_LED,LOW); 
    pinMode(PIN_TRANSISTOR, OUTPUT); digitalWrite(PIN_TRANSISTOR,LOW); 
    pinMode(PIN_SWITCH, INPUT); 
}

 
void loop()
{
    newSwitchState1 = digitalRead(PIN_SWITCH);  delay(1);
    newSwitchState2 = digitalRead(PIN_SWITCH);  delay(1);
    newSwitchState3 = digitalRead(PIN_SWITCH);
 
    // if all 3 values are the same we can continue
    if (  (newSwitchState1==newSwitchState2) && (newSwitchState1==newSwitchState3) )
    {
        if ( newSwitchState1 != oldSwitchState ) 
        {
           oldSwitchState = newSwitchState1;
           if ( newSwitchState1 == HIGH )
           {
               if ( valveStatus == LOW ) { turnON();  }
               else                      { turnOFF(); }
           }

        }  
    }
}


void turnON()
{
  digitalWrite(PIN_LED, HIGH); 
  digitalWrite(PIN_TRANSISTOR, HIGH); 
  valveStatus = HIGH;
}


void turnOFF()
{
  digitalWrite(PIN_LED, LOW); 
  digitalWrite(PIN_TRANSISTOR, LOW); 
  valveStatus = LOW;
}

If you are not familiar with the code that handles the button switch, have a look at the switching things on and off guides.

In brief

The button switch is checked

    newSwitchState1 = digitalRead(PIN_SWITCH);  delay(1);
    newSwitchState2 = digitalRead(PIN_SWITCH);  delay(1);
    newSwitchState3 = digitalRead(PIN_SWITCH);
 
    // if all 3 values are the same we can continue
    if (  (newSwitchState1==newSwitchState2) && (newSwitchState1==newSwitchState3) )
    {
        if ( newSwitchState1 != oldSwitchState ) 
        {
           oldSwitchState = newSwitchState1;
           if ( newSwitchState1 == HIGH )

If the button switch has changed to HIGH we know somebody pressed it and we should do something with the valve.
If the valve is turned off (valveStatus == LOW) we turn it on.
If the valve is already on, we turn it off.

           {
               if ( valveStatus == LOW ) { turnON();  }
               else                      { turnOFF(); }
           }

turnON() and turnOFF() change the relevant pins HIGH or LOW and update the valveStatus variable.

void turnON()
{
  digitalWrite(PIN_LED, HIGH); 
  digitalWrite(PIN_TRANSISTOR, HIGH); 
  valveStatus = HIGH;
}


void turnOFF()
{
  digitalWrite(PIN_LED, LOW); 
  digitalWrite(PIN_TRANSISTOR, LOW); 
  valveStatus = LOW;
}

Leave a Comment