Go Down

Topic: Rapid switching capabilities of Arduino? (Read 2167 times) previous topic - next topic


Hey guys,

I am trying to use Arduino pro mini 16Hz, 5V, to control 38kHz ir transmission. It's being used in a break-beam people counter, with the transmitter on one side of a door, and the receiver on the other side.

I have had it working fine, but I am struggling to get a decent distance of transmission (only achieving 4.3m). I have the setup like this http://www.edaboard.com/attachments/66823d1325891665-circuit-setup.jpg. The 5V connected to the base of the transistor (BC337) is the 5V from the Ardunio. I am aiming to get about 100mA through my ir transmitting diode (QED234). The ir receiver I'm using is a TSOP34138.

I found this tutorial http://jumperone.com/2011/11/break-beam-sensor/ where the guy is achieving around 30m of transmission distance using a 555 timer circuit, with the same TSOP receiver module. Why do you think that using the 555 timer is getting better results than using the arduino?



I can't see your link...
Do you have the same LED as the 30m version?  Have you confirmed beam pattern using a digital camera to look at the IR?
How are you generating the 38kHz, and how accurate is it?  Sensitivity of those receivers goes down significantly as you drift off of center frequency, but not immediately to zero.  If you were putting out 40kHz instead, I would expect it to work with reduced range.


Also you need to make sure that the peak wavelength sensitivity for the receiver is the same as the peak wavelength of the transmitter (IR diode). Again a miss match will result in a loss of range.


Feb 06, 2012, 04:54 am Last Edit: Feb 06, 2012, 05:20 am by LiamLambChop Reason: 1
Which link can't you see?

The receiver is best suited to 950nm and the transmitter trasmits 940nm. This isn't a big difference, so shouldn't matter, right?

Yes, I am using the same ir LED as the 30 version (well actually it uses a TSAL6200, and I use the TSAL7200, but they are identical as far as I can see). And no, I haven't confirmed my pattern using a digital camera. How would I do that?

The 38kHz is being generated by the arduino. Here is the sketch:

Code: [Select]
/* People counter sketch:
 Turns on infrared receiver module.
 Waits 520 microseconds (or 20 phases) then turns on infrared LED, which will pulse/blink at 38kHz
 (turn on for 13 microseconds, off for 13 microseconds - this is equal to phase) for 156 microseconds (6 phases). The irLED will restart this 'pulse cycle' after every 26 phases.

// pin numbers
const int irLED = 9;
const int irREC = 13;

// Variables
int ledState = LOW;             // ledState used to set the irLED
long previousMicros = 0;        // will store the value of 'currentMicros' when the irLED last changed states whilst pulsing, ie from HIGH to LOW
long then = 0; //stores value of now at the end of the last pulse cycle
long interval = 13;           // interval at which to pulse the irLED (microseconds)
long pause = 520; // pause between pulsing (20 phases)
long pausepulse = 676;//time from beginning of pause till end of pulsing (26 phases)

void setup() {
 //sets irLED (pin 9) and irREC (pin 12) as outputs
 pinMode(irLED, OUTPUT);  
 pinMode(irREC, OUTPUT);  

void loop()
 digitalWrite (irREC, HIGH);  //set the infrared receiver to HIGH
 long now = micros();  //variable which stores the time since the sketch began
 //here is the part which makes the irLED pulse
 if (now - then >= pause && now - then <= pausepulse){
   unsigned long currentMicros = micros();  //variable which stores the time since the sketch began

   if(currentMicros - previousMicros > interval) {
   // save the last time irLED changed states
   previousMicros = currentMicros;  

   // if the LED is off turn it on and vice-versa:
   if (ledState == LOW)
     ledState = HIGH;
     ledState = LOW;

   // set the LED with the ledState of the variable:
   digitalWrite(irLED, ledState);
 // restart the cycle after 100 phases
 if (now - then >= pausepulse){
   then = now;}

Interestingly, I get reduced range when I use my BC337 transistor in the circuit. I am using the BC337 to increase the current into the irLED (data sheet: http://www.vishay.com/docs/81012/tsal7200.pdf), which can handle between 100mA-1A (depending on the pulse duration). I had 150mA running through the irLED, but was getting no response from the irREC (data sheet: http://www.newark.com/pdfs/datasheets/vishay/TSOP34.pdf). When I ran the irLED straight off the arduino, it had about 20mA running through it, yet I was getting about 4m transmission. What's with that?

Also, in this link http://pcbheaven.com/circuitpages/Long_Range_IR_Beam_Break_Detector/?p=1I there is quite a relatively elaborate ir receiver circuit. Why is this necessary? My ir receiver circuit consists of the irREC and a relay which closes when the output of the irREC is HIGH. Why has this guy made his much more complicated?


Interestingly, I get reduced range when I use my BC337 transistor in the circuit.

Yes interesting, it suggests you are not wiring something up right. I assume the irLED is in the collector and not the emitter and that you have a base resistor.

Why has this guy made his much more complicated?

Because he is doing something different. This only clicks on the relay when the pulses have been blocked for longer than a certain time. This is set by the NE555 frequency and by how much it counts up before the incoming pulses resets it. When blocked this counter is not reset and so counts up to 0x200, at which time the relay is switched on and the input to the counter disabled so it doesn't count up any more. This allows brief interruptions to go unnoticed  but not longer ones. How would you do that more simply without a micro controller?

I have not timed the rate that your sketch outputs the on / off rate, have you?
It is much better if you use the PWM timers for this. Change the timer to 38KHz and just put out a PWM signal.
This code does that, and also counts how many times the LED has been flashed. It flashed the LED for 8 pulses and then it tuns off the LED for 8 pulses and repeats. If you don't want this aspect then just remove the ISR() function.

Code: [Select]
/* 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
  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(){
  TIMSK2 = _BV(OCIE2B); // Output Compare Match B Interrupt Enable

void loop(){
// do something here


   I built a 555 based transmitter yesterday, its very easy and potentially allows you to put more power through the IR Emitter LED for more range, it also frees you from having to wire the emitter to the Arduino making most applications a lot more practical. Its also a bit of a novelty getting some hardware to do some of the work for you.

   I am powering the IR Emitter directly from a 9V battery or a 2 cell lipo. As 555s are so cheap, pick up a handful or two and have a go, I used an online calculator to get the C,R1 and R2 values I needed for a 40Khz carrier signal that could trigger an IR Receiver.

   Here is a link to the calculator http://www.ohmslawcalculator.com/555_astable.php

   Here is a nice link to some 555 timer applications, the circuit you want is the AStable http://www.kpsec.freeuk.com/555timer.htm

Duane B


Read this
then watch this



long interval = 13;           // interval at which to pulse the irLED (microseconds)

Keep in mind that the other bits of code you have take some time to execute as well.  In particular, digitalWrite() takes over 1 microsecond (the maximum frequency you can get out of a loop with digitalWrite() in it is about 100kHz.  See http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1230286016 )  And micros() is unlikely to be very fast, either.

That will put you 10+% off the desired frequency, which is probably enough to shorten the range considerably.
If you're going to do timing loops accurate withing small numbers of microseconds entirely in software, you have to keep track of exactly how many cycles EVERYTHING takes...
It's easier to use a timer, or a gated 555...

Go Up