I'm looking to drive a relay on a 5V rail from an Arduino 3.3V pin. Obviously the Arduino I'm using doesn't have the voltage to drive the 5V relay, so that's where the 2N2222 comes in. To test out the circuit, I figured I'd substitute an LED for the time being. My circuit looks like this.


simulate this circuit – Schematic created using CircuitLab

Using a standard, run of the mill, red LED, we say the voltage drop is 2V, and requires 20mA. Using Ohm's law, that gives us a resistor of 150 ohms, correct so far?

For the sake of easy math, we'll say hfe is 100. My understanding is that Ic is Ib x hfe. So we have 20mA = Ib * 100. Giving us Ib of 0.2mA. Using Ohm's law again, and factoring in the 0.7v drop from Vb to Ve we have 12k Ohms. Is that math all good so far?

Right, so plug in the Arduino into where 3.3V is, and set the pin to HIGH, and LED is on. Set it to LOW, and LED is still on. That makes no sense.

Remove the Arduino and make the circuit really simple.

I have a breadboard power supply that outputs 5V and 3.3V, so I take a lead and touch 3.3V to the Rb and LED comes on. Remove the lead, LED goes off.

So success right?

I go back to the Arduino and check, when the pin is set to LOW, my multi-meter sees no voltage. When it's set to HIGH, I see ~3.3V as expected.

Why would this not work?

I also noticed simply touching the resistor Rb also triggers the LED, albeit quite dim.

What am I missing? Or doing wrong?

Edit: I should add, I did stumble across this post, and even copied the resistor values from that, and came up with the same issues. Arduino driven LED stays on, touching resistor makes LED come on, and 3.3V line comes on as expected.

This handy YouTube video also helped me understand some of the logic or what I think is the logic.

  • 7
    \$\begingroup\$ Do you have a common ground between the 3.3V and 5V supplies? Also, what happens in your simple scenario when you connect the input to 0V rather than leaving it open? \$\endgroup\$ Mar 27 '20 at 4:21
  • \$\begingroup\$ @SpehroPefhany suggests a very-likely item you're missing. You must connect Arduino's GND to the transistor emitter. Touching the base resistor impresses 60 Hz (or 50 Hz) into the transistor, turning it on/off too quickly to see with your eye. It is dim because the transistor only conducts for a small part of the 60 Hz cycle. \$\endgroup\$
    – glen_geek
    Mar 27 '20 at 14:50
  • 1
    \$\begingroup\$ @SpehroPefhany comment looks to have been where I was going wrong. I'd been driving the power for the Arduino from USB while debugging/testing and had forgotten to connect the grounds. Once changing the power source and grounds for the Arduino, it was behaving as expected. LED comes on when pin is high. Thanks! \$\endgroup\$ Mar 27 '20 at 16:32

When using a BJT as an ON|OFF switch, you want to drive the transistor into hard saturation for the ON state. You do not want to operate the transistor in its forward active mode (small signal amplification). Therefore, you need to use the transistor's saturation beta \$\beta_{sat}\$, not its DC forward active current gain \$\beta, h_{FE}\$, nor its AC forward active current gain \$\beta_{ac}, h_{fe}\$. (Additional information can be found here.)

For a small-signal transistor, \$\beta_{sat}=10\$ is a commonly-used value. Therefore, to drive the transistor into hard saturation the required base current is

$$ I_{B(sat)} = I_{C(sat)} / \beta_{sat} = 20\,\mathrm{mA}/10 = 2\,\mathrm{mA} $$

:: CHECK :: Ensure your microcontroller's general purpose I/O (GPIO) pin can safely source a current of \$I_{B(sat)}\$.
:: CHECK :: Current that exits a GPIO pin (source current) comes from the microcontroller's VCC power pin, and current that enters a GPIO pin (sink current) exits the microcontroller via its GROUND power pin. Ensure the microcontroller's quiescent/operating current plus the combined source/sink currents at all GPIO pins does not exceed the maximum current specification for the microcontroller's VCC and GROUND pins.

Resistor R2's value can now be calculated as follows:

1) Use the microcontroller's datasheet to determine the minimum voltage for a logic HIGH output signal (\$V_{OH}\$). (Reference1, Reference2)

2) Use the parametric data plots in the 2N2222A datasheet (Fig. 1) to get an estimate of the base-emitter voltage drop when the transistor is operating in saturation mode \$V_{BE(sat)}\$ with (in your case) 20 mA of collector current.

enter image description here

Figure 1. Edited screen capture of "Figure 11. 'ON' Voltages" taken from ON Semiconductor publication number P2N2222A/D, Jan. 2013, Rev. 7, pg. 5 [Online]. Available: https://www.onsemi.com/pub/Collateral/P2N2222A-D.PDF

3) Use Ohm's Law to calculate R2's resistance value:

$$ R2_{calc} = \frac{V_{R2}}{I_{R2}} = \frac{V_{OH}-V_{BE(sat)}}{I_{B(sat)}} $$

