Shortest pulse for triggering a digital input

I want to start a simple code with a negative going (high-to-low) pulse at a digital input. The Arduino will be an Uno or a Nano running at stock clock with a 5V supply. The code works as intended with a push-button switch but, in the actual application, it will be triggered by a pulse from another circuit.

What is the shortest pulse that will reliably trigger the action?

I don't think the pulse will be anywhere close to the shortest duration limit but it will be nice to know - for this and for future applications.

If you use interrupts to detect the pulse, then it need to be greater than 2 clocks long.
So 2/16MHz

That's 125nS. My pulse will be several µS long. Thanks.

The interrupt will catch the pulse but there will be a few microsecs before it will be processed. Interrupts have 5 micros overhead plus the code in the IRQ. Reaction only begins in the IRQ but you can grab micros() which steps by 4.

If you are waiting for a return pulse you can poll with a 1 usec count loop and get a closer read.

Thanks for the further clarification. This is a simple operation that doesn't require high timing precision. Some milliseconds of delay or uncertainty will not make any difference. The starting signal is not even a sharp pulse. It's the exponential decay of an R-C network.

Different story.
Then you need to make sure it is 125ns wide at a level of 3V or higher

I know. As I said before, the signal is several microseconds long at the Schmitt hysteresis threshold of an ATMega328P.

No problem then.

I did a test using two Uno R3s to verify what the shortest pulse an interrupt could detect was.

I used one Uno to generate a low going pulse every 100ms.
I used direct port manipulation, so that I could vary the pulse width in steps of 62.5ns.
I varied the pulse width by adding/removing NOPs and recompiling.
Here is the code that I used:

// https://docs.arduino.cc/hacking/software/PortManipulation

#define NOP __asm__("nop\n\t")

void setup() {
  DDRB = B00111111;  // D8-D13 all outputs
  Serial.begin(115200);
}

void loop() {
  PORTB = B00000000;
  NOP;
  PORTB = B00000001;
  delay(100);
}

I used the second Uno to detect the pulses using an interrupt.
In the ISR, I generated a pulse on pin 12.
Here is the code I used:

const byte outputPin = 12;
const byte interruptPin = 2;
unsigned long pulseWidth = 5;

void setup() { 
  pinMode(outputPin, OUTPUT);
  pinMode(interruptPin, INPUT);
  attachInterrupt(digitalPinToInterrupt(interruptPin), generatePulse, FALLING);
  }

void loop() {
}

void generatePulse() {  
  PORTB = B00010000;        // turn pin 12 high
  delayMicroseconds(pulseWidth);
  PORTB = B00000000;        // turn pin 12 low
}

I used an oscilloscope to view the results:

  • Chanel 1 - yellow trace - Pulse going to interrupt pin 2 of Uno.
  • Channel 3 - blue trace - Pulse output from pin 12.


The interrupt would detect a pulse right down to one clock cycle wide (62.5ns).

Thanks. That info will come in handy when I move up to more advanced applications. I'm just a novice with MCUs although I do have some designing experience with analog and fixed logic devices.