3 HC-SR04 With LED

Hi guys,
I am new to the arduino family and have started to go through the basics. I have adjusted this code multiple ways and think I am missing something easy. I want the code to light up an LED when it is with n a certain distance. I have it where it reads 2 lights off of one sensor, even though I thought (from how much I know) it should be off of individual sensors going to the lights. Any ideas would help. I do have 2 extra PING sensors tied to this proto board also that I am not using. Again I am new at this and not a programmer, just having fun with

#define LeftPingSens 7
#define RightPingSens 2
#define RearPingSens 4
#define distancePingLeft 6
#define distancePingRight 3
#define distancePingRear 5
#define led1 8
#define led2 11
#define led3 1

void setup(){
Serial.begin(9600);
pinMode(distancePingLeft, INPUT);
pinMode(distancePingRight, INPUT);
pinMode(distancePingRear, INPUT);
pinMode(LeftPingSens, OUTPUT);
pinMode(RightPingSens, OUTPUT);
pinMode(RearPingSens, OUTPUT);
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);

}
void loop() {
//Rear Ping Sensor
long duration, distance;
digitalWrite(RearPingSens, LOW);
delayMicroseconds(2);
digitalWrite(RearPingSens, HIGH);
delayMicroseconds(10);
digitalWrite(RearPingSens, LOW);
duration = pulseIn(distancePingRear, HIGH);
distance = (duration/2) / 29.1;

if (distance <= 24) {
digitalWrite(led1, HIGH);
}
if (distance >= 24){
digitalWrite(led1, LOW);

long duration, distance;
digitalWrite(RightPingSens, LOW);
delayMicroseconds(4);
digitalWrite(RightPingSens, HIGH);
delayMicroseconds(12);
digitalWrite(RightPingSens, LOW);
duration = pulseIn(distancePingRight, HIGH);
distance = (duration/2) / 29.1;
}

if (distance <= 24) {
digitalWrite(led3, HIGH);

}
if (distance >= 24){
digitalWrite(led3, LOW);
long duration, distance;
digitalWrite(LeftPingSens, LOW);
delayMicroseconds(6);
digitalWrite(LeftPingSens, HIGH);
delayMicroseconds(16);
digitalWrite(LeftPingSens, LOW);
duration = pulseIn(distancePingLeft, HIGH);
distance = (duration/2) / 29.1;
}

if (distance <= 24) {
digitalWrite(led2, HIGH);

}
if (distance >= 24){
digitalWrite(led2, LOW);

}

{
Serial.println(“Out of range”);
Serial.print(distance);
Serial.println(" in");
Serial.print(distance);(" distancePingRear");
Serial.print(" distancePingRight");
Serial.print(" distancePingLeft");
delay(1000);
}

}

Try using the auto format tool in the IDE (ctrl-t) to see if it helps you visualize your program flow.

And please, please use code tags when posting code.

Some simple arrays and a single range function would simplify and shorten your code.

jcloonan: I have adjusted this code multiple ways and think I am missing something easy.

What happens if three people are shouting at you at nearly the same time? Even if your sensors send ultrasonic sound, it still is sound.

You seem to forget about the speed of sound and that you cannot operate three sensors at nearly the same time waiting for sound echos.

You'd have to wait a bit of time after triggering one sensor, so that all echos are gone, before triggering the next sensor. It is not enough to wait for the first echo!

So wrong logic: - trigger first sensor - wait for first echo - trigger second sensor - wait for next echo - trigger third sensor - wait for next echo - wait 1000 ms and restart loop()

Better programming logic: - trigger first sensor - wait for first echo - wait 333 ms - trigger second sensor - wait for next echo - wait 333 ms - trigger third sensor - wait for next echo - wait 333 ms and restart loop()

You'd have to wait until ALL ECHOS of the previous sensor have vanished, before triggering the next sensor.

jurs, that makes a lot of sense. I am new to this and that is spoken well, I am still modifying I appreciate any help

