Some IR / hysteresis suggestions please...

Hi all-

I'm trying to construct a circuit that makes an Arduino pin HIGH in response to receiving a stream of numbers from another Arduino via IR. Essentially a 'beacon' where the [x,y,z] orientation of a handheld IR transmitter is determined by the response of three such receivers. By shielding the receivers with opaque cylinders I have been able to get the receivers to respond only when the handheld transmitter is pointed at them. I added a short tone so that I can easily tell when an IR signal is being received. So that's all good.

The problem is that I'm using a TSOP38238 receiver, which is apparently not appropriate for a continuous signal. My transmitter emits an encoded number (314) at about 10 Hz, which is received correctly but of course intermittently. So pin 10 goes HIGH at about the same rate. What I need is for pin 10 to remain HIGH while pulses are being received, and LOW otherwise. I believe this to be a good example of needing some hysteresis, ie. making the HIGH state 'sticky'. I have read and re-read the hysteresis examples and I do understand them, but as they all relate to analog inputs with (at least) one 'window' I am having difficulty applying these ideas to my situation. Anyway, here is my receiver code so far:

#include "IRLibAll.h"   
#include <IRLib_P01_NEC.h>   
#include <IRLibCombo.h>  
#include <SPI.h>
#include <toneAC.h>

IRrecvPCI myReceiver(2);
IRdecode myDecoder;


void setup() {
  
   pinMode(10, OUTPUT);
   myReceiver.enableIRIn();
    
}

void loop() {

if(myReceiver.getResults() ) {  
      
   myDecoder.decode(); 
      
   if(myDecoder.value == 314) {  
      digitalWrite(10, HIGH);
      toneAC(2000, 10, 5);
   }    
}

myReceiver.enableIRIn();

}

A couple of related questions that I have are:

  1. The code only works with the enableIRIn() function at the end. Everything I have read about this IR library says that it should only need to be in the setup().

2a. It also only works WITH the toneAC, but not without it. ToneAC uses timer1, and should not conflict with the IR library's use of timer2. Is there some other connection that causes this?

2b. Pin 10 goes low 'in between' received pulses (unexpected) with toneAC, but stays HIGH after the first reception without toneAC (expected).

Any help would be greatly appreciated.

Thanks,
Patrick

const uint32_t timeout = 300;
uint32_t lastRx;
bool oldState;

....

void loop() {

  if(myReceiver.getResults() ) { 
     
    myDecoder.decode();

    if(myDecoder.value == 314) { 
      lastRx = now;
      toneAC(2000, 10, 5);
    }
  }

  uint32_t now = millis();
  bool newState = now - lastRx >= timeout;
  if (newState != oldState)
  {
     digitalWrite(10, newState);
     oldState = newState;
  }
}

the tsop382 (see datasheet) has a filter for a 38 kHz pulse stream.

do you pulse the transmitter at 38 kHz?

Yup, sending with an IR LED, with the same library- which modulates a 38kHz carrier with on/off data. I think the attached snip of the datasheet is the reason this would be a lot simpler with another receiver!

Patrick

snip.PNG

Hi pcbbc-

I tried your code and it wouldn't compile- 'now was not declared in this scope' in the inner if statement. I changed it slightly to this:

#include "IRLibAll.h"   
#include <IRLib_P01_NEC.h>   
#include <IRLibCombo.h>  
#include <SPI.h>
#include <toneAC.h>

IRrecvPCI myReceiver(2);
IRdecode myDecoder;

const uint32_t timeout = 300;
uint32_t lastRx;
bool oldState;
uint32_t now;

void setup() {
  
   pinMode(10, OUTPUT);
   myReceiver.enableIRIn();
    
}



void loop() {

  if(myReceiver.getResults() ) {
     
    myDecoder.decode();

    if(myDecoder.value == 314) {
      lastRx = now;
      toneAC(2000, 10, 5);
    }
  }

  now = millis();
  bool newState = now - lastRx >= timeout;
  if (newState != oldState)
  {
     digitalWrite(10, newState);
     oldState = newState;
  }
}

which I believe should be the same (please correct me if not). That compiles, but when I run it

  • the LED attached to pin 10 goes on
  • when I point the 'remote' at the receiver I hear one click, and the LED goes OFF
  • the LED goes back on quickly
  • the receiver stops responding to the remote (LED stays on)

so not quite what we're looking for! I also tried changing to lastRx = millis(); and adjusting the timeout, but I got the same result. I'm currently unraveling the logic and attempting to modify what I started with on my own, but I'm not quite there yet. Any thoughts?

thanks again,
Patrick

pferrick:
Yup, sending with an IR LED, with the same library- which modulates a 38kHz carrier with on/off data. I think the attached snip of the datasheet is the reason this would be a lot simpler with another receiver!

do you understand the concept of automatic gain control (AGC)?

