Easy ultrasonic 4-pin sensor monitoring (hc-sr04)

hello Instructables,
I have had some trouble with my cheap ultrasonic sensor (hc-sr04) and today I found a really easy solution.
It is a really simple edit of the normal 3pin code.

The new code(4pin):

void setup() {
pinMode (2,OUTPUT);//attach pin 2 to vcc
pinMode (5,OUTPUT);//attach pin 5 to GND
// initialize serial communication:
Serial.begin(9600);
}

void loop()
{
digitalWrite(2, HIGH);
// establish variables for duration of the ping,
// and the distance result in inches and centimeters:
long duration, inches, cm;

// The PING))) is triggered by a HIGH pulse of 2 or more microseconds.
// Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
pinMode(3, OUTPUT);// attach pin 3 to Trig
digitalWrite(3, LOW);
delayMicroseconds(2);
digitalWrite(3, HIGH);
delayMicroseconds(5);
digitalWrite(3, LOW);

// The same pin is used to read the signal from the PING))): a HIGH
// pulse whose duration is the time (in microseconds) from the sending
// of the ping to the reception of its echo off of an object.
pinMode (4, INPUT);//attach pin 4 to Echo
duration = pulseIn(4, HIGH);

// convert the time into a distance
inches = microsecondsToInches(duration);
cm = microsecondsToCentimeters(duration);

Serial.print(inches);
Serial.print("in, ");
Serial.print(cm);
Serial.print("cm");
Serial.println();

delay(100);
}

long microsecondsToInches(long microseconds)
{
// According to Parallax's datasheet for the PING))), there are
// 73.746 microseconds per inch (i.e. sound travels at 1130 feet per
// second).  This gives the distance travelled by the ping, outbound
// and return, so we divide by 2 to get the distance of the obstacle.
// See: http://www.parallax.com/dl/docs/prod/acc/28015-PING-v1.3.pdf
return microseconds / 74 / 2;
}

long microsecondsToCentimeters(long microseconds)
{
// The speed of sound is 340 m/s or 29 microseconds per centimeter.
// The ping travels out and back, so to find the distance of the
// object we take half of the distance travelled.
return microseconds / 29 / 2;
}
Remove these ads by Signing Up
AndréanneL3 months ago

Hi! I was wondering if the 3 pin was better than the four pin or is there no big difference between them?

2 months ago

There is not too much of a difference. Just the fact that it saves one pin on the arduino and that you can use it if giving your robot a wide angle sight or about 4 or more sensors.

Giedow (author)  robobot31121 month ago

Also this was by far the cheapest sensor I could get :)

1 month ago

ianyeo19942 months ago

How does one perform this process in reverse? Using a 4-pin sensor code and converting it to 3-pin?

Giedow (author)  ianyeo19941 month ago

"Using a 4-pin sensor code and converting it to 3-pin?"

I did exactly that! I started with the 4 pin code:http://arduino.cc/en/Tutorial/Ping?from=Tutorial.U...

AzkaraWolfe2 months ago

how would i display the serial on an lcd?

Giedow (author)  AzkaraWolfe2 months ago

Try combining code. I mostly used to take code from arduino.cc and make little changes or combine multiple examples. If you combine this code and a simple sensor-to-lcd code you should be able to get it to work. Good luck!

2 months ago

#include <LiquidCrystal.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
int backLight = 13; // pin 13 will control the backlight

void setup()
{
pinMode(backLight, OUTPUT);
digitalWrite(backLight, HIGH);
pinMode (2,OUTPUT);//attach pin 2 to vcc
pinMode (5,OUTPUT);//attach pin 5 to GND
lcd.begin(16, 2);
// initialize the serial communications:
Serial.begin(9600);
}
void loop()
{
digitalWrite(2, HIGH);
// establish variables for duration of the ping,
// and the distance result in inches and centimeters:
long duration, inches, cm;

// The PING))) is triggered by a HIGH pulse of 2 or more microseconds.
// Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
pinMode(3, OUTPUT);// attach pin 3 to Trig
digitalWrite(3, LOW);
delayMicroseconds(2);
digitalWrite(3, HIGH);
delayMicroseconds(5);
digitalWrite(3, LOW);

// The same pin is used to read the signal from the PING))): a HIGH
// pulse whose duration is the time (in microseconds) from the sending
// of the ping to the reception of its echo off of an object.
pinMode (4, INPUT);//attach pin 4 to Echo
duration = pulseIn(4, HIGH);

// convert the time into a distance
inches = microsecondsToInches(duration);
cm = microsecondsToCentimeters(duration);

Serial.print(inches);
Serial.print("in, ");
Serial.print(cm);
Serial.print("cm");
Serial.println();

delay(150);
}

