Sniff is a "Scratch-like" programming language that's designed to help Scratchers move gently from Scratch to more conventional languages. They can start writing programs, without having to learn a new language because Sniff is based on Scratch. They learn a little more about variables, compiling, syntax errors (!), and they can have fun controlling real hardware while they're doing it.

Wednesday, 20 May 2015

HC-SR04 Distance sensor in Sniff

Anyone who's dabbled with Arduino's has come across the HC-SR04 Ultrasonic Distance Sensor. These amazing devices are fire a ping of sound, which bounces off objects and then gets detected. Measure the time of flight and you've got an accurate measure of distance to the object. This is a great science experiment. Best of all they're very cheap, and very accurate... worst of all they're ridiculously unreliable. When they work they're fantastic... and then they stop working. For that reason I'm always skeptical about using them with kids - I find them frustrating, and wouldn't want someone to have a bad experience with one in an introductory class which might discourage them. On the other hand they're really neat when they do work, so I thought I'd finally do a write up:

The hc-sr04 has two data pins: trigger and echo. There's a Sniff hcsr04 device that allows you to connect the sensor to a single arduino pin by connecting trigger and echo together, but today I'm going to to it all in Sniff, so we'll use separate input and output pins:

make trigger digital output 7
make echo digital input 8

I used pins 7 and 8 for absolutly no reason at all.

when start
.set trigger to off
.wait 1 secs

The first thing we'll do is turn the trigger off, and wait 1 second for everything to settle down, and power up correctly.

To send an audio pulse we just set trigger on, wait 10microSeconds and turn it off again:

.set trigger to on
.wait 10 microsecs
.set trigger to off

Then the trigger pin turns off the device emits a series of 8 high pitch clicks.

We need to wait for the echo pin to go high, indicating that the pulses have been sent, and record the start time. We then wait for echo to turn off again, and that gives us the end time.

.wait until echo
.set startTime to fasttimer
.wait until not echo
.say join "Time:"[(fasttimer - startTime)]

In Sniff (and Scratch) we access the time since the program started using the "timer" block. However there's a gotcha - accurate timers are tricky. Sometimes we want to measure time in days (like when we collected the temperature data from the pond), and sometimes (like here) we want to measure things in microseconds. That's a range of 11 orders of magnitude, which causes some technical problems.

To handle that as reliably and flexably as possible Sniff has two timers. The regular timer, which we use for normal stuff, and a special "fasttimer" when we want to measure small time periods accuratly (basically timer is only accurate to 1mS, while fastTimer operates at a microSecond level). Here we're measuring a small time interval and want it to be super accurate so we're using fasttimer.

Sound travels through the air at different speeds depending on the temperature and humidity. If we set up a sensor 1m from a wall we can measure the time it takes to travel the 2m back and forth. We could also measure temperature and use the equation:

Here we'll settle on a typical value of 340m/s. So we multiply the time taken, by the speed to get the distance travelled. Of course the sound travels to the object and back again, so we half the distance travelled by the audio pulses to get the distance to the object. Easy!!

.say join "Distance:" [(fasttimer - startTime)*340/2]

Here's the full code:

make trigger digital output 7
make echo digital input 8

make startTime number

when start
.set trigger to off
..wait 1 secs
..set trigger to on
 ..wait 10 microsecs
..set trigger to off
..wait until echo
..set startTime to fasttimer
..wait until not echo
..say [(fasttimer - startTime)*330/2]

It's in a loop, printing out the result to the serial terminal, but you could just as easily use an embedded display to make a portable, ultrasonic tape measure!

When it works the results are remarkably consistent and accurate - unlike an IR distance sensor its not measuring the intensity of the reflection, but rather the timing, so it doesn't matter of objects are big or small, light or dark.

No comments:

Post a Comment