Ultrasonic distance check and Millis

I'm struggling to figure this issue out. I'm sure it's just me not having a firm grasp on how this works. What I'm doing, in general, is create a robot that runs as a state machine. Everything is working great so far. What I'm doing is working module by module, adding each one in after testing it.

What I'm working on right now is using the ultrasonic sensor to stop the robot if it gets to close. when I set the robot into the FORWARD state it calls the checkDistance function. Right now it works but not great. there is a slight pause when it switched from FORWARD to STOP when the minimum distance is triggered.

my code below works and If I understand what I'm doing correctly, the checkDistance loop runs every 10millis (which honestly might be too fast) but in the loop I still use a delay of (2) and (10) between the writing to the pins to send the ultrasonic signals.

unsigned long prevousTime = 0;
const unsigned long eventInterval = 10;

............

void checkDistance() { // Use the ultrasonic sensor to check distance
  unsigned long currentTime = millis();
  float duration, distance;
  
  if (currentTime - previousTime >= eventInterval) {
  digitalWrite(trigPin, LOW);  
	delayMicroseconds(2);  
	digitalWrite(trigPin, HIGH);  
	delayMicroseconds(10);  
	digitalWrite(trigPin, LOW);  
  duration = pulseIn(echoPin, HIGH); 

  distance = (duration*.0343)/2;
  }
 Serial.print("Distance: ");
 Serial.println(distance);
 previousTime = currentTime;
 if (distance <= d_min){
  Serial.println("Too Close");
  currentState = STOP;
 }
}

if I try and use the Millis code about in place of the delay(10) I start to get weird results, the distance returns as 0.00cm then 50,00cm (or whatever the distance is) then 0.00 then XX.XXcm

..........
        digitalWrite(trigPin, LOW);  
	delayMicroseconds(2);  
	digitalWrite(trigPin, HIGH);  
  if (currentTime - previousTime >= eventInterval) {
	digitalWrite(trigPin, LOW);  
 }
  duration = pulseIn(echoPin, HIGH); 

I'm sure I have absolutely no idea what I'm doing and probably need to go back to the drawing board.

My question is, do I even need to use millis code to replace the delay of (2) and (10), would it really make a difference? If I should replace the delays with millis can someone point me in the right direction of what I'm doing wrong?

Please post your full sketch so that the snippet of code that you posted can be seen in context. For instance, where are you calling checkDistance() from and how often ?

I see there is a test for ZERO being returned that is not there. What do you want to happen when piuseln() returns zero, which it will?

The function checkDistance() should always run when called and return a valid distance. Put the loop timing elsewhere.

checkDistance() should not do any printing. Save the printing for debugging problems.

Make sure that you are using a high serial Baud rate (at least 115200 Baud), so that all the needless printing doesn't introduce additional problematic delays.

In the future, post all the code, such that other potential problems can be addressed.

Sorry, I'm never sure if I should post the whole thing. Please ignore all my spelling mistakes and comments, its so I can figure out what I'm thinking day to day and to remind me to look into things later... I added some code to try and clear up some of the garbage data coming from the ultrasonic sensor

#include <IRremote.hpp> 
#define IR_RECEIVE_PIN A0 // pin IR receiver it attached to

// The list of possible states of our system
// along with a currentState variable taking one of these values
enum {EARS, FORWARD, BACKWARD, LEFT, RIGHT, STOP, BOOT, WAIT} currentState;

// Sets the pins for the ultrasonic sensor
const int trigPin = 12;
const int echoPin = 13;

// Sets the pin for the servo
// const int servoPin = A5; // pin servo plugged into

// Sets the minimun forward distance needed to not hit something
const int d_min = 20; // 20mm?

// Millis Setup
unsigned long previousTime = 0; // does this need to be here?
unsigned long eventInterval = 10; // does this need to be here?
// unsigned long distanceMillis; // not sure why this is here...

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK); // starts the IR receiver
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  currentState = BOOT; // sets the start state as BOOT - not that it does anything there yet
}

