An Arduino, PIR sensor and DC motor circuit - learn how to control a DC motor with a PIR sensor and Arduino.

Turn on a DC Motor with a PIR Motion Sensor and Arduino

Welcome to my comprehensive Arduino tutorial designed to unleash the creative potential of motion-activated projects using DC motors, Arduino, and PIR sensors. Whether you’re crafting spooky animatronics for a haunted house, interactive robots, or dynamic attractions that respond to guests, this guide will walk you through exactly how to turn on your DC motor with a PIR sensor and Arduino. We’ll start with the basics of wiring your PIR sensor, motor driver module, and DC motor to an Arduino, making sure you understand the power supply requirements that keep your projects running smoothly. Then, we’ll dive into practical Arduino code examples, showcasing a variety of DC motor movements that can be triggered by the slightest motion.

In this DC Motor Control with Arduino and PIR Sensor Tutorial:

What You’ll Need for this Arduino Project

You only need a handful of electronic components to control a DC motor with Arduino and a PIR sensor:

  • Arduino Uno (or compatible board): The microcontroller board is the brain of your project. An Arduino Uno is a good choice for beginners because it’s easy to use and has extensive documentation and community support you can lean on. We’ll use it to read the signal from the PIR sensor and control the DC motor’s movement based on whether or not motion is detected.
  • PIR (Passive Infrared) Sensor: This sensor detects motion by measuring changes in the infrared (heat) levels emitted by objects in its field of view. When the PIR sensor detects motion, it will send a signal to the Arduino.
  • DC Motor: You can use just about any DC motor for Arduino projects so pick one that will meet the needs of the load you intend to move. In my case, I’m using every prop-maker’s favorite – a windshield wiper motor. You just can’t beat the torque you get for the price. The voltage and current rating of the DC motor you choose will determine the type of motor driver module you need to power and control it via the Arduino.
  • Motor Driver Module: Most Arduino boards can’t provide enough current to directly power a DC motor. A motor driver module acts as an intermediary between the Arduino and the motor, allowing the Arduino to control the direction and speed of the motor. The specific motor driver module you choose will depend on the voltage and current requirements of your DC motor. A popular choice for beginners is the L298N module which can control two DC motors and provide 2A per motor. Because we’re controlling a much larger motor that draws at least 5A in this example, I need something beefier. I’ll be using the XY-160D motor module which can also run two DC motors and provide 7A of continuous current for each.
  • Jumper Wires: You’ll need both male-to-male and male-to-female jumper wires to connect the PIR sensor and motor driver module to the Arduino and breadboard.
  • Breadboard: A breadboard is a perforated board that allows you to easily connect electronic components without soldering. It’s a great way to prototype and test your circuit before soldering the components onto a permanent PCB.
  • Power Supply: You will need two separate power supplies for this project. One power supply will be used to power the Arduino board, and the other will be used to power the DC motor. For this Arduino tutorial, you can just power your Arduino with the same USB cable that you use to upload code from your computer. As for the DC motor, choose a power supply that exactly matches the voltage requirements and provides enough current to run it. My wiper motor needs 12V and a minimum of 5A to run so I’ll be using a 12V 8A power adapter.
  • Female DC Jack Adapter: I’m not a huge fan of cutting up my power cords, so I always use a female DC jack adapter that I can connect to the motor driver module and plug the male end of my power adapter into. You can either buy the screw terminal variety like I have or the ones with pigtails already attached for a cleaner look.

Now that you have all your components together, let’s wire it all up with an Arduino Uno!

How to Wire a DC Motor and PIR Sensor to an Arduino

Arranging this pile of components into a working circuit that we can then write an Arduino sketch for may look overwhelming at this point. But I always find that focusing on just one component at a time, helps to break down the circuit into easily manageable parts.

I also covered how to wire a PIR sensor to Arduino and how to wire a DC motor to Arduino in fully detailed stand-alone Arduino tutorials if you would like a deeper dive into each of these individual components.

1. Prepare the Breadboard Power Rails

