Using the HC-SR04 sensor which cost me less than 5 €. I was going to buy the SFR05 for 15 € but I thought better for the price.
Using the code below, so you see, is not very accurate, ie, if I leave the HC-SR04 sensor activated and in a fixed location, such as the photo above, the fixed floor pointing at the ceiling. It analyzes each soda 1 second.
In the variation ranges from 2 inches, sometimes 4. If I had an earthquake understand the variation. I want to know why it vary?
No matter if the code, or just the HC-SR04 sensor is not very accurate as compared to other Ping))), SFR05, SFR08 and some more.
The code I've tried is this:
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
const int trigger=10;
const int echo=13;
float distance;
const String nivel_agua = "Nivel de agua:";
void setup(){
lcd.begin(16,2);
Serial.begin(9600);
pinMode(trigger,OUTPUT);
pinMode(echo,INPUT);
}
void loop(){
//Inicializamos el sensor
digitalWrite(trigger,LOW);
delayMicroseconds(5);
// Comenzamos las mediciones
// Enviamos una señal activando la salida trigger durante 10 microsegundos
digitalWrite(trigger,HIGH);
delayMicroseconds(10);
digitalWrite(trigger,LOW);
// Adquirimos los datos y convertimos la medida a metros
distance=pulseIn(echo,HIGH); // Medimos el ancho del pulso
// (Cuando la lectura del pin sea HIGH medira
// el tiempo que transcurre hasta que sea LOW
distance=distance*0.0001657;
// Enviamos los datos medidos a traves del puerto serie y al display LCD
Serial.println("Nivel de agua:");
Serial.print(distance);
Serial.println(" Metros.");
lcd.setCursor(0,1);
lcd.print(distance);
lcd.print(" Metros.");
lcd.setCursor(0,0);
lcd.print(nivel_agua);
delay(1000);
}
probably the formula distance = distance * 0.001657 is not right?
speed of sound is 330 meter/second in normal air. (in air above water it is higher due to the humidity - don't know how much) The pulse time is twice the distance (forth and back). distance = time/2 * 330/second. as time is in microseconds distance = time * 0.000165;
so adjust the formula to match in the order of magnitude. You should now read 1.52 meter while it is 1.38 meter
so we can add a correction factor
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
const int trigger=10;
const int echo=13;
float distance;
char nivel_agua[] = "Water level:";
void setup()
{
lcd.begin(16,2);
lcd.setCursor(0,0);
lcd.print(nivel_agua);
Serial.begin(115200); // use fastest serial possible
pinMode(trigger,OUTPUT);
pinMode(echo,INPUT);
}
void loop()
{
digitalWrite(trigger,LOW);
delayMicroseconds(5);
digitalWrite(trigger,HIGH);
delayMicroseconds(10);
digitalWrite(trigger,LOW);
// take average of 10 measurements
unsigned long time = 0.0;
for (int i=0; i<10; i++)
{
time += pulseIn(echo, HIGH);
delay(10);
}
distance = time * 0.0001657;
// adjust for accuracy
distance = 1.38/1.52 * distance; // correction factor = (wanted/measured)
Serial.println(nivel_agua);
Serial.print(distance, 2);
Serial.println(" Meters.");
lcd.setCursor(0, 1);
lcd.print(distance, 2);
lcd.print(" Meters. ");
}
Did some investigation why there was this factor 10 in the code and concluded there is a bug in the code I posted. The sensor needs a handshake to get started and that is not used in the loop (of 10 readings). That caused to effectively make only one reading and resulted in the factor 10 error. That is why you go a factor 10 too much.
put the measurement in a separate function.
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
const int trigger=10;
const int echo=13;
float distance;
char nivel_agua[] = "Water level:";
void setup()
{
lcd.begin(16,2);
lcd.setCursor(0,0);
lcd.print(nivel_agua);
Serial.begin(115200); // use fastest serial possible
pinMode(trigger,OUTPUT);
pinMode(echo,INPUT);
}
void loop()
{
// MEASUREMENT
float distance = getDistance();
// DISPLAY
Serial.println(nivel_agua);
Serial.print( millis() ); // add a time stamp
Serial.print('\t');
Serial.print(distance, 2);
Serial.println(" Meters.");
lcd.setCursor(0, 1);
lcd.print(distance, 2);
lcd.print(" Meters. ");
}
float getDistance()
{
unsigned long time = 0;
for (int i=0; i<10; i++)
{
digitalWrite(trigger,LOW);
delayMicroseconds(5);
digitalWrite(trigger,HIGH);
delayMicroseconds(10);
digitalWrite(trigger,LOW);
time += pulseIn(echo, HIGH);
}
return time * 0.00001657 * 1.38/1.52; // correction factor = (wanted/measured)
}
can you give it a try (maybe adjust the 0.00001657 factor)
readings should be more stable with the above code
I am trying to use the pulsein function with the HC-SR04 ultrasonic sensor and my problem is to distinguish when the sensor is not connected and when its out of range. Using pulsein fucntion in both cases it returns a zero, so my question is how to i return a different value not zero when the sensor is not connected and zero when the sensor is out of range or vice versa.