long microsecondsToInches(long microseconds)
{
// According to Parallax's datasheet for the PING))), there are
// 73.746 microseconds per inch (i.e. sound travels at 1130 feet per
// second). This gives the distance travelled by the ping, outbound
// and return, so we divide by 2 to get the distance of the obstacle.
// See: http://www.parallax.com/dl/docs/prod/acc/28015-PI...
return microseconds / 74 / 2;
}

long microsecondsToCentimeters(long microseconds)
{
// The speed of sound is 340 m/s or 29 microseconds per centimeter.
// The ping travels out and back, so to find the distance of the
// object we take half of the distance travelled.
return microseconds / 29 / 2;
// when characters arrive over the serial port...
if (Serial.available()) {
// wait a bit for the entire message to arrive
delay(100);
// clear the screen
lcd.clear();
// read all the available characters
while (Serial.available() > 0) {
// display each character to the LCD
}
}
}

That's my current code, any reccomendations?

tolstoyan1 year ago
can i just short the echo and trig pin in the ultra sonic sensor so that i dont have to changed anything in the code?
3 months ago

someone did:

http://www.instructables.com/id/Hack-an-HC-SR04-to-a-3-pin-sensor/

Giedow (author)  tolstoyan1 year ago
Probably not, wouldn't try it
8 months ago

ahhh but you are wrong my freind tolstoyan is correct that is how i do myne and yes you should hear it i have no clue why but you can anyway you can short them Becouse! if you short them they still have enouph time to jump from the arduino then both ways then into them both (The Echo Pin Practicly Ignores The Input Signal) Then The Trig Pin TAkes That Power Gladly And Actavates The Sensor While Still Dischargeing Intime To Have The Sensor Send Power Back To The Arduino And It Dose This The Whole Time You Want It To Contnue Runing.

dogbear5 months ago

Hi Giedow.

Thanks for the code. I wasn't sure how to modify the Arduino sample code from 3 pins to 4 pins but, as you have shown, it is quite easy. Also, it is actually easier to understand having the trigger and the echo as separate pins, rather than having to switch a pin from input to output and back again.

This configuration also lends itself to using an interrupt, as clabelle has shown in her example. I would like, if I may, to clarify a few things in clabelle's code which may not be very clear to those who aren't experienced in programming. The following is a modified version of clabelle's code, with some help from the Arduino wiki about interrupts here: http://arduino.cc/en/Reference/attachInterrupt.

// our sensor pin configuration

const int sensorTriggerPin = 8; // I chose this arbitrarily, you can choose any digitial I/O pin

const int sensorEchoPin = 2; // for the Arduino Uno, I can use pin 2 or pin 3 (see wiki page about available interrupt pins)

/*

* Four-pin sensor:

* Trigger pin should be attached to Digital pin 2 (for interrupt pin 0 )

* Echo pin should be attached to Digital pin 8

*/

unsigned long lastPing = 0; // in milliseconds (the time since we last did a ping)

unsigned long pingInterval = 150; // in milliseconds (the time we want

unsigned long echoStartTimer = 0; // in microseconds

volatile long pingDistance = 0; // the distance returned by the sensor. We label this volatile because our interrupt function will modify its value (see wiki)

// forward declaration of our interrupt function to be called

void echoInterruptCallback();

void setup()

{

Serial.begin(9600); // for debug output

attachInterrupt( 0, echoInterruptCallback, FALLING ); // we set interrupt pin 0 (pin 2 on arduino uno) to call our function "echoInterruptCallback" when the value is FALLING (changes from HIGH to LOW... see wiki. Pin 2 falls after the sensor finishes doing a sonar scan)

// now we set our input and output pins

pinMode( sensorTriggerPin, OUTPUT );

pinMode( sensorEchoPin, INPUT );

// we start by setting the lastPing time to the current time

lastPing = millis();

}

void loop()

