Sunday, March 16, 2014

Presence detection: ultrasonic ranging.

Since several aspects of effective automation (at least the sort I want) depend on being able to tell where people are at, I decided last week to start experimenting with sensors.

I know that the primary sensor throughout the house will be PIR motion sensors. They're cheap and effective, but generally only tell you "a heat source moved somewhere in my field of view". I want to get more information about comings and goings, with an eye to being able to accurately track numbers of people in each room.

One of the ideas I has was to use ultrasonic rangefinders mounted so they're aimed at doorways, hallways and other natural chokepoints, positioned so that people will be walking directly toward or away from the rangefinder. The idea is that when no people are present it will always see the range to the far wall or whatever. When people are moving through the chokepoint, the range will be to the person, and by taking repeated samples we can see if the person is moving toward the sensor or away from it.

I also thought it might be a good idea to place these on the ceiling, angled down, to increase the chance that if multiple people walk through it sees all of them, rather than just the first. That was the idea, anyway.

So, I bought one of these:
The first lesson I learned was to do price comparisons. I paid $10 for mine, but after I got it found other places selling it for $2.99. Oh, well. This SR-04 unit is fairly short-ranged, only out to about 15 feet, but I thought that would be just fine particularly if it were ceiling-mounted and looking slightly downward.

Anyway, I poked it into the breadboard, looked up the datasheet to see how to use it and gave it a try. Using it is pretty simple. As the labels imply, pin 1 is power (+5V) and pin 4 is ground. Pin 2 is "trigger" and 3 is "echo". What that means is that if you pull pin 2 high (+5V) for at least 2 microseconds, then pull it back to zero, you'll have "triggered" the device. It will then pull pin 3 high, send a series of very brief ultrasonic audio pulses and then pull pin 3 low when the echo of the last arrives. You have to wait at least 50 ms before triggering again.

With respect to wiring, it's really that simple. No need for extra resistors or anything; just connect the power, the ground, one output pin and one input pin and you're good.

The software is a little more complicated, though also not bad. First, as soon as you pull pin 2 back low, you need to start a timer, counting microseconds. Then as soon as pin 3 goes low, stop the timer. That timer will give you the time in microseconds that the sound took to get from the emitter and back to the microphone. The Arduino library function pulseIn will actually do all of the timing and monitoring of the input pin for you.

Once you have the echo duration, there's a little more work to do because you have to convert that to distance. Sound travels at approximately 1130 feet per second at standard temperature and pressure, which is 13,560 inches per second. Taking the reciprocal give us ~.000074 seconds per inch, which is 74 microseconds. So, we just have to take the echo time (which is in microseconds) and divide by 74, right? Almost, that echo time is the round trip time, out and back. For a one-way distance measure, we need to divide by two.

So the code is something like:

void setup() {
  pinMode(echoPin, INPUT);
  pinMode(triggerPin, OUTPUT);

void loop() {
  digitalWrite(triggerPin, LOW);
  digitalWrite(triggerPin, HIGH);
  delayMicroseconds(10); // Must be at least 2μs
  digitalWrite(triggerPin, LOW);

  long duration = pulseIn(echoPin, HIGH);
  int distanceInches = (int)(duration / 74 / 2);

  // Do something with distance here.

  delay(50); // Wait 50 ms before polling again.

Of course, real code will be more complex, but that covers the basics of using the sensor.

So how awesome was it? Not very. I've since found a library, called newPing that purports to do a better job of extracting data from the sensor by using lower-level primitives to do the timing rather than calling pulseIn, but I suspect it still won't be very good.

When I first started playing with it, I noticed that it often returned a nonsensically-huge value. I quickly realized that that was the sensor's way of saying "I never got the echo". That was fine; I knew it had a limited range and the other side of my bedroom was farther than 15 feet. When I put my hand very near the sensor (2-8 inches), the sensor was reliable and accurate, but as I moved farther back I started getting the out-of-range value mixed in with sensible values. The farther back I moved the worse it got, to the point that more than about three feet away it hardly saw me at all.

I started thinking about what an ultrasonic ranger does and realized that my soft body and clothing is not a very reflective target. I'm rounded, which means large portions of my body are not perpendicular to the incoming sound wave and will therefore get reflected off in all sorts of directions.

So, I went and got a large hardcover book and held that in front of the sensor... it was flawless right out to the maximum range of the sensor, and a bit beyond. But the book was a nearly ideal surface, hard and flat. At least it was perfect as long as I held it perpendicular to the line between the sensor and book. If I angled it off to the side the sensor immediately started reporting max values again.

The angle issue points out that mounting them in the ceiling looking downward would likely not work, even if people were more reflective, because the sound will bounce off at an angle, heading to the floor rather than back to the sensor. If the microphone were in the floor... but that's not feasible.

I tried various simple filters, first ignoring out-of-range values, then taking a mean, or a median, of multiple samples, and while the filtering helped a little, it still didn't work well. Human bodies just aren't good targets for simple ultrasonic ranging.

I'll experiment a bit more with newPing, just to see if it makes a difference, but I think ultrasonics probably aren't the best choice for this application.

No comments:

Post a Comment

My collection is complete(ish)!

I drive an electric car, a Tesla Model S. Generally, I never worry about how or where to charge it. It has a large battery and a long range,...