For the most part, we’ve been powering the PIR sensor directly through the Arduino Uno by using its 5V pin. In this case, the motor driver module will also need 5V to operate. Since we can’t physically plug two different components into the same Arduino pin, we’re going to set up a breadboard to handle our power needs.

An Arduino Uno and breadboard with a red jumper wire connecting the 5V pin of the Arduino Uno to the positive power rail of the breadboard and a black jumper wire connecting the ground pin of the Arduino Uno to the negative power rail of the breadboard.

  • Take a jumper wire (preferably red) and connect one end to the 5V pin of the Arduino and the other end into any hole along the positive power rail (red) of the breadboard. Now, anything you plug into this positive power rail will get power from the Arduino Uno.
  • With another jumper wire (preferably black), connect one end into a GND (ground) pin of the Arduino Uno and the other end into one of the holes along the negative power rail (blue) of the breadboard. You can now ground all your components by plugging their ground wires into this negative power rail.

3. Wire the PIR Sensor to the Arduino Uno

Let’s start with our easiest component, the PIR sensor. It only has three pin connections – Vcc, OUT and GND. The labels for the pins are usually printed on the top of the circuit board and you’ll have to pop off the white Fresnel lens to see them.

A PIR motion sensor with its Fresnel lens removed to show the pinout - VCC, OUT and GND.

To wire each of the PIR sensor pins, you’ll need female-to-male jumper wires.

A PIR motion sensor wired to a breadboard and Arduino Uno. The VCC and GND pins are connected to the breadboard power rail and the OUT pin is connected to pin 12 of the Arduino Uno.

  • Connect the VCC pin of the PIR sensor to the positive power rail of the breadboard.
  • Connect the OUT pin of the PIR sensor to any digital I/O pin on the Arduino Uno. I picked pin 12 for the examples below.
  • Connect the GND pin of the PIR sensor to the negative power rail of the breadboard.

4. Wire the Motor Driver Module to the Arduino Uno

Be sure to select the right motor driver module that matches or exceeds the requirements of your DC motor. I’m using a 12V windshield wiper motor, which is a favorite among motorized prop makers because it delivers a lot of torque for a low price. This DC motor needs a minimum of 5A to operate so a motor driver module like the XY-160D or even a IBT-2 BTS7960 is a great choice.

For this Arduino project, I’ll be using the XY-160D because it can provide 9-24V and 7A which is enough for my 12V 5A windshield wiper motor.

This motor driver module can control two motors so you’ll see two black screw terminal areas on the right side of the board (where you connect the DC motors) and two vertical columns of identical pins on the upper left portion of the board (where you connect to the Arduino Uno). Since I’m only using one DC motor, I’ll just be using the left column of pins to connect the motor driver module to my Arduino Uno. You’ll need female-to-male jumper wires to make these connections.

A motor driver module wired to a breadboard and Arduino Uno. The +5V and GND pins of the motor driver are connected to the power rail of the breadboard. The ENA pin is connected to pin 6 of the Arduino Uno and the IN1 and IN2 pins are connected to pins 7 and 8 of the Arduino Uno.

Working from top to bottom on the motor driver module:

  • 5V Pin: Connect the 5V pin of the motor driver module to the positive power rail of the breadboard. This will allow the Arduino Uno to power the motor driver module itself and has nothing to do with powering your DC motor.
  • ENA Pin: This pin allows you to control the speed of the DC motor with the Arduino. Be sure to connect this pin to a PWM-capable pin on the Arduino Uno. The PWM (pulse width modulation) pins are the ones that have a squiggly line (~) next to the pin number. I chose pin 6 on my Arduino Uno.
  • IN1 & IN2 Pins: These pins on the motor driver module allow you to control the direction of rotation of the DC motor. Sending a HIGH (5V) signal from the Arduino to IN1 will turn the DC motor in one direction while sending a HIGH (5V) signal to IN2 turns it in the opposite direction. The Arduino pins you choose for IN1 and IN2 don’t have to be PWM-capable. Any digital I/O pin will work. I’m using pin 7 for IN1 and pin 8 for IN2.
  • GND Pin: Connect the GND (ground) pin of the motor driver module to the negative power rail of the breadboard.

