Input Capture with Sleep Enabled on ATM32u4 board only works every 2nd reading

In short: I have an Input Capture code and a Power-Saving code combined into one program. Both are adapted from Nick Gammon’s examples that work fine independently. When I combined them into one code it only reads the data every other time a single pulse is sent to be captured every 20 seconds. The board sleeps during one idle cycle between the 20 second readings, then wakes up but misses the first reading, and then it stays awake during the next idle cycle and reads the pulse correctly at the 40 second mark for the second reading. And repeats. The references of these two Nick Gammon codes are listed in the program.

Details: Adafruit BlueFruit Feather 32u4 w/nrf51 in the Arduino 1.8.10 IDE. Using Nick Gammon’s example for Input Capture an external incoming pulse of around 800 us (micro sec) long pulse is being measured by (ICP3) Input Capture #3 (rewritten from ICP1) on Pin D13 (PC7) (removed the LED). Works good.

Then I had a separate program that puts the board into deep-sleep and using INT0 (D3) to wake it up with an external interrupt signal. Since I was not able to figure out how to use the Input Capture as an ISR Interrupt to wake up the board, I ran the same external pulse signal also to the D3 (INT0) pin. So when the pulse hits both D3 (INT0) and D13 (ICP3) at the same time, and D3 wakes up the board via INT0 and then the ICP3 can capture the pulse and measure it. Then right after that, or several seconds later, can go back to sleep until the next pulse arrives on D13 (ICP3). I spaced the external 800us single pulses 20 seconds apart to make it easier to diagnose. If I remove the line that places the board into sleep “sleep_cpu ();” I get a nice single-shot signal pulse measurement every 20 seconds. Since I am not using the USB-detach and reconnect feature, after the board goes to sleep it disconnects, but I am monitoring the power usage via a Fluke mA meter and I can see when it sleep and when it wakes up, and also monitoring the external pulse going to D13 (ICP3) and D3 (INT0) on the Oscope.

Notes: The Input Capture is listed under the Interrupts, but at a much lower priority then INTo or INT1. I do not need an active USB during the readings or sleep, because using BLE to send the data. The code I posted has the BLE portion removed the make it simpler to troubleshoot. The 800us external single-shot pulse is rock solid I have it showing on the Oscope, at the proper magnitude (0 to 3.3V) and intervals. I am trying to have the CPU sleep between readings. Can be right after the reading or a few seconds later. Interrupts have to be alive and ready to capture in case the 20 seconds becomes 1 or 2 seconds intervals (in real life).

1-InputCaptueCounter_andSleep.ino (8.43 KB)

time the interval between two consecutive pulses.pdf (55.8 KB)

Just to be clear. You want to measure, with extreme precision, the width of the pulse which wakes the microcontroller from deep sleep ? You have also said that pulse is 800uS. The advantage of input capture is that the counter hardware, on being triggered by the selected edge, stores the counter value directly in a register. However, at the time the pulse comes in, the oscillator is not running because the microcontroller is in deep sleep. I can't see that the edge detection mechanism which wakes the microcontroller is valid for initiating an input capture. However, it is an interesting issue and I'll be curious to see something more concrete in the data sheet.

Of course, if you don't need the precision of the input capture mechanism, you can simply store the time value during the ISR that is triggered on wake up.

6v6gt you are exactly right about looking at the level of accuracy needed. I looked at this again, because the "easier" way would be just to run the external pulse into one (or two) of the INT pins (like INT0 INT1) for attachInterrupt measurements that would also wake up the CPU at the same time. I could compensate for the time it takes to enter and leave ISR, which according to Nick Gammon is around 5us total (and empirically can be calculated).

The way I understood, the INT0 and INT1 etc are pin interrupt macros that use the same Timer/Counters/Captures that one would use at the register level (so same inherent accuracy to calculate) but has the downside that it takes extra clock ticks to enter the ISR macro and to exit it. But if you can account for the time required to enter/exit the ISR macros, one should arrive to the same accuracy as using directly the Timers/Counters/Captures?

I used 800us as about the middle of the range for testing purposes. But the minimum range of pulses I want to measure is 200-2000us single-shot pulse. The desired range would be 70us-2000us range single-shot pulse. On the extreme end of the application would need to measure a 70us (micro second) pulse with 0.02 us accuracy. Theoretically an 8Mhz 32u4 in Timer mode has one tick that is 125ns long. Which is 0.125us per tick. So a 70us pulse with a 125ns long clock signal tick would have 560 counts. 70/560 = 0.125us If I make it 561 count, then it would lead to 70.125us signal. which is a 0.125us accuracy vs the desired 0.02us. That is a 6.25x difference.

Using the minimum range of 200-2000us pulses, I would like to have a 0.2us accuracy. So, that would be 1600 counts per 0.125us clock tick. With a 200us pulse and 1601 count it would be 200.125us which is a 0.125us accuracy vs the 0.2us minimum required. So this would work if I want to consider the minimum measurement range.

As far as measurement accuracy, if I want to go for the extreme end of 70us at 0.02us: I see an option to increase the CPU clock from 8mhz to 20mhz using the Atmega family. This would get me closer. Or go with an ARM processor based board with a 70-240Mhz CPU. But that brings with it for me programming problems, since I am already on shaky grounds with the AVR family of CPUs.

Unless, my suspicions is confirmed that using INT0-type pin interrupts with proper clock-tick time added on for entering and leaving the ISR loop, is as accurate as using direct TIMER/COUNTER/CAPTURE register coding? In that case, I could use one or two INT pins to measure the signal with an ARM M0 or M4 CPU clock rate of let's say 70mhz.

Would appreciate any advice and suggestion.

On the other hand, I was thinking that maybe a dedicated external Counter/Capture chip with enough speed could feed the ATM32u4 and let the ATM32u4 process the information, etc?

The other way of approaching this is to review your requirements for having the device sleep between input pulses. The benefits of sleep mode will be reduced, in your case anyway, because you are using a board with lots of power hungry components (voltage regulator, usb chip, power led etc.)

Any external device you add as a work around will also introduce its own power consumption issues.

Maybe also explain what the application is and you may get other suggestions for a solution.

Thank you for the advice. I will look into streamlining my setup to see where I can reduce power via hardware changes.