wireless light break sensor, signal when sensor is 3ms low/high, sportstiming

Hi,

I’m trying to build a wireless light break sensor for equestrian sports-timing. Actually now I think of it, after this is done I probably want to build the timer as well.

I’ve had this project laying dormant for at least 4 years. But I have more time, space and a 3D printer for building the parts. And so a few weeks ago I start using parts I have around. An arduino, a mosfet an IR LED, a TSOP1738, and some custom made lens holders and two lenses an started testing.

I used code from Nick Gammon to create a 38 kHz carrier wave Modulated at 1 kHz. Connected the led, the tsop, connected a logic analyzer to the tsop and measured a minimum of 4ms low signal when interrupting the beam. I say Succes! I connected a LED to the output of the tsop and started testing outside. It seems that I have a reach of 40-50m.

After this long introduction I’ve searched and searched to achieve the following:
One module (arduino etc) to transmit a modulated IR signal, and this same module to receive the signal. If the signal from the TSOP is high for more then 3ms I want it to transmit a signal. Although at this point I have not decided what kind of wireless transmitter I’m gonna use but I won’t be surprised if it involves SPI.

Transmitting the IR signal
I’ve already used the following code which I don’t fully understand.

For example what does “|” do?

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) clockspeed 
 TCCR1A = 0; 
 TCCR1B = _BV(WGM12) | _BV (CS10);   // CTC, No prescaler
 OCR1A =  104;//dit bepaald de draagfrequentie 104 voor 38khz bij 8mhz clock         // 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  = 63;            // count up to 125  (zero relative!!!!) gehalveerd omdat het een 8Mhz xtal is
 TIMSK2 = _BV (OCIE2A);   // enable Timer2 Interrupt
 TCCR2B =  _BV (CS20) | _BV (CS22) ;  // prescaler of 128

}  // end of setup

void loop()
 {
 // all done by interrupts 
 }

Receiving and interpreting the IR signal
The TSOP is active low. In the image that I added the signal is reversed.
I considered the following options:

  • Overflowing timer 0 every 3 ms, reset the timer when the signal from the TSOP goes LOW (interrupt).

  • Overflowing timer 0 every ms and increase a (volatile)variable. Reset this variable with every interrupt from the TSOP and let the timer go on

I would like your opinion about how to proceed.

JoerideMan:
I used code from Nick Gammon to create a 38 kHz carrier wave Modulated at 1 kHz.

I do too, but without the 1kHz modulation.
I use a continuous 38kHz signal for my beambreak sensor.
That way I get a <=1mSec reaction time.

I also use narrow beam IR LEDs with integrated glass lense (SFH400), so no optics needed there.
Simple code attached.
Leo…

const byte IR_LED = 11; // IR transmitter LED with 100ohm (minimum) CL resistor
const byte IR_Receiver = 8; // from receiver output
const byte onboard_LED = 13; // onboard indicator LED
boolean receiverState;

void setup() {
  pinMode (onboard_LED, OUTPUT);
  pinMode (IR_LED, OUTPUT);
  pinMode (IR_Receiver, INPUT);
  // from Nick Gammon
  TCCR2A = _BV (COM2A0) | _BV(WGM21);
  TCCR2B = _BV (CS20);
  OCR2A =  209; // ~209 = ~38kHz | ~219 = ~36kHz
}

void loop() {
  receiverState = digitalRead (IR_Receiver);
  if (receiverState == HIGH) { // beam interrupted
    digitalWrite(onboard_LED, LOW); // green onboard LED off
    delay(1000);
  }
  else { // beam detected
    digitalWrite(onboard_LED, HIGH); // green LED on
  }
}

According to the datasheet of this sensor the sequence has to be modulated. It isn't a beambreak sensor, but an IR data sensor. What is your range with the SFH400 in bright sunlight?

So the questions still stand, how to measure this "gap" of 3ms and what does | do

Data sensors like the TSOP1738 aren't designed for continuous carrier reception or beam break applications. They expect periods of silence in order to do their automatic gain control and other housekeeping functions. If it works for you, great, but don't be surprised if sometimes it's unreliable.

There are specific beam break sensors ICs available that have a fixed gain. They are not as common, but they do exist.

Alternatively, if you don't mind running a cable between transmitter and receiver you can make a synchronous detector using a photodiode, op amp and an analog input to sample the received signal in step with transmitted pulses. The Arduino ADC is fast enough to give sub millisecond timing.

Well they are not designed specifically for this but, I am far away from the limits for this device. The 1kHz modulation is specifically for the necessary pause between bursts.

No cables aloud. I have seen the beambreak receivers, and if I order via mouser of something I will try them. Same problem though. I want to detect passing trough that takes at least 3ms. Anything less is an error.

I have heard that some IR receivers don’t work reliably with continuous signals.
But all the ones I have used worked just fine without. No false triggers.

I have used the 38kHz PNA4602M receiver in a low power project.
The gap was about 5meters, and it was used in bright indoor light.
The transmitter with SFH400 was pulsed with only ~25mA, and ran 2-3 days continuous on two NiMh AA batteries. Reliability dropped at ~7meters.
Leo…

