Go Down

Topic: How to create a 38 Khz pulse with arduino using timer or PWM? (Read 23412 times) previous topic - next topic

praky

Thanks for the explanation. This method it is, then!

praky

#16
Apr 24, 2012, 10:41 am Last Edit: Apr 24, 2012, 10:43 am by praky Reason: 1
I used the following 2 fxn to measure frequency using your (nick gammon's timer method) code.

long getFrequencySampled()
{
 #define SAMPLES 4096
 long freq = 0;
 for(unsigned int j=0; j<SAMPLES; j++) freq+= 500000/pulseIn(pin, HIGH, 250000);
 return freq / SAMPLES;
}

long getFrequency()
{
 long duration=pulseIn(pin, HIGH, 250000);
 Serial.print("duration of pulse is: ");
 Serial.println(duration);  //in microseconds
 duration=duration*2;
 Serial.print("duration of pulse is: ");
 Serial.println(duration);  //in microseconds
 freq = 1000000/duration;
 Serial.print("Frequency is: ");
 Serial.println(freq);
 
 return freq;
}

getFrequencySampled() returned a value of 40.5-41 Khz.
getFrequency() returns a value that alternates randomly between 35 Khz and 41 Khz. (for pulse durations of 12 & 14 microseconds)

Any idea why the frequency doesn't equal the theoretical value?

Nick Gammon


 long duration=pulseIn(pin, HIGH, 250000);


My code doesn't use pulseIn. Can you post the whole sketch?
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

praky

I used pulseIn to measure the freq.

Here is the whole code...
Code: [Select]
const int pin = 7;
unsigned long duration;
long x;
long freq;
const byte LED = 10;  // Timer 2 "A" output: OC2A
void setup()
{
  pinMode(pin, INPUT);
  Serial.begin(9600);
 
  //
  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
 
//  tone (10, 38000);
}
long getFrequency()
{
  long duration=pulseIn(pin, HIGH, 250000);
  Serial.print("duration of pulse is: ");
  Serial.println(duration);  //in microseconds
  duration=duration*2;
  Serial.print("duration of pulse is: ");
  Serial.println(duration);  //in microseconds
  freq = 1000000/duration;
  Serial.print("Frequency is: ");
  Serial.println(freq);
 
  return freq;
}
void loop()
{
  x=getFrequency();
  Serial.print("Frequency is: ");
  Serial.println(x);
 
}
long getFrequencySampled()
{
  #define SAMPLES 4096
  long freq = 0;
  for(unsigned int j=0; j<SAMPLES; j++) freq+= 500000/pulseIn(pin, HIGH, 250000);
  return freq / SAMPLES;
}

praky

Is it possible to create a 38 khz modulated wave by the same method?

AWOL

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.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Grumpy_Mike

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.

Nick Gammon

PulseIn isn't particularly accurate. From the documentation:

Quote
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.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Nick Gammon


Code: [Select]

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:

Code: [Select]
1 / ((1 / 16e6) * 8 * 52) = 38461.538

So, his timer will generate 38.46 KHz, as advertised.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

praky

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.

Nick Gammon

What was wrong with Claghorn's suggestion on page 1?
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

praky

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?

DuaneB

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 -

http://rcarduino.blogspot.com/2012/03/punk-consoles-and-ir-transmitters-555.html

It costs about 2 dollars to build.

Duane B

rcarduino.blogspot.com
Read this
http://rcarduino.blogspot.com/2012/04/servo-problems-with-arduino-part-1.html
then watch this
http://rcarduino.blogspot.com/2012/04/servo-problems-part-2-demonstration.html

Rcarduino.blogspot.com

praky

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

praky

@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?

Go Up