Pin Change Interrupt

Hello All,

This post is quite long, but the issue I am reporting is quite easy to follow and I decided to add a lot of details to avoid confusion. I hope you'll be interested. Thanks!

==

I'm doing some basic testing to check the behavior of the Pin Change Interrupt on an Arduino Nano.

Among other things, it seems that the interrupt routine gets called only one time, no matter how many pins have changed their state "recently". I was testing this with a two pin configuration and using another microcontroller to drive the arduino port with a highly predictable timing.

However, I got stuck in an issue and decided to send this post asking for help. I've made a simplified version of the code, dealing with a single pin:

volatile unsigned short rxInterruptCount = 0;
unsigned short rxInterruptCountCopy;
unsigned int busyWaitCount = 0;

void setup() {
  
  Serial.begin(115200);
  pinMode(7, INPUT);
  digitalWrite(7, LOW);
  Serial.println("Init!");
  delay(1000);
  Serial.println("Enabling interrupts!");
  cli();		 // switch interrupts off while messing with their settings  
  PCICR = 0x04;          // Enable PCINT2 interrupt
  PCMSK2 = 0b10000000;
  sei();		 // turn interrupts back on
}

ISR(PCINT2_vect) {
  rxInterruptCount++;            
}

void loop() {
  while (1) {
    busyWaitCount = 0;
    while (busyWaitCount<50000) { busyWaitCount++; }
    delayMicroseconds(1); // this is the weird part of the code (the issue I am referring to)      
    if (rxInterruptCount > 0) break;
  }
  rxInterruptCountCopy = rxInterruptCount;
  rxInterruptCount = 0;
  Serial.print("rxInterruptCountCopy = ");    
  Serial.println(rxInterruptCountCopy, DEC);          
}

Basically, the code sets up the interrupt on pin D7 and spends most of the time either on the "busy" loop or printing on the serial port. Every time the busyWaitCount reaches the target, the code checks the interrupt counter to see if we had an interrupt. If not, it goes back to the loop and keeps checking for an interrupt counter greater than zero. Once it finds it, it makes a copy of that value, resetting the counter, and prints the original value over the serial port.

The D7 pin is being driven by this code (running on a PIC12F1822):

  while (1) {
    PORTA = 0b00100000;
    Delay_us(50);
    PORTA = 0b00000000;
    Delay_us(50);
    PORTA = 0b00100000;
    Delay_us(50);
    PORTA = 0b00000000;
    Delay_us(50);
    PORTA = 0b00100000;
    Delay_us(50);
    PORTA = 0b00000000;
    Delay_ms(5000);
  }

That is, the PIC pin is changed "quickly" (6 times with a 50us delay between changes), and then the line is kept "low" for 5 seconds. This pin (called RA5 on the PIC) is directly tied by a wire to pin D7 on the arduino.

This is the output I get from the arduino (which is expected):

Init!
Enabling interrupts!
rxInterruptCountCopy = 6
rxInterruptCountCopy = 6
rxInterruptCountCopy = 6

However, if I remove the "delayMicroseconds(1)" and upload, I start getting:

Init!
Enabling interrupts!
rxInterruptCountCopy = 1
rxInterruptCountCopy = 5
rxInterruptCountCopy = 1
rxInterruptCountCopy = 5
rxInterruptCountCopy = 1
rxInterruptCountCopy = 5

Which does not make sense for me. That is: why are these 6 "pin changes" being split in two groups? I've tested changing the "delayMicroseconds(1)" to another loop "while (busyWaitCount<50000) { busyWaitCount++; }", but the results kept like:

Init!
Enabling interrupts!
rxInterruptCountCopy = 1
rxInterruptCountCopy = 5
rxInterruptCountCopy = 1
rxInterruptCountCopy = 5

I have not yet find any good reasoning on why this is behaving this way. Any ideas?

BTW: I'm writing this code to be able to handle multiple channels on an Remote Control Rx receiver, just in case you're wondering. I'm being extremely picky on this code because I do not want any planes crashing due to wrong assumptions on my part. :slight_smile:

Thanks,

