Ultrasonic sensor maths problem

I am writing the code for an ultrasonic sensor for my diy car for an Arduino Pro Mini. I am using interrupts to obtain the two micros() of the echo pin of the HC-SR04. But I can't do calculations with it.

unsigned long prev_trig;
volatile unsigned long echo[2] = {1,1};
float distanceFoward;
bool echo_end = false;
bool haltFoward = false;

void setup() {
  Serial.begin(9600);
  pinMode(2,INPUT); //Echo
  pinMode(4,OUTPUT); //Trig
  attachInterrupt(digitalPinToInterrupt(2),time_echo,CHANGE);
}

if(prev_trig+100<millis()){
    distanceFoward = (echo[1]-echo[0])*0.17;
    Serial.print(echo[1]-echo[0]);
    Serial.print("\t");
    Serial.print(distanceFoward);
    Serial.print("\t");
    Serial.print(echo[0]);
    Serial.print("\t");
    Serial.println(echo[1]);
    if(distanceFoward<60)
      haltFoward = true;
    else
      haltFoward = false;
    echo[0] = 0;
    echo[1] = 0;
    echo_end = false;
    digitalWrite(4,HIGH);
    delayMicroseconds(15);
    digitalWrite(4,LOW);
}
    

void time_echo(){
  if(echo_end==false){
    if(echo[0]==0){
      echo[0] = micros();
    } else {
     echo[1] = micros();
     echo_end = true;
    }
  }

Output

2	0.00	1	1
0	0.00	3183452	0
0	0.00	0	0
0	0.00	0	0
0	0.00	0	0
0	0.00	3185648	0
0	0.00	3202832	3205052
0	0.00	3227792	3229960
0	0.00	3252752	3254972
0	0.00	3277712	3279932
0	0.00	3302672	3304888
0	0.00	3327632	3329800
0	0.00	3352592	3354760
0	0.00	3377552	3379724
0	0.00	3402512	3404732
0	0.00	3427472	3429640
0	0.00	3452432	3454652
0	0.00	3477392	3479560
0	0.00	3502348	3504544
0	0.00	3527312	3529480
0	0.00	3552272	3554492

The two time can be obtained, but the interval cannot be calculated somehow and is always zero. What have I done wrong?

You code is incomplete: loop() is missing.

The problem is not with maths, instead with programming errors and poor structure.

Use of interrupts is completely unnecessary for this application, and introduces problems with event sequencing and variable mangling (for example, a multibyte variable can be changed by the interrupt, halfway through being accessed by the main code).

Variables shared between interrupt and non-interrupt code MUST be declared volatile (echo_end).

This is the wrong way to check for elapsed time:

if(prev_trig+100<millis()){

You must do this

if (millis() - prev_trig > 100)

Or it will fail at wrap-around. The subtraction is the key step.

You are not sampling the ISR variables in a critical section:

  noInterrupts() ;
  unsigned long start = echo[0] ;
  unsigned long end = echo[1] ;
  interrupts() ;

This will give you unmanged and matching values of the two timestamps. Your existing
code is reading each several times while interrupts are still flying about - so you'll get
junk readings even without the mangling issue.

jremington:
The problem is not with maths, instead with programming errors and poor structure.

Use of interrupts is completely unnecessary for this application, and introduces problems with event sequencing and variable mangling (for example, a multibyte variable can be changed by the interrupt, halfway through being accessed by the main code).

Variables shared between interrupt and non-interrupt code MUST be declared volatile (echo_end).

Thanks for your reply.
The problem I encountered when not using interrupts is that the ultrasonic sensor sometimes will return a pulse of a few thousand milliseconds long if the sound wave cannot be received properly. If I were to not use interrupts, it would stop other processes of my car for that period of time and I would lose control of it from my remote.
P.S. There are other parts of my program that I have excluded since they are irrelevant to this problem, thus I have accidentally deleted the void loop(), sorry for that.

Yom092090:
The problem I encountered when not using interrupts is that the ultrasonic sensor sometimes will return a pulse of a few thousand milliseconds long if the sound wave cannot be received properly.

pulseIn() is blocking indeed, if no pulse is received it times out after 1 second. You should never get longer than that.

Use the third parameter: the timeout. Set it to a sensible length (e.g. if you never expect to measure more than 1 meter, set it to the time it takes for sound to travel 2-3 meters).