1.3.1 Motor

Introduction

In this project, we’ll learn how to control a DC motor with our Raspberry Pi, making it spin in both directions. We’ll use a special motor driver chip called L293D and a separate power supply to safely run the motor.

Components

_images/list_1.3.1.png

What is a DC Motor?

A DC motor is an electric motor that converts electrical energy into mechanical movement (rotation). Unlike LEDs or buzzers we’ve used before, motors: - Need more power to operate - Can spin in either direction (clockwise or counterclockwise) - Are used in toys, fans, robots, and many other moving devices

_images/image114.jpeg

Why We Need a Motor Driver (L293D)

The Raspberry Pi can’t directly power a motor because: 1. Motors need more current than the Pi can safely provide 2. Motors can create electrical “noise” that might damage the Pi 3. The Pi can’t reverse a motor’s direction on its own

The L293D chip solves these problems by: - Acting as a bridge between the Pi and the motor - Handling the higher current needed by the motor - Allowing us to control the motor’s direction

_images/image111.png

How the L293D Works

The L293D has three important types of pins: - Enable pins (EN): Turn the motor control on/off - Input pins (A): Control the direction (forward/reverse) - Output pins (Y): Connect to the motor

When EN is HIGH: - If input A is HIGH → output Y is HIGH - If input A is LOW → output Y is LOW

_images/image334.png

Power Supply Module

Motors need extra power, especially when starting and stopping. Using a separate power supply module: - Protects your Raspberry Pi from power spikes - Provides steady 5V power to the motor - Makes the project safer and more reliable

The power module can use a 9V battery and provides both 3.3V and 5V outputs.

_images/image115.png

Connect

T-Board Name

physical

wiringPi

BCM

GPIO17

Pin 11

0

17

GPIO27

Pin 13

2

27

GPIO22

Pin 15

3

22

_images/1.3.1.png

Note

For power, you can connect a 9V battery using the battery connector included in the kit. Make sure to connect the power module’s 5V output to the breadboard’s power rail.

_images/image118.jpeg

Code

For C Language User

Go to the code folder compile and run.

cd ~/super-starter-kit-for-raspberry-pi/c/1.3.1/
gcc 1.3.1_Motor.c -lwiringPi
sudo ./a.out

As the code runs, the motor first rotates clockwise for 5s then stops for 5s, after that, it rotates anticlockwise for 5s; subsequently, the motor stops for 5s. This series of actions will be executed repeatedly.

This is the complete code

#include <wiringPi.h>
#include <stdio.h>

// Motor control pin definitions
#define MOTOR_PIN1    0    // Motor direction pin 1
#define MOTOR_PIN2    2    // Motor direction pin 2
#define MOTOR_ENABLE  3    // Motor enable pin (speed control)

// Timing constants
#define RUN_DURATION   3000  // Motor run time in milliseconds (3 seconds)
#define STOP_DURATION  3000  // Motor stop time in milliseconds (3 seconds)
#define SHORT_DELAY    100   // Short delay for state transitions

// Motor direction definitions
#define CLOCKWISE      1
#define ANTI_CLOCKWISE 2
#define STOP           0

/**
* @brief Initializes GPIO pins for motor control
* @return 0 on success, 1 on failure
*/
int setupHardware() {
    // Initialize wiringPi library
    if (wiringPiSetup() == -1) {
        printf("Failed to setup wiringPi!\n");
        return 1;
    }

    // Configure motor control pins as outputs
    pinMode(MOTOR_PIN1, OUTPUT);
    pinMode(MOTOR_PIN2, OUTPUT);
    pinMode(MOTOR_ENABLE, OUTPUT);

    printf("Motor control hardware initialized successfully!\n");
    return 0;
}

/**
* @brief Controls motor direction and enable state
* @param direction Motor direction (CLOCKWISE, ANTI_CLOCKWISE, or STOP)
*/
void setMotorDirection(int direction) {
    switch (direction) {
        case CLOCKWISE:
            printf("Motor: Clockwise rotation\n");
            digitalWrite(MOTOR_ENABLE, HIGH);
            digitalWrite(MOTOR_PIN1, HIGH);
            digitalWrite(MOTOR_PIN2, LOW);
            break;

        case ANTI_CLOCKWISE:
            printf("Motor: Anti-clockwise rotation\n");
            digitalWrite(MOTOR_ENABLE, HIGH);
            digitalWrite(MOTOR_PIN1, LOW);
            digitalWrite(MOTOR_PIN2, HIGH);
            break;

        case STOP:
        default:
            printf("Motor: Stop\n");
            digitalWrite(MOTOR_ENABLE, LOW);
            break;
    }
    delay(SHORT_DELAY);  // Small delay for state transition
}

/**
* @brief Main motor control loop
*/
void motorControlLoop() {
    while (1) {
        // Run motor clockwise for 3 seconds
        setMotorDirection(CLOCKWISE);
        delay(RUN_DURATION);

        // Stop motor for 3 seconds
        setMotorDirection(STOP);
        delay(STOP_DURATION);

        // Run motor anti-clockwise for 3 seconds
        setMotorDirection(ANTI_CLOCKWISE);
        delay(RUN_DURATION);

        // Stop motor for 3 seconds
        setMotorDirection(STOP);
        delay(STOP_DURATION);
    }
}

