Let's Make Robots!

tiny2313 pwm timer1 does not work the OCR1A and OCR1B

Hello

 

I want to control 2 DC motors...

 

I set the Timer1 for fast pwm no problem... I run at 4 mhz....

 

what prescaller I need?

and even if I set the OCR1A and OCR1B the speed is constant... any ideea?

 

 

thanks

 

TCCR1A |= (1<<WGM10)|(1<<WGM11)|(1<<COM1B1)|(1<<COM1B0)|(1<<COM1A1)|(1<<COM1A0);

TCCR1B |= (1<<CS11)|(1<<WGM13)|(1<<WGM12); //prescaller

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

ok working :D

... well let's get you out of trouble again:

- Take this code:

TCCR1A = 0x00;
TCCR1A |= (1<<WGM10)|(1<<WGM11)|(1<<COM1A1)|(1<<COM1B1)|(1<<COM1B0);
btimer();
TCCR1C = 0x00;

and make a function called pwm_init or something and call it only once at the beginning including that btimer it is enough.

- this does not feel right:

TCCR1A |= (1<<WGM10)|(1<<WGM11)|(1<<COM1A1)|(1<<COM1B1)|(1<<COM1B0);

TCCR1B |= (1<<CS10)|(1<<CS12)|(1<<WGM13)|(1<<WGM12); //prescaller

This means you selected :

Mode 15 - fast pwm with top on OCR1A

No wonder it does not work ...

For fast pwm 8 bit you should have:

TCCR1A |= (1<<WGM10)|(1<<COM1A1)|(1<<COM1B1);

TCCR1B |= (1<<CS10)|(1<<CS12);

 

hello

 

mersi de reply...

 

ohm, mode 3 is a phase correct... right? should it work with fast pwm? mode 5?

 

I have to use inverted too so setting COM1A1 and COM1A0 sometimes is needed, and COM1B1 and COM1B0 too... for directions... cause when inverting the negative side gives the speed, and in other way the positive part gives the speed... of course I can use non-inverting too but with 255-speed

 

ohm and for so on, I used fast pwm mode 3 on other robots, which has TOP = 0xFF, UPDATE OF OCR1x on TOP and TOV flag set on MAX

 

here I can't find this mode...

 

I will try this at home today what you suggested...


Thank you,

Hesit8

hey check this link out: http://www.arcfn.com/2009/07/secrets-of-arduino-pwm.html

it has some formulas that should help you calculate the prescaler and the output frequency.

Next step: you got fast pwm with SET on compare match and CLEAR at bottom. Point is that the TOP is OCR1A....so basically it sets at the TOP and right after that it CLEARS, i guess that's a problem as it stays on for almost no time, this would make the OC1A output useless. (mind that it's 24.00 so i'm really tired...could have made some mistakes in checking the datasheet)

I suggest you use a fast PWM mode with a fixed TOP, such as the 0101, 0110 or 0111 (these 4 bits are WGM13, 12, 11 and 10).

Strange how speed doesn't change though...

here is the whole code

 

 

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
/* PB4 M1    - pwm
 * PB2 M1
 * PB3 M2    - pwm
 * PB1 M2
 * PD6 M1    -enable
 * PB0 M2    -enable
 * forward: PB1,PB2 low, pwm
 * reverse: PB1,PB2 high, inverted pwm
 * stop: PB1,PB2 low, pwm 0(low);
 * protocol has to send first the direction, 2. left speed (M2), 3. right speed
 */

void forward(void);
void reverse(void);
void left(void);
void right(void);
void stop(void);
void USART_init(uint16_t ubrr_value);
unsigned char USART_get(void);
void btimer(void);

int direction;  //0-stop, 1-forward, 2-reverse, 3 - left, 4 - right

int main()
    {
    DDRB |= 0xFF;    //motors output
    DDRD |= (1<<PD6);    //motor output
    PORTD |= (1<<PD6);    //enable 1
    PORTB |= (1<<PB0);    //enable 2
    USART_init(51);    //9600 baud
    sei();

    while(1)
    {
    direction = 1;
    switch(direction)
        {
    case 0:
        stop();
        while(direction==0);
        break;
    case 1:
        forward();
        OCR1A = 25;
        OCR1B = 25;
        while(direction==1);
        break;
    case 2:
        reverse();
        while(direction==2);
        break;
    case 3:
        left();
        while(direction==3);
        break;
    case 4:
        right();
        while(direction==4);
        break;
        }
    }
    };

void reverse()
    {
    PORTB = 0x00;
    PORTB |= (1<<PB2)|(1<<PB0);
    PORTD |= (1<<PD6);
    TCCR1A = 0x00;
    TCCR1A |= (1<<WGM10)|(1<<WGM11)|(1<<COM1A1)|(1<<COM1B1)|(1<<COM1B0);
    btimer();
    TCCR1C = 0x00;
    };

void forward()
    {
    PORTB = 0x00;
    PORTB |= (1<<PB1)|(1<<PB0);
    PORTD |= (1<<PD6);
    TCCR1A = 0x00;
    TCCR1A |= (1<<WGM10)|(1<<WGM11)|(1<<COM1A1)|(1<<COM1B1)|(1<<COM1A0);
    btimer();
    TCCR1C = 0x00;
    };

void right()
    {
    PORTB |= (1<<PB1);
    PORTB |= (1<<PB2);
    PORTB |= (1<<PB0);
    PORTD |= (1<<PD6);
    TCCR1A = 0x00;
    TCCR1A |= (1<<WGM10)|(1<<WGM11)|(1<<COM1B1)|(1<<COM1B0)|(1<<COM1A1)|(1<<COM1A0);
    btimer();
    TCCR1C = 0x00;
    };

void left()
    {
    PORTB = 0x00;
    PORTB |= (1<<PB0);
    PORTD |= (1<<PD6);
    TCCR1A = 0x00;
    TCCR1A |= (1<<WGM10)|(1<<WGM11)|(1<<COM1A1)|(1<<COM1B1);
    btimer();
    TCCR1C = 0x00;
    };

void stop()
    {
    if(direction==2)
    {
    forward();
    _delay_ms(100);
    };
    if(direction==1)
    {
    reverse();
    _delay_ms(100);
    };
    PORTB = 0x00;
    PORTD = 0x00;
    TCCR1A = 0x00;
    TCCR1B = 0x00;
    TCCR1C = 0x00;
    };


//UART PART
void USART_init(uint16_t ubrr_value)
{
   UBRRL = ubrr_value;
   UBRRH = (ubrr_value>>8);

   UCSRC = (1 << UCSZ1) | (1 << UCSZ0);        //8bit 1 stop bit
   UCSRB=(1<<RXEN)|(1<<TXEN)|(1<<RXCIE);    //interrupt enable
};


unsigned char USART_get(void)
{
    while ( !(UCSRA & (1<<RXC)) );
    return UDR;
};


ISR(USART_RX_vect)
    {
    direction=USART_get();
    OCR1A=USART_get();
    OCR1B=USART_get();
    };

void btimer()
    {
    TCCR1B = 0x00;
    TCCR1B |= (1<<CS10)|(1<<CS12)|(1<<WGM13)|(1<<WGM12); //prescaller
    };