To build a reliable arduino half bridge for driving DC motors, solenoids, or inductive loads up to 40V and 30A, use the IR2104 gate driver paired with two IRFZ44N N-channel MOSFETs. This combination provides hardware-level dead-time generation to prevent shoot-through, while keeping the bill of materials under $8. Below is the exact wiring, the physics of the bootstrap circuit, and the fault-handling code you need to get it running safely on the bench.
Time to Build: 45 minutes on a breadboard, 2 hours for soldered perfboard
Target Board: Arduino Uno R3 (ATmega328P) or Nano v3
The Verdict: Which Half-Bridge Setup Should You Build?
Not all half-bridge designs are created equal. Your choice of driver and MOSFETs depends entirely on your voltage, current, and switching frequency requirements. Use this decision path to lock in your hardware.
| Application Scenario | Recommended Driver + MOSFET | Why This Wins |
|---|---|---|
| High-current (>43A) quick prototyping, low PWM freq (<1kHz) | BTS7960 Pre-built Module | Massive copper pours handle heat; integrated logic-level gates. No discrete wiring needed. |
| High-voltage AC inversion or >60V DC bus | IR2110 + IRFP460 (N-CH) | IR2110 supports independent high/low control up to 600V; IRFP460 handles high Vds. |
| Standard 12V-36V DC motor control, <30A, high PWM (up to 20kHz) | IR2104 + IRFZ44N (DEFAULT PICK) | IR2104 has built-in 520ns dead-time preventing shoot-through. IRFZ44N offers 17.5mΩ Rds(on) for low heat at 30A. |
Concrete Pick: Unless you are pushing past 43A continuous or dealing with mains-level voltages, build the IR2104 + IRFZ44N circuit. It teaches proper bootstrap physics, avoids the massive heat generation of linear drivers, and fits standard 0.1" breadboards.
Parts List and Pin Mapping for the IR2104 Build
Before wiring, gather these exact components. Do not substitute the bootstrap capacitor with a standard electrolytic; the high dV/dt of the switching node will cause electrolytics to fail due to Equivalent Series Inductance (ESL).
- Microcontroller: Arduino Uno R3 (ATmega328P)
- Gate Driver: IR2104 (DIP-8 package)
- MOSFETs: 2x IRFZ44N (N-Channel, TO-220)
- Bootstrap Capacitor: 1x 10µF 50V X7R Ceramic Capacitor (Critical)
- Bootstrap Diode: 1x UF4007 Ultrafast Recovery Diode
- Gate Resistors: 2x 10Ω 1/4W (Dampens LC ringing on gate traces)
- Pull-down Resistor: 1x 10kΩ (Keeps low-side gate grounded during MCU boot)
- Current Shunt: 1x 0.01Ω 2W power resistor (For overcurrent sensing)
Spec Sheet: IR2104 and IRFZ44N Limits
| Parameter | IR2104 Driver | IRFZ44N MOSFET |
|---|---|---|
| Max Voltage (Vds / Vbus) | 600V (Bootstrap limit ~25V) | 55V |
| Max Continuous Current | N/A (Outputs +1.4A / -1.8A peak) | 49A (at 25°C case temp) |
| Key Timing | 520ns internal dead-time | Qg (Gate Charge) = 72nC |
Pin Mapping Table
| IR2104 Pin | Function | Connect To |
|---|---|---|
| 1 (VCC) | Logic Supply | Arduino 5V |
| 2 (HIN) | High-Side Input | Arduino Pin 9 (PWM) |
| 3 (LIN) | Low-Side Input | Arduino Pin 10 |
| 4 (SD) | Shutdown (Active Low) | Arduino 5V (Keeps driver enabled) |
| 5 (VSS) | Logic Ground | Arduino GND & Power GND |
| 6 (VB) | High-Side Float Supply | Bootstrap Cap (+) & UF4007 Cathode |
| 7 (HO) | High-Side Gate Output | 10Ω Resistor -> High-Side IRFZ44N Gate |
| 8 (VS) | High-Side Float Return | Switch Node (High-Side Source & Low-Side Drain) |
For a deeper look at why the bootstrap capacitor must be tied to the switch node (VS) to charge the high-side gate above the bus voltage, refer to the Texas Instruments SLUA341 Gate Driver Fundamentals application note.
Compilable Arduino Code with Fault Handling
This firmware targets the Arduino Uno R3. It uses hardware PWM on Pin 9 for the high-side and manual digital switching on Pin 10 for the low-side. It includes an analog read loop to monitor a low-side current shunt, triggering a hardware shutdown if the current exceeds 24A.
// Arduino Half Bridge Controller - IR2104 + IRFZ44N
// Target: Arduino Uno R3 (ATmega328P)
#define HIN_PIN 9 // High-side PWM (Hardware Timer 1)
#define LIN_PIN 10 // Low-side control
#define CURRENT_PIN A0 // Analog input from low-side shunt
#define FAULT_LED 13 // Onboard LED for fault indication
// 0.01 ohm shunt. At 24A, V = 0.24V.
// With a 10x op-amp gain, V_in = 2.4V.
// Arduino ADC: 2.4V / 5.0V * 1023 = ~491.
#define OVERCURRENT_THRESHOLD 491
const char* ERR_MSG = "ERR: OVERCURRENT_ADC_THRESHOLD";
bool systemFault = false;
void setup() {
Serial.begin(115200);
pinMode(HIN_PIN, OUTPUT);
pinMode(LIN_PIN, OUTPUT);
pinMode(FAULT_LED, OUTPUT);
pinMode(CURRENT_PIN, INPUT);
// Ensure both gates are LOW on boot to prevent shoot-through
digitalWrite(HIN_PIN, LOW);
digitalWrite(LIN_PIN, LOW);
digitalWrite(FAULT_LED, LOW);
Serial.println("SYS: IR2104 Half-Bridge Initialized");
}
void loop() {
if (systemFault) {
// Halt all operations if a fault was latched
return;
}
// Read current sense ADC
int currentADC = analogRead(CURRENT_PIN);
if (currentADC > OVERCURRENT_THRESHOLD) {
triggerFault();
return;
}
// Normal Operation: Synchronous Buck / Motor Drive
// LIN acts as the freewheeling path when HIN is off
digitalWrite(LIN_PIN, HIGH); // Enable low-side for freewheeling
// Ramp up PWM on high-side (Example: 50% duty cycle)
// analogWrite on Pin 9 uses Timer 1 (approx 490Hz default)
analogWrite(HIN_PIN, 127);
delay(10); // Small delay to prevent ADC reading jitter
}
void triggerFault() {
systemFault = true;
// Immediately kill both gates
analogWrite(HIN_PIN, 0);
digitalWrite(LIN_PIN, LOW);
// Signal fault
digitalWrite(FAULT_LED, HIGH);
Serial.println(ERR_MSG);
Serial.print("SYS: ADC Value at fault = ");
Serial.println(analogRead(CURRENT_PIN));
Serial.println("SYS: Halting. Press reset to restart.");
}
Debugging: First Three Things to Check When It Fails
When your motor stutters, the MOSFETs overheat instantly, or the serial monitor throws an error, do not blindly swap parts. Follow this ranked troubleshooting path.
ERR: OVERCURRENT_ADC_THRESHOLDIf you see this in your serial monitor, the Arduino has detected a current spike and latched the gates off. This is usually caused by a shorted load or a shoot-through event, not necessarily a software bug.
- Check the Bootstrap Capacitor Charge Path (Most Common)
If the high-side MOSFET gets hot but the low-side stays cool, the high-side gate isn't receiving enough voltage to fully enhance (Vgs < 10V). The IR2104 relies on the low-side MOSFET turning ON to pull the VS pin to ground, allowing VCC to charge the bootstrap capacitor through the UF4007 diode. Fix: Ensure your PWM routine periodically turns the low-side ON. If you are running 100% duty cycle on the high-side, the bootstrap cap will drain and the high-side MOSFET will enter its linear region and burn up. Keep max PWM at 95%. - Verify Common Ground and Star Topology
If the Arduino resets randomly when the motor starts, you have ground bounce. The high di/dt of the motor current flowing through the ground plane creates a voltage spike that resets the ATmega328P. Fix: Use a star-ground topology. The Arduino GND, the IR2104 VSS (Pin 5), and the low-side MOSFET source must meet at a single physical point, separate from the high-current motor ground return. - Measure Gate Ringing with an Oscilloscope
If the driver IC is physically cracking or getting too hot to touch, parasitic inductance in your gate traces is causing high-frequency ringing, rapidly switching the internal driver transistors. Fix: Probe the gate-to-source voltage (Vgs) with an oscilloscope. If you see spikes exceeding ±20V, increase the 10Ω gate resistors to 22Ω or 47Ω to dampen the LC tank circuit formed by the trace inductance and the MOSFET's gate capacitance.
For more on diagnosing parasitic ringing in power electronics, the All About Circuits Half-Bridge Tutorial provides excellent oscilloscope capture examples of shoot-through versus normal switching.
Extending and Simplifying the Build
Once you have the baseline circuit running safely, you will likely want to adapt it for your specific project constraints. Here is how to modify the design without starting from scratch.
How to Extend: Adding Hardware Dead-Time
The IR2104 has 520ns of internal dead-time, which is sufficient for the IRFZ44N at frequencies under 20kHz. However, if you upgrade to MOSFETs with massive gate charge (like the IRFP460) or switch at 50kHz+, 520ns isn't enough to prevent both MOSFETs from conducting simultaneously during the Miller plateau region.
The Fix: Add a 74HC08 (Quad AND gate) IC. Feed your Arduino PWM into one input of the AND gate, and feed a delayed/inverted version into the other to create a hardware-enforced 1µs dead-time before the signal ever reaches the HIN and LIN pins. This completely offloads the timing safety from the Arduino's software interrupts.
How to Simplify: The Module Route
If you are building a line-following robot or a quick RC car repair and do not want to calculate bootstrap capacitance or worry about ground bounce, abandon the discrete IR2104 build.
The Fix: Buy a BTS7960 43A High-Power Motor Driver Module (usually $6-$10 on Amazon or AliExpress). It integrates the half-bridge drivers, logic level shifting, and massive heat sinks onto a single board. You only need to wire VCC, GND, R_EN, L_EN, R_PWM, and L_PWM. It sacrifices switching speed (max 25kHz) and efficiency at low loads, but it guarantees you will not blow up your microcontroller during your first bench test.
By selecting the right driver for your exact current and frequency needs, you eliminate the most common embedded power failures before you even write a line of code.






