Sonar HC-SR04 returns bizarre values

Hi,

I'm using 1 HC-SR04 sonar as a test. I'm pinning it 5 times (using an UNO), and recording those values to an SD card.

I've noticed often, some pings all have values, but other times, the pings return 0.00 in the mix. Sometimes several in a row.

In the example code for the sonar, it says that min. time between ping should be 29ms. I have tried 50 - 500ms, but that does not seem to make a difference.

Any ideas?

/*
  SD card datalogger

 The circuit:

*SONAR
 pin 2 - sonar / Trigger 
 pin 3 - sonar / Echo

*SD card attached to SPI bus
 pin 4 - SD card / CS
 pin 11 - MOSI
 pin 12 - MISO
 pin 13 - CLK

 */

#include <SPI.h>
#include <SD.h>
#include <NewPing.h>  // sonar library

const int chipSelect = 4;

int i = 0; // initialize loop counter
int a = 0; // void loop counter, it should run only once
int b = 0; // 1st element of array
int c = 0; // counter for printing array elements

// Sonar set up
#define TRIGGER_PIN  2  // Arduino trigger pin on sonar
#define ECHO_PIN     3  // Arduino echo pin on sonar
#define MAX_DISTANCE 200 /* Maximum distance we want to ping for (in centimeters). 
                            Maximum sensor distance is rated at 400-500cm.
                         */
// SONAR
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.

// STRING
  /*  Make a string to log data  */
String dataString = "";

// ARRAY
/*  Make an array to log data  */
int array_size = 5;
double dataArray[5] = {};  // set array to size of 5 elements

void setup() 
{
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial)
  {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  Serial.print("Initializing SD card...");

  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) 
  {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    return;
  }
  
  Serial.println("card initialized.");
}

void loop() 
{
  // run entire loop only once
  for (a; a<1; a++)
  {
    
// read and write sensor values for each conected pin per sensor
  // record 5 readings of the sensors, so that there are 5 string lines
for (i;i<5;i++)
{
// read sensor values
  
  // SONAR
  delay(50);    // Wait 50ms between pings (~ 20 pings/sec). 29ms should be min delay between pings
  
   // initially, these types were 'unsigned int', but seemed to be no difference
   int uS = sonar.ping(); // Send ping, get ping time in microseconds (uS)
   double distance = (uS / US_ROUNDTRIP_CM) / 2.54;  // Convert ping time to distance, 0 = outside set distance range
                                                    // units are converted from cm to inches
double sensor_value = distance;

// print to serial monitor
Serial.print("Distance: ");
Serial.print(distance);      // units are in inches
Serial.println("in");

// add sonar values to string
dataString += String(sensor_value);

    if (i < 4) 
        {
          dataString += ",";
        }
 

// add sonar values to array
 if (b<5)
  {
    dataArray[b] = sensor_value;
    b++;
  }
}       
 

// OPEN FILE
/* microSD card 
   Note that only one file can be open at a time,
     so you have to close this one before opening another.
     (But if you only have 1 card, no worries.)
*/

// CREATE FILE
  File dataFile = SD.open("datalog.txt", FILE_WRITE);
                       //(file name, function)
                         
// WRITE TO FILE
  // if the file is available, write to it:
  if (dataFile) 
  {

// CLOSE FILE    
    dataFile.println(dataString); //print to microSD card
    dataFile.close();
    
    // print string to serial monitor
    Serial.println("\nString printed to microSD card:");
    Serial.println(dataString);

       // print array to serial monitor
    Serial.println("\nArray printed to microSD card:");
    
    for (c; c < array_size; c++)
    {
      Serial.print(dataArray[c]); // print value at current element position

      // add a comma between elements, but not after last one
      if (c < array_size - 1)
      {
        Serial.print(","); 
      }
    }

      // test: print only 1 element of array to serial monitor
      Serial.println("\n");
      Serial.print("3rd element in array: ");
      Serial.println(dataArray[2]);
    
  }
  
  // if the file isn't open, pop up an error:
  else 
  {
    Serial.println("error opening datalog.txt");
  }
 }

}

All sensors occasionally return bad data. Your program needs to recognize and ignore obviously incorrect values.

There are various sorts of moving averages and filters that can be applied, but 0.0 is obviously easy to ignore.