Digital toggle question - very basic question

Hi all -
I'm very new to the Arduino and somewhat to electronics in general but have been programming for far too long. Which is why this is a frustrating question.

I've got a used HP motor from an inkjet printer. On the end of it is a positional sensor that is basically an LED IR transmitter/receiver combo with a wheel with very small slots cut in it. I'm simply trying to watch what is going on with the sensor. I know that, for example, there are 40 "pulses" per revolution.

But I'm obviously missing something pretty big as I can't successfully handle the counts. If I spin the shaft at a fairly low speed (with my hand) I see what appear to be the correct number of pulses and the program below works great. But, again with just my hand, if I spin the shaft quickly I am missing many pulses. Indeed, the faster I try to spin it the more pulses I miss. I have a simple LED out to watch the pulses but my counters quickly get messed up.

I don't feel for an instant that I'm spinning too fast for the Arduino (Uno) to keep up. This isn't some 25K RPM test - it's with my hand. So I ask for some guidance as to a better way to program for this problem.

Thanks very much for any help in advance.

int ledPin = 13;
int inputPin1 = 2;
int clicksInARevolution = 40;

//
// some initialization
//
int clickCounter = 0;
int lastClickCounter = 0;
int lastLoopValue = LOW;
int revolutionCount = 0;


void setup() {
  pinMode( ledPin, OUTPUT);
  pinMode( inputPin1, INPUT);
  
  Serial.begin(9600);
  Serial.println( "setup done" );
}

void loop() {
  if( digitalRead(inputPin1) == LOW) {
    if( lastLoopValue == HIGH ) {
      clickCounter++;
      lastLoopValue = LOW;
      Serial.print( "clickCounter is now " );
      Serial.println( clickCounter );
    }
    digitalWrite( ledPin, LOW );
  }
  else {
    digitalWrite( ledPin, HIGH );
    if( lastLoopValue == LOW ) {
      lastLoopValue = HIGH;
    }
  }
  
  if( ( clickCounter % clicksInARevolution == 0 ) && ( clickCounter != lastClickCounter ) ) {
      revolutionCount++;
      Serial.print( "revolutionCount is " );
      Serial.print( revolutionCount );
      Serial.print( " and clickCounter is " );
      Serial.println( clickCounter );
      lastClickCounter = clickCounter;
  }
}

Unless I'm very much mistaken, the presence of the Serial.print() and Serial.println() methods inside your loop are the likely culprit. Serial.print() blocks until output is complete, and that can be many many milliseconds.
Try taking the Serial calls out, and see how it performs (or crank up the baud rate considerably in the serial.setup() call...)

Maybe put a switch on a new pin (say... 11?) with a pulldown and if it's high, do a serial output...

if (digitalRead(4)==HIGH) {
Serial.print("Current counter is bleh bleh bleh");
Serial.println(variable);
Serial.println("Counting suspended untill switch is opened...");
delay(50); // To help debouce the switch...
while (digitalRead(4)==HIGH); // Empty loop.
}

+5 to one side of the switch, other side of the switch a 10k resistor going to ground, and a wire going to the junction of the resistor and the switch leg from arduino pin 4... Happy pulldown.

Perhaps that'll help.

Then you press your button, and as long as it's held down the program will sit there waiting for you to let it go, and then resume counting happily.

Also you are better off using interrupts. Set up a "falling" interrupt (you are already using pin 2 which is good) and have the interrupt routine count things. Then all the main loop has to do is output the count every second, say.

Just to expand on what dsacmul wrote, at 9600 bits per second, one character takes 1 / 960 of a second to transmit, or a little over one millisecond.
This:

Serial.print( "clickCounter is now " );
      Serial.println( clickCounter );

would take over 20ms to print out, limiting your output rate (and therefore you input rate) to less than 50Hz.

AWOL is right. Outputting data whilst trying to keep up with a fast-moving wheel is fundamentally flawed. Even without interrupts, if you just stored up your results and sent them later things would improve dramatically. But with interrupts, where the ISR (Interrupt Service Routine) did as little as possible, you would maximize your chances of capturing each pulse.

It's always useful to do some metrics. How fast does the wheel spin? How many pulses per second? How many instructions does it take to capture one pulse? When you multiply all that out you can see how fast a wheel you can handle.

And for ultimate speed you can program timer1 as a 16bit input pulse counter that will run up to several MHz... That might be overkill for this case though.