5. Wire the DC Motor to the Motor Driver Module

Unless you’re using a windshield wiper motor like me, your DC motor should only have two wires attached to it – a positive and a negative. Insert the wires of your DC motor into the motor 1 screw terminal of the motor driver module and tighten down the set screws to secure them.

In my case, the yellow wire is the high speed wire and the black wire is ground.

A DC motor wired to a motor driver module which is controlled by an Arduino Uno.

The orientation of the wires doesn’t matter. It simply determines the direction of rotation when the DC motor spins. We can also change this in the Arduino sketch through the IN1 and IN2 pins.

6. Power Your Motor via the Motor Driver Module

The XY-160D motor driver module will get it’s power from the Arduino Uno, but the DC motor will need it’s own separate power supply. There’s a dedicated screw terminal block on the motor driver module for wiring in the DC motor’s power supply – mine is green.

A power supply for the DC motor is wired to a motor driver module that will provide separate power to the motor.

You’ll notice that your power adapter has a male jack at the end which you can’t just plug into the motor driver module. Rather than cut it off, I prefer to use a female DC power jack adapter.

Pay special attention to the polarity of your power supply connection. Make sure the positive and negative wires are going into the correct screw terminal slots.

DC Motor with PIR Sensor Arduino Code Examples

With all our components wired up, let’s explore some Arduino code examples for turning on the DC motor as well as controlling direction and speed when the PIR sensor detects motion.

Test your PIR Sensor Connections

Before we start writing Arduino code to control the DC motor based on motion detection, let’s test the PIR sensor to be sure it’s wired up correctly. This Arduino sketch uses the Serial Monitor to print out the results of the PIR sensor.

Upload this Arduino sketch and pop open the Serial Monitor. If your PIR sensor is wired up correctly, you should see your PIR sensor at work when you wave your hand in front of it.

Arduino Serial Monitor showing the readings from a PIR Sensor connected to an Arduino Uno.

This is also a good time to adjust your PIR sensor settings like the Time Delay and Sensitivity potentiometers.

A PIR motion sensor showing the locations of the Time Delay and Sensitivity potentiometers and Trigger Mode jumper.

If this is your first time working with a PIR sensor, I encourage you to check out my beginner’s guide on how to use a PIR sensor with Arduino which goes into great detail about the adjustments you can make on the motion sensor itself as well as an introduction to Arduino code for PIR sensors.

For these Arduino code examples, I turned both potentiometers all the way down (counter-clockwise), which means that the PIR sensor will stay HIGH for the shortest amount of time (about 3 seconds) and have the shortest detection range (around 3 meters). You can fine tune these settings later depending on how long you want your DC motor to stay active after being triggered by the PIR sensor.

Arduino Code Example 1: Spin the DC Motor when Motion is Detected

If you simply want to turn on a DC motor when motion is detected by the PIR sensor and then turn it off once the motion has passed, this Arduino sketch is an easy way to do it.

As soon as you wave your hand in front of the PIR sensor, the DC motor should start spinning at full speed. It will continue spinning for as long as you have the Time Delay knob set.

Adjust PIR Sensor Time Delay Potentiometer

If you had your Time Delay knob on the PIR sensor turned all the way counter-clockwise like me, the DC motor will only spin for a short time. Try increasing the Time Delay by turning the potentiometer on the PIR sensor clockwise. The DC motor will spin for a longer period of time. Adjusting the Time Delay knob on the PIR sensor is an easy way to set how long you want your DC motor to spin for when the PIR sensor detects motion.

Change the DC Motor’s Direction of Spin with Arduino Code

Before moving on to the next Arduino code example, try spinning the DC motor in the opposite direction by swapping the HIGH and LOW for the IN1 and IN2 pins on lines 24 and 25 so it looks like:

digitalWrite(IN1pin, LOW);
digitalWrite(IN2pin, HIGH);
analogWrite(ENApin, 255);

When you wave your hand in front of the PIR sensor, does the DC motor turn in the opposite direction that it was turning previously? If so, then your IN1 and IN2 pins are wired correctly to the Arduino Uno.

