Source: A ATMEGA128-based DC Motor lock-Dead program
Let me tell you something about my hardware: a ATMEGA128 test board; a 80:1 variable speed motor with encoder, the output of the encoder is connected to the PD4 and PD5 pin of the microcontroller, and a motor drive circuit, the input of this circuit is: 24v power supply, two PWM signal input, The output is the positive and negative pole of the motor, to use the circuit to drive the motor, you must let the two PWM input signal the duty ratio of 0, the other way is not 0, equivalent to make the motor of one pole ground, another pole-to-PWM, by controlling the two-way PWM duty ratio to control the motor speed and rotation direction. The input terminal of the PWM signal is connected to the PD6 and PD7 pins of the microcontroller.
Here is my program's design idea: This program uses two timers: Timer0 and Timer1.
The Timer0 is used to generate PWM. Timer0 generated PWM signal is implemented: there is a Timer0 overflow event counter in the program, and two to save two PWM signal duty ratio of the variable, when the Timer0 overflow event counter count is more than 100, if a PWM signal duty ratio is not 0, The corresponding PWM pin is set high, while clearing this counter, when this counter is equal to a duty cycle, the corresponding pin is low, so that the Timer0 overflow event counter from 0 to 100 when the output of a period of PWM signal. The frequency of the PWM signal output can be adjusted by adjusting the overflow frequency of the TIMER0.
The timer1 is used to count the output of the encoder while adjusting the duty ratio of the PWM to achieve control of the motor. The output count of the encoder is the use of timer1 input capture function, because the motor can be forward, can also be reversed, resulting in the encoder cha and ChB output is also different, so you can determine in the program is the motor is forward or reverse, and then the output pulse of the encoder to count, When the motor is turning when the count increases, the motor reversal when the count is reduced, so the encoder value is positive or negative . This allows you to know when to control the motor by adjusting the PWM.
Here is my debugging process, but also a bit of experience: to start with the idea is as long as the encoder count value is not 0, I will let the motor in reverse direction to keep the motor to hold, the PWM sent to the motor is a fixed value, but this is not to die, it is in front and back jitter , and The larger the duty ratio of the PWM , the greater the jitter of the motor, which is obviously not possible; later thought of a way, that is, if the count of the encoder in a certain range, I do not have to turn the motor in the opposite direction . Because this motor is a variable speed motor, if the motor inside only a little bit, in the outside seems to be equivalent to not moving, so that the motor reserved a part of the rotation of space to eliminate Jitter , that is, in this space is not to send PWM to the motor, Or, the PWM duty ratio of the motor poles is 0. This way, when the PWM duty is low, it is possible to eliminate jitter, but the strength is not strong, that is still can be twisted with pliers, adjusted for a long time cannot be in the jitter and motor strength to strike a balance. Later, I thought of a way to improve on this basis, because the previous PWM duty ratio is constant, so it is difficult to achieve satisfactory results, the current method is that the root of the motor is twisted angle, or the size of the encoder count value to adjust the PWM duty ratio, Encoder count Value Deviation 0 more (positive or negative greater), PWM duty ratio is greater, the strength of the motor is greater, so that the motor will not appear as soon as the maximum speed to turn back to the situation, jitter is eliminated, and the motor strength is great.
编译环境是AVR Studio 5.0,下面是程序代码:
#include <avr/io.h>#include<avr/interrupt.h>intForward =0, reverse =0;//variable to store motor forward and reverse PWM duty-freeintTimer0_count =0;//Timer0 Overflow Event counterintCapt_count =0;//Input Capture Event counter voidPort_init (void) {PORTA=0x00;DD RA=0x00; PORTB=0x00;DD RB=0x00; PORTC=0x00;//m103 Output onlyDDRC=0x00; PORTD=0x00;DD Rd=0xC0; PORTE=0x00;DD re=0x00; Portf=0x00;DD RF=0x00; PORTG=0x00;DD RG=0x00;} voidTimer0_init (void) {TCCR0|=5;//256 frequency, Normal modeTimsk|=0x01;//Timer0 Overflow InterruptTCNT0=0xFE;//TCNT0 Assignment Initial value} voidTimer1_init (void) {tccr1b=0x00;//StopTccr1a=0x00;//Normal Modetccr1c=0x00; TCNT1=0;//Count Initial valuetccr1b=0xc4;//start timer, 256-way, enable input capture noise suppressor, input capture trigger edge selection: Rising edgeTimsk=0x24;//input capture interrupt enable, T/C1 overflow interrupt enable} /************************************************************************//*Timer0 Overflow Interrupt function that generates the PWM supplied to the motor*//************************************************************************/ISR (Timer0_ovf_vect<span style="Color:rgb (255, 0, 0);">)//200kHz</span>{TCNT0=0xFE;//TCNT0 re-assigning values//When timer0_count equals 100, the corresponding PIN output is high if the duty ratio of the forward or reverse is not 0if(++timer0_count >= -)//<span style= "Color:rgb (255, 0, 0); > Timer0 Overflow Event Count 100 times, equivalent to 100 frequency, the last output to the motor PWM frequency is 2kHz</span>{Timer0_count=0;if(Forward! =0<span style="Color:rgb (255, 0, 0);">)//forward, reverse storage motor forward and reverse PWM duty-free variable</SPAN>{PORTD |= (1<<6);}if(Reverse! =0) {PORTD|=(1<<7);}}//<span style= "Color:rgb (255, 0, 0); > When the timer0_count equals a positive or reverse duty ratio, the corresponding pin output is low to achieve the output PWM signal</span>if(Timer0_count = =forward) {PORTD&= ~ (1<<6);}if(Timer0_count = =reverse) {PORTD&= ~ (1<<7);}} /************************************************************************//*timer1 input capture interrupt function to count the rising edge of the encoder output*//************************************************************************/ISR (timer1_capt_vect) {if(PIND & (1<<5))//Motor Reversal{Capt_count--;}//input Capture counter minus 1 Else //Motor is turning{Capt_count++;}//Input Capture counter plus 1} /************************************************************************//*<span style= "Color:rgb (255, 0, 0); >timer1 overflow interrupt function, 100Hz, for adjusting the motor speed and direction of rotation, to achieve motor holding </span>*//************************************************************************/ISR (timer1_ovf_vect) {TCNT1=64910;//re-assigning TCNT1 to a valueStaticUnsignedChar<span style="Color:rgb (255, 0, 0);">motor_state =0;//motor status, flag motor is forward or reverse, 0: Positive turn, 1: Reverse</span>Switch(motor_state) { Case 0<span style="Color:rgb (255, 0, 0);"://when the motor is turning</span>if(Capt_count > +) <span style="Color:rgb (255, 0, 0);">//if the encoder is counting more than 40, the motor needs to be reversed to keep the motor still</span>{reverse = Capt_count- +;}//subtract 40 of the encoder count value directly as the duty ratio of the reversalElse if(Capt_count <0) <span style="Color:rgb (255, 0, 0);">//if the encoder count value is less than 0</span>{motor_state =1;}//Enter status 1Else<span style="Color:rgb (255, 0, 0);">//if the encoder count value is within 0~40, the reversal is not required in order for jitter to occur</span>{reverse =0;}//reversal duty ratio of 0, equivalent to negative groundingforward=0;//the duty ratio of the positive turn is 0, equivalent to the positive grounding Break; Case 1:if(Capt_count <- +) <span style="Color:rgb (255, 0, 0);">//if the encoder reversal count exceeds 40, the motor needs a positive turn </span> to keep the motor still{forward= (-capt_count)- +;}//subtract 40 of the encoder count value directly as the duty ratio of the positive turnElse if(Capt_count >0) <span style="Color:rgb (255, 0, 0);">//if the encoder count value is greater than 0</span>{motor_state =0;}//Return status 0Else<span style="Color:rgb (255, 0, 0);">//if the encoder count value is within the -40~0, no forward transfer is required in order for the jitter to occur</span>{forward =0;}//the duty ratio of the positive turn is 0, equivalent to the positive groundingReverse=0;//reversal duty ratio of 0, equivalent to negative grounding Break; default: Break;}} voidInit_devices (void) {CLI ();//turn off global interruptsport_init ();//I/O port initializationtimer1_init ();//Timer/Counter 1 initializationtimer0_init ();//Timer/Counter 0 initializationsei ();//turn on global interrupts} intMainvoid) {init_devices (); while(1) {} return 0;}
A ATMEGA128-based DC Motor Kill program (RPM)