How to Control a DC Motor using an Ultrasonic Sensor and Arduino.

Control a DC Motor with an Ultrasonic Sensor and Arduino

Ever wanted to make a motor react to movement—like an automatic door, a spooky Halloween prop, or a robot that speeds up when you get close?

In this Arduino tutorial, we’re making that happen! You’ll learn how to use an ultrasonic sensor to detect distance and control a DC motor using an Arduino and an XY-160D motor driver.

First, we’ll trigger the motor when an object gets within range. Then, we’ll take it up a notch and make the motor’s speed adjust dynamically based on distance—because why settle for just on and off?

Let’s wire it up, code it out, and bring your project to life!

If this is your first time working with ultrasonic sensors or DC motors, no worries—I’ve got you covered!

I’ve already created in-depth tutorials on how these components work with Arduino individually. So, we’ll jump straight into the wiring here, but if you need more details on how they function, wiring diagrams, or extra code examples, be sure to check out these tutorials:

Wire a DC Motor & Ultrasonic Sensor to an Arduino

Start by positioning your ultrasonic sensor on the breadboard so that jumper wires or other components don’t obstruct the large round transducers.

I often find that wiring from behind is the best way to wire up these sensors but wiring diagram programs don’t make it possible to show you my preferred layout.

That’s why all my components are in front of the sensor in the wiring diagram below. It’s best to put them all behind the sensor so it gets a clear field of “listening”.

Breadboard wiring diagram showing how to wire an ultraosnic sensor, dc motor and motor driver to an Arduino.

Step 1: Connect the Ultrasonic Sensor to the Arduino

Alright, it’s time to get your ultrasonic sensor talking to your Arduino! Let’s break down its four pins—each one has a specific job, like a well-organized group project where everyone actually does their part. Here’s the lowdown:

  • VCC (Power): Connect it to 5V on the Arduino, and it’ll be ready to send out ultrasonic waves like a tiny, high-tech bat.
  • GND (Ground): This pin connects to GND on the Arduino and keeps everything in balance.
  • Trig (Trigger): When you send a short pulse (10 microseconds) from your Arduino to the Trig pin, the sensor knows it’s time to fire off sound waves. Think of it as the “go” signal for the sensor to do what it’s made for—measure time to calculate distance. I’m using pin 9 on the Arduino.
  • Echo (Receiver): After the Trig pin does its job, the Echo pin listens. It stays HIGH while waiting for the sound waves to return after bouncing off an object. The longer it stays HIGH, the farther away the object is. The Arduino times this signal and uses some quick math to calculate the exact distance. I’m using pin 10 on the Arduino.
ULTRASONIC SENSORARDUINO UNO
Vcc5V
Trig9
Echo10
GNDGND

And just like that, your ultrasonic sensor is officially hooked up and ready to start detecting distances! With this setup, your Arduino now has Daredevil eyes—or at least a pretty cool sonar system. Let’s move on and see how we can put this newfound power to work!

Step 2: Connect the Motor Driver and DC Motor to the Arduino

DC motors are power-hungry beasts, and your poor Arduino simply isn’t built to handle that kind of current. If you try to power the motor directly from the Arduino, you’ll either burn out the board, underpower the motor, or both (and neither is fun).

The motor driver steps in as the middleman, handling the high current draw from your DC motor while letting the Arduino safely send control signals. This means you get direction control, variable speed, and protection for your Arduino, all in one compact module.

Power Connections for the Motor and Driver

The XY-160D is a high-power motor driver that’s perfect for handling the beefy current demands of a wiper motor, making it a solid choice for props, robotics, or anything that needs a strong motor with smooth control.

Motor Power (VCC & GND)

  • The XY-160D needs its own high-current power source for the wiper motor. Connect the positive terminal of your 12V power supply to the VCC terminal on the motor driver.
  • Connect the negative terminal of your power supply to the GND terminal on the driver.
  • Make sure to use thick wires capable of handling the current load—wiper motors can draw several amps under load.
XY-160D DRIVER MODULEPOWER SUPPLY
VCCPositive Terminal or Wire
GNDNegative Terminal or Wire

Logic Power (5V)

  • The XY-160D has a 5V logic interface, which means it can safely communicate with the 5V logic level of your Arduino.
  • Connect the 5V output from the Arduino to the 5V pin on the motor driver or positive rail of the breadboard.
  • Connect the GND of the Arduino to the GND of the motor driver (this is important—shared ground ensures proper communication!).
XY-160D DRIVER MODULEBREADBOARD
5VBreadboard Positive Rail
GNDBreadboard Negative Rail

Control Pins (IN1, IN2, PWM)