void checkDistance() { // Use the ultrasonic sensor to check distance
  unsigned long currentTime = millis(); // sets currentTime to the computer clock
  float duration, distance; // creates variables for time duration and the distance calculation
  
  // subtracts the previous time - a global - from the current time
  // then checks to see if it is greater than the interval - a global 
  if (currentTime - previousTime >= eventInterval) { 
  digitalWrite(trigPin, LOW);  
	delayMicroseconds(2);  
	digitalWrite(trigPin, HIGH);  
	delayMicroseconds(10);  
	digitalWrite(trigPin, LOW);  
  duration = pulseIn(echoPin, HIGH); 

  distance = (duration*.0343)/2; // equation to make the distance cm
 }
 // sanity check
 Serial.print("Distance: ");
 Serial.println(distance);

 previousTime = currentTime;
 
 // checks the distance against the minimum then checks to make sure the
 // distance is not 0 - which is an invalid results - then checks to make
 // sure it is not over 500 - which also is an invalid response
 // is there some sort of interferance?
 if (distance <= d_min && distance != 0 && distance <= 500){ 
  Serial.println("Too Close"); // sanity check
  currentState = STOP;
 }

}


void Move_Backward() { // Function to get the wheels going backward
  digitalWrite(2, HIGH); // writes data to pin 2
  digitalWrite(4, LOW); // writes data to pin 4
  digitalWrite(7, HIGH); // writes data to pin 7
  digitalWrite(8, LOW); // writes data to pin 8
  analogWrite(5, 200); // writes data to anaglog pin 5
  analogWrite(6, 200); // writes data to ana log pin 6
}

void moveEars() { // Use the servo motor to move ears

}

void Move_Forward() { // Function to get the wheels going forward
  checkDistance(); // checks for front distance to make sure the head does not bump anything - is this the right spot for this?
  digitalWrite(2, LOW); // writes data to pin 2
  digitalWrite(4, HIGH); // writes data to pin 4
  analogWrite(5, 200); // writes data to analog pin 5
  digitalWrite(7, LOW); // writes data to pin 7
  digitalWrite(8, HIGH); // writes data to pin 8
  analogWrite(6, 200); // writes data to analog  pin 6
}

void Rotate_Left() { // Function to get the wheels moving in opposite directons to turn left
  digitalWrite(2, LOW); // writes data to pin 2
  digitalWrite(4, HIGH); // writes data to pin 4
  digitalWrite(7, HIGH); // writes data to pin 7
  digitalWrite(8, LOW); // writes data to pin 8
  analogWrite(5, 200); // writes data to analog pin 5
  analogWrite(6, 200); // writes data to analog pin 6
}

void Rotate_Right() { // Function to get the wheels moving in opposite directons to turn right
  digitalWrite(2, HIGH); // writes data to pin 2
  digitalWrite(4, LOW); // writes data to pin 4
  digitalWrite(7, LOW); // writes data to pin 7
  digitalWrite(8, HIGH); // writes data to pin 8
  analogWrite(5, 200); // writes data to analog pin 5
  analogWrite(6, 200); // writes data to analog pin 6
}