{

// time to do a ping? (we want to ping every pingInterval milliseconds)

unsigned long now = millis();

if( now - lastPing > pingInterval )

{

// reset our lastPing time

lastPing = now;

// reset our found distance

pingDistance = 0;

// do the ping trigger

digitalWrite(sensorTriggerPin, LOW );

delayMicroseconds(2);

digitalWrite(sensorTriggerPin, HIGH );

delayMicroseconds(5);

digitalWrite(sensorTriggerPin, LOW );

// set the echo timer (use micros instead of millis)

echoStartTimer = micros();

// ...now the interrupt will do its work when the echo pin goes from HIGH to LOW...

}

// the true benefit of an interrupt happens here...

// we can continue processing something else here (rotating servos, making other calculations, etc)

// while we wait for the interrupt to get called.

if( pingDistance < 30 )

{

Serial.print( "Something is close!" );

Serial.println();

}

}

// this is the function that is called by the interrupt

void echoInterruptCallback()

{

unsigned long duration = micros() - echoStartTimer;

pingDistance = duration / 29 / 2; // mind you this distance calculation is not very accurate... but you can play around with the calculation to get it to a more acceptable reading.

// for debugging

Serial.print( pingDistance );

Serial.print( " cm" );

Serial.println();

}

clabelle6 months ago

I would do it this way, cause pulseIn() hang the system for a certain time and interrupt does not.

Code:

#define broche_Trig 12
#define broche_Echo 3
#define broche_Piezo 8

volatile unsigned long last_detection = 0;
unsigned long last_detection2 = 0;
const int Ping_interval = 150;

const double k_Mach = 29.4117647;

int duration;
double distance;

void setup() {

attachInterrupt(1, got_echo, FALLING);

pinMode(broche_Trig, OUTPUT);
pinMode(broche_Echo, INPUT);

Serial.begin (115200);

}

void loop() {

if(millis() - last_detection >= Ping_interval) {

digitalWrite(broche_Trig, HIGH);
delayMicroseconds(5);
digitalWrite(broche_Trig, LOW);
last_detection = millis();
last_detection2 = micros();

}

}

void got_echo(){

duration = micros() - last_detection2 ;
distance = (0.5  *(duration / k_Mach)) - 8  ; // - 8 ???
Serial.println((String)distance + F(" cm"));

}

6 months ago

ahah I got this code from my BF Frederic Plante. ;)

viper558 months ago

whats supposed to happen?

Dietrick K.1 year ago
it works but i can here the ping is that normal? also i am not getting a distance input to the computer so it isn't sending back a read is it something i am doing wrong?
Giedow (author)  Dietrick K.1 year ago
I don't think you should be able to hear it, because it is utrasonic. Have you checked all the connections, software inputs, serial ports, etc.
I don't recall having these kinds problems, so I am not sure, sorry.
chanakyapm1 year ago
Shorting the echo and trig pin may not work! Read more about it here http://www.digibay.in/hc-sr04-ultrasonic-proximity-sensor
Is there any way to convert the 4 pin HCSR04 to a 3 pin? I want to connect 5 sensors to an RJ45, and it would be fine with the 3 pin Parallax))) sensor since there are 8 inputs, but I don't have that unfortunately. I need basically need the HCSR04 to be 3 pins before I connect it to the board, is it possible?
If u use a breadboard you can just hook the 5v input and the ground to the standard ground and 5v output on the board. That way pin 2 and 5 are free to use.
You just have to delete these lines:
- pinMode (2,OUTPUT);//attach pin 2 to vcc
- pinMode (5,OUTPUT);//attach pin 5 to GND
-digitalWrite(2, HIGH);
amandaghassaei2 years ago
can you explain a little bit more about what you changed and why? thanks!
Giedow (author)  amandaghassaei2 years ago
Sure,
the only thing I had to change were:
-const int pingPin = 7
This was excess material, because pin7 doesn't function as output and input
anymore (I changed those in 3 and 4 so I could just plug the sensor in the
arduino)
-pinMode(3, OUTPUT)
pin 3 became the output instead of pin 7(pingPin)
So digitalWrite under "pinMode(3, OUTPUT)" was changed into 3 aswell
-pinMode (4, INPUT)
Here I changed pingPin into pin 4
And in the line underneath I did the same thing

That is all. I did it because I saw that pingPin(pin 7) functioned as both INPUT and OUTPUT and I thought why not make it two different pins, because I have two different pins for InPUT and OUTPUT.