While you are at it, having an LED on the hardware serial pin, while trying to use that pin for Serial, is an exercise in frustration (for you, the Arduino doesn't mind).

jcloonan:
jurs, that makes a lot of sense. I am new to this and that is spoken well, I am still modifying I appreciate any help

I have completely rewritten your code.

This example will handle three ultrasonic sensors with structured programming and does different tasks in time slices of different duration.

All the pins used are put to data structures, three sensors are represented by an array of struct with three elements.

A single sensor is handled by a function named ‘readSensor()’. The function expects to be given the ‘index’ of the sensor as an parameter (0, 1 or 2) and then will do:

  • trigger the triggerPin
  • wait for response on the echoPin
  • calculate distance and save the value for further usage
  • set an led on or off accordingly to the actual distance

Have a look:

struct sensor_t {byte triggerPin; byte echoPin; byte ledPin; int distance;};

sensor_t sensors[]={
  {7, 6, 11},  // index 0: trigger, echo and led pin 'left' sensor
  {2, 3, 13},  // index 1: trigger, echo and led pin 'right' sensor
  {4, 5, 8},   // index 2: trigger, echo and led pin 'rear' sensor
};

#define NUMSENSORS sizeof(sensors)/sizeof(sensors[0])
#define MAXRANGE_ECHOTIME 20000 // microseconds

void readSensor(byte index)
{
  digitalWrite(sensors[index].triggerPin, LOW); 
  delayMicroseconds(2);
  digitalWrite(sensors[index].triggerPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(sensors[index].triggerPin, LOW); 
  long duration = pulseIn(sensors[index].echoPin, HIGH, MAXRANGE_ECHOTIME);
  if (duration==0) sensors[index].distance=-1;
  else sensors[index].distance = (duration/2) / 29.1; // // time to centimeters
  if (sensors[index].distance>=0 && sensors[index].distance <= 24)
    digitalWrite(sensors[index].ledPin, HIGH); 
  else   
    digitalWrite(sensors[index].ledPin, LOW); 
}

void setup(){
  Serial.begin(9600);
  for (int i=0;i<NUMSENSORS;i++)
  {
    pinMode(sensors[i].triggerPin,OUTPUT);
    pinMode(sensors[i].echoPin,INPUT);
    pinMode(sensors[i].ledPin,OUTPUT);
  }
}

byte currentSensor=0;
unsigned long lastSensorTime, lastOutputTime;
#define SENSORINTERVAL 100 // milliseconds

void loop() {
  // first task: measure sensors one after another in time slices of SENSORINTERVAL
  if (millis()-lastSensorTime>=SENSORINTERVAL)
  {
    lastSensorTime+=SENSORINTERVAL;
    readSensor(currentSensor);
    currentSensor++;
    if (currentSensor>=NUMSENSORS) currentSensor=0;
  }
  // second task: show sensor readings each second on serial monitor
  if (millis()-lastOutputTime>=1000)
  {
    lastOutputTime+=1000;
    for (int i=0;i<NUMSENSORS;i++)
    {
      Serial.print(sensors[i].distance);
      Serial.print(':');
      if (digitalRead(sensors[i].ledPin)) Serial.print("ON");
      else Serial.print("OFF");
      Serial.print('\t');
    }
    Serial.println();
  }
  // insert other tasks here
}

Currently there are two tasks running at the same time:

One task is reading the sensors in a round robin scheduling: Every 100 milliseconds one sensor is triggered and the distance is read and the associated led is switched on or off.

The second task is sending the distances and led states to the serial monitor once per second.

BTW: PaulS is right, you better NOT use a pin that is already used for Serial for another purpose at the same time. So stay away from Pin-0 (RX) and Pin-1 (TX) on Arduino boards which use these pins for Serial communication!

If you should become short of digital pins, you can easily use the analog pins as if they were digital pins, such like using three analog pins for trigger, echo and led of the ‘left’ sensor:

sensor_t sensors[]={
  {A0, A1, A2},  // index 0: trigger, echo and led pin 'left' sensor
  {2, 3, 13},    // index 1: trigger, echo and led pin 'right' sensor
  {4, 5, 8},     // index 2: trigger, echo and led pin 'rear' sensor
};

I really appreciate the help on this. This is a great forum, especially since I am just starting out. the help I have received in one post and such detail explanation is great. I was starting to rewrite the code with the help of a book, I am going to incorporate all of this also in this and future experiments Thanks again Jurs! I did notice the headache involved witht he LED that wouldn't turn off that was in the serial D1 also. THanks again

jcloonan: I really appreciate the help on this. This is a great forum, especially since I am just starting out. the help I have received in one post and such detail explanation is great. I was starting to rewrite the code with the help of a book, I am going to incorporate all of this also in this and future experiments Thanks again Jurs! I did notice the headache involved witht he LED that wouldn't turn off that was in the serial D1 also. THanks again

I don't know if you already have fully understood what's going on in my source code, but perhaps you can try and learn one after the other. I'd just like to mention three aspects:

  1. Using 'struct' to define your own data types In C/C++ you are not bound to the simple data types like char, int, byte, long and arrays of them, but you always can define your own complex data types using the 'struct' keyword to define the contents of your new data type. Then in your program you can easily create variables or even arrays that consists of such complex structures.

  2. Seperating data and code If you seperate data from code you can write programs that can be easily maintained. If you didn't realize: The code I provided is not bound to three sensors. If you like to have 4 or 5 ultrasonic sensors, you just would add the required data to the 'sensors[]' array. And you need to change NOTHING in the code to make the program work with 4 or 5 or even more sensors.

  3. Avoiding 'delay()' to make "several things run at the same time" Other than your initial code that is blocking the program execution with "delay(1000)" each time the loop function ends, my code never uses 'delay'! If things are needed to happen delayed, the sketch creates 'time slices' for each task and each task runs once after the time slice is finished. That way you can easily add other tasks than run from time to time, without blocking the program execution for the existing tasks.

Hello All,

Iam busy with a project te let to sensors work together and showing a few different messages on a LCD screen.

What I want to do is if there is something in the range of 50MM of the left sensor I need to see Message 1. Of its further then 50MM it need to Message 2. If there is something in the range of 50MM of the right sensor it needs to show Message 3 and further then 50MM Message 4. When something is in front of Sensor1 it needs to overwrite everything from Sensor 2

This is the code how I have it right now:

#include <LiquidCrystal.h>

LiquidCrystal lcd(8,9,4,5,6,7); // LCD Keypad Shield

int readPingSensor(byte triggerPin, byte echoPin)
{
 #define MAXRANGE_ECHOTIME 20000
 pinMode(triggerPin,OUTPUT);
 pinMode(echoPin,INPUT);
 digitalWrite(triggerPin, LOW); 
 delayMicroseconds(2);
 digitalWrite(triggerPin, HIGH);
 delayMicroseconds(10);
 digitalWrite(triggerPin, LOW); 
 long duration = pulseIn(echoPin, HIGH, MAXRANGE_ECHOTIME);
 if (duration==0) return -1;
 else return (duration/2) / 2.91;
}


void setup() {
 lcd.begin(16, 2);
}

byte currentSensor=0;
unsigned long lastSensorTime, lastOutputTime;
#define SENSORINTERVAL 100 

void loop() 
{
 if (millis()-lastSensorTime>=SENSORINTERVAL) // trigger sensor every 100 milliseconds
 {
   lastSensorTime+=SENSORINTERVAL;
   int distance= readPingSensor(A4,A5); // call function with trigger- and echo-pin as parameters
   char buf[17];
   lcd.setCursor(0, 0);
   
     if (distance<50)
     strcpy(buf,"Message 1");
   else  if (distance<100) // distance less than 50 mm
     strcpy(buf,"Message 2");
   else
     snprintf(buf,sizeof(buf),"D= %d mm",distance);
   lcd.print(buf); // print message
   for (int i=0;i<16-strlen(buf);i++) lcd.print(' '); // clear to end of line*/
 }
 
 if (millis()-lastOutputTime>=1000) // trigger sensor every 100 milliseconds
 {
   lastOutputTime+=1000;
   int distance= readPingSensor(A2,A3); // call function with trigger- and echo-pin as parameters
   char buf[17];
   lcd.setCursor(0, 0);
  
     if (distance<50)
     strcpy(buf,"Message 3");
   else  if (distance<100) // distance less than 50 mm
     strcpy(buf,"Message 4");
   else
     snprintf(buf,sizeof(buf),"D= %d mm",distance);
   lcd.print(buf); // print message
   for (int i=0;i<16-strlen(buf);i++) lcd.print(' '); // clear to end of line*/
 }
 
 
 
 
}

The problem now is that everything in sensor 1 (Message 1 and 2) is showing good but if I change it to the otherside it keeps flickkering.

I hope that someone knows a solution! Thanks in advance!

raen: The problem now is that everything in sensor 1 (Message 1 and 2) is showing good but if I change it to the otherside it keeps flickkering.

The problem is now, that you are displaying everything at the same position of the LCD.

If you have one LCD with two lines of 16 characters each, you'd at first have to make up your mind: - which messages and - which data - when and - where to print on the display

If you display one message on top of other messages, while some messages stay 100 ms and other messages stay 1000 ms, you will of course see some flickering display showing different messages for different duration at the same position of the display.

First this, then that. You cannot make three sensors displaying different messages at the same place of the display at the same time.

If you don't know what you want, you never will be able to get exactly that on your display. An Arduino is no mind-reader. You'd have to tell the board EXACTLY what to do by providing the appropriate code.

And before you can write the appropriate code, you first should be able to explain what you want in simple words.

Iam searching for the right way to explain it. Is it possible to get back in "stock display" if the which is always showing when there is something in front of the twe sensors. And when you get rid of the stuff before Sensor 1 it will show text 1 and if your get rid of the stuff before sensor 2 it will show text 2. I can get two lines on LCD screen but how do you poisition it?

raen: I can get two lines on LCD screen but how do you poisition it?

lcd.setCursor()

If you want to create some kind of "priority message display", you'd have to define the priority of messages and which message has higher priority as others, if it happens that different messages are to be displayed at the same time while there is not enough room to show all messages at the same time.

Or you'd have to deal with horizontal scrolling: With horizontal text scrolling you'd be able to show texts longer than the line length. Not at once, but with scrolling.

Or, which is simpler to create: A switching display which shows one message for one second, then another message for another second. And then starts over.

Jurs, you have been a big help so far, but I still have a few questions if you don’t mind…

The code is much simpler and easy to read compared to where I started.

What I am having trouble with is when I go in front of the sensors it reads good, When I go in front of sensor 2 it sometimes reads on the wrong pin OUTPUT or doesn’t read at all. Do you think it has to do with timing of the sensors and going to fast? I have changed the pins and tried to get it so the left lights up LED 1, right lights up LED 2, and Rear lights up LED 3. I am trying to get it so they always light up the same one. I am making a directional detection device. Any ideas

When I go in front of sensor 2 it sometimes reads on the wrong pin OUTPUT

Can we have some clarification on what that means, please?

The serial output is

206:OFF -1:OFF 104:OFF 208:OFF -1:OFF 106:OFF 206:OFF -1:OFF 106:OFF 208:OFF -1:OFF 108:OFF 207:OFF -1:OFF 106:OFF 207:OFF -1:OFF 107:OFF 208:OFF -1:OFF 110:OFF 206:OFF -1:OFF 112:OFF

When I go in front of PING Sensor 1 Column 1 goes to "ON" When I go in front of PING Sensor 2 Column 2 doesn't change When I go In front of PING Sensor 3 Column 3 goes to "ON"

But sometimes if I move around the sensors to fast they switch the wrong output "ON" Does that help?

jcloonan: When I go in front of PING Sensor 2 Column 2 doesn't change

If the serial output for a sensor is "-1:OFF", then the sensor is not sensing an echo. No echo after triggering.

The meaning is either: - measuring distance is out of range - using incorrect software - using faulty hardware

Did you change something to the code I posted in reply #5? Do you have a replacement sensor to use instead of the sensor which receives no echo?

I have tried a few different ones. I even used sensor 1 or 3 to see if it would work

jcloonan: I even used sensor 1 or 3 to see if it would work

Duplicate pin usage in your circuit?

Do you perhaps try to use pin-0 or pin-1, which are the serial rx/tx pins, as pins for any ultrasonic sensor?

I was in the beginning but I switched the pins to

{7, 6, 3}, // index 0: trigger, echo and led pin ‘left’ sensor
{13, 9, 11}, // index 1: trigger, echo and led pin ‘right’ sensor
{4, 5, 12}, // index 2: trigger, echo and led pin ‘rear’ sensor

I just tried another sensor, just now also.

jcloonan: I was in the beginning but I switched the pins to

{7, 6, 3}, // index 0: trigger, echo and led pin 'left' sensor {13, 9, 11}, // index 1: trigger, echo and led pin 'right' sensor {4, 5, 12}, // index 2: trigger, echo and led pin 'rear' sensor

I just tried another sensor, just now also.

Is there any other hardware connected to the Arduino board?

In reply #8 you posted a sketch which used a LCD Keypad Shield:

LiquidCrystal lcd(8,9,4,5,6,7); // LCD Keypad Shield

You don't use that same shield with the sensor pins you posted, don't you?

If you use anything else than the ultrasonic sensors and LEDs connected to an Arduino board, post full schematics or detailed cabling description!