If you're going to use it for modulated IR, just connect one end of your LED to your constant 38kHz source, and the other end to another output pin.
Waggling the other output pin at your desired (<38kHz!) rate produces a modulated 38kHz IR beam.
If you want to modulate the IR then that is what the interrupted service routine was to do in the code I originally posted. It is best to do this since the modulation can be synchronised with the carrier.
PulseIn isn't particularly accurate. From the documentation:
The timing of this function has been determined empirically and will probably show errors in longer pulses
I checked the timer output on the oscilloscope. Plus, assuming your clock is accurate, it matches the theory. PulseIn just works by counting in a loop.
It looks like Mike's solution incorporates an ISR to turn the output of the timer on or off, exactly at the start of each pulse, which, as he says, would synchronize with the carrier.
Grumpy_Mike:
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
}
He's using a different mode (PWM) and a different prescaler, but you can work out the maths:
1 / ((1 / 16e6) * 8 * 52) = 38461.538
So, his timer will generate 38.46 KHz, as advertised.
I am a newbie with assembly with avr. can you please post the code of 38 Khz wave modulated with 1 Khz wave to be used with TSOP1738.
Will be a life saver. Thanks.
What was wrong with Claghorn's suggestion on page 1?
i don't know a lot about modulation and synchronization. I get the idea that grumpy_mike's code with little modification will produce a modulated 38 Khz wave with 1 Khz. Any idea what to modify in that code?
Hi,
If all you are trying to do is generate a 38khz carrier, switched at 1khz, why not do it in hardware with a single 556 Timer, that what this does -
It costs about 2 dollars to build.
Duane B
As I have said before, I really don't want to do that unless I can't do it with software.
I am successful in generating 38 Khz thanks to you guys, now I just need it modulated with 1Khz
@nick
Your code produces output at pin 10 using timer 2. Can't I similarly produce output of 1 KHz using Timer1 at some other pin? Then connect this pin at the other end of led?
Yes you could do that. But this does it with only one pin:
const byte LED = 9; // Timer 1 "A" output: OC1A
ISR (TIMER2_COMPA_vect)
{
TCCR1A ^= _BV (COM1A0) ; // Toggle OC1A on Compare Match
if ((TCCR1A & _BV (COM1A0)) == 0)
digitalWrite (LED, LOW); // ensure off
} // end of TIMER2_COMPA_vect
void setup() {
pinMode (LED, OUTPUT);
// set up Timer 1 - gives us 38.095 MHz (correction: 38.095 KHz)
TCCR1A = 0;
TCCR1B = _BV(WGM12) | _BV (CS10); // CTC, No prescaler
OCR1A = 209; // compare A register value (210 * clock speed)
// = 13.125 nS , so frequency is 1 / (2 * 13.125) = 38095
// Timer 2 - gives us our 1 mS counting interval
// 16 MHz clock (62.5 nS per tick) - prescaled by 128
// counter increments every 8 uS.
// So we count 125 of them, giving exactly 1000 uS (1 mS)
TCCR2A = _BV (WGM21) ; // CTC mode
OCR2A = 124; // count up to 125 (zero relative!!!!)
TIMSK2 = _BV (OCIE2A); // enable Timer2 Interrupt
TCCR2B = _BV (CS20) | _BV (CS22) ; // prescaler of 128
} // end of setup
void loop()
{
// all done by interrupts
}
Output (pin D9 this time):
There is your 38 KHz signal pulsed at 1 KHz.
Can't thank you enough mate.
Just one question, Since Timer 2 is assigned pins 9 & 10, I won't use them for other purposes as a precaution while using this code. Any pther precaution?
Again, thanks a lot mate.
// set up Timer 1 - gives us 38.095 MHz
!
Ah yes, I just put that there to make sure everyone was paying attention. ![]()
That should read 38.095 KHz.
Come to think of it, it would be surprising to get a 38 MHz pulse out of a 16 MHz processor.
praky:
Just one question, Since Timer 2 is assigned pins 9 & 10, I won't use them for other purposes as a precaution while using this code. Any pther precaution?
The latest version, above, only uses pin 9. Feel free to use the other pins for whatever you want. Other precautions? Avoid bad dates.
![]()
Hello Nick. The project I am working on is currently using the TLC5940 library and the IRremote library. The two both utilize pin 2 on the Uno. Within the IRremote library I found a place to designate the IR output pin to pin 9.
// Arduino Duemilanove, Diecimila, LilyPad, Mini, Fio, etc
#else
#define IR_USE_TIMER1 // tx = pin 9 //uncommented for Tlc5940 project
//#define IR_USE_TIMER2 // tx = pin 3 //commented for Tlc5940 project
However, the TLC5940 library also uses pin 9.
I've been poking around the net for a couple of days now seeking a solution and just recently came across your post using this code:
const byte LED = 10; // 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() { }
Could this code be adapted for use on a Uno and not use pins 3 or 9? - Scotty
As described in here: http://www.gammon.com.au/forum/?id=11504
The timer pins are:
Timer 0
input T0 pin 6 (D4)
output OC0A pin 12 (D6)
output OC0B pin 11 (D5)
Timer 1
input T1 pin 11 (D5)
output OC1A pin 15 (D9)
output OC1B pin 16 (D10)
Timer 2
output OC2A pin 17 (D11)
output OC2B pin 5 (D3)
Hello Everybody
I have a little issue, and I just can't get it worked out. I already spent a good amount of time on it but I'm still super new to the Arduino board.
I would like to pulse width modulate a 38kHz carrier signal at 500hz, and adjust the duty cycle of the 500hz signal by reading a value from a potentiometer (value between 256 and 0 (100% to 0% duty cycle)).
So far, I came up with the code bellow, which does the following: It uses the tone() command to output a 38kHz signal on pin 11 and uses the delayMicroseconds() command to modulate it at 500hz. By
adjusting the delays for the on/off period of the 38kHz signal (by using a value I get from the Potentiometer), I can adjust the duty cycle of the 500hz modulated signal. (In the example below, I have 2048 increments by which I can adjust the duty cycle, but I would only need 256.)
void loop () {
Bval = analogRead(PodPin) * 2;
//(Read Potentiometer, then multiplay value by x2 and store it in "Bval" (Value will be between 0 and 2048)
tone(11,38000);
//create 38kHz signal on pin 11)
delayMicroseconds(Bval);
//delay for "Bval" microseconds
noTone(11);
//turn off 38kHz signal on pin 11
delayMicroseconds(2048 - Bval);
//delay for "2048 - Bval" microseconds.
}
For some reason, my code doesn't work very reliable. My guess would be that everything is extremely "time sensitive" and by doing it with "delays" it will never be very accurate. I think it should be possible to do it much more reliably with timers but I just can't get it to work (I tried to play with code posted above by Nick Gammon, but didn't have much luck yet). Any chance somebody could help me on this? I would greatly appreciate any input...
PS: I have an Arduino Uno
