Should I use PWM instead?

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

I have been working on an IR controller for a while, you can see my other posts to see the sort of issues I have had so far.

Basically I am using 2 timers to send the code, the 16-bit timer to do the low and high pulses and the 8-bit timer to do the modulation at 36 KhZ, this works great and everything is looks good, except that I have now discovered that the modulation is at around 64% duty and I don´t seem to be able to achieve that with my current method. Here´s how I was doing the modulation with the 50% duty.

ISR (TIMER1_COMPA_vect)
{
	if(setMode)
	{
		OCR1A = data[bitnumber]; // Set CTC compare value to the next data bit length
		
		if (pulseIsHigh)
		{
			pulseIsHigh = 0;
		}
		else
		{
			pulseIsHigh = 1;
		}
		
		bitnumber++;	 //Go to the next bit
	}
	else
	{
		qtrSecTimer++;  //Add 1 to the quarter second timer.
	}
}
ISR (TIMER0_COMPA_vect)
{
	if (pulseIsHigh)
	{
		irLED_PORT ^= (1<< irLED); 
	
	}
	else
	{
		irLED_PORT &= ~(1 << irLED); //Make sure the pin is Low at end of pulse

	}

}

I tried changing that code to,

ISR (TIMER0_COMPA_vect)
{
	if (pulseIsHigh)
	{
		irLED_PORT ^= (1<< irLED); 
		if (!(dutyCycle)) {OCR0A = 137; dutyCycle = 1;} //Set the timing to get 64/36 duty cycle
		else {OCR0A = 74; dutyCycle = 0;}		
	}
	else
	{
		irLED_PORT &= ~(1 << irLED);
		dutyCycle = 0;
		OCR0A = 74;
	}

}

That sort of works, but it takes 2 pulses to change from OCR0A=74 to OCR0A=137. What I mean by that is that I get should 1 pulse low (it goes low first) for 74, the 1 pulse high for 137, then low for 74 etc. What actually happens is that I get 1 pulse low for 137, then 1 pulse high for 74, then another low 74, then another high for 74 then the correct high for 137. In other words, every other low pulses flip between 74 and 137, when they should all be 137. If I make 74 a bigger number like 150, then it seems to work correctly, but now the frequency is out. So I think that the 74 is too quick for the uC to process before the next interrupt is called. I looked in to PWM but it seems that is fixed frequency depending on the Fcpu and prescaler, so that doesn´t help, unless there is a way to be able to modify the frequency.

I am using an ATmega328P @ 8MhZ and an AVR dragon for debugging.

Any help would be greatly appreciated.

[/code]

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

paul23 wrote:
I looked in to PWM but it seems that is fixed frequency depending on the Fcpu and prescaler, so that doesn´t help, unless there is a way to be able to modify the frequency.

I am using an ATmega328P @ 8MhZ and an AVR dragon for debugging.

PWM would greatly reduce INTs.
The docs are not great, but looking at

Table 18-8. Waveform Generation Mode Bit Description

it seems you want Mode =7, TOP=OCRA

ie you can define the period first, then choose any fraction of that many clocks as duty cycle.

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

You need not timer0 interrupt.
In mode 7 you can set frequency with OCR0A and prescaler,
duty cycle with OCR0B. Output 36 kHz is on the pin OC0B (PORTB.5).
You can modulate the output with DDRB.5 .

// mega88, 8 MHz
int main()
{
   DDRB |= (1<<PD5); // output pin OC0B

   // mode=7, fast pwm, top=OCR0A, prescaler=1
   TCCR0A = (1<<WGM00)|(1<<WGM01)|(1<<COM0B1);
   TCCR0B = (1<<WGM02)|(1<<CS00);
   OCR0A  = 221; // 36 kHz
   OCR0B  = 141; // duty 64 percent

   while(1)
   {
     setbit(DDRB,5); // pulse
     clrbit(DDRB,5); // pause
   }
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

I've managed to get an IR remote working with an Arduino - but not without help

A fellow named Ken Shirriff made a library that handled all of the actual IR pulse control. He did it via the PWM.

He was also kind enough to explain how he uses the PWM

http://www.righto.com/2009/07/se...

This link describes the librariers and points to the github where they can be found.
http://www.arcfn.com/2009/08/mul...

I can't say that I totally understand what he's doing, but all of the information seems to be there, and I get the basic concepts.

The fact that I'm using an Arduino speaks to my general skill level -- so, it will probably be crystal clear to the average freak :)

Anyway, just my .02

hj

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

Thanks it works now. I didn´t know you could use OC0RB like that, I though A and B were separate, so that´s good to know. I have just one more bug to find then it´s working 100%.

Thanks again.