Some choices for a fan control station

Today is a rainy day so it was time for some foul programming. I was unhappy with that if I stopped the fan manually the code started to say that the revs are increasing. That is ofc bec the pulseIn-command reads the pulse lengths and they usually get shorter when the revs are increasing, but with one exception: it returns zero pulselength if it doesnt find a pulse. And zero is short.

I just couldnt make things work with If/ElseIf/Else or While commands so I ended up doing Gotos. Is this considered foul programming, could it be done neater? I shall say the code works. It does alarm when I stop the fan and it goes back to normal if I release it.

      /*
   * This code reads the length of the DC fans built in hall sensor(s) activity.
   * The readings are in microseconds and with a formula this can be converted
   * and presented as Revolutions Per Minute (RPM) and/or percentage spinning
   * of the fans max revolutions per time unit.  
  */

int hallSensorPin = 2;            // Pin 2 is used to read the Hall sensors activity
unsigned long previousPulseTime;  // Variable for storing the duration of a pulse.
word highPulseTime;               // It stores the previous value to have something
word lowPulseTime;                // compare a new value with
unsigned long newPulseTime;       // Since it is in microseconds it needs to be able
                                  // to store a large value.

                              
int revsPerMinute;                // Variable for storing RPM value
int smoothedRevsPerMinute;        // Variable for storing the smoothed RPM value
int percentage;                   // Variable for storing percentage value
int samples = 3;                  // Amount of samples that will be stored and used
                                  // for smoothing

int ledPin = 13;                  // Pin 13 is used to test alarm

  /*
   * Set the pin that shall read the Hall Sensor to pull up its input to 5 V
   * with the built in 20k resistor. I have seen some lifting to fan 12 V line but that is
   * a much dirtyer voltage then the internal regulated 5 V line. Holding it internal also  
   * makes the electrical loop much smaller and less sensitive to interference.
   * The hall sensors activates a sinking transistor that takes the voltage to LOW when
   * the hall sensors are active, ie it shorts its input to ground.
   * And start serial for test purpouse read outs to serial monitor. 
  */
  
void setup() {

  pinMode(ledPin, OUTPUT);                        // Set LedPin to output
  pinMode(hallSensorPin, INPUT_PULLUP);           // Pull up the sensor pin to 5V
  highPulseTime = pulseIn(hallSensorPin, HIGH);   // Read once for how long the pulse is high
  lowPulseTime = pulseIn(hallSensorPin, LOW);     // Read once for how long the pulse is low
  newPulseTime = highPulseTime + lowPulseTime;    // Create a previous value by telling it to
  previousPulseTime = newPulseTime;               // be the same as the new value we just read.
                                                  // to get a starter position
  
  Serial.begin(9600);                             // We start a serial for debugging readouts

}

  /*
   * The pulseIn function reads a pulse, either the high part or the low part. My fan makes two
   * pulses per revolution, ie high-low-high-low so first I read the high pulse, then I read the
   * low pulse. Then in the calculation to revs per minute I sum the high and low pulse and after
   * that multiplies by factor 2. This shall be a full revlution that we time.
   * 
   * The pulseIn way of measuring a fans revolutions per time unit is not very exact. A more
   * exact way would be to count the pulses over a longer time period. This is on the other hand
   * taking up a longer processing time of maybe a second to get good readings. I want to avoid  
   * that so I read the pulses instead which only takes a couple of milliseconds.
   * 
   * 1200 RPM is 20 RPS which meens a full revolution takes 50 ms. I measure half a revolution.  
   * The downside with this is that a fan is not very exact when you come down to microseconds
   * and the hall sensor readings can once in a while bug out and give a strange value.
   * I am on the other hand not interested in weather the fan spins with 1207 or or 1211 revs per
   * minute, I am interested to see if they do the work they are set to do so I dont care about
   * the exact value. On the other hand I do prefer a value that doesnt jump one step every time
   * it renews itself so therefore I am smoothing the output values so every new reading adds  
   * the three readings before it and divides the total four readings with four to present a
   * smoothed average. This makes it less jumpy on the last digit.  
   * 
   * I also added an outlier corrector which is described below.
  */

void loop() {  
  
run:                                                // goto tag, see below

  digitalWrite(13, LOW);

  highPulseTime = pulseIn(hallSensorPin, HIGH);     // Read for how long the pulse is high

  lowPulseTime = pulseIn(hallSensorPin, LOW);       // Read for how long the pulse is low

  newPulseTime = highPulseTime + lowPulseTime;

  /*
   * Here I tried with alot of If, Else If and Else commands but it would not work for me.
   * If I tried If => Pulse Time = 0 and Else If if it was not 0, somehow the smoothing
   * algorithms below bugged out so it just told me that the revs are going up all the way
   * to 100% while tha fan was actually stopped and the Led Pin did not want to shine. I
   * guess the interpretation of If => Else If and then new If commands does not work.
   * I also tried While for the alarm if the fan stoppes and it worked so far but when I
   * released the fan it was stuck in the While-loop.
   */

      if (newPulseTime == 0) {                      // A goto command. If statement is true
        goto alarm;                                 // we jump down to alarm: in the end
  }
  
      if (newPulseTime < (previousPulseTime * 0.9)) {   //Kind of a high-pass filter
        (newPulseTime = (previousPulseTime * 0.9));     //Takes outlier values down
    }

      if (newPulseTime > (previousPulseTime * 1.1)) {   //Kind of a high-pass filter
        (newPulseTime = (previousPulseTime * 1.1));     //Takes outlier values down
    }   

  revsPerMinute = (1000000 * 60)/(newPulseTime * 2);  // Convert pulse time to RPM
                             
  // Smoothing out the value by adding earlyer values and divide to an average
  
  smoothedRevsPerMinute = smoothedRevsPerMinute + ((revsPerMinute - smoothedRevsPerMinute)/samples);
  
  // Calculate the fans spinning in percentage of its max which is approximately 1560 RPM
  
  percentage = (smoothedRevsPerMinute / 15.55);       //The fans max revs are about 1550
  percentage =  constrain(percentage, 0, 100);        //Constrains percentage scale

  // Do some serial printing for checking the result for now
  
  Serial.print("High Pulsetime");
  Serial.print("\t");
  Serial.print("\t");
  Serial.println(highPulseTime, DEC);
  Serial.print("Low Pulsetime");
  Serial.print("\t");
  Serial.print("\t");
  Serial.println(lowPulseTime, DEC);
  Serial.print("Halfrev Microseconds");
  Serial.print("\t");
  Serial.println(newPulseTime, DEC);
  Serial.print("Revolutions per minute");
  Serial.print("\t");
  Serial.println(smoothedRevsPerMinute, DEC);
  Serial.print("Percentage of max revs");
  Serial.print("\t");  
  Serial.println(percentage, DEC);

  previousPulseTime = newPulseTime;

  alarm:
  if (newPulseTime > 0) {           //If the pulse is not zero wait a while and go to run
     delay(5000);
     goto run;
  }
  else {                            //otherwise activate alarm, wait a bit and check again
  digitalWrite(ledPin, HIGH); 
  }
  delay(5000);
}