/* pwm_direct_t0.c ** PWM routines for ORANGUTAN motor controller from Pololu ** atmega168/LB1836M motor controller, WinAVR ** these routines use TIMER0 in phase correct PWM mode, no interrupts ** by Jim Remington (sjames_remington _at_ yahoo dot com) ** for more information, see http://www.uoxray.uoregon.edu/orangutan */ #include #define F_CPU 8000000UL #include /* ** pwm_init - Set up the pwm ports (PORT B1=IN1, B2=IN3, D5=IN2, D6=IN4) ** Initialize Timer 0 to phase correct PWM mode 1 */ void pwm_init( void ) { DDRB |= 6; //set PORTB.1 and PORTB.2 to output PORTB &= ~6; //clear outputs DDRD |= (3<<5); //set PORTD.5 and PORTD.6 to output PORTD &= ~(3<<5); //clear outputs (motor driver is now off) TCCR0A = (1< 255 right motor = PB.1(IN1) and PD.5 (IN2, OC0B) left motor = PB.2(IN3) and PD.6 (IN4, OC0A) If direction of travel is wrong, switch motor leads, but note asymmetry of PWM modes in forward and reverse directions. Brake mode is more power-hungry but more power at low speed. Truth Table for LB1836 controller from data sheet. IN1/3 IN2/4 MODE ---- ----- ---- 1 0 forward 1 1 brake (both outputs low), power hungry mode. 0 1 reverse 0 0 coast (both outputs off), power saving mode. */ void pwm_set( signed int left_speed, signed int right_speed ) { if ( right_speed > 0 ) { PORTB |= (1<<1); //IN1=1 TCCR0A |= (3< 0 ) { PORTB |= (1<<2); //IN3=1 TCCR0A |= (3<0;i--) { pwm_set(i,i); _delay_ms(20); } for(i=0;i<255;i++) { pwm_set(-i,-i); _delay_ms(20); } for(i=255;i>0;i--) { pwm_set(-i,-i); _delay_ms(20); } } return 0; }