Moderator edit:
</mark> <mark>[code]</mark> <mark>

</mark> <mark>[/code]</mark> <mark>
tags added.

mnery9:
Which does not make sense for me. That is: why are these 6 "pin changes" being split in two groups?

Well, you break out of the loop when the count is greater than zero so it stands to reason that a count of one is going to break out of the loop...

if (rxInterruptCount > 0) break;

Before you do any more work with interrupts you need to educate yourself about critical sections and protected access...

Hello,

Thanks for your quick reply and the post regarding interrupts. I've spent some time going over it and I haven't found a solution yet. But it is a good reference on the topic. It seems to still lack the info about getting a single interrupt or multiple ones when multiple pins change at roughly the same time (let's say, a microsecond or less), but I'll look at in more details to see if I can find this answer. Thanks!

Regarding the code I posted, I was aware of the issue regarding multi-byte access and the volatile keyword, so, I declared the shared variable as volatile unsigned short rxInterruptCount = 0; which AFAIK should be a 1-byte variable.

Regarding breaking the loop when I get a count of one, this should not happen often due to the structure of the signal that I am feeding on the pin. The signal is made by 6 edges, separated by a 50us interval, happening about every 5 seconds. So, getting these groups of 1 and 5 all the time is really not likely. So, I believe something else is going on.

After reading the material you sent, I changed my code to:

void loop() {
  while (1) {
    busyWaitCount = 0;
    while (busyWaitCount<50000) { busyWaitCount++; }
    delayMicroseconds(1);      
    noInterrupts ();
    rxInterruptCountCopy = rxInterruptCount;
    interrupts();
    if (rxInterruptCountCopy > 0) break;
  }
  noInterrupts ();
  rxInterruptCount = 0;
  interrupts();
  Serial.print("rxInterruptCountCopy = ");    
  Serial.println(rxInterruptCountCopy, DEC);          
}

The "delayMicroseconds(1);" is still key on getting an output like:
Init!
Enabling interrupts!
rxInterruptCountCopy = 6
rxInterruptCountCopy = 6
rxInterruptCountCopy = 6

instead of:
Init!
Enabling interrupts!
rxInterruptCountCopy = 1
rxInterruptCountCopy = 5
rxInterruptCountCopy = 1
rxInterruptCountCopy = 5
rxInterruptCountCopy = 1
rxInterruptCountCopy = 5

Maybe I am skipping something elementary here, but this apparently unrelated function call changing the behavior this much in quite intriguing. Note that it is not every function call that will make a difference, but some will do. Like micros() which will make " 6" to come up, and unlikely "noInterrupts()" which still made 1 and 5 to appear.

Thanks,

mnery9:
Regarding the code I posted, I was aware of the issue regarding multi-byte access and the volatile keyword, so, I declared the shared variable as volatile unsigned short rxInterruptCount = 0; which AFAIK should be a 1-byte variable.

unsigned short is 2 bytes in AVR land.

Regardless of the size of the variable, you have another issue that requires a critical section. Which you almost corrected.

So, I believe something else is going on.

The signal is made by 6 edges, separated by a 50us interval, happening about every 5 seconds.

Exactly 5 seconds elapses just as the inner while loop finishes. The PIC sets the pin HIGH. The interrupt fires incrementing the counter. The interrupt service routine returns. rxInterruptCount is greater than zero (one) so the outer while loop is broken. While your code is outputting to Serial, the remaining five pulses are generated causing five more interrupts to occur. When loop runs again, rxInterruptCount is five.

The two processors are in a well synchronized dance causing that sequence to repeat as many times as you've allowed them to run. Which is certainly possibly because both processors are deterministic. The delayMicroseconds alters that dance causing them to synchronize at a different point.

Extracted from Original Post

I'm writing this code to be able to handle multiple channels on an Remote Control Rx receiver,

As far as I know R/C signals are very slow by Arduino standards and the pulse widths are usually measured using the pulseIn() function.

Is it necessary to use interrupts at all?

Second question - how is the R/C system going to produce interrupts on several dfferent pins - the usual output from an R/C Tx is a single stream of pulses.

...R

I agree with Robin2 - from what you've told us so far this doesn't seem like a problem that needs interrupts. My advice is to not use interrupts unless/until you have to, and then only use them reluctantly and to the minimum extent possible.

In your solution that does use them, the reason your groups of pulses are being divided into separate groups is that you have an arbitrary 50ms delay in your loop() during which time you won't be checking whether the count has been incremented. Depending when the sequence of incoming pulses arrives relative to this delay, you might find you have received all of them, or only some of them. I'm not sure why the delay is there at all. Also note that on most Arduinos the microseconds clock has a granularity of 4us so delayMicroseconds(1) is probably not giving you an accurate delay. Depending why you're trying to use this curious delay loop, that might become important to you.

If you decide that you do need to continue using interrupts, since your volatiole variable is bigger than a byte you need to temporarily disable interrupts while you access it in the main context. I suggest you disable interrupts, copy the volatile variable to a local temporary variable and then resume interrupts immediately so that interrupts are disabled for the shortest possible time. The best way to count interrupts as you're doing is to maintain a non-volatile variable which holds the previous value of the volatile value. You can subtract the two to see how much the counter has incremented by. This avoids having to re-zero the volatile counter, which halves the number of times you need to access the volatile value while interrupts are disabled.

But, to repeat, you probably don't need interrupts and in that case I suggest you avoid them.

quoting Coding Badly:
The two processors are in a well synchronized dance causing that sequence to repeat as many times as you've allowed them to run. Which is certainly possibly because both processors are deterministic. The delayMicroseconds alters that dance causing them to synchronize at a different point.

This was one of my first hypothesis. And to account for that, I started adding different code right after the "delay/busy" loop, trying to break that possible synchronized dance. Turns out that the dance was not being that much synchronized in the first place. At least, if I change my inner loop count to 49123 instead of 50000, the same behavior happens. That is, I still get 6 interrupt count in some runs, and groups of 1 and 5 interrupt counts in another run. This is consistent for every run, as long as the code for that run is not changed.

quoting Robin2:
pulse widths are usually measured using the pulseIn() function. Is it necessary to use interrupts at all?

From the arduino docs, pulseIn in a blocking call which will give me the pulse width happening on a given pin. Assuming that the signal structure of these RC signals is a pulse of 1ms to 2ms hapenning on a 20ms interval, reading 6 of these pulses (one for each of the 6 channels existing in my tx/rx system) will get me a lot of blocked time on the pulseIn calls.

quoting Robin2:
how is the R/C system going to produce interrupts on several dfferent pins

The rx system has 6 independent channels, so it has 6 "signal" physical pins producing their own stream of pulses. As of know, I am not studying if the pulses start all at the same time or not. I just assume there are 6 independent pulse streams and my code should look for the edges on every pin and produce a separate output according to each pulse width.

Note the code that I posted is a simplification of the actual code. I made it that way so that we could focus the discussion on a baseline which is easy to read.

Quoting PeterH:
Depending when the sequence of incoming pulses arrives relative to this delay, you might find you have received all of them, or only some of them. I'm not sure why the delay is there at all.

So, the delay is there to simulate actual work that is being done on my full featured code. Namely, I read values coming from sensors and adjust a simplified version of a PID controller I have running on the arduino. Then I look for the rx values I have last adjusted (based on the interrupts) and I act on some actuators. Assuming that I won't spend time on any pulseIn calls, this will make my whole read/compute/act loop way faster.

You can subtract the two [variables] to see how much the counter has incremented by. This avoids having to re-zero the volatile counter, which halves the number of times you need to access the volatile value while interrupts are disabled.

Nice hint! Thanks!

===

So, I've changed the code and the behavior is still the same. I mean, the commented line below has a crucial effect on the output of the code. Note that this version has a 49123 constant, instead of the previous 50000. That is, it makes me believe this is not just a "timing" issue, as if it were, it would be a matter of changing the busy loop duration only (and not having to make any calls to other functions in order to change the interrupt counts behavior). I've made the delayMicroseconds call to have 20, so we avoid issues with this delay being too small. I'll still apply the "subtract" hint on the code. I didn't want to change it now to avoid tweaking multiple places at once.

void loop() {
  while (1) {
    busyWaitCount = 0;
    while (busyWaitCount<49123) { busyWaitCount++; }
    // delayMicroseconds(20);      
    noInterrupts ();
    rxInterruptCountCopy = rxInterruptCount;
    interrupts();
    if (rxInterruptCountCopy > 0) break;
  }
  noInterrupts ();
  rxInterruptCount = 0;
  interrupts();
  Serial.print("rxInterruptCountCopy = ");    
  Serial.println(rxInterruptCountCopy, DEC);          
}

I hope you're finding this entertaining. And thanks again for all the help. At this point, I am dealing with this on a "nice to investigate issue". I hope the bottom line will not be something stupid on my part, but I am in for it. So far, I've already learned some nice things. :slight_smile: Thanks!

Latency-critical activities like measuring the length of multiple short pulses is the sort of problem where the use of interrupts might be justified.

It seems that you're interested in pulse lengths rather than counts so you won't need to worry about subtracting counters and so on - you will just have a volatile variable holding a 'current pulse length' for each input channel. An array indexed by channel number would seem the most obvious solution for that. You don't say what you want to do with the pulse lengths after they have been read, but if you need to know them inside the main context you'll need to use the techniques mentioned earlier to read the volatile data.

The 'pin change' interrupts have a slightly misleading name and are really port change interrupts. They will be triggered when any input on a given hardware port changes state. Your handler would need to determine which input had changed state (by comparing with the previous state), record the current time at the start of the pulse for each pin, and subtract that from the current time at the end of the pulse to get the pulse length, and write that length to volatile data.

Hi PeterH,

I am aware of the "port change" characteristic. On my initial post, I said:

Among other things, it seems that the interrupt routine gets called only one time, no matter how many pins have changed their state "recently". I was testing this with a two pin configuration and using another microcontroller to drive the arduino port with a highly predictable timing.

Later, I said:

Thanks for your quick reply [refferring to Coding Badly] and the post regarding interrupts. I've spent some time going over it and I haven't found a solution yet. But it is a good reference on the topic. It seems to still lack the info about getting a single interrupt or multiple ones when multiple pins change at roughly the same time (let's say, a microsecond or less), but I'll look at in more details to see if I can find this answer. Thanks!

This suggests that I was already dealing with the multiple pin changes.

I have simplified it to a single pin configuration just to isolate the issue for this post. For now, and if you guys don't mind, I'd like to keep the focus of the discussion on the different behaviors that are being presented. Once we get to a conclusion to that, then I'd move to the multiple pulse length code (that I already have and is quite similar to what you described) and I would post it here or in another thread (if you think it might help other people).

Thanks,

mnery9:
The rx system has 6 independent channels, so it has 6 "signal" physical pins producing their own stream of pulses. As of know, I am not studying if the pulses start all at the same time or not. I just assume there are 6 independent pulse streams and my code should look for the edges on every pin and produce a separate output according to each pulse width.

When the data leaves the R/C transmitter all 6 channels are transmitted one after the other - the receiver then sorts them out for each different servo or ESC according to their position in the stream.

I suspect you will find that the output pulses from the receiver for each channel still have the same time variation as when they were transmitted and could be multiplexed again and fed to a single Arduino pin. Even if you don't want to use pulseIn() you would find it easier to manage all the timing on a single pin. I can understand that using pulseIn() would probably waste too much of the Arduino's cpu time.

And, of course, you haven't said what sort of receiver you are using or where it is getting its data from. I think you can get some receivers that will output the multiplexed data as generated by the Tx.

...R

I can see the attraction of using a separate input pin for each channel - it leave the ppm decoding to the receiver module, which is presumably very good at it, and avoids any possibility of the Arduino getting confused about which channel a given pulse belongs to. The approach that's being proposed doesn't seem unreasonable. However, if there's an outstanding question I don't know what it is.

However, if there's an outstanding question I don't know what it is.

The question is:
Given I am using a separate microcontroller to build a signal based on the following code running on a PIC12F1822:

while (1) {
    PORTA = 0b00100000;
    Delay_us(50);
    PORTA = 0b00000000;
    Delay_us(50);
    PORTA = 0b00100000;
    Delay_us(50);
    PORTA = 0b00000000;
    Delay_us(50);
    PORTA = 0b00100000;
    Delay_us(50);
    PORTA = 0b00000000;
    Delay_ms(5000);
  }

and feeding this signal (bit 5) directly to the D7 pin on my Arduino Nano, why do I get different results if I add the delayMicroseconds call, but not when I change the number of times I stay in the loop (in the following code):

void loop() {
  while (1) {
    busyWaitCount = 0;
    while (busyWaitCount<49123) { busyWaitCount++; }
    // delayMicroseconds(20);      
    noInterrupts ();
    rxInterruptCountCopy = rxInterruptCount;
    interrupts();
    if (rxInterruptCountCopy > 0) break;
  }
  noInterrupts ();
  rxInterruptCount = 0;
  interrupts();
  Serial.print("rxInterruptCountCopy = ");    
  Serial.println(rxInterruptCountCopy, DEC);          
}

Robin2: I'm using some "FlySky" receivers (not sure which model), it sure doesn't expose the multiplexed signal and I believe it is way easier and more interesting to have a deeper understanding of AVR interrupts, than to try to explore some specific characteristics of the receiver I am using and relying on that. Thanks for your suggestion anyway.

Thanks,

It's a quirk of timing. The particular delay loop you're using happens to get in phase with the incoming pulse train since it always ends the delay loop as soon as it detects the first signal, and the remaining pulses in that group have all arrived by the time it returns to check the count again. Given that this bit of logic isn't related to what you're trying to do, I'm not sure why you're concerned about it. I guess you'll throw this away and aren't too worried about how robust it is, but for what it's worth the approach of reading the count in one protected block and then clearing it in another introduces a race condition that might cause lost pulses in some scenarios. The approach I suggested of maintaining a copy of the counter and subtracting that from the volatile value avoids this problem since you never need to clear the counter. It's academic though since your real project won't be counting pulses.

mnery9:
The question is:
Given I am using a separate microcontroller to build a signal based on the following code running on a PIC12F1822:

Robin2: I'm using some "FlySky" receivers (not sure which model), it sure doesn't expose the multiplexed signal and I believe it is way easier and more interesting to have a deeper understanding of AVR interrupts, than to try to explore some specific characteristics of the receiver I am using and relying on that. Thanks for your suggestion anyway.

Thanks,

Is the PIC output an accurate representation of the output of the receiver? I don't think it is. Normal servo pulses vary from about 1000 to 2000 usecs with a gap of about 20,000 usecs. Your PIC code seems to have 50usec pulses.

Have you tried "re-multiplexing" the outputs from the 6 receiver channels so they could all be read by one interrupt pin. That seems to me at least as interesting and deep as any other approach. And if it works it should result in less Arduino code and therefore more time for the Arduino to do other stuff.

Have you the option of using a different receiver?

...R

Is the PIC output an accurate representation of the output of the receiver?

No, it is not. I've crafted this signal by hand so I could control it closely and verify my assumptions about the AVR interrupts. For example, that experiment about the ISR being called one or multiple times when multiple pins change almost at the same time. I didn't find the authoritative answer to that yet and as of now I believe the ISR gets called only once if the pins change "at the same time", lets say, on a single instruction on the PIC side.

Also, if I had the 20us interval of the regular servo signal, I'd be in bad shape to be able to debug the arduino code, as I'd have to write more logic and print some aggregate results. You may be wondering why I am spending all this effort on this issue and the reason is not only because I want to solve this "problem", but because I want to have great control over this topic. I'll reply PeterH post once I have time to do some other experiments.

On the other hand, I am not planning to try the "re-multiplexing" approach. For that, I'd have to tie this code to a given receiver behavior that I would have to inspect using a logic analyzer and external hardware to multiplex the pins. The rx behavior would potentially not be "portable" to other receivers and I'd have to verify them all. Not that I have as many, but I have spare pins on the arduino. Over that, I'm not really sure how the channel ids would be embedded in that single multiplexed pulse stream so that I could break them apart.

Have you the option of using a different receiver?

Not really. I have two instances of the same receiver module. Only that.

You are in charge. If you don't want to try re-multiplexing that is your decision and I will leave the matter alone.

I don't think you are doing yourself any favours by deliberately setting the Arduino a much more severe task than will be required to interpret real servo signals from a receiver. I can understand the need to simplify the output of the PIC compared with a real receiver but you should try to get close to the real situation. Writing interrupt driven code is tricky in the easiest of circumstances.

It seems to me the logic should be something like this
get an interrupt
figure out which pin it was
figure out if it is rising or falling
if it is rising, record the value of micros() into startPinXmicros
if it is falling, record the value of micros() into endPinXmicros
and set pinXdone to true
return from interrupt

elsewhere in the code (not in an interrupt)
if pinXdone is true figure out the pulsewidth by subtracting startPinXmicros from endPinXmicros

...R

Writing interrupt driven code is tricky in the easiest of circumstances.

There is where the joy begins. :slight_smile:

I'll get back to the actual receiver signal in the near future. And hopefully that code could even become a library for other to use. I'd like it to be robust, but I know little about publishing the end code to other people (I'll get into that if this code ever meets a minimum bar).

Thanks,

Hello PeterH / All,

It's a quirk of timing. The particular delay loop you're using happens to get in phase with the incoming pulse train since it always ends the delay loop as soon as it detects the first signal, and the remaining pulses in that group have all arrived by the time it returns to check the count again.

I'd be amused if this consistently gets in phase so that I'll always get this 1 and 5 grouping, instead of the expected group of 6.

Given that this bit of logic isn't related to what you're trying to do, I'm not sure why you're concerned about it.

That's because I'd like to have a comprehensive understanding of what I am doing. Actually, I got a bug with my rx code and then I decided to delve deeper on the basics and since I got into this, I am intrigued and playing, like an addictive game. :slight_smile:

I guess you'll throw this away and aren't too worried about how robust it is, but for what it's worth the approach of reading the count in one protected block and then clearing it in another introduces a race condition that might cause lost pulses in some scenarios. The approach I suggested of maintaining a copy of the counter and subtracting that from the volatile value avoids this problem since you never need to clear the counter. It's academic though since your real project won't be counting pulses.

I've made updates to the code based on the discussion on this thread. Please check if I got your idea on the "subtract" thing you mentioned.

So, getting back to the main topic:

I've changed my PIC code to have less chances of getting in phase to whatever is reading its output. The code that generates the pulse train is now like this:

void main() {
  char delays[] = {43,47,53};
  char i = 0;
  char j = 0;
  OSCCON = 0b01111011;
  TRISA = 0x00;
  PORTA = 0b00000000;
  while (1) {
    PORTA = 0b00100000;
    Delay_us(50);
    PORTA = 0b00000000;
    Delay_us(50);
    PORTA = 0b00100000;
    Delay_us(50);
    PORTA = 0b00000000;
    Delay_us(50);
    PORTA = 0b00100000;
    Delay_us(50);
    PORTA = 0b00000000;
    for (j=0; j<delays[i]; j++) {
      Delay_ms(59);
    }
    i++;
    i = i % 3;
  }
}

And my Arduino code is now like this:

volatile byte rxInterruptCount = 0;
byte rxInterruptCountCopy;
unsigned int busyWaitCount = 0;

volatile unsigned long timer0_millis_clone = 0;

void setup() {
  
  Serial.begin(115200);
  pinMode(7, INPUT);
  digitalWrite(7, LOW);
  Serial.println("Init!");
  delay(1000);
  Serial.println("Enabling interrupts!");
  cli();  
  PCICR = 0x04;
  PCMSK2 = 0b10000000;
  sei();
}

ISR(PCINT2_vect) {
  rxInterruptCount++;            
}

unsigned long myMillis()
{
	unsigned long m;
	uint8_t oldSREG = SREG;

	// disable interrupts while we read timer0_millis or we might get an
	// inconsistent value (e.g. in the middle of a write to timer0_millis)
	cli();
	m = timer0_millis_clone;
	SREG = oldSREG;

	return m;
}

void loop() {
  while (1) {
    myMillis();
    // millis();    
    busyWaitCount = 0;
    while (busyWaitCount<49123) { busyWaitCount++; }
    noInterrupts ();
    rxInterruptCountCopy = rxInterruptCount;
    rxInterruptCount -= rxInterruptCountCopy;
    interrupts();
    if (rxInterruptCountCopy > 0) break;
  }
  Serial.print("rxInterruptCountCopy = ");    
  Serial.println(rxInterruptCountCopy, DEC);
}

The running output is the following.

Using the code as:

    myMillis();
    // millis();

I get:

Init!
Enabling interrupts!
rxInterruptCountCopy = 1
rxInterruptCountCopy = 5
rxInterruptCountCopy = 1
rxInterruptCountCopy = 5
rxInterruptCountCopy = 1
rxInterruptCountCopy = 5
rxInterruptCountCopy = 1
rxInterruptCountCopy = 5

Using the code as:

    // myMillis();
    millis();

I get:

Init!
Enabling interrupts!
rxInterruptCountCopy = 6
rxInterruptCountCopy = 6
rxInterruptCountCopy = 6
rxInterruptCountCopy = 6

So, the question is: could anyone explain why does the millis() call before the busy loop makes the expected result to appear, and why does the fake myMillis() call does not have a similar effect?

I know nothing about the inner workings about arduino or the toolchain being used to compile the code, but I noticed that the binary file being generated does not match in size, which makes me believe that calling the original millis() code is actually doing more than what I'd believe it would, and thus causing this change in the final output.

myMillis IDE output:

Sketch uses 2,994 bytes (9%) of program storage space. Maximum is 30,720 bytes.
Global variables use 247 bytes (12%) of dynamic memory, leaving 1,801 bytes for local variables. Maximum is 2,048 bytes.

millis IDE output:

Sketch uses 3,016 bytes (9%) of program storage space. Maximum is 30,720 bytes.
Global variables use 243 bytes (11%) of dynamic memory, leaving 1,805 bytes for local variables. Maximum is 2,048 bytes.

Thanks,
Marcelo

Whether the output shows 1, 5 or 6 is just determined by how quickly your code will recognise that the first pulse has arrived, process it and get back to checking for the second pulse. Since you have a substantial delay in your polling loop, it's entirely understandable that the rest of the pulse train can have arrived by the time it makes that second check for rxInterruptCount > 0.

As to why the timing has changed depending which millis() implementation you call, maybe the two implementations of millis() are optimised differently because in one of them, the result is a constant value which is discarded by the caller. Or maybe that change hasn't made any difference and it's simply a coincidence that on one occasion the first pulse arrived early on in your delay and in the other it arrived later. Since the behaviour depends on exactly where abouts within that delay the pulse train starts, the algorithm you have implemented is vulnerable to anything that can affect that phase between the two processors.

The method you're using to detect changes in rxInterruptCount is not what I was suggesting, but it's academic since your project does not need to count pulses.

Since you have a substantial delay in your polling loop, it's entirely understandable that the rest of the pulse train can have arrived by the time it makes that second check for rxInterruptCount > 0.

I completely agree that the rest of the pulse train would have arrived completely after getting a count of 1. My point is that I'd go even further and believe that I should always get the whole pulse train completely (or at least most of the times), given the way the experiment was set up (substantial delay in polling loop, unmatched delays on the PIC side and the arduino side, narrow pulses close to each other and separated by a relatively and extremely large delay,etc).

But since this thread only sparked interest by a few of us, I guess that I'll just postpone this issue to another time. :confused:

The method you're using to detect changes in rxInterruptCount is not what I was suggesting, but it's academic since your project does not need to count pulses.

Is it not? Could you please update the code so I can learn your suggestion for that case of counting the pulses?

Thanks,