I see. I will be using mine outdoor. 50m will be a bit overkill but a solid 20m is very necessary.

Vishay do some continuous modulated signal receivers .

TSOP4038

This will help explain the “|” symbol:Bitwise Compound OR

Hi, The company I work for has done a more elaborate version of what you are trying to achieve. Timing beams and cameras and signal lights at regular intervals on a training track with a PC based data logging.

The biggest problem was the environment and the beams, humidity and temperature were the culprits. The lenses of the beam devices would cloud or mist with dew in the early hours when most of this horsey activity takes place.

We used commercial sensors and switched to versions with internal heaters to over come the problem. Our units were Tx/Rx units with a reflector at 10m maximum distance. In extreme conditions the operator has to send someone around with a cloth to wipe the reflectors before starting.

It would have been nice to have a separate Tx and Rx, but over here customers did not want their precious track cut up with a trench at every timing point to provide power to the Tx.

If you continue with making the sensors yourself, you can integrate power resistor heaters into your design if needed.

Tom.... :)

TomGeorge: The biggest problem was the environment and the beams, humidity and temperature were the culprits. The lenses of the beam devices would cloud or mist with dew in the early hours when most of this horsey activity takes place.

If you continue with making the sensors yourself, you can integrate power resistor heaters into your design if needed.

Tom.... :)

Astrophotographers have some nice designs for this, PWM controlled "lens de-misting" if the OP wants to go down this route.

Thank you for the answers. That silly | finally has a meaning. Googling wasn't that easy.

Nothing as elaborate as de-misters at this point.

I actually got a 50m range using two units. One receiver and one transmitter. I've tried a reflector but indoor that means I need to use less power on the transmitter, that could easily be done with a potentiometer.

So outdoor I will probably use two units. However it would be nice if the hardware is capable of being both or only a transmitter or receiver.

Hi, You will certainly get better range with separate Tx and Rx, your beam width will also be tighter.

Tom... :)

TomGeorge: You will certainly get better range with separate Tx and Rx, your beam width will also be tighter.

True. Reflection systems need more drive power.

You can also increase range by using several narrow beam IR LEDs (post#5) in a vertical array. 4-6 IR LEDs (Vf ~1.5volt@200mA) can be used in series on e.g a 9 or 12volt supply. Switched with e.g. a mosfet with active current limiting (shunt in the source, with NPN transistor that cuts gate voltage). Four LEDs will give you twice the range for the same LED current. 200mA peak LED current could probably do what you want. Leo..

I have doubts about using more LED's vs. optics. My current LED is 20 degrees. While I'm certainly buying LED's with an even smaller angle I already have an high range.

Now the real questions are about the programming of the receiver part.

If the time between pulses is 3ms or more it means a beambreak. Normally it would give a pulse every 1ms.

Something like this?

if (!receiverOutput) { // if beam is detected
  trigger = millis(); // keep trigger updated with every loop
}
else if (millis() >= (trigger + interval)) { // if beam is interrupted longer than the interval time
  //do something
}

"trigger" and "interval" need to be declared as unsigned long. The if statement might need extra flags for starting/stopping the race. The else part could get the time from a RTC. Leo..

Because of reasons I have not worked on this project for since April. I have not even thanked you for the insight and help.

 while(digitalRead(IRontvanger) == 0){// wait here as long as it is receiving
  }

  unsigned long started_waiting_at = micros();               // Set up a timeout period, get the current microseconds
 
unsigned long Stopped_waiting_at = 0;
  
  while ( digitalRead(IRontvanger) == 1) {//Als er geen signaal signaal is
  Stopped_waiting_at = micros();
    if (Stopped_waiting_at - started_waiting_at >= doorgang ) {           // If waited longer than set time at doorgang, indicate timeout and exit while loop
      
      digitalWrite(13, HIGH);
      tone(speaker, 300);
      delay(20);
      noTone(speaker);
      
      Serial.print("Doorgang gedetecteerd teller = ");
      teller = teller +1;
      Serial.println(teller);
      
     digitalWrite(13, LOW);
      
      delay(300);
      break;
    }
  }

Anyway @Wawa, you reminded me that my timing was not that critical and therefore easy to measure.

I still want to try if I can combine the modulation and the receiving of the signal in one code and run it simultaneously. Next weekend perhaps.

So far there the transmitter has an average current of 80mA at 5V and the receiver 10mA at 5V. As long as I don’t need any defogging a 1000mAh battery will be enough to power this for a day.

*I was outdoors around 9PM and with this dim light I had a range of 120m with ease. I even had to tighten the opening towards the sensor otherwise it was hard to block the beam. After I finish this project I will seriously consider lasertag.

Did you get that distance with one IR LED, or with an array.

It seems that TSOP receivers are not made for continuous signals, but the TSSP receivers are. Makes coding for the transmitter and receiver easier, and no detection gaps. RS components stocks the TSSP4038 (38kHz). Leo..

One single LED, and not even a High power one.