Speed and Direction Control of DC Motor using AVR Microcontroller

Controlling the direction and speed of a DC motor is a crucial requirement in various applications, including:

1. Robotics: Adjusting the movement direction and speed of a robot.
2. Industrial Machinery: Modifying the direction and speed of rotating equipment.
3. Home Appliances: Regulating the speed of a battery-operated portable fan.
4. Defense Systems: Rotating radar systems, automatic guns, and tank gun barrels in both directions.
5. Communication Equipment: Adjusting the position of a dish antenna vertically or horizontally.

Hence, there is a multitude of applications where the need arises to alter the direction and/or speed of a DC motor. The motor’s direction can be controlled by simply reversing the polarity of the power supply. To vary the speed, several methods can be employed, with one of the most effective techniques being Pulse Width Modulation (PWM). This technique involves adjusting the width of the applied pulse to vary the average voltage supplied to the motor, consequently changing its speed.

This project serves as a demonstration of how to manipulate the speed and direction of a basic 12V 500 RPM DC series motor using an AVR microcontroller, specifically the ATmega32.

System block diagram: –

Fig. 1: Block Diagram of AVR ATMega32 based DC Motor Controller

The essential components of this system, depicted in the figure, consist of the ATmega32 microcontroller and the DC motor driver chip L293D. Additionally, we require push buttons for operational control and LEDs for status indications. Each component is briefly explained below.

Five push buttons are provided for functions such as initiating, stopping, adjusting the speed, and changing the direction of the DC motor.

The L293D chip serves as an intermediary between the microcontroller and the DC motor. It amplifies the current output from the microcontroller, as the microcontroller alone cannot directly power the DC motor. This chip features four half H-bridge drivers, collectively supplying the motor with a sufficient 600 mA current to drive it effectively.

LED status indicators – six LEDs serve various signaling purposes.

The ATmega32 AVR microcontroller is a high-performance, low-power, 8-bit microcontroller with an advanced RISC architecture. It features 32 KB of in-system programmable FLASH memory and includes built-in peripherals such as a 10-bit, 8-channel ADC, 4 PWM channels, 1 16-bit and 2 8-bit timers/counters, USART, SPI, IIC, and more. In this system, it carries out the following functions:

– Continuously scans push buttons to receive user input.
– Provides various LED indications.
– Controls the operation and speed of a DC motor, including changing its direction.

The circuit is composed of the ATmega32 microcontroller, an L293D motor driver, and various discrete components like LEDs, registers, capacitors, and push buttons. Here’s a breakdown of the key connections:

– Five push buttons (SW1 – SW5) are linked to the PORTA pins (PA0 to PA4), and external pull-up resistors ensure that all port pins are pulled high.
– Four LEDs (LED1 – LED4) are connected to the PORTD pins (PD0 to PD3) through current-limiting resistors.
– PORTC pins (PC0 and PC1) are connected to the input of the L293D chip. Two LEDs (LED5 and LED6) are also linked to these pins through current-limiting resistors.
– The DC motor is connected to the output of the L293D chip.
– A 16 MHz crystal, with two 22 pF capacitors, is connected to the crystal input pins XTAL1 and XTAL2.
– A 5V Vcc supply is connected to the necessary pins of both chips along with pull-up resistors.
– An additional 12V supply is provided to the L293D chip specifically for the motor.

Working & Programming

System working and operation: –

Here’s a rephrased version:

At the initial state, the motor remains stationary, and all LEDs are in the OFF state.

– A momentary press of SW1 initiates the motor’s clockwise rotation. The green LED blinks in sync with the PWM frequency.
– Pressing SW4 or SW5 after the motor is running allows you to increase or decrease the motor’s speed. This change is indicated by the blinking of LED1 or LED2.
– Continuous pressing of SW4 or SW5 results in a continuous increase or decrease in motor speed. When the speed reaches its maximum or minimum limits, LED3 or LED5 will light up accordingly.
– While the motor is rotating clockwise, pressing SW2 immediately changes its direction to counterclockwise, and vice versa.
– Pressing SW3 brings the running motor to a halt.


