#define hallSensorPin 8
#define outputPin 3

const float wheelCircumference = 2.2; // Circumference of the bike wheel in meters (adjust this based on your wheel size)
const unsigned long debounceDelay = 50; // Debounce delay in milliseconds

volatile unsigned long lastHallPulseTime = 0;
volatile unsigned long timeBetweenPulses = 3001;
volatile unsigned long targettimeBetweenPulses = 3001;
volatile float speedKmh = 0.0;
volatile float lastspeedKmh = 100.0;

volatile unsigned long lastOutputTime = 0;


void setup() {
  pinMode(hallSensorPin,INPUT_PULLUP); // Set the Hall sensor pin as input with internal pullup resistor
  pinMode(outputPin, OUTPUT);
  attachInterrupt(digitalPinToInterrupt(hallSensorPin), calculateSpeed, FALLING); // Trigger the calculateSpeed function on a falling signal edge
}

void loop() {

  if (timeBetweenPulses < 3000) //to avoid startup with a speed value
  {
    float speedMetersPerSecond = (wheelCircumference * 1000) / timeBetweenPulses; // Calculate the speed in meters per second
    speedKmh = (speedMetersPerSecond * 3600) / 1000; // Convert the speed to km/h
  }

  // check stop, no input on the sensor for a while, speed should go to zero
  unsigned long nowTime = millis();
  if (nowTime - lastHallPulseTime > 3000) {
    speedKmh = 0;
  }

  // make the output pulse
  if (speedKmh > 0) {
      if (nowTime >= lastOutputTime + targettimeBetweenPulses)
      {
          //turn pin high
          digitalWrite(outputPin, HIGH);
          //pulse width
          delay(targettimeBetweenPulses * 0.0124);
          //turn pin down
          digitalWrite(outputPin, LOW);
          lastOutputTime = nowTime;
      }   
  }

  // only update screen and calculate target pulse timing when different speed
  if (speedKmh != lastspeedKmh) {
    
    // the magic formula
    targettimeBetweenPulses = timeBetweenPulses + 160;

    lastspeedKmh = speedKmh;
  }
}

void calculateSpeed() {
  unsigned long currentTime = millis();
  if (currentTime - lastHallPulseTime > debounceDelay) { // Debounce the sensor
    timeBetweenPulses = currentTime - lastHallPulseTime;
    lastHallPulseTime = currentTime; // Update the lastHallPulseTime
  }
}
