M-SoM Interrupt Issue

I'm running a relatively simple piece of firmware on the M404 at device OS 5.9.0 which has an interrupt running on a GPIO rising that increments a counter, essentially:

attachInterrupt(TEST_PIN, interruptFunction, RISING);

void interruptFunction()
{
interruptCount++;
}

When required, I rotate an axle attached to a hall effect sensor, of which the output is to TEST_PIN. I expect about 120 interrupts per second from this, and most of the time that's exactly what I get. The issue is, sometimes I get 0 interrupts for seemingly no reason (I spin the axle , generating 120Hz, none are picked up or the first x are, but the rest aren't) even though I know for certain that there is a ~120Hz square wave at TEST_PIN. It's as though the interrupt no longer exists - but if I spin the axel again, there's a 50/50 chance the interrupt will count again.

Fortunately, I also have a b5 SoM. If I run the same firmware and the same OS, I have a 100% success rate, it literally works every time vs the 50% success rate I get with the M-SoM.

I have also tried (on the M-SoM):

  • disabling the system thread and switching to manual mode (no cellular), which seemed to boost the success rate to 80-90%.
  • using thread block (no difference)
  • using Interrupts() (no difference)
  • using a falling edge (no difference)

Is this a known issue with the M-SoM, or are there any changes I can make to force my interrupt to hit every time like it does with the B-SoM?

I appreciate your help.

I'd try using the atomic functions. Writing the value from the ISR and reading it, presumably from the loop thread. can result in unexpected values. See this post:

Since the P2 and M-SoM use nearly identical RTL872x processors, I'd try that first.

1 Like

Hi Rick, thanks for the reply.

I implemented:
std::atomic<uint32_t> interruptCount;
void pulseInterrupt()
{
interruptCount.fetch_add(1, std::memory_order_relaxed);
}

uint32_t finalCount = interruptCount.load(std::memory_order_relaxed); // for publishing
interruptCount4Particle = interruptCount.load(std::memory_order_relaxed); // for particle variable

interruptCount.store(0, std::memory_order_relaxed); // to clear

And, unfortunately, I still have sessions where I miss interrupts. For consistency, I flashed the same code and OS onto the b5 SoM, and it never missed a beat (over 50 test runs):


Whereas the M404 failed after 9 tests in this instance:

It's extremely strange to me that we can't replicate the problem on the b5 SoM. Please let me know if you have any other fixes to try.

Which pin, and how is it connected?

If it's open collector or a SPST switch, are you using an external pull? What size and up or down?

Hi Rick,

As part of my reply, I was going to send you screenshots from our oscilloscope - and in doing so, I noticed that the voltage on the hall effect was far lower when using the M404.

As it turns out, I the ground pin of the sensor was connected to A4 and not GND this entire time. After I wrote A4 low, the issue was resolved.

Apologies for the stuff-up, and thanks for the extra atomic type variable info - we'll use this as part of our firmware going forward.

I guess one other takeaway is the surprise that the B5 SoM worked in this scenario! Would you happen to have any idea why? Also, if you have any other in-depth interrupt tips, please share them.

Thanks for your help.

Also, extra details for anyone else viewing this thread:

  • The pin was A3, external 10k pull-down
  • The sensor was a latching push-pull hall effect sensor

I don't know, but ADC inputs on the RTL872x are much lower in impedance than the nRF52, and I'd guess that probably has something to do with it.

1 Like