Communication between 2 HC-SR04 sensors (pulseIn(echo, HIGH) = 0)

Hi, I’m creating a project where I’m using two HC-SR04 sensors to measure the distance between them. I’m using the receiver from one HC-SR04 and the transmitter from another to communicate. Ideally, the HC-SR04 transmitter would send a signal and the receiver would detect it by triggering its own trigger pin to set the echo pin to high (I covered the trigger pin of the HC-SR04 receiver so its echo pin can’t detect the signal it sent). However, the receiver is not detecting any signal (pulseIn(echo, HIGH) = 0) which is where the problem comes in. Initially, I used time delays for the sensors to sync with each other but it resulted in inaccurate and imprecise distances which is why I thought I’d use a radio module (NRF24L01) to sync the sensors. Unfortunately, this time, the receiver echo pin did not read anything and I’m basically getting 0 distances. Here’s the code I made for reference:

Transmitter:

#include <nRF24L01.h>
#include <RF24.h>
#include <SPI.h>

RF24 radio (7,8);
const byte address[6] = "00001";

const int trig = 9;
const int echo = 10;
const unsigned long event;
unsigned long prevTime;

void setup() {
  pinMode(trig, OUTPUT);
  pinMode(echo, INPUT);
  radio.begin();
  radio.openWritingPipe(address);
  radio.setPALevel(RF24_PA_LOW);
  radio.stopListening();
}

void loop() {
  unsigned long now = millis();
  int x = 1;
  if (now - prevTime >= 3000){
    radio.write(&x, sizeof(x));
    trigpin();
    prevTime = now;
  }
}

void trigpin(){
  digitalWrite(trig, HIGH);
  delayMicroseconds(10);
  digitalWrite(trig, LOW);
}

Receiver:

#include <nRF24L01.h>
#include <RF24.h>
#include <SPI.h>

RF24 radio (7,8);
const byte address[6] = "00001";

const int trig = 9;
const int echo = 10;
long duration;
float distance;

void setup() {
  pinMode(trig, OUTPUT);
  pinMode(echo, INPUT);
  radio.begin();
  radio.openReadingPipe(0, address);
  radio.setPALevel(RF24_PA_LOW);
  radio.startListening();
  Serial.begin(9600);
}

void loop() {
  if (radio.available()){
    int x = 0;
    radio.read(&x, sizeof(x));
    if (x = 1){
      duration = 0;
      trigpin();
      duration = pulseIn(echo, HIGH);
      distance = duration * (0.034 / 2);
      Serial.println(duration);
      Serial.println(distance);
      Serial.println("---");
    }
  }
}

void trigpin(){
  digitalWrite(trig, HIGH);
  delayMicroseconds(10);
  digitalWrite(trig, LOW);
}

How it works:
The transmitter is supposed to send an ultrasonic wave every 3 seconds to the receiver. But before doing so, it notifies the receiver to send a fake trigger to set the echo pin to high. The receiver then calculates the distance and prints it.

Result:
The printed values are “0” for both duration and distance.

Possible cause(s):
I was thinking that maybe I got zero values was because it took too long for the echo pin to be set to high-maybe it might have missed its window to receive the signal from the transmitter. I tried adding delays before triggering the transmitter trig pin and after sending the radio signal from transmitter to receiver but I got the same results.

Can someone point out what I did wrong and how I can fix it? I hope I didn’t take too much of your time. Thanks very much for your help and happy new year! :smiley:

P.S. I’ve only started studying Arduino mainly through YouTube tutorials so please go easy on me :sweat_smile:

Hi,
Can you post a picture of your project and a circuit diagram please.

The Ultrasonic units are each a separate controller, if you get one to ping, then its own receiver expects the return ping, not the other unit.

Tom... :slight_smile:

The receiver is only enabled after a trigger.

Unless you have some way to very precisely synchronize the sender and receiver, I cannot see how this could work.

if (x = 1){

You probably meant:if (x == 1){

      distance = duration * (0.034 / 2);

Remember that this calculation is for round-trip echo time. Get rid of the "/ 2" for one-way time.

A while back I posted working code for a similar project here (see post #20 of thread): https://forum.arduino.cc/index.php?topic=451490.15

I used a simple 433 MHz Transmitter / Receiver pair to perform node synchronization in that scheme. An issue with the NRF24L01 in this application is that there are latencies between issuing the sync message and when it is received. These latencies include at least the following events:

  • Sending the sync message to the transmitter as a serial message.
  • Transmit side NRF24L01 configuring the message packet and sending it.
  • Receive side NRF24L01 receiving the message packet and checking validity. I believe the NRF24L01 transmitter will attempt re-tries if it doesn't receive acknowledgement of receipt, so steps 2 & 3 may repeat in the worst case.
  • Sending the received message via serial port to the receive side Arduino.

I've never tried measuring this latency or its variation, but the NRF24L01 probably isn't the best choice for this application.

MrMark:
A while back I posted working code for a similar project here (see post #20 of thread): https://forum.arduino.cc/index.php?topic=451490.15

Thanks so much MrMark! I've been searching for other projects like this but this is the only time I've ever seen a working one.

MrMark:
I used a simple 433 MHz Transmitter / Receiver pair to perform node synchronization in that scheme. An issue with the NRF24L01 in this application is that there are latencies between issuing the sync message and when it is received. These latencies include at least the following events:

I had a feeling as well that the issue was due to how the NRF24L01 communicated with each other. I add this part to my code

while (digitalRead(echo)==HIGH) {Serial.println(duration);}

and it turns out that the echo pin was permanently set to high because it didn't receive any ping from the transmitter.
I do have some questions regarding your project if you don't mind:

  • Will any 433MHz transmitter/receiver pair suffice? I was wondering what were on pins 10, 11, and 12 (post #20 of your thread) because my RF module only has data pins on it.
  • Have you tested out your revisions on post #23? If not, it's fine. Your code was a huge help and I'm just curious if you managed to improve it.

Again, thank you very much MrMark! And to the others who replied, I'll take everything into account, so thank you too!

okinam:
. . . I do have some questions regarding your project if you don’t mind:

  • Will any 433MHz transmitter/receiver pair suffice? I was wondering what were on pins 10, 11, and 12 (post #20 of your thread) because my RF module only has data pins on it.
  • Have you tested out your revisions on post #23? If not, it’s fine. Your code was a huge help and I’m just curious if you managed to improve it.

Again, thank you very much MrMark! And to the others who replied, I’ll take everything into account, so thank you too!

  1. I used the cheap regenerative receivers for my experiments (see photo), but the any of the super-heterodyne receivers (RXB6, RXB12, etc) could be used as well and they’re far better receivers for not much more cost. The key is to have a radio that is modulated directly, that is, via the “data” pin, rather than something that has its own protocol layer, that is, something with a serial, SPI, or I2C interface to the microcontroller.


    Pins 10, 11, 12 were used for debug of the receiver side code and map to similarly-named traces in the logic analyzer picture attached to post #20 of the linked thread. The code will work with the digitalwrite() to these pins removed. In working with Arduino it is common to use Serial.write() to output debug information, but for time-critical code setting a digital output pin and observing it is a useful technique to verify that some part of the code has been reached.

  2. The code in post #20 of the linked thread is corrected to make a one-way vs round trip range calculation (as per John Wasser’s post #5 of this thread). I never tried an implementation with more than one HC-SR04 per node, but it should be straightforward enough to do so.