Society of Robots - Robot Forum

Software => Software => Topic started by: tristantech on January 30, 2009, 05:11:40 PM

Title: avr generate 38khz in hardware
Post by: tristantech on January 30, 2009, 05:11:40 PM
I'm stumped on a problem I've been working weeks on. I want to use the ATmega 88's 8-bit timer0 to generate a 38khz wave for an ir light gate. I want to do this completely in hardware without interrupts because my chip is running at only 1 Mhz. I'm using the code below:

Code: [Select]

TCCR0A |= (1 << WGM01); // Configure timer 0 for CTC mode

 TCCR0A |= (1 << COM0B0); // Enable timer 0 Compare Output channel B in toggle mode

 OCR0B = 13; //Toggle the output every 13 uS

 TCCR0B |= (1 << CS00); // Start timer w/o presaler


When I program the chip and turn it on, my oscilloscope show no waveform on the pin. I have all the outputs and inputs correctly configured.

What's wrong with the code? ??? ???
Title: Re: avr generate 38khz in hardware
Post by: brijesh on January 31, 2009, 09:40:59 AM
Maybe you have done it and not mentioned it here. Have you changed the mode of the respective pin as output pin?
Title: Re: avr generate 38khz in hardware
Post by: TrickyNekro on January 31, 2009, 10:04:15 AM
Ok... This is how it should look

TCCR0A =&B01000010
TCCR0B =&B00000001

Then you should be fine...
I set prescaler to 1...
With a prescaler at 8 you get no good resolutions...


Cheers, mate
Title: Re: avr generate 38khz in hardware
Post by: tristantech on January 31, 2009, 03:26:18 PM
I'm using Channel B, not A

You set the Channel A pin to toggle, but I am using the Channel B pin. So you actually need to set bit 4 in TCCR0A (COM0B0)
Title: Re: avr generate 38khz in hardware
Post by: TrickyNekro on January 31, 2009, 07:59:03 PM
Ok then... It's

TCCR0A =&B00010010
TCCR0B =&B00000001

That isn't working too???
That's set on B channel toggle mod....
Title: Re: avr generate 38khz in hardware
Post by: tristantech on January 31, 2009, 08:29:12 PM
No that doesn't work.

