3

I am an Arduino beginner and want to build a obstacle detection system. I've IR Leds and TSOP receivers(38kHz). How can I modulate the LED to blink at 38kHz? Could you please help me out with some code!

Kortuk
  • 13,362
  • 8
  • 60
  • 85
gomek
  • 465
  • 2
  • 7
  • 12

3 Answers3

2

Since you're mentioning Vishay's TSOP I guess the 38Hz should be 38kHz.
I don't know the Arduino platform, but the usual way to do this is set up a timer to interrupt at 76kHz (twice the frequency you want) and toggle the LED output on every interrupt as long as a "send" flag is set.

edit
Be sure to shield the receiver from HF fluorescent lamps; they are often controlled at +/-40kHz, which a 38kHz receiver may easily pick up. If your robot is too far from obstacles to receive the LED's reflected signal, the receiver's AGC may lock upon the lamp's "signal".
Don't worry if you can't have a heartbeat interrupt exactly every 13.16us. A small deviation may even be a good idea because the receiver's sensitivity is lower the farther from the center frequency. This means that you won't reacting to signals reflected from meters away, which commercial IR remotes tend to do. Of course you can always reduce the LED current to the same effect.

stevenvh
  • 145,145
  • 21
  • 455
  • 667
  • The IR LEDs use automatic gain when I have used them. This means you need to not continuously send a signal because if it constantly receives one with will remove it in the gain stage. A continuous modulation is calibrated out over time. if you just need a signal to go low when you approach an object then the pulse should go low when you approach the object, but you may find that if you approach it too slowly it will be calibrated out. – Kortuk Nov 27 '10 at 16:31
  • Sorry for the mistake; it should have been 38kHz. Why do you need to set the timer at twice the frequency required? What's the logic behind that? – gomek Nov 27 '10 at 17:12
  • I just tried doing this but it didn't work. I just tried modifying the Blink sample which came with the Arduino IDE to blink every 13.16us but the TSOP sensor didn't sense it. – gomek Nov 27 '10 at 17:34
  • @gomek: You need twice the frequency because you have two level changes in 1 period: signal goes low, wait 13us, signal goes high, wait 13us, signal goes low again. So your total period is 2 x 13us = 26us, which gives you 38kHz = 1 / 26us. – stevenvh Nov 27 '10 at 17:43
  • Thanks, it worked!! How do I optimize the frequency so as to measure long and short distances? – gomek Nov 28 '10 at 07:51
  • You can't really measure distances this way, see [my answer](http://electronics.stackexchange.com/questions/7208/tsops-to-measure-distance/7209#7209) to your other question about this. The only thing you can do is use a slightly different frequency, like 36kHz, which will reduce sensitivity. But it's not like you can detect objects at 1m @ 38kHz and at 70cm @ 36kHz, for instance. Too much depends on the texture, material and orientation of the reflecting surface. – stevenvh Nov 28 '10 at 11:40
1

Some of the newer PICs, such as the 16F1826, have a digital modulator hardware module that makes that sort of thing quite trivial.

Here are lots of hits I obtained on the Arduino forum when I searched on IR modulation. You should find some code amongst those. It's also the best place to get Arduino-related questions answered.

Leon Heller
  • 38,774
  • 2
  • 60
  • 96
0

One way to transmit IR commands, such as RC-5 IR commands, is to set up a hardware timer that oscillates at the appropriate frequency ( 36 kHz for RC-5 ) and duty cycle. The CPU turns the oscillator on and off for each bit -- at about 562 bits per second, the CPU has to do something at most once every 889 us. (It's much easier to program the Arduino CPU to do something once every 889 us than once every 13.9 us).

#include <Tone.h>
Tone tone1;
const unsigned int frequency = 36000; // Hz
const unsigned int half_bit_time = 889; // microseconds

void setup(){
  tone1.begin(13);
}

void send_bit(boolean the_bit){
    if(the_bit){
      noTone();
      delayMicroseconds(half_bit_time );
      tone1.play(frequency);
      delayMicroseconds(half_bit_time );
      noTone();
    }else{
      tone1.play(frequency);
      delayMicroseconds(half_bit_time );
      noTone();
      delayMicroseconds(half_bit_time );
    };
}

void loop(){
    send_bit(1);
    send_bit(1);
    send_bit(0);
    send_bit(1);
    send_bit(0);
    // ... etc.
}

EDIT: I see now that the current Tone library sets up an interrupt at twice the selected frequency, as stevenvh suggested. But some of the other links I posted describe a free-running timer that oscillates at the right frequency, free-running without interrupting the CPU.

davidcary
  • 17,426
  • 11
  • 66
  • 115