Small DC Motor Control Example

Publisher:lidong4069Latest update time:2016-10-29 Source: eefocus Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere
I am a beginner in AVR and don't have any specific practical topics. I disassembled a few small motors and learned a lot while playing with them. I hope this can help beginners. 
This small DC motor control system is easy to implement. It uses PWM speed regulation. The drive circuit can be built with discrete components (there are many such circuits on the Internet) or integrated IC devices. I use L293. The circuit is very simple, so I won't draw a picture. The 
wiring description is as follows: 
   PORTC7, PORTC6 are connected to L293 IN1, IN2 respectively. According to the L293 data, ENA=H, IN1=H, IN2=L Forward 
                                                        ENA=H, IN1=L, IN2=H Reverse 
                                             ENA=H, same as IN2 (IN4), same as IN1 (IN3) Quick stop 
                                             ENA=L, stop 
   OCR2 connected to L293 ENA 
   speed measurement feedback signal connected to T0 
Code description is as follows: 
   This system can receive host computer control commands through the serial port, and can realize start, stop, speed regulation, and timely speed feedback. The serial port adopts the receiving interrupt mode, and the command protocol is as follows: the command adopts the M**C mode, and all command strings start with M and end with C. The definition of the two characters in the middle: s means speed regulation, and the ratio of the third command character and 0xff is used as the duty cycle of PWM for speed regulation. 
    d means sending the current speed to the upper computer. 
    t means stop, 
    r means start, 
    and o means direction reversal  .
The speed measurement uses the speed measurement pulse signal (Hall speed sensor) as the external counting pulse of T2, T1 CTC mode, to achieve 1s timing, compare match interrupt is allowed, and the interrupt service program reads the value of TCNT2, which is the speed. After reading, Timer2 is reinitialized. 
For beginners, the speed measurement can be tested with the CPU fan. The CPU fan comes with a speed output line, and the internal Hall sensor is used. Note that the output end of the Hall sensor is an OC gate open circuit, and a pull-up resistor needs to be connected. You can get a very standard square wave! In addition: pay attention to connecting the fan ground and your development board ground together. 
The original code is as follows: 
  The program uses ICC to automatically generate code, and then ported to codevision. I think the ICC automatically generated code has a clear structure and is very suitable for beginners, but there may be some inappropriate places! 
 // Target : M16 
// Crystal: 4.0000Mhz 

#include  
#include  
#include  
unsigned char rx_data[5];//Data buffer 
volatile unsigned char rx_counter=0; 

volatile unsigned char crut_sped;//Current speed 
//const unsigned char seg_table[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d, 
//0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};  
void port_init(void) 

 PORTA = 0x00; 
 DDRA = 0x00; 
 PORTB = 0x00; 
 DDRB = 0x00; 
 PORTC = 0b01000000; //m103 output only 
 DDRC = 0xFF; 
 PORTD = 0xFF; 
 DDRD = 0xFF; 

//External event count 
void timer0_init(void) 

TCCR0 = 0x00; //stop 
TCNT0 = 0x00;  
OCR0 = 0x00;    
TCCR0 = 0x07; //start 
}   
//TIMER1 initialize - prescale:64 
// WGM: 4) CTC, TOP=OCRnA 
// desired value: 1Sec 
// actual value: 1.000Sec (0.0%) 
void timer1_init(void) 

 TCCR1B = 0x00; //stop 
 TCNT1H = 0x0B; //setup 
 TCNT1L = 0xDD; 
 OCR1AH ​​= 0xF4; 
 OCR1AL = 0x23; 
 OCR1BH = 0xF4; 
 OCR1BL = 0x23; 
 ICR1H = 0xF4; 
 ICR1L = 0x23; 
 TCCR1A = 0b00000000; 
 TCCR1B = 0b00001011; //start Timer 
}  
//TIMER2 initialize - prescale:64 
// WGM: PWM Phase correct 
// desired value: 122Hz 
// actual value: 122.549Hz (0.4%) 
void timer2_init(void) 

 TCCR2 = 0x00; //stop 
 TCNT2 = 0x01; //set count 
 OCR2  = 0x3f;  //set compare 
 TCCR2 = 0b01100011; //start timer 


 interrupt [TIM1_COMPA] void timer1_compa_isr(void) 

 //compare occured TCNT3=OCR3A 
 crut_sped=TCNT0; 
 timer0_init();  
}   
//UART0 initialize 
// desired baud rate: 19200 
// actual: baud rate:19231 (0.2%) 
// char size: 8 bit 
// parity: Disabled 
void uart_init(void) 

 UCSRB = 0x00; //disable while setting baud rate 
 UCSRA = 0x00; 
 UCSRC = 0x06; 
 UBRRL = 0x0C; //set baud rate lo 
 UBRRH = 0x00; //set baud rate hi 
 UCSRB = 0x98; 



interrupt[USART_RXC] void uart_rx_isr(void) 

  /*if (rx_counter >= 4)  
       { 
               rx_counter = 0; 
                if ((!(rx_data[0] == 'M'))||(!(rx_data[3] == 'C'))) 
                  { 
                    rx_data[0]=0; 
             rx_data[1]=0; 
             rx_data[2]=0; 
             rx_data[3]=0; 
                  }   
       }   */ 
    rx_data[rx_counter] = UDR; 
      
     if (rx_data[rx_counter]=='M') 
       { 
                 rx_data[0]=rx_data[rx_counter]; 
                 rx_counter=0; 
       } 
     rx_counter++;  
   
        
}     

void init_devices(void) 

 //stop errant interrupts until set up 
#asm("cli"); //disable all interrupts 
 port_init(); 
 timer0_init(); 
 timer1_init(); 
 timer2_init(); 
 uart_init(); 
 MCUCR = 0x00; 
 GICR  = 0x00; 
 TIMSK = 0b00010000; //输出比较匹配A中断使能 
 #asm("sei");//re-enable interrupts 
 //all peripherals are now initialized 

void timer2_reset(unsigned char i) 

 if((i>0x00)&&(i<0xff)) 
 { 
 TCCR2 = 0x00; //stop 
 TCNT2 = 0x01; //set count 
 OCR2  = i;  //set compare 
 TCCR2 = 0b01100011; //start timer 
 } 
  
}  
 void speed_direction(void) 
 { 
  PORTC^=0x80; 
  PORTC^=0x40;   
 } 

void main(void) 
{  
 init_devices(); 
  while(1) 
  {  
    if (rx_counter==4) 
       { 
          rx_counter=0; 
          if ((rx_data[0] == 'M')&&(rx_data[3] == 'C')) 
          { 
            if(rx_data[1]=='s')//设定速度 
            { 
             timer2_reset(rx_data[2]); 
            } 
             else if(rx_data[1]=='d') 
               { 
              putchar(crut_sped); 
               }   
             else if(rx_data[1]=='t') 
               { 
              PORTC=0x00; 
               }  
             else if(rx_data[1]=='r') 
             { 
             PORTC=0x80; 
             }  
             else if(rx_data[1]=='o') 
             { 
             speed_direction(); 
             } 
            }   
           else   
             
           {   
          printf("your command is wrong 
"); 
             } 
              rx_data[0]=0; 
              rx_data[1]=0; 
              rx_data[2]=0; 
              rx_data[3]=0; 
            }   
        
  } 
Reference address:Small DC Motor Control Example

Previous article:Transplant ICCAVR to WINAVR to play the first song (music.c)
Next article:18B20 program under M8-ICCAVR

Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号