The output is set right, my scope is hooked up right to the avr's OC0B pin.
Title: Re: avr generate 38khz in hardware
Post by: pomprocker on February 01, 2009, 12:14:13 AM
Check out the source code for ladyada's tv-b-gone...It runs at 8MHz and has code to generate IR diode pulses for tv's which is around 38Khz
Code: [Select]
#define freq_to_timerval(x) ((F_CPU / x - 1 )/ 2)

 
// Code 000 -- Sony, Baur, Neckermann, Otto Versand, Palladium, Quelle, SEI, Sinudyne, Sonolor, Universum
const struct powercode sonyCode PROGMEM = {
  freq_to_timerval(37470), // 37.47 KHz 
  {{245, 60},
   {123, 60},
   {61 , 60},
.....


Title: Re: avr generate 38khz in hardware
Post by: tristantech on February 01, 2009, 09:30:01 PM
That looks like it may work. I downloaded the source code of one of the many TV-B-Gone kits on the web.
Title: Re: avr generate 38khz in hardware
Post by: tristantech on February 02, 2009, 03:10:49 PM
I looked through the source code but couldn't find anything about 38kHz.
Title: Re: avr generate 38khz in hardware
Post by: pomprocker on February 02, 2009, 03:49:45 PM
I think it is simply inserting a delay to create a pulse at the appropriate frequency. The first number in the struct is the amount of time it is on, the second it the amount of time it is off.
Title: Re: avr generate 38khz in hardware
Post by: Webbot on February 02, 2009, 05:49:55 PM
I know it doesn't cover the ATMMega88 specifically but it may still be worth checking http://www.societyofrobots.com/member_tutorials/node/233 (http://www.societyofrobots.com/member_tutorials/node/233)
Title: Re: avr generate 38khz in hardware
Post by: tristantech on February 02, 2009, 06:48:42 PM
Can anyone just give me some source code?
Title: Re: avr generate 38khz in hardware
Post by: Webbot on February 02, 2009, 09:05:53 PM
The ATMega88 is similar to ATMega168 (with different memory sizes). So looking at the sheet of the 168 from the link I gave you http://www.societyofrobots.com/member_tutorials/files/ATMega168.pdf (http://www.societyofrobots.com/member_tutorials/files/ATMega168.pdf)


Assumptions: you said your processor is running at 1Mhz and you MUST use Timer0

Here's the formula from my tutorial:-

Output_PWM_Frequency =  Clock_Speed / (Prescaler * (1 + TOP))

Where:
Output_PWM_Frequency = 38kHz = 38,000
Clock_Speed = 1Mhz = 1,000,000
As per my sheet then, for Timer0, the value of TOP is fixed at 255.

So we can re-write the formula as:
38,000 = 1,000,000 / (Prescaler * (1+255))
38,000 = 1,000,000 / (Prescaler * 256)
38,000*256 = 1,000,000 / Prescaler
Prescaler = 1,000,000 / (38,000 * 256)
Prescaler = 1,000,000/9,728,000
Prescaler = (approx) 0.1

So you can't do it!!! The minimum for the prescaler is 1


If we use a 16 bit timer like Timer 1 then we have more control over the value of TOP:
TOP = (Clock_Speed / (Prescaler * Output_PWM_Frequency)) - 1
TOP=(1,000,000 / (Prescaler * 38,000))-1
Assuming Prescaler=1 then
TOP=(1,000,000/38,000)-1 = 26 -1 = 25  // NB This is approximate
Since TOP isn't one of the fixed values: 255, 511, 1023 then we need a mode that sets TOP using ICR1 - so lets choose 16 bit fast pwm.


Here is some untested code:-
Code: [Select]
// Set Timer1 to 16 bit fast PWM  using ICR1 (NB this code could be made smaller):-
TCCR1B &= ~( (1<<CS12) | (1<<CS11) | (1<<CS10)); // disable PWM
TCCR1B |= (1<<WGM13);
TCCR1B |= (1<<WGM12);
TCCR1A |= (1<<WGM11);
TCCR1A &= ~(1<<WGM10);

// Set up the prescaler to clock div 1 (assuming 1MHz)
TCCR1B |= (1<<CS10);

// Set the value of TOP
ICR1 = 25;

You can now get the output on either OC1A and/or OC1B

To output on OC1A:
TCCR1A |= (1<<COM1A1) | (1<<COM1A0);
OCR1A = (ICR1>>1); // 50% duty cycle

To output on OC1B:
TCCR1A |= (1<<COM1B1) | (1<<COM1B0);
OCR1B = (ICR1>>1); // 50% duty cycle

while(1){
    // Adjust duty cycle by changing OCR1A or OCR1B
    // Adjust frequency by changing ICR1
}




Title: Re: avr generate 38khz in hardware
Post by: Ro-Bot-X on February 03, 2009, 06:43:22 AM
The only way you can use Timer0 or Timer2 (8 bit timers) is if you use an external clock source - a crystal. So, using Webbot's calculations. for 38kHz you need a crystal of 9.728MHz with a prescaler of 1. Using internal 8MHz clock, the max frequency you can generate is 31.250kHz, for this frequency you can use a 32kHz sensor instead of a 38kHz one.

Long time ago I was struggling with this because I was using ATmega8 that has 1 PWM output for Timer0 and Timer1 so I coud not use that to drive the motors. So I have designed my Ro-Bot-X board to use a 9.728MHz crystal. Now, that ATmega168 has 2 PWM outputs for each Timer, I would use Timer1 to generate the 38kHz signal and Timer2 to drive the motors, since the motors don't need such a high frequency PWM.
Title: Re: avr generate 38khz in hardware
Post by: tristantech on February 04, 2009, 07:11:50 PM
I feel stupid...I knew I was making some obvious mistake!! I think I'll just use an external oscillator circuit using a 555 or TTL chip.

I'm already using the 16-bit timer. The project i'm doing is a track timer for measuring the speed of robots and things. I planned on using 2 ir 38khz lightgates and the 16 bit timer for measuring the ellapsed time.
Title: Re: avr generate 38khz in hardware
Post by: Webbot on February 04, 2009, 07:33:54 PM
Could you not use of the 8bit timers to measure the elapsed time instead - thus freeing the 16 bit timer?  You could have the 8bit timer overflow interrupt increment another variable so that your elapsed time would be (external variable)*256 + (timer count in range 0...255)
Title: Re: avr generate 38khz in hardware
Post by: tristantech on February 05, 2009, 04:12:24 PM
the 8-bit timer overflow interrup will interrupt my program every 255 instructions (assuming the prescale is 1) and won't give as good of a resolution as the 16-bit timer could.