void readRemote() { // deals with the signals from the ir remote
 if (IrReceiver.decode()) { // sanity check - what is this code saying?
      Serial.println(IrReceiver.decodedIRData.decodedRawData, HEX); // Print "old" raw data
      IrReceiver.printIRResultShort(&Serial); // Print complete received data in one line
      IrReceiver.printIRSendUsage(&Serial);   // Print the statement required to send this data
      Serial.println(IrReceiver.decodedIRData.command); // prints the decoded command
      IrReceiver.resume(); // Enable receiving of the next value

  if (IrReceiver.decodedIRData.command == 24) { // 24 is the command code for the up button
  currentState = FORWARD;
  IrReceiver.resume();  // Enable receiving of the next value
 } else if (IrReceiver.decodedIRData.command == 28) { // 28 is the command code for the OK button
  currentState = STOP;
  IrReceiver.resume();  // Enable receiving of the next value
 } else if (IrReceiver.decodedIRData.command == 8) { // 8 is the command code for the left button
  currentState = LEFT;
  IrReceiver.resume();  // Enable receiving of the next value
 } else if (IrReceiver.decodedIRData.command == 90) { // 90 is the command code for the right button
  currentState = RIGHT;
  IrReceiver.resume();  // Enable receiving of the next value
 } else if (IrReceiver.decodedIRData.command == 82) { // 82 is the command code for the down button
  currentState = BACKWARD;
  IrReceiver.resume();  // Enable receiving of the next value
  }
  // to check the moveEars function
  else if (IrReceiver.decodedIRData.command == 25) { // 25 is the command code for the "0" button
  currentState = EARS;
  IrReceiver.resume();  // Enable receiving of the next value
 }
}
}

void Stop_Robot(){ // Function to stop the wheels from turning
  digitalWrite(2, HIGH); // writes data to pin 2
  digitalWrite(4, HIGH); // writes data to pin 4
  digitalWrite(7, HIGH); // writes data to pin 7
  digitalWrite(8, HIGH); // writes data to pin 8
  analogWrite(5, 200); // writes data to pin 5
  analogWrite(6, 200); // writes data to pin 6
}

void Other_Stop() { // Function to stop other things that need to be stopped

}

void checkStates() { // Function that checks to see what state the robot is in and take an appropriate actions
 switch (currentState) {
   case STOP:
   Stop_Robot();
   currentState = STOP; // do i need this here?
   IrReceiver.resume();
 break;
   case FORWARD:
   currentState = FORWARD;  // do i need this here
   Move_Forward();
   IrReceiver.resume();
 break;
   case BACKWARD:
   Move_Backward();
   currentState = BACKWARD; // do i need this here
   IrReceiver.resume();
 break;
   case LEFT:
   Rotate_Left();
   currentState = LEFT; // do i need this here
   IrReceiver.resume();
 break;
   case RIGHT:
   Rotate_Right();
   currentState = RIGHT; // do i need this here
   IrReceiver.resume();
 break;
    case WAIT:
   // Rotate_Right();
   currentState = WAIT; // do i need this here - do i need this when i have the stop state?
   IrReceiver.resume();
 break;
    case BOOT: // for later
    currentState = BOOT; // do i need this here
    IrReceiver.resume();
 break;
    case EARS: // makes the ears move - do i even need this state?
    currentState = EARS; // do i need this here
    IrReceiver.resume();
 }
}
void runStateMachine(){ // calls all the functions needed to run the robot. Hopefully with no delay...
readRemote();
checkStates();
// checkDistance(); // Does this work better hear or in the Move_Forward function?
}

void loop() { // main loop that controls everything
  // put your main code here, to run repeatedly:
runStateMachine(); // this runs the whole enchilada

// sanity check - check to make sure what state the robot is in
if (currentState == FORWARD) {
    Serial.println("State Forward");
  } else if (currentState == STOP) {
    Serial.println("State STOP");
  } else if (currentState == LEFT) {
    Serial.println("State LEFT");
  } else if (currentState == RIGHT) {
    Serial.println("State RIGHT");
  } else if (currentState == WAIT){
    Serial.println("State WAIT");
  } else if (currentState == BACKWARD){
    Serial.println("State BACKWARD");
  } else if (currentState == EARS){
    Serial.println("State EARS");
  } else if (currentState == BOOT){
    Serial.println("State BOOT");
  }
}

It is always best to post a whole sketch that illustrates your problem. That does not always have to be your whole project sketch, it could be a smaller but compete sketch showing the same problem

At that rate, Serial takes 1 millisecond to print a single character, and in that time, sound waves travel 0.34 meters (1.2 feet).