/**
* @brief Main function
* @return 0 on success, 1 on failure
*/
int main(void) {
    // Initialize hardware
    if (setupHardware() != 0) {
        return 1;  // Exit if setup fails
    }

    // Start motor control loop
    motorControlLoop();

    return 0;  // This line is unreachable due to infinite loop
}

For Python Language User

Go to the code folder and run.

cd ~/super-starter-kit-for-raspberry-pi/python
python 1.3.1_Motor.py

As the code runs, the motor first rotates clockwise for 5s then stops for 5s, after that, it rotates anticlockwise for 5s; subsequently, the motor stops for 5s. This series of actions will be executed repeatedly.

This is the complete code

#!/usr/bin/env python3

 import RPi.GPIO as GPIO
 import time

 # Motor control pin definitions (BCM numbering)
 MOTOR_PIN1 = 17    # Motor direction pin 1
 MOTOR_PIN2 = 27    # Motor direction pin 2
 MOTOR_ENABLE = 22  # Motor enable pin (speed control)

 # Timing constants
 RUN_DURATION = 3.0   # Motor run time in seconds (3 seconds)
 STOP_DURATION = 3.0  # Motor stop time in seconds (3 seconds)
 SHORT_DELAY = 0.1    # Short delay for state transitions

 # Motor direction definitions
 CLOCKWISE = 1
 ANTI_CLOCKWISE = -1
 STOP = 0

 def setupHardware():
     """
     Initializes GPIO pins for motor control.
     Returns: 0 on success, 1 on failure.
     """
     try:
         # Set the GPIO modes to BCM Numbering
         GPIO.setmode(GPIO.BCM)
         GPIO.setwarnings(False)

         # Configure motor control pins as outputs
         GPIO.setup(MOTOR_PIN1, GPIO.OUT, initial=GPIO.LOW)
         GPIO.setup(MOTOR_PIN2, GPIO.OUT, initial=GPIO.LOW)
         GPIO.setup(MOTOR_ENABLE, GPIO.OUT, initial=GPIO.LOW)

         print("Motor control hardware initialized successfully!")
         return 0

     except Exception as e:
         print(f"Failed to setup GPIO: {e}")
         return 1

 def setMotorDirection(direction):
     """
     Controls motor direction and enable state.
     Parameters: direction - Motor direction (CLOCKWISE, ANTI_CLOCKWISE, or STOP)
     """
     if direction == CLOCKWISE:
         print("Motor: Clockwise rotation")
         # Set direction
         GPIO.output(MOTOR_PIN1, GPIO.HIGH)
         GPIO.output(MOTOR_PIN2, GPIO.LOW)
         # Enable the motor
         GPIO.output(MOTOR_ENABLE, GPIO.HIGH)

     elif direction == ANTI_CLOCKWISE:
         print("Motor: Anti-clockwise rotation")
         # Set direction
         GPIO.output(MOTOR_PIN1, GPIO.LOW)
         GPIO.output(MOTOR_PIN2, GPIO.HIGH)
         # Enable the motor
         GPIO.output(MOTOR_ENABLE, GPIO.HIGH)

     elif direction == STOP:
         print("Motor: Stop")
         # Disable the motor
         GPIO.output(MOTOR_ENABLE, GPIO.LOW)

     time.sleep(SHORT_DELAY)  # Small delay for state transition

 def motorControlLoop():
     """
     Main motor control loop.
     """
     # Define a dictionary to make the script more readable
     # CW as clockwise, CCW as counterclockwise, STOP as stop
     directions = {'CW': CLOCKWISE, 'CCW': ANTI_CLOCKWISE, 'STOP': STOP}

     while True:
         # Run motor clockwise for 3 seconds
         setMotorDirection(directions['CW'])
         time.sleep(RUN_DURATION)

         # Stop motor for 3 seconds
         setMotorDirection(directions['STOP'])
         time.sleep(STOP_DURATION)

         # Run motor anti-clockwise for 3 seconds
         setMotorDirection(directions['CCW'])
         time.sleep(RUN_DURATION)

         # Stop motor for 3 seconds
         setMotorDirection(directions['STOP'])
         time.sleep(STOP_DURATION)

 def destroy():
     """
     Clean up function for GPIO resources.
     """
     # Stop the motor
     GPIO.output(MOTOR_ENABLE, GPIO.LOW)
     print("Motor stopped")

     # Release resource
     GPIO.cleanup()
     print("GPIO cleanup completed")

 def main():
     """
     Main function.
     Returns: Integer status code. 0 for success, 1 for error.
     """
     # Initialize hardware
     if setupHardware() != 0:
         return 1  # Exit if setup fails

     try:
         # Start motor control loop
         motorControlLoop()
     except KeyboardInterrupt:
         # When 'Ctrl+C' is pressed, the program destroy() will be executed
         print("\nProgram interrupted by user")
         destroy()
         return 0
     except Exception as e:
         print(f"An error occurred: {e}")
         destroy()
         return 1

 # If run this script directly, do:
 if __name__ == '__main__':
     main()

Phenomenon

_images/131.gif