Inconsistent results from pulseIn()

Hi everyone,

I am attempting to build an IR transmitter/receiver, however, I have run into a few issues with pulseIn.

I am transmitting 19 bits of information along with a header bit and a stop bit (for a total of 11 bits)

If I have my receiver in a while loop (just receiving only) it registers all of the bits correctly.

The problem comes from if I want the receiver doing other things and just checking the input occasionally.

Here is my code for the receiver:

//SimpleIR

int sensorPin = 19;
int counter = 0;

void setup(void) {
  pinMode(sensorPin, INPUT);
  Serial.begin(9600);
  Serial.println("Ready to receive");
}

void loop()
{
  sensorcheck();
}

void sensorcheck()
{
  if(pulseIn(sensorPin,LOW) > 200) {
    Serial.println(counter);
    counter++;
    Serial.println(pulseIn(sensorPin,LOW));
  }
}

If I comment out the last println, the receiver gets bits 0-10 if I add it in, it gets 5 bits (in the middle of the 11 bit stream)

I have been trying everything I can to get this resolved, but it's got to the point I have to ask now!

The incoming pulse lengths are:

startBit = 2400 usec
one = 1200 usec
zero = 400 usec
endbit = 3600 usec

there is a wait time between pulses of 300 usec from the transmitter

I have tried using some demo code by LadyAda (which worked) but is blocking (only listens all the time) so any solutions would be great!

Serial is slow. Very slow.

When you do a Serial.print you place characters into the serial buffer. If the buffer is full the Serial.print blocks (waits) until there is room in the buffer.

The buffer is emptied by an interrupt.

It takes a considerable amount of time to transmit one character out of the serial buffer (9600 symbols per second, 10 symbols per character) - that's 960 characters per second, or 1/960 or about 1ms per character.

Your doing a println, which adds 2 extra characters.

But that's not all.

First you're waiting for a pulse of at least 200µs. Fair enough. You're then adding to a counter. Ok. Then you're printing the results of another call to pulseIn which waits for a second pulse of indeterminate length to arrive and then prints the length of that pulse.

So, of your 10 pulses you have:

  1. Read this pulse and check if it's > 200µS - add one to counter
  2. Read this pulse and display the value
  3. Read this pulse and check if it's > 200µS - add one to counter
  4. Read this pulse and display the value
  5. Read this pulse and check if it's > 200µS - add one to counter
  6. Read this pulse and display the value
  7. Read this pulse and check if it's > 200µS - add one to counter
  8. Read this pulse and display the value
  9. Read this pulse and check if it's > 200µS - add one to counter
  10. Read this pulse and display the value

So you see, you are receiving all 10 pulses, but you're only counting 5, and you're displaying the pulse length of the pulses you're 'missing'.

Better way:

void loop() {
  static unsigned long pulses[10];
  static unsigned char counter = 0;

  unsigned long pv = pulseIn(sensorPin, LOW);

  if (pv > 200) {
    pulses[counter] = pv;
    counter++;
  }
  if (counter == 10) {
    for (counter = 0; counter < 10; counter++) {
      Serial.print(counter, DEC);
      Serial.print(": ");
      Serial.println(pulses[counter]);
    }
    counter = 0;
  }
}

(note: untested.)

thanks for that!
I hadn't considered the serial to be the issue.. (silly me) eventually all serial output will be removed - it's just here for now for testing/verifying.

I have reworked my code, it seems to be pretty consistent now...

void sensorcheck()
{
  if(pulseIn(sensorPin,LOW,6000) > startBit) {
  for(int i=0; i<9; i++) {
    dataIn[i] = pulseIn(sensorPin,LOW,3000);
    //Serial.println(dataIn[i]);
  }
  dataIn[9] = pulseIn(sensorPin,LOW,6000);
  if(dataIn[9] > endBit) {
    Serial.println("Valid Packet");
  }
  } else {
    //Serial.println(".");
    return;
  }
}

If there is any simple improvements to this, please let me know as sometimes valid packets aren't received (distance from led to receiver = approx. 20CM currently)

The timeout option of pulseIn() seems to be a little weird...
If I set it below the expected length of the pulse, it ignores them - is this a change from the documentation in the reference?

Thanks!