Managing DC Motor Speed and Direction with AVR Microcontrollers (Part 20/46)

Managing the speed and direction of a DC motor holds significant importance across various applications:

– In robotic applications, altering the speed and direction is crucial for controlling the movement of robots.
– Industrial scenarios require the ability to adjust the speed and direction of rotating machinery.
– Within domestic settings, regulating the speed of battery-operated portable fans is essential.
– Defense applications often necessitate rotating radar, automatic guns, or tank guns in different directions.
– Communication applications involve tasks such as adjusting dish antenna positions both vertically and horizontally.

Numerous applications demand altering the direction and/or speed of DC motors. The motor’s direction can be controlled by reversing the polarity of the supplied power. To regulate the speed, multiple methods exist, yet the most effective among them is Pulse Width Modulation (PWM). This technique involves adjusting the pulse width, which consequently modifies the average voltage applied to the motor, thereby altering its speed.

This project aims to illustrate the process of adjusting the speed and altering the direction of a simple 12V 500 RPM DC series motor using the AVR microcontroller ATmega32.

System block diagram:

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

The fundamental components of this system, depicted in the figure, comprise the ATmega32 and the DC motor driver chip L293D. Additionally, the setup requires push buttons for control purposes and LEDs for signaling. Here’s a concise description of each block:

Five push buttons are allocated for executing operations such as initiating, halting, modifying the speed, and altering the direction of the DC motor.

Button

Function

Button 1 Run motor in clockwise direction
Button 2 Run motor in anticlockwise direction
Button 3 Stop motor
Button 4 Increase speed
Button 5 Decrease speed

L293D chip – this chip takes input from micro controller and drives DC motor. The micro controller output current is not enough to drive DC motor directly. The chip has quad half H bridge drivers. It will provide up to 600 mA current to motor that is enough to drive it.

LED indications – six LEDs are used for different indications

LED

colour

indication

LED 1

red

Blinks when motor runs in clockwise direction

LED 2

green

Blinks when motor runs in anticlockwise direction

LED 3

Blue

Blinks when speed in increased

LED 4

Orange

Blinks when speed is decreased

LED 5

red

Lits ON when speed limit is maximum

LED 6

red

Lits ON when speed limit is minimum

The ATmega32, an 8-bit microcontroller based on Advanced RISC architecture, boasts low power consumption and high performance capabilities. It encompasses 32 KB of in-system programmable FLASH memory and comes equipped with various 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, among others. In this particular system, the ATmega32 executes several functions:

– Continuously scans push buttons to gather user input
– Provides diverse indications using LEDs
– Controls the operation (start/stop) of a DC motor
– Modifies the motor’s direction or speed

The circuit comprises the ATmega32, L293D, and a few discrete components including LEDs, resistors, capacitors, and push buttons:

– Five push buttons, labeled as SW1 to SW5, are linked to PORTA pins PA0 to PA4. Additionally, all port pins are pulled high via external pull-up resistors, as illustrated.
– Four LEDs, identified as LED1 to LED4, are connected to PORTD pins PD0 to PD3 using current-limiting resistors.
– PORTC pins PC0 and PC1 are connected to the input of the L293D chip. Two LEDs, labeled as LED5 and LED6, are also linked to these pins via current-limiting resistors.
– The DC motor is connected to the output of the L293D chip.
– A 16 MHz crystal, along 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 and pull-up resistors.
– An additional 12V supply is allocated to the L293D chip specifically for the motor’s operation.

Working & Programming

System working and operation:

· Initially, the motor remains stationary, and all LEDs are inactive.

· Upon a momentary press of SW1, the motor initiates rotation in a clockwise direction. Simultaneously, the green LED flashes at the frequency of the PWM.

· Subsequently, pressing SW4 or SW5 results in an increase or decrease in the motor’s speed. This adjustment is indicated by LED1 or LED2 blinking accordingly.

· Continued pressing of SW4 or SW5 causes a continuous increase or decrease in speed. Upon reaching the maximum or minimum limit, the corresponding LED3 or LED5 illuminates.

· While the motor rotates clockwise, pressing SW2 immediately prompts a switch to anticlockwise rotation, and vice versa.

· Pressing SW3 halts the motor’s operation.

Program:

AVR microcontrollers possess an integrated capability to produce PWM using internal timers. This feature allows for PWM generation, enabling the adjustment of a DC motor’s speed. However, not all microcontrollers offer this feature. In cases where it’s unavailable, PWM needs to be generated programmatically. In this scenario, PWM is generated using a program written in C language, compiled, and simulated using AVR Studio software. The comprehensive program comprises various functions:

– **Keydly() function:** This function generates a debounce delay of approximately 0.2 seconds required when a key is pressed.

– **Incspeed() function:** Responsible for increasing the width of the pulse supplied to the motor by extending the ON time and reducing the OFF time. It also monitors the maximum speed limit. Upon reaching the maximum speed, LED3 is activated.

– **Decspeed() function:** Decreases the width of the pulse supplied to the motor by reducing the ON time and increasing the OFF time. It also checks for the minimum speed limit. When the minimum speed is reached, LED4 is illuminated.

– **Clockwise() function:** Continuously delivers PWM to the motor to rotate it in a clockwise direction until any button is pressed.

– **Anticlockwise() function:** Provides continuous PWM to rotate the motor in an anticlockwise direction until any button is pressed.

– **Main() function:** Initializes ports as input or output and subsequently scans all buttons in a continuous 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;
   for(i=0;i<7;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
          _delay_loop_2(ton);
          PORTC=0x00;
         _delay_loop_2(toff);                                    
  }           
 }
void anticlockwise()     // rotate motor anticlockwise
  {
    while(PINA==0xFF)   // till any key is not pressed
    { 
          PORTC=0x02;  // apply PWM to motor
          _delay_loop_2(ton);
           PORTC=0x00;
          _delay_loop_2(toff);                                     }                         
  }
int main(void)
{
    uint8_t r=0,d;        // run and direction flag
    DDRC=0x03;           // initialize ports as input and output
    DDRD=0x0F;
    DDRA=0x00;
    PORTC=0x00;
    PORTD=0x00;
    while(PINA==0xFF);  //wait till any key is pressed       
loop:switch(PINA)
            {
            case 0xFE:      // for 1st key                                   keydly();
            r=1;            // set run flag                                  d=0;    clear direction flag for CLK direction
            clockwise(); // start rotating motor clockwise
            break;
            case 0xFD:      // for 2nd key
            keydly();
            r=1;           // set run flag
            d=1;   // set direction flag for ACLK direction
           anticlockwise(); // start rotating motor anticlockwise
              break;
             case 0xFB:       // for 3rd key
             PORTC = 0x00;   // stop motor
             PORTD = 0x00;   // all indications off
             r = 0;         // clear run flag
             Break;
             case 0xF7:      // for 4th key
             PORTD=(1<<PD0);    // blink LED1
              keydly();
              PORTD=(0<<PD0);
              incspeed();               // increase speed
              if(r==1)               // if motor was running
              {
              if(d==0) clockwise();  // keep it running clockwise
              else anticlockwise();       // or anticlockwise
               }
               break;
               case 0xEF:                // for 5th key
               PORTD=(1<<PD1);          // blink LED2
               keydly();
                PORTD=(1<<PD1);
                decspeed();                 // decrease speed                    if(r==1)                 // if motor was running
               {
                 if(d==0) clockwise();       // keep it running
                  else anticlockwise();
                }
                break;                                 
                }                                                    goto loop;
}




###

Project Video

 


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:
LinkedinTwitter

Leave a Comment

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

Scroll to Top