The Direct Answer: Which Arduino Solenoid Driver to Pick
An Arduino GPIO pin outputs 5V at a maximum safe continuous current of 20mA. A standard 12V water or air solenoid valve draws between 1A and 2A. You cannot wire a solenoid directly to an Arduino pin; doing so will instantly destroy the ATmega328P microcontroller. You need a driver circuit.
Use this decision tree to select the correct driver for your specific hardware.
| Solenoid Spec | Driver Type | Concrete Pick (Part Number) |
|---|---|---|
| 5V DC, < 200mA (Micro valves) | Direct GPIO Drive | None (Wire directly to D9 via 220Ω resistor) |
| 5V-24V DC, < 5A (Standard irrigation/pneumatic) | Logic-Level N-Channel MOSFET | IRLZ44N (Default Pick) |
| 12V-24V DC, > 5A (High-flow industrial) | High-Current Relay or MOSFET Module | Songle SRD-12VDC-SL-C (30A Relay) |
| 24V-120V AC (HVAC/Industrial valves) | Solid State Relay (SSR) | Omron G3NA-210B-DC5-24 |
Parts List & Spec Sheet
This build assumes a standard 12V DC brass water valve. Prices are approximate based on 2026 component market rates.
| Component | Exact Variant / Model | Critical Spec | Est. Price |
|---|---|---|---|
| Microcontroller | Arduino Uno R3 (DIP-28 ATmega328P) | 5V logic, 20mA max GPIO | $24.00 |
| Driver | IRLZ44N N-Channel MOSFET (TO-220) | Vgs(th) max 2.0V, Id 47A | $1.50 |
| Flyback Diode | 1N4007 Rectifier Diode | 1000V PIV, 1A forward current | $0.10 |
| Resistors | 220Ω and 10kΩ (1/4W Carbon Film) | Gate protection and pull-down | $0.05 |
| Power Supply | 12V 2A Switching PSU (Barrel Jack) | 24W max output, 5.5mm x 2.1mm plug | $8.00 |
| Solenoid Valve | US Solid 1/2' NPT 12V DC (Normally Closed) | 12V DC, ~1.2A draw, 11.5W | $14.00 |
Wiring the Arduino Solenoid Circuit
Safety Note: While 12V DC is safe from an electrocution standpoint, a 1.2A continuous current will melt standard 24 AWG breadboard jumper wires over time. Use at least 18 AWG stranded wire for the 12V power loop (PSU to Solenoid to MOSFET Drain), and solder the connections if this is a permanent installation.
Pin Mapping Table
| Arduino Uno R3 Pin | Connects To | Purpose |
|---|---|---|
| D9 (PWM capable) | 220Ω Resistor -> MOSFET Gate | Logic signal to switch the valve |
| GND | 10kΩ Resistor -> MOSFET Gate & PSU GND | Shared reference ground & gate pull-down |
| 5V | (Not used for solenoid power) | Do NOT power the solenoid from the Arduino 5V rail |
Step-by-Step Wiring Procedure
- Establish Common Ground: Connect the GND terminal of your 12V external power supply directly to one of the Arduino Uno's GND pins. If you skip this, the MOSFET gate will not have a reference voltage and the valve will not switch.
- Wire the Gate Pull-Down: Connect a 10kΩ resistor between the MOSFET Gate (middle pin) and GND. This ensures the valve stays closed if the Arduino reboots or the pin floats during startup.
- Wire the Gate Signal: Connect a 220Ω resistor between Arduino D9 and the MOSFET Gate. This limits inrush current into the gate's internal capacitance, protecting the ATmega328P GPIO.
- Wire the Solenoid Power Loop: Connect the 12V PSU positive terminal to one terminal of the solenoid valve.
- Wire the MOSFET Drain: Connect the other terminal of the solenoid valve to the MOSFET Drain (left pin, tab facing you).
- Wire the MOSFET Source: Connect the MOSFET Source (right pin) to the shared GND rail.
- Install the Flyback Diode: Place the 1N4007 diode in parallel with the solenoid coil. The cathode (silver stripe) must point toward the 12V positive side, and the anode must point toward the MOSFET Drain. Reversing this will cause a dead short and blow your power supply fuse.
Complete Arduino Solenoid Code
This code targets the Arduino Uno R3 (ATmega328P). It uses a non-blocking millis() timer to pulse the solenoid and includes a critical safety feature: a maximum runtime limit. If your code logic hangs or a sensor fails, the solenoid will automatically shut off to prevent flooding or coil burnout.
// Target Board: Arduino Uno R3 (ATmega328P)
// Project: 12V Solenoid Valve Non-Blocking Control
const int SOLENOID_PIN = 9;
const int BUTTON_PIN = 2; // Optional manual override button
// Timing variables (milliseconds)
unsigned long previousMillis = 0;
unsigned long solenoidStartTime = 0;
const unsigned long PULSE_DURATION = 5000; // Open for 5 seconds
const unsigned long MAX_RUNTIME = 60000; // Safety cutoff: 60 seconds max
bool solenoidState = false;
bool pulseActive = false;
void setup() {
Serial.begin(9600);
// Pin configuration
pinMode(SOLENOID_PIN, OUTPUT);
pinMode(BUTTON_PIN, INPUT_PULLUP); // Active LOW button
// Ensure valve is closed on boot
digitalWrite(SOLENOID_PIN, LOW);
Serial.println("System Initialized. Solenoid closed.");
}
void loop() {
unsigned long currentMillis = millis();
// Read manual override button (debounced implicitly by state change check)
bool buttonPressed = (digitalRead(BUTTON_PIN) == LOW);
// Trigger a new pulse if button is pressed and no pulse is currently active
if (buttonPressed && !pulseActive) {
openSolenoid(currentMillis);
}
// Handle active pulse timing
if (pulseActive) {
unsigned long timeElapsed = currentMillis - solenoidStartTime;
// Normal completion
if (timeElapsed >= PULSE_DURATION) {
closeSolenoid("Pulse duration complete.");
}
// Safety Error Handling: Hard cutoff to prevent flooding
if (timeElapsed >= MAX_RUNTIME) {
closeSolenoid("ERROR: Max runtime exceeded. Forcing close.");
// Add a delay to prevent immediate re-triggering if button is stuck
delay(2000);
}
}
}
void openSolenoid(unsigned long currentTime) {
digitalWrite(SOLENOID_PIN, HIGH);
solenoidState = true;
pulseActive = true;
solenoidStartTime = currentTime;
Serial.println("Solenoid OPENED.");
}
void closeSolenoid(String reason) {
digitalWrite(SOLENOID_PIN, LOW);
solenoidState = false;
pulseActive = false;
Serial.print("Solenoid CLOSED. Reason: ");
Serial.println(reason);
}
Debugging: First 3 Things to Check When It Fails
The most common failure mode in solenoid circuits is the Arduino resetting when the solenoid fires. On the Arduino Uno R3, this manifests as the Serial monitor clearing and re-printing the setup() initialization text. If you swap to an ESP32, the serial monitor will output the exact error string: Brownout detector was triggered followed by rst cause:4.
This happens because inductive kickback or voltage sag on the 12V rail is coupling back into the Arduino's 5V logic rail, triggering the microcontroller's internal Brownout Detector (BOD). Check these three things in order:
1. The Flyback Diode is Missing or Reversed
The Fix: Verify the 1N4007 diode is physically across the solenoid coil (not across the MOSFET). Ensure the silver stripe (cathode) faces the 12V positive wire. If the diode is backwards, it acts as a dead short when the MOSFET turns on, causing the PSU to fold back its voltage, which starves the Arduino of power and causes a brownout reset.
2. You Used a Standard MOSFET Instead of Logic-Level
The Fix: Check the part number printed on your transistor. If it says IRF520 or IRFZ44N, throw it in the bin and buy an IRLZ44N (the 'L' stands for Logic-level). Standard MOSFETs require 10V on the gate to fully open. Driven by a 5V Arduino, they operate in their linear (high-resistance) region. They will get blisteringly hot, fail to pass enough current to pull in the solenoid, and can cause ground-bounce that resets the Arduino. (Reference the Arduino transistor guide for more on Vgs thresholds).
3. Missing Common Ground or Undersized Power Supply
The Fix: Measure the voltage between the Arduino GND pin and the 12V PSU GND terminal with a multimeter while the solenoid is firing. It should read < 0.1V. If it reads higher, your ground wire is too thin. Furthermore, ensure your 12V PSU is rated for at least 2A. A 500mA PSU will experience severe voltage droop when the solenoid's inrush current hits, collapsing the 5V regulator on the Arduino board.
Extending and Simplifying the Build
How to Simplify (The Relay Alternative)
If you don't want to deal with raw MOSFETs, gate resistors, and loose diodes, simplify the build by using a pre-assembled 5V Optocoupler Relay Module (featuring the Songle SRD-05VDC-SL-C relay).
- Wiring: Connect VCC to Arduino 5V, GND to Arduino GND, and IN to D9.
- Solenoid Loop: Wire the 12V PSU and solenoid through the relay's COM (Common) and NO (Normally Open) screw terminals.
- Trade-off: The relay module includes its own built-in flyback diode and optocoupler isolation, making it virtually bulletproof against brownouts. However, mechanical relays are rated for roughly 100,000 click cycles and are louder than a solid-state MOSFET.
How to Extend (Automated Scheduling)
To turn this manual push-button circuit into an automated irrigation system, add a DS3231 I2C Real Time Clock (RTC) module.
- Wire the DS3231 SDA to A4 and SCL to A5 on the Uno R3.
- Use the
RTCliblibrary to read the current time. - Add logic to the
loop()to trigger theopenSolenoid()function at specific hours (e.g., 06:00 AM and 06:00 PM). - Pro-Tip: Add a soil moisture sensor (analog output to A0) and implement hysteresis. Only allow the RTC to open the solenoid if the soil moisture reading is below 30%, preventing overwatering during rain events.