AVR microcontrollers possess a built-in capability for generating PWM signals using an internal timer. This feature allows us to create PWM signals and vary the speed of a DC motor. However, not all microcontrollers offer this built-in PWM feature. In such cases, we must generate PWM signals programmatically. In this context, I am not utilizing the internal PWM feature but rather generating PWM signals through a program written in the C language. This program is compiled and simulated using AVR Studio software, and it consists of various functions:

1. The “Keydly()” function generates a debounce delay of approximately 0.2 seconds, which is necessary when a key or button is pressed.

2. The “Incspeed()” function increases the pulse width supplied to the motor by extending the ON time while reducing the OFF time. It also includes a check for the maximum speed limit, and if the limit is reached, it activates LED3.

3. The “Decspeed()” function decreases the pulse width supplied to the motor by reducing the ON time and increasing the OFF time. It also checks for the minimum speed limit, and if the limit is reached, it activates LED4.

4. The “Clockwise()” function continuously provides PWM signals to the motor to rotate it in a clockwise direction until a button is pressed.

5. The “Anticlockwise()” function continuously provides PWM signals to the motor to rotate it in an anticlockwise direction until a button is pressed.

6. The “main()” function initializes ports as input or output and then continuously scans all the buttons within a loop.

Project Source Code


#include <avr/io.h>
#include <util/delay.h>
uint16_t ton=5000,toff=5000;
void keydly()                         // key debounce delay
   uint8_t i;
  _delay_loop_2(10000);           // delay loop library function
void incspeed()                  // increase width of pulse
  PORTD = (0<<PD3);            // led indication
  if(toff>1000)               // check for minimum off time
      toff=toff-500;          // if not then decrease off time
    ton=ton+500;              // and increase on time
  if(toff==1000) PORTD = (1<<PD2);
// if max limit is reached - LED on             
void decspeed()               // decrease width of pulse
  PORTD = (0<<PD2);          // led indication
  if(ton>1000)              // check for minimum on time
     toff=toff+500;        // if not then increase off time
     ton=ton-500;         // and decrease on time
  if(ton==1000) PORTD = (1<<PD3);  
                            // if min limit is reached – LED off
void clockwise()           // rotate motor clockwise
    while(PINA==0xFF)     // till any key is not pressed
          PORTC=0x01;    // apply PWM to motor
void anticlockwise()     // rotate motor anticlockwise
    while(PINA==0xFF)   // till any key is not pressed
          PORTC=0x02;  // apply PWM to motor
          _delay_loop_2(toff);                                     }                         
int main(void)
    uint8_t r=0,d;        // run and direction flag
    DDRC=0x03;           // initialize ports as input and output
    while(PINA==0xFF);  //wait till any key is pressed       
            case 0xFE:      // for 1st key                                   keydly();
            r=1;            // set run flag                                  d=0;    clear direction flag for CLK direction
            clockwise(); // start rotating motor clockwise
            case 0xFD:      // for 2nd key
            r=1;           // set run flag
            d=1;   // set direction flag for ACLK direction
           anticlockwise(); // start rotating motor anticlockwise
             case 0xFB:       // for 3rd key
             PORTC = 0x00;   // stop motor
             PORTD = 0x00;   // all indications off
             r = 0;         // clear run flag
             case 0xF7:      // for 4th key
             PORTD=(1<<PD0);    // blink LED1
              incspeed();               // increase speed
              if(r==1)               // if motor was running
              if(d==0) clockwise();  // keep it running clockwise
              else anticlockwise();       // or anticlockwise
               case 0xEF:                // for 5th key
               PORTD=(1<<PD1);          // blink LED2
                decspeed();                 // decrease speed                    if(r==1)                 // if motor was running
                 if(d==0) clockwise();       // keep it running
                  else anticlockwise();
                }                                                    goto loop;

Source: Speed and Direction Control of DC Motor using AVR Microcontroller

About The Author

Ibrar Ayyub

I am an experienced technical writer holding a Master's degree in computer science from BZU Multan, Pakistan University. With a background spanning various industries, particularly in home automation and engineering, I have honed my skills in crafting clear and concise content. Proficient in leveraging infographics and diagrams, I strive to simplify complex concepts for readers. My strength lies in thorough research and presenting information in a structured and logical format.

Follow Us:

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top