pulseIn timeout and readout

I need a measure a pulse length and need the length in further processing, but I need to have a timeout when the pulse is longer than x milliseconds. (since I can't afford to wait 3 minutes for the max length of a pulseIn)
And I was wondering if there is any code who can do so.

Declaration variables
data*= Where I need to store the length of the pulse*
TimeOut = the timeout in ms where the code needs to stop after it reaches a longer pulse than this
PI_IRSensor = The pin where the pulse needs to be measured from
What I tried
data = pulseIn(PI_IRSensor, HIGH) //Would get the number but no time out
while (pulseIn(PI_IRSensor, HIGH) < TimeOut); //Would get a timeout, but I cant get the number
data = while (pulseIn(PI_IRSensor, HIGH) < TimeOut); //Doesn't work like this.. Error= "expected primary-expression before 'while'"
What I want
Measure and save a pulse length, but stop if it's longer than X ms
My complete Arduino code

int PI_IRSensor = 2;                          //The pin where the IR sensor is connected to
int IRData = 0;                               //This is where we store the (valid) IRData until it's processed
String IRDataBinarData = "";                  //Raw binary sensor data

void setup() {                            //This code will be called once on startup
  pinMode(PI_IRSensor, INPUT);                //Set the IR pin to be an input (just to be sure)
  Serial.begin(9600);                         //Start the connection with the pc
  attachInterrupt(digitalPinToInterrupt(PI_IRSensor), infraredRead, FALLING);   //When the IR sensor signal is pulled low, call the loop to read the data
}

void loop() {                             //This code will keep on looping over like a 'While(1)'
  if (IRData != 0) {                          //If there is IRData
    Serial.println(IRData);                   //Print the IRData to the pc
    //-1 = Timout waiting on start bit
    //-2 = Timout waiting on Data bit
    IRData = 0;                           //Reset IRData value (since we have processed it)
  }
  if (IRDataBinarData != 0) {                 //If there is IRDataBinarData
    Serial.println(IRDataBinarData);          //Print the IRData to the pc
    //1 = HIGH
    //0 = LOW
    //E = Error
    IRDataBinarData = "";                      //Reset IRDataBinarData value (since we have processed it)
  }
  delay(1);                                   //Just some delay (so this loop will go max 1000x/second)
}

void infraredRead() {                     //This loop will be called when the pin is pulled low (and we need to read the data)
  Serial.print(String("R:"));                   //Tell the pc we are staing retrieving data (be aware this has a lower prior, and could be delayed in real world sending)
  int LowOrHighPoint = 1050;                    //turnover point of low/high   High =(1500 - 1700)   Low = (400 - 600)
  int TimeOut = 2000;                           //The point where we we are having a timeout (it's to much time to be called high)
  int BeginAt = 16;                             //Real data begins here
  int TheLength = 10 + BeginAt;                 //The length of the date we need
  int data[TheLength];                          //Create a array to put the bits in
  int start_bit = 4000;                         //Minium microseconds length of startbit

  while (pulseIn(PI_IRSensor, HIGH, 100000) < start_bit); //Wait for the data be pulled HIGH (100ms timeout). and then count the length of this pulse ['A' in the image]

  int i = 0;                                    //A counter
  while (i < TheLength - 1) {                   //Do the next part as much as we are expected bits
    i++;                                        //Increade the counter
    //    data[i] = pulseIn(PI_IRSensor, HIGH);       //Start measur length of the HIGH pulse
    //If pulse is to long high, stop code above?
    //New code:?


    data[i] = while (pulseIn(PI_IRSensor, HIGH) < TimeOut);      //Start measur length of the HIGH pulse



    if (data[i] >= TimeOut) {                   //If the pin was longer HIGH than it could be (and thus it was not data)
      IRData = -2;                              //Tell the PC we have a timeout
      return;
    }
  }
  int a = 0;                                    //A new counter (this is where to store the new data at in the array)
  i = BeginAt;                                  //Where the real data geginds at (so where we need to start reading from)
  while (i < TheLength) {                       //While there is still data to be read
    a++;                                        //Increade the counter
    i++;                                        //Increade the counter
    if (data[i] > LowOrHighPoint) {             //is it a 1?     (1500 - 1700)
      data[a] = 1;                              //Set in the new array the data of this bit HIGH
      IRDataBinarData = IRDataBinarData + "1";  //DEBUG Save the state so we can read it out later
    } else if (data[i] < LowOrHighPoint) {      //is it a 0?  (400 - 600)
      data[a] = 0;                              //Set in the new array the data of this bit LOW
      IRDataBinarData = IRDataBinarData + "0";  //DEBUG Save the state so we can read it out later
    }
  }

  int result = 0;
  i = 0;
  while (i < TheLength) {
    i++;
    if (data[i] == 1) {
      result |= (1 << i);
    }
  }
  IRData = result;
}

The pulse

Have you read pulseIn() - Arduino Reference ?

Syntax
pulseIn(pin, value)

pulseIn(pin, value, timeout)

Parameters
pin: the number of the pin on which you want to read the pulse. (int)

value: type of pulse to read: either HIGH or LOW. (int)

timeout (optional): the number of microseconds to wait for the pulse to start; default is one second (unsigned long)

UKHeliBob:
Have you read pulseIn() - Arduino Reference ?

Yes I read that, and I did comment on that. sorry for being unclear.

But I don't need the timeout to start, I need a timeout of the pulse length.

But I don't need the timeout to start, I need a timeout of the pulse length.

In that case don't use pulseIn()

When you detect the start of the pulse (the input pin changes state) save the value of millis() as start time
Keep monitoring the state of the input pin leaving loop() running without blocking
When the pulse ends (the input pin changes state) save the value of millis() as end time and calculate the pulse length.
If the maximum pulse period is exceeded (time now - start time >= maximum pulse length) act how you want/need

UKHeliBob:
In that case don't use pulseIn()

When you detect the start of the pulse (the input pin changes state) save the value of millis() as start time
Keep monitoring the state of the input pin leaving loop() running without blocking
When the pulse ends (the input pin changes state) save the value of millis() as end time and calculate the pulse length.
If the maximum pulse period is exceeded (time now - start time >= maximum pulse length) act how you want/need

That sound like a doable option. thanks! I will look in too it

UKHeliBob:
In that case don't use pulseIn()

When you detect the start of the pulse (the input pin changes state) save the value of millis() as start time
Keep monitoring the state of the input pin leaving loop() running without blocking
When the pulse ends (the input pin changes state) save the value of millis() as end time and calculate the pulse length.
If the maximum pulse period is exceeded (time now - start time >= maximum pulse length) act how you want/need

That sound like a doable option. thanks! I will look in too it

UKHeliBob:
In that case don't use pulseIn()

When you detect the start of the pulse (the input pin changes state) save the value of millis() as start time
Keep monitoring the state of the input pin leaving loop() running without blocking
When the pulse ends (the input pin changes state) save the value of millis() as end time and calculate the pulse length.
If the maximum pulse period is exceeded (time now - start time >= maximum pulse length) act how you want/need

"Inside the attached function, delay() won’t work and the value returned by millis() will not increment."

Also I would need 'micros()' but that also doesn't increment. So this solution you propose would not work, Do you might have other ideas?

I think that you will find that micros() does increment in an ISR but you don't need it to. You just need the start and end times of the pulse.

UKHeliBob:
I think that you will find that micros() does increment in an ISR but you don't need it to. You just need the start and end times of the pulse.

Since the counter does not increment in a loop (micros() also doesn't seem to work) the begin time is (practically ) the same as the end time, I tried to print the value to the PC with a minute interval, but I got the same numbers

Show your code.

MorganS:
Show your code.

"millis() relies on interrupts to count, so it will never increment inside an ISR. Since delay() requires interrupts to work, it will not work if called inside an ISR. micros() works initially, but will start behaving erratically after 1-2 ms. "

I've made a quick test sketch to check this, and it what the Arduino Reference stated was indeed true. I can't find the sketch anymore. But that's not the point here?

The only 'solution' I could think off, is changing the original code stated in my first post, so it just flags that there is data, and then hope that the loop can catch it fast enough since millis() would work in the loop.
But this would be far from ideal and defeats the purpose.

Show your code

As I said previously

You just need the start and end times of the pulse.

I think you have confused "doesn't increment" with "doesn't work". millis() and micros() will return correct values if you call them in an interrupt.

If you stupidly stay in the interrupt for some number of microseconds or (gasp) a whole millisecond then calling those functions again will start to return bad values. Note that you still have not broken the clock: when you leave the interrupt the timers can increment and no time is lost.

This means the solution to correct pulse timing is to interrupt on CHANGE. Record the start time when the pulse goes on. Leave the interrupt and let the main loop run. When the pulse goes off, that interrupt can calculate the duration and whatever else you need.

MorganS:
I think you have confused "doesn't increment" with "doesn't work". millis() and micros() will return correct values if you call them in an interrupt.

If you stupidly stay in the interrupt for some number of microseconds or (gasp) a whole millisecond then calling those functions again will start to return bad values. Note that you still have not broken the clock: when you leave the interrupt the timers can increment and no time is lost.

This means the solution to correct pulse timing is to interrupt on CHANGE. Record the start time when the pulse goes on. Leave the interrupt and let the main loop run. When the pulse goes off, that interrupt can calculate the duration and whatever else you need.

As could be seen in the image (https://i.imgur.com/8SBtBSJ.jpg), my start pulse exists of 10 milliseconds low, and then 4 milliseconds high. And that's my problem. The interrupt timer doesn't go that far :frowning:
(As I tried before the timer only works for the first 1-2ms, as described on the Arduino Webpage)

Thank you for thinking along with me. I think I could indeed store the time of the pulse change and state and then process than later but this would get messy fast, since we need an array and put stuff in it and calculate in the main loop. And even probably check data for corruption?. I just wish there was an easy option, that I could just set the timeout time or something.

Personally I was thinking since math does work, to do an increasing while loop. This would give me an easy option to timeout, but I don't yet know if the counter would be a stable enough option for this kind of data. But I will for some do some testing with it in the next week (if I have the time for it)

I don't see the problem.

Remember a millisecond is a long time for an Arduino. It can make a note of a time and then go back to doing whatever else it was doing almost one thousand times in a single millisecond. "Whatever else" might include doing the maths to work out when the next pulse is expected and then waiting around for that pulse to arrive. It really will spend most of its time waiting, even during the short pulses you show.