4) Use R2's calculated value \$R2_{calc}\$ to choose R2's actual value \$R2\$ from a table of standard resistor values.

5) Using R2's actual (chosen) resistance value, calculate the power dissipation in resistor R2: \$P_{R2} = I_{B(sat)}^2 R2\$. Select a resistor for R2 whose power dissipation rating is \$\ge (2 \times P_{R2})\$. For example, if the calculated power dissipation is 100 mW, choose a resistor whose power rating is ≥ 200 mW.

6) Connect (add) a 10 kΩ "pull-down" resistor between ground and the LEFT side of resistor R2 (see resistor R3 in Fig. 2). (NB: Do not connect this resistor to the circuit node that includes the right side of R2 and the transistor's base.) When power is first applied to a microcontroller its I/O pins are (typically) configured as inputs by default; the I/O pins are not configured as outputs and do not actively drive a logic LOW or HIGH voltage signal. In this case, the voltage at the BJT's base is indeterminate (note 1), and if the base voltage is high enough the BJT could turn ON, if only partially. In this situation the added 10 kΩ pull-down resistor R3 anchors the BJT's base voltage to ≈0 V, and thereby ensures the BJT remains cutoff (turned OFF) when no other circuit is actively driving a voltage onto the BJT's base.

NOTE 1) Assuming the input pin does not have and enable an internal pull-up or pull-down resistor at the moment when power is turned ON.

enter image description here

Figure 2.

  • 1
    \$\begingroup\$ So if I'm understanding correctly, the calculations I did above, and reading the charts correct. R1 is 150 Ohms (R = 3V / 20mA). Using the chart on that datasheet, and drawing a line straight up from 20mA, it looks like Vbe(sat) should be ~0.75. So 3.3v / 2mA = 1650 Ohms. Conveniently, there is a 1.6k Ohm resistor for R2. Does that seem correct? Or round up to 1.8K. \$\endgroup\$ Mar 27 '20 at 17:25
  • 1
    \$\begingroup\$ R1's value is okay. When selecting R2, I usually round down--so, 1650 down to 1.6 kohm. If R2's value goes up from the calculated value, chances are it's not a problem but it does reduce the base current into Q1, and you want to avoid a design that does not drive Q1 into hard saturation. \$\endgroup\$ Mar 27 '20 at 20:00
  • 1
    \$\begingroup\$ That's the curve for V_BE(on) @ V_CE = 1.0 V \$\endgroup\$ Jan 19 at 8:46
  • \$\begingroup\$ Nice post Jim. I wonder what the arrow pointing to the curve with the '1V' label means in that manufacturer data sheet Fig. 11. And I don't think they defined VBE(on). ----- Thanks Jim (above) for mentioning the details from my question about that curve with the 1V label. \$\endgroup\$
    – Kenny
    Jan 19 at 19:56

Assuming the 2N2222 is good, and the MCU gnd === the emitter voltage, and assuming the MCU output goes to 0.0 volts, that circuit should work.

Lets diagnose a bit.

Make the base resistor about 1,000 ohms. That puts a (good) transistor well into saturation when MCU output is near 3.3v. And when MCU output Is nominally 0.0v, any leakage current from collector-base junction will be shunted to gnd.

By the way, your base voltage will increase about 0.06 volts for each 10x increase in current.


You need a pull-down resistor on the Arduino side of the transistor. Otherwise, even if the Arduino is driving 'low', the voltage can't get to a low enough level to switch off the transistor. Put like a 100k resistor that stretches between your 12k and ground.


simulate this circuit – Schematic created using CircuitLab

  • 2
    \$\begingroup\$ I am curious about this pull-down resistor being here. Based on my reading of the Arduino docs, when setting the pin to LOW, voltage is 0v, though switching to mV on multimeter it looks to actually be about 1.1mV. Even with the pull down resistor in place, this would behave like a voltage divider, the transistor would still see about 1mV. \$\endgroup\$ Mar 27 '20 at 16:18
  • \$\begingroup\$ Oops, you are correct - I think I misspoke. That will act as a voltage divider. You can avoid that by putting the pull down on the other side of the 12k. I've fixed it \$\endgroup\$
    – epiolba
    Mar 28 '20 at 22:10
  • 1
    \$\begingroup\$ This isn't correct, @epiolba. The Arduino MCU GPIOs can easily pull low enough (below 0.6 V) to turn the transistor off. R1 is not required. See Jim Fisher's answer. \$\endgroup\$
    – Transistor
    Mar 28 '20 at 22:14
  • \$\begingroup\$ @Transistor Oh interesting! Looks like Jim still has the pull-down, but for a different reason! I didn't know the Arduino was capable, thanks \$\endgroup\$
    – epiolba
    Mar 28 '20 at 22:43
  • \$\begingroup\$ @epiolba - a pull-down resistor is not required for normal operation, when the Arduino is emitting an active low it can drive the voltage to zero. One case where a pull-down (or in other circumstances a pull-up) is useful is for defining the state just after rest before the software has activated the port as an output. \$\endgroup\$ Jun 29 at 23:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.