Pages: [1] 2 3 ... 5   Go Down
Author Topic: How to create a 38 Khz pulse with arduino using timer or PWM?  (Read 18817 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 36
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I want to create a square wave of 38 KHz to be fed to an IR led.

One way is to make a pin high and low for 13 microseconds each. But I can not use that approach since this requires use of loop function.

My program is rather big and I would not be able to handle the complexities of doing other tasks as well as creating this 38 Khz wave both in loop() (if it can be done at all)

My question is, is there a way, by using a timer or something else to achieve this purpose? So that I can just start the timer in setup() and the pin in question will have 38Khz square as long as the program runs.

I am using ArduinoMEGA

Thanks
« Last Edit: April 21, 2012, 07:10:20 pm by praky » Logged

Leeds, UK
Offline Offline
Full Member
***
Karma: 0
Posts: 134
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I don't have any experience with the Mega, but it looks like it has quite a few timers knocking about. It seems like it should be possible to take one of the unused timers and Have it toggle one of the OCxn pins.

Take a look at the timer section in the data sheet, and also have a look here http://maxembedded.wordpress.com/2011/07/14/avr-timers-ctc-mode/ for more information on having a timer toggle a pin in the background purely through hardware.

Just make sure you don't tread on anything else that is using a particular timer, or there might be issues.
Logged

Delray Beach, FL USA
Offline Offline
Full Member
***
Karma: 0
Posts: 113
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Sounds like the BackgroundIR class I wrote as part of my project is just what you need. It runs entirely at interrupt level from timer interrupts and pulls the length of the next pulse off a circular buffer you can fill at any time (if you don't wait too long, anyway :-).

You can find the latest version in the tarball pointed at here:

http://home.comcast.net/~tomhorsley/hardware/arduino/software.html

A lot of the code was adapted from:

http://www.arcfn.com/2009/08/multi-protocol-infrared-remote-library.html

(but I moved it all to interrupts).
Logged


UK
Offline Offline
Shannon Member
****
Karma: 223
Posts: 12631
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I want to create a square wave of 38 KHz to be fed to an IR led.

Are you absolutely determined to do this in software? If not, have you considered doing it with a 555 timer?
Logged

I only provide help via the forum - please do not contact me for private consultancy.

Offline Offline
Newbie
*
Karma: 0
Posts: 36
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

If this can't be done in software then only I wish to go to a 555 timer.
Logged

Leeds, UK
Offline Offline
Full Member
***
Karma: 0
Posts: 134
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

If this can't be done in software then only I wish to go to a 555 timer.

You have several software options open to you. Or a 555 timer.
Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 620
Posts: 34006
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Yes you can do it with the timers with no overhead.
This code fires off an ISR every cycle but there is no need to do this:-
Code:
/* Code to pulse pin 3 with a modulated signal
* Can be used to drive an IR LED to keep a TSOP IR reciever happy
* This allows you to use a modulated reciever and a continious beam detector
* By Mike Cook Nov 2011 - Released under the Open Source licence
*/
 volatile byte pulse = 0;

ISR(TIMER2_COMPB_vect){  // Interrupt service routine to pulse the modulated pin 3
    pulse++;
  if(pulse >= 8) { // change number for number of modulation cycles in a pulse
    pulse =0;
    TCCR2A ^= _BV(COM2B1); // toggle pin 3 enable, turning the pin on and off
  }
}

void setIrModOutput(){  // sets pin 3 going at the IR modulation rate
  pinMode(3, OUTPUT);
  TCCR2A = _BV(COM2B1) | _BV(WGM21) | _BV(WGM20); // Just enable output on Pin 3 and disable it on Pin 11
  TCCR2B = _BV(WGM22) | _BV(CS22);
  OCR2A = 51; // defines the frequency 51 = 38.4 KHz, 54 = 36.2 KHz, 58 = 34 KHz, 62 = 32 KHz
  OCR2B = 26;  // deines the duty cycle - Half the OCR2A value for 50%
  TCCR2B = TCCR2B & 0b00111000 | 0x2; // select a prescale value of 8:1 of the system clock
}

void setup(){
  setIrModOutput();
  TIMSK2 = _BV(OCIE2B); // Output Compare Match B Interrupt Enable
}

void loop(){
// do something here
}
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 36
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok. I will try this. But please note that I also make use of serial communication (Serial & Serial1) and a single interrupt(0) in my code.

Will the above code interfere with these?

since you code uses interrupt which interrupt I can't utilize in further coding?

Also I understand pin 3 and pin 11 cannot be use for any other purpose. Any other pins used and not available?
« Last Edit: April 22, 2012, 04:25:02 pm by praky » Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 620
Posts: 34006
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Will the above code interfere with these?
No.

Quote
since you code uses interrupt which interrupt I can't utilize in further coding?
As the code uses pin 3 you can't use that pin as an interrupt, but if that is a problem just change it to use pin 11 instead of pin 3.

Quote
Also I understand pin 3 and pin 11 cannot be use for any other purpose
If that is what you understand then you are wrong.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 36
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
This code fires off an ISR every cycle but there is no need to do this:-

What do you mean by that?

P.s. I am no pro in assembly programming with avr. Though I know assembly with 8085 and 8051.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 36
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Also I understand pin 3 and pin 11 cannot be use for any other purpose
If that is what you understand then you are wrong.

Please explain. I am not an experienced coder.

I see in the comments that pin 11 is being disabled for the output that why i said i t is not available for use.
As for pin 3, i meant that since the 38 Khz wave will be available on that pin, it has been made use of.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 1
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Why not just use the Tone() function?
http://arduino.cc/en/Reference/Tone
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 481
Posts: 18742
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

This code generates 38 KHz on pin D11 on the Mega2560:

Code:
const byte LED = 11;  // Timer 2 "A" output: OC2A

void setup() {
  pinMode (LED, OUTPUT);
  
  // set up Timer 2
  TCCR2A = _BV (COM2A0) | _BV(WGM21);  // CTC, toggle OC2A on Compare Match
  TCCR2B = _BV (CS20);   // No prescaler
  OCR2A =  209;          // compare A register value (210 * clock speed)
                         //  = 13.125 nS , so frequency is 1 / (2 * 13.125) = 38095

}  // end of setup

void loop() { }

It does not use interrupts and does not interfere with any other pin.

(edit) Changed from D10 to D11. OC2A outputs on D11.
« Last Edit: March 14, 2013, 03:57:33 am by Nick Gammon » Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 36
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Why not just use the Tone() function?
http://arduino.cc/en/Reference/Tone

This looks interesting!! and hugely simplistic.

Can this produce a freq. as large as 38 Khz? In the example they are using quite low frequencies. will test this tomorrow.
« Last Edit: April 22, 2012, 05:23:41 pm by praky » Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 481
Posts: 18742
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
void setup ()
{
tone (10, 38000);
}
void loop () {}

That generates a 38 KHz output, more or less. However it's not as smooth as the hardware timer.

The tone library uses a timer, but that causes an interrupt. Inside the interrupt it does a counter. When the counter is met it toggles the pin. So there is a bit of jitter (because other interrupts might fire), and it consumes CPU resources.

The pure hardware solution described above runs without any code being called at all (once you set it up).
Logged


Pages: [1] 2 3 ... 5   Go Up
Jump to: