HC-SR04 Better Echo



  • Hi, why this code never give MAX in the serial monitor?

    /* Ultrasonic distance sensor example - Better Version
    
       Paul Carpenter, PC Services
       26-Jan-2017
    
       Update 4-Feb-2017 PC make variables more obvious
       Update 13-May-2017 PC add half bit rounding to distance calculation
    
       Uses HC-SR04 four pin ultrasonic sensor to continuously output distances
       found when in range (every second).
    
       Results WHEN valid output onto serial port at 115,200 baud
    
       Both LEDs ON when program starts and any other time for no start of echo
       received (probably bad wiring or faulty unit) on start up also serial port
       error string
        
       Lights RED Led when No Reading received or out of range
       Lights Yellow LED when too close (less than 5 cm)
       LEDs are connected via 330R or similar resistor other end of LED to GND
    
       Works on principle sound travels at 343.2 m/s in dry STILL air at 20 deg C
    
       So time per cm is 29.137529 micro seconds /cm
    
       For round trip (there and back)  58.275058 micro seconds /cm
    
       In order to reduce code size and execution time values are kept as integers
       and factor of 58 to calculate distances
    */
    
    /* Pin definitions */
    #define echopin     21
    #define trigpin     22
    //#define redled      6
    //#define yellowled   7
    
    /* time between readings in ms
       On Arduino Mega readings belown 20ms interval could 
       have residual echo issues */
    #define INTERVAL    30
    
    /* Scale factor round trip micro seconds per cm */
    #define SCALE_CM    58
    #define SCALE_CM_ROUND  (SCALE_CM/2)
    
    /* Timeout for distance sensing rather than 1 second in us */
    #define MAX_ECHO    300000
    #define MIN_ECHO    (3 * SCALE_CM)
    
    /* Timeout for start of ECHO pulse being received in us */
    #define MAX_START_ECHO  1000
    
    /* Limits for application ranges in cm */
    #define MIN_RANGE   4 //era 4
    #define MAX_RANGE   500 // era 500
    
    #define MAX_ERROR 10
    
    /* calculated distance in centimetres */
    unsigned long distance;
    unsigned int echotime;
    unsigned long next_time, new_time;
    
    
    /* Distance sensor function to get echo time
       Note most ultrasonic distance sensors are only usable beyond 3 cm
       So usable range is 3 * SCALE_CM to MAX_ECHO, therefore anything below
       3 * SCALE_CM should be treated as error
    
       Returns echo time in microseconds
            Maximum MAX_ECHO
            Minimum 3 * SCALE_CM    (minimum usable)
       error codes
            Error   2   Echo HIGH before start
            Error   1   Echo did not start
            Error   0   NO ECHO (Timeout)
    
       Timeout for measurements set by MAX_ECHO
    */
    unsigned long GetEchoTime( )
    {
    unsigned long start_time;
    unsigned long end_time;
    
    /* check Echo if high return error */
    if( digitalRead( echopin ) )
      return( 2 );
      
    /* note start time */
    start_time = micros( );
    
    /* send the trigger pulse */
    digitalWrite( trigpin, HIGH );
    delayMicroseconds( 10 );
    digitalWrite( trigpin, LOW );
    
    /* Set timeout for start of echo pulse */
    end_time = start_time + MAX_START_ECHO;
    
    /* check ECHO pin goes high within MAX_START_ECHO
       if not return error of 1  */
    while( !digitalRead( echopin ) )
       if( micros( ) > end_time )
         return( 1 );
    
    /* Check for Length of echo occurred or timeout */
    start_time = micros( );
    end_time = start_time + MAX_ECHO;
    while( digitalRead( echopin ) )
       if( micros( ) > end_time )
         break;
    end_time = micros( );
         
    /* Return time or timeout   */
    return( ( start_time < end_time ) ? end_time - start_time: 0 );
    }
    
    
    void setup( )
    {
    /* set time from reset */
    next_time = INTERVAL;
    
    Serial.begin( 115200 );
    
    /* Configure pins and ensure trigger is OFF */
    pinMode( trigpin, OUTPUT );
    digitalWrite( trigpin, LOW );
    pinMode( echopin, INPUT );
    
    /* Configure LED drive and both LEDs On at start up */
    //pinMode( redled, OUTPUT );
    //pinMode( yellowled, OUTPUT );
    //digitalWrite( redled, HIGH );
    //digitalWrite( yellowled, HIGH );
    
    /* Send signon message */
    Serial.println( F( "PC Services - Better Range test" ) );
    
    /* Do test reading to check if unit connected */
    distance = GetEchoTime( );
    if( distance > 0 && distance <= 10 )
      {
      Serial.println( F( "No unit found - Error = " ) );
      Serial.println( distance );
      }
    }
    
    
    void loop( )
    {
    new_time = millis( );           /* check if to run this time */
    if( new_time >= next_time )
      {
      /* Turn LEDs Off */
    //  digitalWrite( redled, LOW );
     // digitalWrite( yellowled, LOW );
    
      /* Calculate distance */
      echotime = GetEchoTime( );
      /* only scale valid readings 0 is timeout or 1 is no echo
         realistically minimum accurate or physical range is 3cm */
      if( echotime > MAX_ERROR )
        {
        // Valid number covert to cm
        distance = echotime;
        distance += SCALE_CM_ROUND;  // add in half bit rounding  
        distance /= SCALE_CM;
        }
    
      /* catch errors first */
      if( echotime <= MAX_ERROR || distance > MAX_RANGE )
        {
      //  digitalWrite( redled, HIGH );               // Range error too large
        if( echotime > 0 && echotime <= MAX_ERROR )
       //   digitalWrite( yellowled, HIGH ); // Light 2nd LED error
       Serial.println("MAX");
        }
      else
        if( distance < MIN_RANGE )
      //    digitalWrite( yellowled, HIGH ); // Range too close
         Serial.println("MIN");
        else
          Serial.println( int( distance ) );        // In range output distance
    
      next_time = new_time + INTERVAL;       // save next time to run
      }
    }
    

    which parameters I need to change to go far? (more than 5 mt)



  • First, your code is badly indented (remember to press ^T in the Arduino IDE to format it properly) and thus unreadable. After proper formatting, here is what loop() looks like:

    void loop() {
      new_time = millis(); /* check if to run this time */
      if (new_time >= next_time) {
        /* Calculate distance */
        echotime = GetEchoTime();
        /* only scale valid readings 0 is timeout or 1 is no echo
           realistically minimum accurate or physical range is 3cm */
        if (echotime > MAX_ERROR) {
          // Valid number convert to cm
          distance = echotime;
          distance += SCALE_CM_ROUND; // add in half bit rounding
          distance /= SCALE_CM;
        }
        /* catch errors first */
        if (echotime <= MAX_ERROR || distance > MAX_RANGE) {
          if (echotime > 0 && echotime <= MAX_ERROR)
            Serial.println("MAX");
        } else if (distance < MIN_RANGE)
          Serial.println("MIN");
        else
          Serial.println(int(distance)); // In range output distance
        next_time = new_time + INTERVAL; // save next time to run
      }
    }
    

    Now the simplest answer as to why "MAX" is never displayed is because the conditions are not reached. However, I'm not sure that the logic in your ifs is correct. You have an if/else if/else main test, and inside the if another if, and that doesn't make much sense. Work on that logic first.