Change the Speed of the DC Motor with Arduino Code

Now try different speeds by selecting PWM values from 0 to 255 for the ENA pin on line 26:

analogWrite(ENApin, 100);

As you try lower and lower speeds, you’ll notice that your DC motor stops turning well before hitting 0. This has to do with how often the PWM pin on the Arduino is instructing the motor driver module to pulse 12V to my motor. For instance, at a value of 255, my DC motor gets 12V continuously. But at half that value, say 128, the motor driver module is only pulsing 12V to my DC motor 50% of the time which causes the motor to spin half as fast. As the PWM value for speed gets lower, my DC motor receives too few 12V pulses to operate.

It’s important to find the “floor” value at which your DC motor stops turning reliably because you don’t want to go through the trouble a orchestrating a sequence of rotations and speeds only to find out that your motor doesn’t operate for parts of your Arduino sketch.

The “floor” will be different for each DC motor. My windshield wiper motor stops spinning reliably at about a PWM value of 65 so I’m going to use 70 for my slowest speed.

Arduino Code Example 2: Spin the DC Motor in Both Directions when Motion is Detected

Perhaps you have a prop, like a scary spider that you want to roll down from the ceiling when the PIR sensor detects motion. This spider can spend a moment at the bottom of the drop to scare passersby and then get pulled back up into the ceiling, ready for the next scare.

Let’s write an Arduino sketch that spins the motor in one direction for a set period of time, then pauses the motor for a few seconds before changing directions to retract our imaginary spider.

When you wave your hand in front of the PIR sensor, the DC motor animation sequence should start immediately. It will spin in one direction for 2 seconds, pause for 3 seconds and then change direction and spin for 2 seconds. Finally, the DC motor will stop and be ready to be triggered again by the PIR sensor.

If the Time Delay potentiometer on the PIR sensor is set to a short trigger period, then the motor animation sequence will happen one time. But if you increase the Time Delay, you’ll notice that the DC motor will repeat the sequence, sometimes multiple times if you have the Time Delay knob cranked all the way clockwise (longest trigger period).

How do we trigger our DC motor animation sequence just one time? Otherwise, my Halloween spider prop will look like it’s broken or confused.

The easiest fix is to dial down the Time Delay potentiometer on the PIR sensor so it only remains HIGH for a short period of time after detecting motion. But we can also fix this in the Arduino code.

Activating Components Based on a PIR Sensor’s Current State vs. State Change

So far, we’ve been turning on our DC motor based on the current state of the PIR sensor. So long as the OUT pin of the PIR sensor remains HIGH, your components will keep getting triggered repeatedly. Another option we’re going to explore is to trigger components based on a PIR sensor’s state change, which is a singular event and can give you more control over animation or movement sequences.

Activating Components Based on PIR Sensor Current State

In this scenario, the component (DC motor in our case) is activated directly in response to the current state of the PIR sensor. For example, if the PIR sensor’s output is HIGH (indicating motion is detected), the component is activated. If the sensor’s output is LOW (indicating no motion), the component is deactivated.

This approach is straightforward and best for simple applications where immediate response to motion presence is needed, such as turning on a light when someone enters a room.

Since this method reacts to the PIR sensor’s ongoing output, it can lead to the component being repeatedly activated or deactivated in short intervals, especially if the sensor detects intermittent movements. This might not be ideal for applications where such frequent switching is undesirable or where a more discrete event trigger is needed.

Activating Components Based on PIR Sensor State Change

The best way to control specific sequences or orchestrate events that happen only once, regardless of the Time Delay knob setting, is to do it based on the state change of the PIR sensor.

Here, the component activation is based on the change in state of the PIR sensor, not just its current state. Specifically, the transition from LOW to HIGH (indicating the onset of motion) or from HIGH to LOW (indicating the end of motion) triggers the action. This approach requires monitoring the PIR sensor’s output over time to detect these transitions.

This method is ideal for scenarios where you want to trigger an action at the moment something starts or stops moving, such as starting a sequence when someone enters an area and having the sequence complete without interruption, regardless of continued motion.

