Electric Imp and HC-SR04 Sensor

Anybody got HC-SR04 sensor working with Electric Imp?

Not much comes up in a search except for this thread
http://forums.electricimp.com/discussion/comment/5827#Comment_5827

This works for me:

trigPin <- hardware.pin9;
trigPin.configure(DIGITAL_OUT);
echoPin <- hardware.pin1;
echoPin.configure(DIGITAL_IN);

function ping_sensor() {
local duration = 0, distance = 0, count = 0;

trigPin.write(0);   
imp.sleep(0.01);
trigPin.write(1);

while (echoPin.read() == 0) {}; 
count = hardware.micros(); 
while (echoPin.read() == 1) {};      

duration=hardware.micros()-count;
distance = (duration / 2) / 29.1;

return distance;

}

True, only one or two is coming in search.

@juanh64, I tried your code but it is giving values like 217.9, etc… and after 4 or 5 seconds it hangs, any idea?

`trigger <- hardware.pin5;
echo <- hardware.pin7;
led <- hardware.pin9;

class Pulse {
pulsePin = null; // Pin to look for pulses on
pulseValue = null; // 1 for HIGH -> LOW, 0 for LOW -> HIGH
timer = null; // Time since start of pulse
callback = null; // callback function when pulse finished
startValue = 0;

constructor(_pulsePin, _inputType, _pulseValue, _callback) {
    this.pulsePin = _pulsePin;
    this.pulseValue = _pulseValue;
    this.timer = 0.0;
    this.callback = _callback;
    
    this.pulsePin.configure(_inputType, pinChanged.bindenv(this));
}

function pinChanged() {
    local p = pulsePin.read();
    if (p == pulseValue) {
        startValue = hardware.micros();
    }
    else {
        this.timer = hardware.micros() - startValue;
        this.callback(timer);
    }
}

}

function ping(){
trigger.write(0);
imp.sleep(0.000002);
trigger.write(1);
imp.sleep(0.000010);
trigger.write(0);

distance = (duration / 2) / 29.1;

if(distance > 0 && distance < 200){
    server.log("Distance: " + distance + " cm");
    
    if(distance < 10){
        led.write(1);
    }
    else{
        led.write(0);
    }
}
else{
    led.write(0);
}

imp.wakeup(1.0, ping);

}

function pulsed(microseconds){
duration = microseconds;
}

trigger.configure(DIGITAL_OUT);
led.configure(DIGITAL_OUT);
duration <- 0;
distance <- 0;

pulsePin <- Pulse(echo, DIGITAL_IN_PULLDOWN, 1, pulsed);

ping();
`

I tried this code and is working somewhat, but it is not as good as Arduino.

Krv, The distance value it return is in centimeters, you will have to change the formula for your specific units. I’m not sure why it would hang, it has been working on my IMP device for a month, pinging very 5 minutes. Try changing your loop weak up time to be at least 1 second.

@juanh64, thanks man, let me check and get back here.

Any idea whether the PulsePin will be incorporated in the Electric Imp firmware, just to know?

That would be a good question for Hugo.

Not in a form like that, no. Being able to output (and capture) accurate pulse trains is something we have on the roadmap though.

Waiting for that @Hugo

I’ve been getting some pretty good results by combining the above too codes:
`trigger <- hardware.pin5;
echo <- hardware.pin7;
local duration = 0, distance = 0, count = 0;

function ping(ledState){
trigger.write(0);
imp.sleep(0.0000001);
trigger.write(1);

trigger.write(0);

while (echo.read() == 0) {};
count = hardware.micros();
while (echo.read() == 1) {};

duration=hardware.micros()-count;
distance = ((duration / 2) / 29.1)*0.39;

server.log(“Distance: " + distance + " in”);

}

trigger.configure(DIGITAL_OUT);
echo.configure(DIGITAL_IN);

ping(0);

agent.on(“ping”, ping);
`

It’s still not right, but it’s pretty close (off by maybe a few inches), anyway, it does not do well if the object is really close, less then a foot away, and then anything over about 2 feet seem to give it issues.

Like the other person, the 1st set of code was hanging after the 1st read, it never seemed to come back even after a very long time of waiting, but the 1st reading seemed promising as far as distance goes.

The 2nd set of code was just wacky off in it’s distances, but seemed to always give some answer if it was way way wrong.

I figured what the heck, and the results are pretty good.

I did try to mess with the timings a bit to see if I could get a slightly better reading, with a imp.sleep(0.02); in between the trigger.write(1); and the trigger.write(0);

It made some difference, but nothing fantastic, and it seemed turning the ping sensor on and off quickly might be the key to this.

Thou I think my timings are still a little off. I was getting 17 inches from me to my monitor, and between 26 to 30 inches from my desk to my low ceiling - and it gave me the same results over and over again.
I think it’s pretty close to being right. Anyways, good luck with it.

Might be that every IMP is a little different too, and every ping sensor I know is a little different.

-LeRoy

A bit old topic, but I hope someone is still around. :slight_smile:

What are you doing about the 5V on the sensor going to the Imp?

Update
Brainfart there… I was thinking about level shifter chips and stuff, but then it hit me… Voltage divider!

All that is needed is a 10k and a 5.1k resistor, and then the output is 3.311v

Update 2
Another thing… The Impee running this code keeps disconnecting, most likely because it hangs in one of the while()'s, and while doing so it is going from using ~45mA to ~80mA.

You can always add a timeout in the while, though this will then offset the time a little which you’d need to correct for in software.

I didn’t have hanging problems myself though.

I tried to add a timeout, but failed to make it work as intended… it went from 26cm which was the correct distance, to 3.something cm, never got it to work properly with that in either.

Another problem I also got was triggering it, 3v3 from a pin does not seem to reliably trigger the sensor, might need to add a transistor for that too.

So I found out one loop with some time checking in takes about 101 microseconds more, how would I go around to implement that into the code? To do that I also need to know how many times it did that calculation, and multiply by that number? But that would probably take some time to keep track of that number too?

Quite possibly if you had the transistor you wouldn’t need the timeout (ie if the issue is that the device isn’t running then that’d explain the hanging). I was using the parallax version of the sensor and never had an issue, but it migth be 3.3v happy.

Looks like a problem was the sensor I was using, for some reason it stops sending the pulses on the echo pin, changing the sensor to another fixed it.

But what would be a way to handle the hangup in the while{}? Is it possible to somehow make it reset itself, check for new code, then resume operation, without putting extra stuff in the while loop?

The “recover automatically from unfortunate infinite loops” feature is coming in a future release, yes. I suspect it’ll be release 32.