Counting the number of pulses in a second
As already explained in Michel Keijzers' answer, instead of counting how
many times you find the input HIGH, you should count the LOW →
HIGH transitions. This requires saving the previous input state and
counting a transition only when the input is HIGH while it was LOW
last time you saw it:



static int last_pin_state = LOW;
int pin_state = digitalRead(SPEED_PIN);
if (pin_state == HIGH &amp;&amp; last_pin_state == LOW) {  // rising edge
    count++;
}
last_pin_state = pin_state;


For displaying the count every second, use the technique explained in
the Blink without delay Arduino tutorial:

static uint32_t last_time = 0;
if (millis() - last_time &gt;= PERIOD) {
    Serial.println(count);
    count = 0;
    last_time += PERIOD;
}


Note that you have to reset the count every time you print it.

VE7JRO suggests using interrupts. Interrupts save you the pain of
writing the edge detection. On the other hand, they also make things
slightly more complicated, because you now have to worry about
atomicity, race conditions, volatile variables and such. There is no
need to use interrupts unless the pulses are so fast (or your loop()
is so slow) that you may miss a pulse. If your loop() gets bigger and
slower, and you risk missing pulses, then interrupts can really help.
But the proper way to use them is to count the pulses in the ISR. If you
use the ISR only to rise a flag, you loose the speed advantage of the
interrupts, which is the whole point of this approach.

The interrupt service routine would then be like this:

volatile unsigned int count;

void count_pulse()
{
    count++;
}


Then, the loop only has to print and reset the count:

void loop()
{
    // Periodically print and reset the count.
    static uint32_t last_time = 0;
    if (millis() - last_time &gt;= PERIOD) {
        noInterrupts();
        unsigned int count_copy = count;
        count = 0;
        interrupts();
        Serial.println(count_copy);
        last_time += PERIOD;
    }
}


Note that the variable count is shared between the ISR and the main
loop. That's why it has to be declared volatile. Also, its access
within loop() has to be protected within a critical section delimited
by a noInterrupts()/interrupts() pair, otherwise you would have a
race condition. Also note that, in order to keep the critical section as
short as possible, the value of count is only copied within the
critical section, and the actual printing is deferred to after the
critical section is finished.