Let's Make Robots!

PWM at 38KHZ with Arduino

Hi guys.

I'm trying to modulate my IR led at 38KHz so that the receiver will pick up the signal. I've googled around and all i've seen is some people modding the wiring.c file, but this way the only get a limited number of possible frequencies. Some other guys say that you have to use a 555 cause you can't do that with arduino. Then i've found this: http://www.arduino.cc/playground/Code/Timer1 and i thought it could work, since it gives you the pwm command which also lets you specify the period....but it doesn't work, my IR receiver doesn't pick it. Maybe i just specified a wrong period? (i wrote 26, which is 26 micro seconds)

 Did i get something wrong? Do you know another method to achieve custom frequencies on PWM?

this is the circuit (not really needed though) 

thank you! Immagine_0.png

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

UPDATE 

I've used RobotFreak's code and it works. But...not always. Both the sender and the receiver are working at 2400 and "strange" things happen. The sender is using the code "serial.print(9)", and the receiver gets "57" (correct, it's its ascii value). But it doesn't only receive one, it receives something like eight 57s every time the IR led light's up. Not only, but sometimes after getting those eight 57s it also gets some other random values like 230 or 190. 

I will try to tweak it up a bit, both on the software and hardware part, and see if it gets better. 

Hmm strange. I tested the program with Hyperterm on a PC via the Asuro IR programming dongle. There is only 1 charcater received, when I send one, never multiple characters. Sometimes there are wrong characters. This IR connection is not 100% error free. You need some kind of error detection (CRC) . Keep in mind that this is a half duplex connection. You can only send or receive at one time. If both partners send at the same time there will be interferences.

One more tip, try to decrease the data rate to 1200 Baud. 

Haven't solved it yet but i understood where the problem is. I've used your hardware setup and it worked fine. So the problem must be in my setup (the one at the top of the page). I still can't understand what could be wrong though. I have already used a similar setup with the picaxe and it worked fine, only difference was that the serial was normally low instead of normally high so there was no pnp transistor to reverse the signal. 

No idea why it sends data multiple times.. 

 

EDIT!!! :

It works! I re-read the page carefully and noticed that you suggested 1KOhm resistors between the gate and the pins. Guess what, it worked! You are my new god, RobotFreak :D 

Good to here, it's working. What is the maximum distance you can reach? I think about to increase the range the Asuro communication with such kind of a booster.  At the moment 50cm is the maximum.

Just tried it. It works correctly at 350cm. If increase the distance i start to get errors (instead of receiving 57 i get other values). I've tested it in a well-lit room. Oh and it had a 330Ohm resistor in series.

IR led: tsal6100

IR receiver: tsop1238 

Radio Shack and Parts Express used to sell the detector card for about $5.00.
I've checked but i can't find them anymore. Tried searching for "ir sensor", "ir card", etc..

Here is a code sample for the IR communication between an Arduino an a PC (taken from the Asurino Lib). It uses Pin 11 and Timer 2 for the carrier frequency. The Hardware interface is the same I mentioned in another post.

Maybe its better to strart with a simpler circuit. I am not an expert for FETs but I think you should always use a resistor beetween gate and microcontroller (1kOhm). Also I would mention a resistor for current limit in series to the IR LED(10..100Ohm).

ir_interface.jpg

This is the sketch. You just need to adjust the IR_CLOCK_RATE to your needs:

#define IR_CLOCK_RATE    36000L

#define pwmPin 11   // IR Carrier


void setup()  {
  // set the data rate for the Serial port
  Serial.begin(2400);
 
  // toggle on compare, clk/1
  TCCR2A = _BV(WGM21) | _BV(COM2A0);
  TCCR2B = _BV(CS20);
  // 36kHz carrier/timer
  OCR2A = (F_CPU/(IR_CLOCK_RATE*2L)-1);
  pinMode(pwmPin, OUTPUT);
 
}

void loop()
{
  char i;
  for(i='A'; i<='Z'; i++)
  {
    Serial.print(i);
  }
  delay(40);
}
 

Cool! So all those TCCR2A and stuff actually go into the main program and not in the core files! Thanks for the code RbotoFreak!
I would never change the Arduino core files. It is alwasy better to overwrite the hardware registers in your own setup function.