/*
  HC-SR04 Ultrasonic sensor with plain, non-blocking state-machine coding
  https://wokwi.com/projects/404439179947636737

  This code blinks the trigger pin periodically,
  records the time of the falling edge of the trigger, and the flight time of the echo.

  The code avoids blocking by ussing a small State Machine to blink the trigger pin
  and a State Change Detection scheme to measure the time of flight of the echo.
  Then another state change detection to report only changes in distance.
  
*/
/*
  Uno with Scope https://github.com/Dlloydev/Wokwi-Chip-Scope
        and https://github.com/Dlloydev/Wokwi-Chip-PWM


  Wokwi Uno https://wokwi.com/projects/390819301187622913
  Wokwi Mega: https://wokwi.com/projects/390819455604080641

  See also https://wokwi.com/projects/359331973918199809

*/

const byte TriggerPin = 13;
const byte EchoPin = 12;

// timing variables
uint32_t nowMs = 0, triggerUs = 0, echoUs = 0;
uint32_t echoRiseUs = 0, echoFallUs = 0;
const uint32_t PingInterval = 100;
const float CmPerUs = 34320.0 / 1000000;
float distance = 0;

// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(TriggerPin, OUTPUT);
  pinMode(EchoPin, INPUT);
  Serial.begin(115200);
  Serial.print("Round trip timing:");
  Serial.print(CmPerUs/2,4);
  Serial.print(" cm/us, ");
  Serial.print(2/CmPerUs,4);
  Serial.println(" us/cm");
  
}

// the loop function runs over and over again forever
void loop() {
  nowMs = millis();
  doPings();
  if (watchEchoFall()) {
    calculateDistance();
  }
  report();
  //delayMicroseconds(1000); // experiment with slower loops and resolution
}

float calculateDistance() {
  echoUs = echoFallUs - echoRiseUs;
  // could print on pulses, or calculate distance
  distance = echoUs * CmPerUs / 2; // cm/sec for round trip 
  return distance;
}

void doPings(void) {
  static uint32_t lastPingMs = 0;
  static bool triggerState;
  if (nowMs - lastPingMs >= PingInterval) {
    triggerState = triggerState == HIGH ? LOW : HIGH;
    digitalWrite(TriggerPin, triggerState);
    if (triggerState == LOW) {
      triggerUs = micros();
      //   Serial.print('*');
    }
    lastPingMs += PingInterval;
  }
}

bool watchEchoFall() {
  bool echoFell = false;
  static byte lastEcho = LOW;
  uint32_t nowUs = micros();
  byte echoState = digitalRead(EchoPin);
  if (echoState != lastEcho) {
    if (echoState == HIGH) {
      echoRiseUs = nowUs;
    } else {
      echoFallUs = nowUs;
      echoFell = true;
    }
    lastEcho = echoState;
  }
  return echoFell;
}
void report() {
  static uint32_t lastEchoUs = -1;
  if (echoUs != lastEchoUs) {
    lastEchoUs = echoUs;
    Serial.print(echoUs);
    Serial.print("us ");
    Serial.print(distance);
    Serial.println("cm ");
  }
}
Loading chip...chip-scope
Wokwi UnoScope https://wokwi.com/projects/390819301187622913