Offline
Newbie
Karma: 0
Posts: 36
|
 |
« on: April 21, 2012, 07:01:23 pm » |
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
Full Member
Karma: 0
Posts: 134
|
 |
« Reply #1 on: April 22, 2012, 06:32:27 am » |
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
|
|
|
|
|
|
|
UK
Offline
Tesla Member
Karma: 100
Posts: 6787
-
|
 |
« Reply #3 on: April 22, 2012, 08:29:24 am » |
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
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 36
|
 |
« Reply #4 on: April 22, 2012, 03:00:50 pm » |
If this can't be done in software then only I wish to go to a 555 timer.
|
|
|
|
|
Logged
|
|
|
|
|
Leeds, UK
Offline
Full Member
Karma: 0
Posts: 134
|
 |
« Reply #5 on: April 22, 2012, 03:07:17 pm » |
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
Brattain Member
Karma: 299
Posts: 26031
Solder is electric glue
|
 |
« Reply #6 on: April 22, 2012, 03:46:55 pm » |
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 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
Newbie
Karma: 0
Posts: 36
|
 |
« Reply #7 on: April 22, 2012, 04:16:32 pm » |
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
Brattain Member
Karma: 299
Posts: 26031
Solder is electric glue
|
 |
« Reply #8 on: April 22, 2012, 04:46:47 pm » |
Will the above code interfere with these? No. 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. 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
Newbie
Karma: 0
Posts: 36
|
 |
« Reply #9 on: April 22, 2012, 04:51:25 pm » |
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
Newbie
Karma: 0
Posts: 36
|
 |
« Reply #10 on: April 22, 2012, 04:54:00 pm » |
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
|
|
|
|
|
|
|
Global Moderator
Melbourne, Australia
Offline
Shannon Member
Karma: 226
Posts: 14121
Lua rocks!
|
 |
« Reply #12 on: April 22, 2012, 05:05:00 pm » |
This code generates 38 KHz on pin D11 on the Mega2560: 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
Newbie
Karma: 0
Posts: 36
|
 |
« Reply #13 on: April 22, 2012, 05:21:13 pm » |
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
Melbourne, Australia
Offline
Shannon Member
Karma: 226
Posts: 14121
Lua rocks!
|
 |
« Reply #14 on: April 22, 2012, 05:59:56 pm » |
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
|
|
|
|
|
|