Here’s where we tell the motor what to do:

  • IN1 & IN2: These control the direction of the motor.
    • IN1 HIGH + IN2 LOW = Motor spins forward
    • IN1 LOW + IN2 HIGH = Motor spins in reverse
    • IN1 LOW + IN2 LOW = Motor stops
  • ENA (Speed Control): The ENA pin on the XY-160D allows you to control the speed of the motor using Pulse Width Modulation (PWM).
    • Connect this pin to a PWM-capable pin on the Arduino.
    • By adjusting the PWM signal, you can make the wiper motor run faster or slower instead of just full-speed or off.
XY-160D DRIVER MODULEARDUINO UNO
ENA5
IN16
IN27

    Motor Connections

    Motor Output Terminals (OUT1 & OUT2)

    • Your wiper motor has two terminals—connect them to the OUT1 and OUT2 outputs on the XY-160D.
    • Reversing these connections will swap the motor’s direction, but don’t worry, you can also flip the direction in code.
    XY-160D DRIVER MODULEDC MOTOR
    OUT1Positive Wire (or high speed wire of wiper motor)
    OUT2Negative Wire

    With your XY-160D motor driver wired up, your wiper motor is now under full Arduino control! You can change speed, reverse direction, and stop the motor on command—all without overloading your Arduino. Next up: Let’s put some code behind it and bring this setup to life!

    Arduino Code Example 1: Triggering the Motor at a Specific Distance

    In this example, we’ll program the Arduino to turn on the motor when an object or person comes within a specific distance—kind of like a motion-activated prop or an automatic door system.

    Here’s the plan:

    • The ultrasonic sensor will continuously measure distance.
    • If an object is closer than our set threshold (say, 10 cm), the motor will turn on.
    • If the object moves away beyond that threshold, the motor turns off again.

    It’s a simple but powerful way to make your projects react to movement.

    Turn On a DC Motor at a Specific Distance
    // Arduino pin connections
    const int trigPin = 9;
    const int echoPin = 10;
    const int ENApin = 3;
    const int IN1pin = 6;
    const int IN2pin = 7;
    
    // variables for distance calculations
    float duration; // variable to store time values
    float distanceCM; // variable to store distance in cm
    float distanceIN; // variable to store distance in inches
    
    void setup() {
      // initialize the serial monitor
      Serial.begin(9600);
      // set Arduino pins to either INPUT or OUTPUT
      pinMode(trigPin, OUTPUT);
      pinMode(echoPin, INPUT);
      pinMode(ENApin, OUTPUT);
      pinMode(IN1pin, OUTPUT);
      pinMode(IN2pin, OUTPUT);
    }
    
    void loop() {
      // start with a clean signal
      digitalWrite(trigPin, LOW);
      delayMicroseconds(2);
      // send trigger signal
      digitalWrite(trigPin, HIGH);
      delayMicroseconds(10);
      digitalWrite(trigPin, LOW);
      // return pulse duration in microseconds
      duration = pulseIn(echoPin, HIGH);
      // calculate distance in cm:
      // 343 m/s = .034 cm/microseconds
      distanceCM = (duration * 0.034) / 2;
      // convert to inches, 1in = 2.54cm
      distanceIN = distanceCM / 2.54;
      // print distance
      Serial.print("Distance: ");
      Serial.print(distanceCM);
      Serial.print(" cm | ");
      Serial.print(distanceIN);
      Serial.println(" in");
    
      // if object is 10 cm or less away from sensor:
      if (distanceCM <= 10) {
        // turn motor on
        digitalWrite(IN1pin, HIGH);
        digitalWrite(IN2pin, LOW);
        analogWrite(ENApin, 255);
      }
    
      // or else, if object is farther than 10 cm:
      else {
        // turn motor off
        digitalWrite(IN1pin, LOW);
        analogWrite(ENApin, 0);
      }
    }

    Code Explanation: Triggering a Motor at a Specific Distance

    This sketch makes an ultrasonic sensor detect an object’s distance and turns on a motor when the object is 10 cm or closer. Let’s break it down step by step!

    Declaring Arduino Pin Connections

    const int trigPin = 9;
    const int echoPin = 10;
    const int ENApin = 3;
    const int IN1pin = 6;
    const int IN2pin = 7;
    • trigPin (9): Sends the ultrasonic sound wave.
    • echoPin (10): Receives the bounced sound wave to measure distance.
    • ENApin (3): Controls motor speed using PWM.
    • IN1pin (6) and IN2pin (7): Control the motor’s direction.

    Declaring Variables for Distance Calculation

    float duration;
    float distanceCM;
    float distanceIN;
    • duration: Stores the time it takes for the sound wave to return.
    • distanceCM: Stores the calculated distance in centimeters.
    • distanceIN: Stores the distance converted to inches.

    Setting Up the Arduino

    void setup() {
      Serial.begin(9600);
      pinMode(trigPin, OUTPUT);
      pinMode(echoPin, INPUT);
      pinMode(ENApin, OUTPUT);
      pinMode(IN1pin, OUTPUT);
      pinMode(IN2pin, OUTPUT);
    }
    • Serial.begin(9600): Opens (initializes) the Serial Monitor so we can see the distance readings.
    • pinMode(trigPin, OUTPUT): The trigger pin sends the ultrasonic pulse.
    • pinMode(echoPin, INPUT): The echo pin receives the reflected pulse.
    • pinMode(ENApin, OUTPUT), pinMode(IN1pin, OUTPUT), pinMode(IN2pin, OUTPUT): Set motor driver pins as outputs to control the motor.

    Sending the Ultrasonic Pulse

    void loop() {
      // start with a clean signal
      digitalWrite(trigPin, LOW);
      delayMicroseconds(2);
      // send trigger signal
      digitalWrite(trigPin, HIGH);
      delayMicroseconds(10);
      digitalWrite(trigPin, LOW);
    
    • First, we reset the trigPin to LOW for 2 microseconds to ensure a clean signal.
    • Then, we send a 10-microsecond HIGH pulse—this is the sound wave being emitted.
    • Finally, we set trigPin back to LOW, completing the pulse.

    Measuring the Echo Time

    duration = pulseIn(echoPin, HIGH);
    • pulseIn(echoPin, HIGH): Waits for the reflected sound wave and returns the time (in microseconds) it took to come back.
    • The longer this duration, the farther the object is.

    Calculating Distance

    distanceCM = (duration * 0.034) / 2;
    // convert to inches, 1in = 2.54cm
    distanceIN = distanceCM / 2.54;
    • Why divide by 2? The sound wave travels to the object and back, so we divide by 2 to get the one-way distance.
    • We also convert the result to inches for reference.

    Displaying Distance in the Serial Monitor

    Serial.print("Distance: ");
    Serial.print(distanceCM);
    Serial.print(" cm | ");
    Serial.print(distanceIN);
    Serial.println(" in");
    • This prints the distance in both centimeters and inches so you can monitor it in real-time.

    Controlling the Motor Based on Distance

    // if object is 10 cm or less away from sensor:
    if (distanceCM <= 10) {
      // turn motor on
      digitalWrite(IN1pin, HIGH);
      digitalWrite(IN2pin, LOW);
      analogWrite(ENApin, 255);
    }
    • If the object is 10 cm or closer, the motor turns on.
    • digitalWrite(IN1pin, HIGH); digitalWrite(IN2pin, LOW); → Spins the motor in one direction.
    • analogWrite(ENApin, 255); → Runs the motor at full speed (255 = max PWM value).

    Turning Off the Motor if the Object Moves Away

    // or else, if object is farther than 10 cm:
    else {
      // turn motor off
      digitalWrite(IN1pin, LOW);
      analogWrite(ENApin, 0);
    }
    }
    • If the object moves farther than 10 cm, the motor turns off.
    • digitalWrite(IN1pin, LOW); → Stops the motor.
    • analogWrite(ENApin, 0); → Sets motor speed to zero (turns it off).

    This is a great foundation for motion-activated props, automatic doors, or interactive robotics. Next up—let’s explore how to control the motor speed based on distance!

    Arduino Code Example 2: Controlling Motor Speed Based on Distance

    Now that we’ve successfully turned the motor on and off based on distance, let’s take things up a notch! In this example, we’ll make the motor’s speed increase as an object gets closer to the ultrasonic sensor—just like an automatic response system that reacts dynamically to movement.

    Here’s how it works:

    • The ultrasonic sensor will continuously measure distance.
    • Instead of just turning the motor on or off, we’ll adjust its speed using PWM (Pulse Width Modulation).
    • The closer the object gets, the higher the speed, and if it moves away, the motor will slow down accordingly.

    This technique is perfect for interactive props, robotics, and even touchless control systems.

    Control Motor Speed with an Ultrasonic Sensor
    // Arduino pin connections
    const int trigPin = 9;
    const int echoPin = 10;
    const int ENApin = 3;
    const int IN1pin = 6;
    const int IN2pin = 7;
    
    // variables for distance calculations
    float duration; // variable to store time values
    float distanceCM; // variable to store distance in cm
    float distanceIN; // variable to store distance in inches
    
    void setup() {
      // initialize the serial monitor
      Serial.begin(9600);
      // set Arduino pins to either INPUT or OUTPUT
      pinMode(trigPin, OUTPUT);
      pinMode(echoPin, INPUT);
      pinMode(ENApin, OUTPUT);
      pinMode(IN1pin, OUTPUT);
      pinMode(IN2pin, OUTPUT);
    }
    
    void loop() {
      // start with a clean signal
      digitalWrite(trigPin, LOW);
      delayMicroseconds(2);
      // send trigger signal
      digitalWrite(trigPin, HIGH);
      delayMicroseconds(10);
      digitalWrite(trigPin, LOW);
      // return pulse duration in microseconds
      duration = pulseIn(echoPin, HIGH);
      // calculate distance in cm:
      // 343 m/s = .034 cm/microseconds
      distanceCM = (duration * 0.034) / 2;
      // convert to inches, 1in = 2.54cm
      distanceIN = distanceCM / 2.54;
      // print distance
      Serial.print("Distance: ");
      Serial.print(distanceCM);
      Serial.print(" cm | ");
      Serial.print(distanceIN);
      Serial.println(" in");
    
      // if object is 30 cm or less away from sensor: 
      if (distanceCM <= 30) {
        // map distanceCM to a PWM motor speed
        int motorSpeed = map(distanceCM, 2, 30, 255, 50);
        // run motor at calculated PWM speed
        digitalWrite(IN1pin, HIGH);
        digitalWrite(IN2pin, LOW);
        analogWrite(ENApin, motorSpeed);
      }
    
      // or else, if object is farther than 30 cm:
      else {
        // turn motor off
        digitalWrite(IN1pin, LOW);
        analogWrite(ENApin, 0);
      }
    }

    Code Explanation: Adjusting Motor Speed Based on Distance

    Since the top part of the sketch is the same as before, we’ll focus on the two blocks of code at the bottom.

    In this section of the code, we’re using the ultrasonic sensor to adjust the motor speed dynamically—the closer an object gets, the faster the motor spins. Let’s break it down step by step!

    Checking if the Object is Close Enough

    // if object is 30 cm or less away from sensor: 
    if (distanceCM <= 30) {
    • We check if the detected object is within 30 cm of the sensor.
    • If the object is closer than or equal to 30 cm, we’ll adjust the motor speed based on how near it is.
    • If the object is farther than 30 cm, we’ll turn the motor off (handled in the else statement later).

    Mapping the Distance to a PWM Speed

    // map distanceCM to a PWM motor speed
    int motorSpeed = map(distanceCM, 2, 30, 255, 50);
    • What’s happening here?
      • We use the map() function to convert the distance value into a usable PWM speed for the motor.
      • The closer the object gets, the higher the speed (PWM value).
      • The farther the object is, the slower the speed (lower PWM value).
    • Breaking Down map(distanceCM, 2, maxDistance, 255, 50);
      • distanceCM: The actual distance measured.
      • 2: The minimum distance we’re considering (when the object is super close).
      • 30: The maximum distance we care about (set to 30 cm in this case).
      • 255: The highest PWM speed (full motor speed when the object is very close).
      • 50: The lowest PWM speed (slow motor speed when the object is near 30 cm).
    • Why 2 cm as the minimum?
      • Anything closer than 2 cm can be inaccurate for ultrasonic sensors, so we set a lower limit.
    • Why PWM 255 to 50?
      • 255 is full speed, and 50 is a gentle start instead of completely stopping.

    Running the Motor at the Calculated Speed

    // run motor at calculated PWM speed
    digitalWrite(IN1pin, HIGH);
    digitalWrite(IN2pin, LOW);
    analogWrite(ENApin, motorSpeed);
    • digitalWrite(IN1pin, HIGH); → Sets the motor direction (forward).
    • digitalWrite(IN2pin, LOW); → Completes the direction setup.
    • analogWrite(ENApin, motorSpeed); → Runs the motor at the PWM speed we just calculated.

    So, when an object moves closer, the motor gets more power. When it moves away, the motor slows down.

    Turning Off the Motor if No Object is Detected Close Enough

    // or else, if object is farther than 30 cm:
    else {
      // turn motor off
      digitalWrite(IN1pin, LOW);
      analogWrite(ENApin, 0);
    }
    • If the object is farther than 30 cm, we stop the motor.
    • digitalWrite(IN1pin, LOW); → Stops the motor’s movement.
    • analogWrite(ENApin, 0); → Sets PWM to 0, turning the motor completely off.

    This technique is great for interactive props, touchless controls, or even robotic systems that need proximity-based speed control.

    What’s Next? More Fun with Sensors and Motors

    Now your motor doesn’t just mindlessly spin—it reacts to its surroundings as if it has eyes.

    Whether you’re building interactive props, smart automation, or just having fun experimenting, you now know how to control a DC motor using an ultrasonic sensor. From simple on/off control to dynamic speed adjustments, your project just got way more exciting.

    So go ahead—tweak the distances, fine-tune the speed, and get creative! Who knows? This might just be the start of your next epic robotics build.