you may need to repeatedly send you message which allows the AGC to adjust and once to receive the message you ignore immediate retransmissions

I'm not sure I'm following you, gcjr. The part of the datasheet I referenced is concerned with distinguishing between data and noise. As I understand it the AGC is a circuit that minimizes gain when it detects certain kinds of signals, like a constant frequency (possibly even a constant 38 kHz) in favor of the desired data signal.

Maybe I was not clear about the alternative arrangement: a 38 kHz IR square wave from the transmitter that is either present or absent (here I don't mean on or off, I mean the receiver can or cannot see it!), with the TSOP returning basically a TRUE or FALSE accordingly. I get the impression that the receiver would not behave this way, as it is designed to receive binary encoded data, but I think I'm going to test it out and see!

Various threads I have read about this very situation match up with this, unless maybe I am really misunderstanding the whole thing! I'll come back with the results of my experiment soon.

thanks,
Patrick

pferrick:
I tried your code and it wouldn't compile- 'now was not declared in this scope' in the inner if statement.

My bad, sorry. Well done on fixing it. It will probably work like that, but it should really go at the start of loop...

void loop() {

  uint32_t now = millis();

  if(myReceiver.getResults() ) {
     
    myDecoder.decode();

    if(myDecoder.value == 314) {
      lastRx = now;
      toneAC(2000, 10, 5);
    }
  }

  bool newState = now - lastRx >= timeout;
  if (newState != oldState)
  {
     digitalWrite(10, newState);
     oldState = newState;
  }
}

Really for this type of application you need something like a TSSP4038 which can receive a continuous 38kHz modulated carrier.

I use these in a light beam application for sports timing and they work really well. I started out with TSSP4838s and discovery to my cost they really don’t like continuous 38khz. Really should have believed the datasheet :wink:

I'm not sure I'm following you, gcjr. The part of the datasheet I referenced is concerned with distinguishing between data and noise.

a couple things

the following block diagram shows that the IR receiver i more than just a photo transistor, it also has a circuit: AGC, bandpass filter and demodulator

the following waveform illustrates that when sending data, the data enables a 38 kHz waveform driving an IR LED. many 38 kHz pulses occur during each bit period of the data. if the data is transmitted at 9600 bit-per-second, 3.96 38 kHz pulses occur during each data bit

the bandpass filter filters out constant level signals -- such as sunlight, and will pass a signal at a specific frequency. anything other than a 38 kHz pulse stream is considered noise and suppressed

in order for automatic gain control to work under all conditions, it must gradually increase gain to it's maximum when there is no signal so that it can detect a potentially weak signal. it only adjusts its signal when it can detect the signal. so it is very likely to have too much gain when receiving a signal for the first time. it then lowers the gain to a desired level.

the demodulator only outputs signal while is detects output from the bandpass filter.

Thanks for the AGC clarification. What I was speculating about was how a TSOP38238 would respond to a continuous stream of 38 kHz pulses (ie. not pulses of 38 kHz signal at a much lower frequency).

Just for fun, I modified my transmitter code to emit a continuous 38 kHz square wave, and I find that the TSOP38238 ignores it...! So I either have to account for the intermittent nature of binary-encoded data as planned (which I'm pretty close to having figured out) or switching to an IR receiver designed to work with a continuous signal.

Truth be told, I started with the '238 because I had some on hand. Not always the smartest way to go about designing stuff!!

Patrick

pferrick:
Just for fun, I modified my transmitter code to emit a continuous 38 kHz square wave, and I find that the TSOP38238 ignores it...!

did you see pg 5 on the datasheet discussing max burst length and minimum gap time between bursts

why don't you try sending the optical test signal they describe on pg 3, 600 usec on and 600 usec off.

gcjr:
why don't you try sending the optical test signal they describe on pg 3, 600 usec on and 600 usec off.

That signal is also 7 pulses worth every 60ms.

My experiments seemed to suggest the waveform requires quite long OFF periods (as would be typically be produced by a consumer IR remote). The data sheet recommends the data duty cycle should be no more than a 1/10th of the overall transmission frequency.

See datasheet....
tpi >= 10/f0 is recommended for optimal function
Some examples which are suppressed are: Continuous signals at any frequency
Maximum number of continuous short bursts/second: 1800
YMMV

Well, I have things working with the TSOP38238...sorta. It works most of the time, but it's still a wee bit squirrely sometimes. The LED fails to turn off about 10% of the time, and I have a feeling there are some subtle timing issues beyond the timeout that I am not addressing.

I'm going to go with one of the constant-signal varieties of the receiver, which I should have done in the first place! The only small hitch is that for some reason 38 kHz versions (TSSP4038) are unavailable for a bunch of weeks. (one exception: I can pay $8 each from the UK...no thanks!) I'm going to switch to the 56 kHz parts which are fortunately plentiful.

Thanks for all the help everyone!

Patrick