PWM stuck at 100% duty cycle

Go To Last Post
4 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
#include 
#include 
#include 
#include 

//Definitions
#define Trigger (PINC&_BV(PINC2))
#define Gearbox_Sensor (PINC&_BV(PINC0))
#define Turn_On_SW2 (PORTD |= _BV(PIND2)) 
#define Turn_Off_SW2 (PORTD &= ~_BV(PIND2)) 
#define Turn_On_SW3 (PORTD |= _BV(PIND3)) 
#define Turn_Off_SW3 (PORTD &= ~_BV(PIND3)) 
#define Turn_On_SW4 (PORTD |= _BV(PIND4)) 
#define Turn_Off_SW4 (PORTD &= ~_BV(PIND4)) 
#define Turn_On_Motor (PORTD |= _BV(PIND6)) 
#define Turn_Off_Motor (PORTD &= ~_BV(PIND6)) 
#define Set_CSxx TCCR0B |= 0x01
#define Clear_CSxx TCCR0B &= ~0x01
#define Set_COMBits TCCR0A |= 0x80;
#define Clear_COMBits TCCR0A &= ~0x80;

//Global Variables
volatile static bool gearbox_sensor_flag;	
volatile uint8_t value;

//Fucntion Prototypes
bool Fire(bool t_flag);
bool Stop_Firing(bool t_flag);
void Count_Gearbox_Cycles(bool gs_flag);

int main(){
	//Sets pin direction, PD6 Motor Drive, PB1 Motor Brake
	DDRD |= 0x40;
	DDRB |=	0x02;	

	//Sets initial state of PD6 and PB1
	PORTD &= ~0x40;	//Motor Drive off
	PORTB &= ~0x02;	//Motor Brake off

	//Enable Pull Up Resistors
	PORTC |= 0x05;	//PC0(Gbx. Pos.),PC2(Trig.) 
	PORTD |= 0xA0;	//PD5,PD7	
	PORTB |= 0x05;	//PB0,PB2

	//Enable Global Interrupts and PCINT8
	sei();				
	PCICR  |= 0x02;		
	PCMSK1 |= 0x01;			

	//Sets TC0 for Phase Correct PWM on PIND6, Non-Inverted
	TCCR0A |= 0x01;	//WGM00:Mode 5
	TCCR0B |= 0x08;	//WGM02:Mode 5
	OCR0A = 100;

	//Local Variables
	static bool trigger_flag;

		//Main Loop
		while(1){
			trigger_flag = Fire(trigger_flag);

			trigger_flag = Stop_Firing(trigger_flag);

			Count_Gearbox_Cycles(gearbox_sensor_flag);

			if( trigger_flag ){
				Turn_Off_SW3;
			}
			else{
				Turn_On_SW3;
			}

		}//End Main Loop		
}

//Main Interrupt
ISR(PCINT1_vect){	
	gearbox_sensor_flag = (Gearbox_Sensor != 0) ? true : false; 
}//End Main Interrupt

//Function Deifinitions--------------------------------------------------------------------------
bool Fire(bool t_flag){	
	if( t_flag ){
		if( Trigger == 0 )
		{
			Set_COMBits;	//sets PD6 for TMR0 PWM Mode 5
			Set_CSxx;	//turn on PWM on OC0A by turning on clock by setting divider to 1x
			t_flag = false;
		}
	}
	return t_flag;
}//End Fire

bool Stop_Firing(bool t_flag){
	if( Trigger != 0 )
	{
		Clear_CSxx;		//turn off PWM on OC0A by turning off clock by setting divider to 0x
		Clear_COMBits;	//sets PD6 back to GPIO mode
		Turn_Off_Motor;	
		t_flag = true;
	}
	return t_flag;
}//End Stop Firing

void Count_Gearbox_Cycles(bool gs_flag){
	static bool cgc_flag;

	if( cgc_flag != gs_flag ){
		if( gs_flag ){
			value++;
		}
	cgc_flag = gs_flag;
	}
}//End Gearbox Cycle Counter4

The title says it all, looking directly at the gate of the MOSFET that OC0A(aka PD6) is connected to all I get is full on and full off using a 15mhz scope. This is an ATMega88PA at 20mhz. I first set WGM bits to mode 5 for Timer 0, set OCR0A to 100, so I should be getting less than 40% duty cycle, then to start PWM on OC0A I set the COM bits to 2(COMOA1 set to 1), then set the CS00 bit to 1 for a 1x divider, that should enable PWM shouldn't it? Or do I still need to set TCNT0? I was under the impressiont hat TCNT0 in PWM mode was set to 0xFF automatically, I didnt' see a specific mention of setting up TCNT0 in the data sheet. Thanks.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you are in fact using mode 5 then OCR0A is TOP, and you won't get a PWM on OC0A. Set up and use OC0B, or use a different mode.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
or use a different mode.

Specifically, mode 1 will use OCR0A as the duty cycle and 0xff as TOP (and still be Phase Correct).

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Oh ok, I misunderstood the data sheet. Thanks.