PWM Motor Control

Environment

  • Ubuntu 16.04
  • Pololu 3pi Robot (ATmega328P)

Code

#include <avr/io.h>

void initM1()
{
    // configure for inverted fast PWM output on motor control pins:   
    //  set OCxx on compare match, clear on timer overflow   
    //  Timer0 and Timer2 counts up from 0 to 255 and then overflows directly to 0   
    TCCR0A = 0b11110011;  //0xF3
 
    // use the system clock/8 (=2.5 MHz) as the timer clock,
    // which will produce a PWM frequency of 10 kHz
    // Arduino uses Timer0 for timing functions like micros() and delay() so we can't change it
    TCCR0B = 0b00000010;    //0x02

    // initialize all PWMs to 0% duty cycle (braking)   
    OCR0A = 0;
    OCR0B = 0;
    
    // pin5
    PIND &= ~0b00100000;
    DDRD |= 0b00100000;

    // pin6
    PIND &= ~0b01000000;
    DDRD |= 0b01000000;\
}

void setM1Speed(int speed)
{
    if (speed < 0) // backward { OCR0B = 0; // hold one driver input high OCR0A = 255-speed; // pwm the other input } else // forward { OCR0B = speed; // pwm one driver input OCR0A = 0; // hold the other driver input high } } int main(void) { DDRD = 0b00000010; // Set to one => output
    PORTD &= 0b11111101;    // Port D pin 1 set to off

    initM1();

	for(;;) {
        // blink
        PORTD ^= 0b00000010;  // Toggle the pins on/off

        // PWM 0~255
        setM1Speed(0);

        // wait
        uint64_t i = 0;
        for (i = 0; i < 150000; i++);
	}
}

Reference