How long does my digital pulse need to be for it to be read? I have the following really simple code. On every iteration it'll read the first pin, and if it's high - do some serial IO. Then do the same with the second pin. Nice and simple, works during my tests.

My concern is that (in production), the digital pulse I'm receiving (and trying to mimic during testing) would be too quick for the arduino to read. So, for example, the race condition could be:


First pin is low Read first pin - result is low.
First pin is now high Read second pin - result is low.
Fist pin now low again Read first pin - result is low again (missed the 'high')


How much of an 'edge case' is this? Am I worrying about something that's likely to be a non-issue here? In production, each single pulse would represent a significant amount of product (I multiply it elsewhere) - so even skipping one could throw my data off.

boolean count1High = false;
boolean count2High = false;
int count1 = 7;
int count2 = 8;
int a = 1;
void setup() {
  pinMode(count1, INPUT);
  pinMode(count2, INPUT);
  Serial.begin(9600);
}

void loop()
{
  if (digitalRead(count1) == HIGH)
  {
    if (!count1High)
    {
      count1High = true;
      a++;
      Serial.println(a); 
    }
  }
  else 
  {
    count1High = false;
  }

  if (digitalRead(count2) == HIGH)
  {
    if (!count2High)
    {
      count2High = true;
      a++;
      Serial.println(a); 
    }
  }
  else 
  {
    count2High = false;
  }
}


EDIT:

I know best approach here might be to attach an interrupt but I've been advised to avoid serial IO from within interrupts, I don't see an alternative here.
As explained by Majenko's answer, you should detect the pulses from an
interrupt and print the result from the regular code. However, instead
of just setting a flag in the interrupt handler, I suggest you instead
count the pulses within the handler. This will make the handler a tiny
bit slower, which is often something you want to avoid. However, the
extra overhead is really tiny, and you gain the ability to count
not only pulses that are short but also pulses that are closely spaced.

There is, however, something to be aware of when sharing a variable
between interrupt code and regular code. If the variable cannot be read
in a single CPU instruction (which is the case of an int on an
AVR-based board), there is some risk that the value gets changed in the
middle of you reading it. To void this problem, you have to disable
interrupts when reading the variable from regular code.

Here is an implementation of this strategy highlighting this point:

const uint8_t intPin1 = 2;
const uint8_t intPin2 = 3;

// This is volatile because it is shared between interrupt context
// and regular code.
volatile unsigned int sharedCount = 0;

// Interrupt handler.
void countPulse() { sharedCount++; }

// A variable shared with interrupt context should be accessed from
// regular code with interrupts disabled, in order to avoid race
// conditions.
unsigned int getCount() {
    noInterrupts();
    unsigned int countCopy = sharedCount;
    interrupts();
    return countCopy;
}

void setup() {
    pinMode(intPin1, INPUT);
    pinMode(intPin2, INPUT);
    attachInterrupt(digitalPinToInterrupt(intPin1), countPulse, RISING);
    attachInterrupt(digitalPinToInterrupt(intPin2), countPulse, RISING);
    Serial.begin(9600);
}

void loop() {
    static unsigned int previousCount = 0;
    unsigned int count = getCount();
    if (count != previousCount) {
        Serial.println(count);
        previousCount = count;
    }
}


Note that if the pulses come very fast, you may miss printing the
value, but you will not miss counting it (up to some limit, of
course). Thus you may see non-consecutive numbers being printed.