Implementing state change detection typically involves some extra Arduino code for tracking the PIR sensor’s previous state and comparing it to its current state. But, it prevents your component from being constantly activated or deactivated due to the sensor’s sensitivity to ongoing motion, making it better for applications requiring a singular response to the start or end of motion.

Arduino Code Example 3: Spin the DC Motor in Both Directions when Motion is Detected (based on State Change)

In order to get our DC motor to react according to the PIR sensor’s state change instead of its current state, all we have to do is to move our animation block of code to another part of the Arduino sketch.

Looking through this Arduino sketch, you’ll notice that we moved our block of code further down into the next if statement on line 24. This if statement is responsible for tracking when a change in state of the PIR sensor happens. Only when the state of the PIR sensor changes from LOW to HIGH will our DC motor animation sequence start. And because a state change is a singular event, so will be our motor animation sequence.

Upload this Arduino sketch and wave your hand in front of the PIR sensor. If you have your Time Delay potentiometer on the sensor itself turned down to a shorter time period, try increasing it. You’ll notice that your DC motor animation sequence runs through only one time.

Arduino Code Example 4: Accelerate and Decelerate the DC Motor

For more realism in my motorized prop motions, I prefer to accelerate the DC motor into its final speed when motion is detected and then decelerate the motor into a full stop once the motion has ended. How fast you want to accelerate your prop into motion or decelerate it to a stop depends on the mood you’re trying to create.

For instance, if you have a creepy doll in a rocking chair, you might want to start the rocking motion slowly when someone passes by and then gradually accelerate it over time. Then, once the motion has ended, the rocking chair can slowly come to a stop.

On the other hand, a groundbreaker zombie could accelerate to life with arms flailing quickly for a fun scare.

Let’s write an Arduino sketch where our DC motor accelerates to full speed when the PIR sensor detects motion and then decelerates to a stop once the signal returns to LOW. This is another animation sequence that is best handled by placing code in the state change area versus the current state area of our Arduino sketch.

On line 8 of this Arduino sketch, I created another variable, mSpeed, to store the PWM values for the motor speed. Since we’re going to moving through speeds, I won’t be able to hardcode any PWM values like we’ve been doing up until now.

Upon detecting a state change in the PIR sensor from LOW to HIGH, the first thing I do is specify a direction in lines 30 & 31. Then the DC motor acceleration happens in a for loop, taking the PWM value for mSpeed from 70 to 255 in increments of 5, every 150 ms.

Once the PWM value for mSpeed reaches 255, I then hold it there for the remainder of the HIGH period.

Once the motion has ended and the PIR sensor changes states from HIGH to LOW, I then begin the deceleration process. On lines 51 and 52, I maintain the same direction of rotation and use another for loop to decelerate from 255 to 50 in increments of 5, every 150ms. Once the mSpeed value reaches 50, my DC motor won’t be turning anyways so I stop the motor by turning both direction pins LOW on lines 61 and 62.

Perfecting DC Motor Control with a PIR Sensor & Arduino

Throughout this Arduino tutorial, we’ve journeyed from the basic concepts of wiring a PIR sensor, motor driver module, and DC motor to an Arduino, through to power supply considerations and writing Arduino code examples to bring motion-activated movements to life. My goal was to give you the foundation to create interactive props, animatronics, robots, and attractions, adding a dynamic layer to your Arduino projects. By now, you should feel confident in your ability to integrate motion detection into your creations, opening up a world of possibilities for innovation and interactivity.

Remember, the Arduino code examples we tried out are just a starting point; the real magic lies in how you adapt and expand upon these ideas to realize your unique visions. Check out my controlling DC motors with Arduino tutorial for even more Arduino code examples that you can integrate with a PIR sensor.

Whether you’re enhancing a haunted house, building an interactive exhibit, or designing a robot with personality, the skills you’ve acquired here are a powerful tool in your maker’s arsenal. Keep experimenting, learning, and pushing the boundaries of what you can create. The world of interactive electronics is vast and endlessly fascinating, and you’re now better equipped to explore it.