In this project you learn how to make an ultrasonic distance-sensing combination switch.

Updated 18/03/2013

Time for a follow-up to the Single Button Combination Lockby creating another oddball type of switch/lock. To activate this switch we make use of a Parallax Ping))) Ultrasonic sensor, an Arduino-style board and some other hardware – to make a device that receives a four-number code which is made up of the distance between a hand and the sensor. If Arduino and ultrasonic sensors are new to you, please read this tutorial before moving on.

The combination for our ‘lock’ will consist of four integers. Each integer is the distance measured between the sensor and the user’s hand (etc.). For example, a combination may be 20, 15, 20, 15. So for the switch to be activated the user must place their hand 20cm away, then 15, then 20, then 15cm away. Our switch will have a delay between each measurement which can be modified in the sketch.

To keep things simple the overlord of the switch must insert the PIN into the switch sketch. Therefore we need a way to take measurements to generate a PIN. We do this with the following sketch, it simply displays the distance on the LCD):

LiquidCrystal_I2Clcd(0x27,16,2);// set the LCD address to 0x27 for a 16 chars and 2 line display

intsignal=8;

voidsetup()

{

pinMode(signal,OUTPUT);

lcd.init();// initialize the lcd

lcd.backlight();// turn on LCD backlight

}

intgetDistance()

// returns distance from Ping))) sensor in cm

{

intdistance;

unsignedlongpulseduration=0;

// get the raw measurement data from Ping)))

// set pin as output so we can send a pulse

pinMode(signal,OUTPUT);

// set output to LOW

digitalWrite(signal,LOW);

delayMicroseconds(5);

// now send the 5uS pulse out to activate Ping)))

digitalWrite(signal,HIGH);

delayMicroseconds(5);

digitalWrite(signal,LOW);

// now we need to change the digital pin

// to input to read the incoming pulse

pinMode(signal,INPUT);

// finally, measure the length of the incoming pulse

pulseduration=pulseIn(signal,HIGH);

// divide the pulse length by half

pulseduration=pulseduration/2;

// now convert to centimetres. We're metric here people...

distance=int(pulseduration/29);

returndistance;

}

voidloop()

{

lcd.print(getDistance());

lcd.println(" cm ");

delay(500);

lcd.clear();

}

And here is a demonstration of the sketch in action:

Now for the switch itself. For our example the process of “unlocking” will be started by the user placing their hand at a distance of 10cm or less in front of the sensor. Doing so will trigger the function checkPIN(), where the display prompts the user for four “numbers” which are returned by placing their hand a certain distance away from the sensor four times, with a delay between each reading which is set by the variable adel. The values of the user’s distances are stored in the array attempt[4].

Once the four readings have been taken, they are compared against the values in the array PIN[]. Some tolerance has been built into the checking process, where the value entered can vary +/- a certain distance. This tolerance distance is stored in the variable t in this function. Each of the user’s entries are compared and the tolerance taken into account. If each entry is successful, one is added to the variable accept. If all entries are correct, accept will equal four – at which point the sketch will either “unlock” or display “*** DENIED ***” on the LCD.

Again, this is an example and you can modify the display or checking procedure yourself. Moving forward, here is our lock sketch:

LiquidCrystal_I2Clcd(0x27,16,2);// set the LCD address to 0x27 for a 16 chars and 2 line display

intsignal=8;// digital pin for Ping))) signal

voidsetup()

{

pinMode(signal,OUTPUT);

lcd.init();// initialize the lcd

lcd.backlight();// turn on LCD backlight

Serial.begin(9600);// for debug

}

intgetDistance()

// returns distance from Ping))) sensor in cm

{

intdistance;

unsignedlongpulseduration=0;

// get the raw measurement data from Ping)))

// set pin as output so we can send a pulse

pinMode(signal,OUTPUT);

// set output to LOW

digitalWrite(signal,LOW);

delayMicroseconds(5);

// now send the 5uS pulse out to activate Ping)))

digitalWrite(signal,HIGH);

delayMicroseconds(5);

digitalWrite(signal,LOW);

// now we need to change the digital pin

// to input to read the incoming pulse

pinMode(signal,INPUT);

// finally, measure the length of the incoming pulse

pulseduration=pulseIn(signal,HIGH);

// divide the pulse length by half

pulseduration=pulseduration/2;

// now convert to centimetres. We're metric here people...

distance=int(pulseduration/29);

returndistance;

}

voidcheckPIN()

{

intattempt[4];// stores user's attempt values

intaccept=0;// used for checking resulting user entry

intt=5;// +/- tolerance

intadel=1500;// delay between movement attempts

lcd.setCursor(0,0);

lcd.print("Get ready... ");

delay(adel);// delay before first distance measurement

lcd.setCursor(0,0);

lcd.print(" Position One ");

lcd.setCursor(0,1);

lcd.print(">>>>____________");

attempt[0]=getDistance();

delay(adel);

lcd.setCursor(0,0);

lcd.print(" Position Two ");

lcd.setCursor(0,1);

lcd.print(">>>>>>>>________");

attempt[1]=getDistance();

delay(adel);

lcd.setCursor(0,0);

lcd.print("Position Three ");

lcd.setCursor(0,1);

lcd.print(">>>>>>>>>>>>____");

attempt[2]=getDistance();

delay(adel);

lcd.setCursor(0,0);

lcd.print(" Position Four ");

lcd.setCursor(0,1);

lcd.print(">>>>>>>>>>>>>>>>");

attempt[3]=getDistance();

delay(adel);

lcd.clear();

lcd.print("Checking ... ");// for visual effect more than anything

delay(2000);

lcd.clear();

// display user entry on serial monitor for debugging

for(intz=0;z<4;z++)

{

Serial.println(attempt[z]);

}

Serial.println("------");

delay(2000);

// now compare against preset values

// allow a +/- tolerance (tolerance in integer 't')

if(attempt[0]>=(pin[0]-t)&&attempt[0]<=(pin[0]+t)){accept++;}

if(attempt[1]>=(pin[0]-t)&&attempt[1]<=(pin[0]+t)){accept++;}

if(attempt[2]>=(pin[0]-t)&&attempt[2]<=(pin[0]+t)){accept++;}

if(attempt[3]>=(pin[0]-t)&&attempt[3]<=(pin[0]+t)){accept++;}

if(accept==4)

{

// correct entry

lcd.setCursor(0,0);

lcd.print(" ** Accepted ** ");

// here you would enter code to run when the switch was successfully activated

delay(2000);

}

elseif(accept!=4)

{

// incorrect entry

lcd.setCursor(0,0);

lcd.print(" *** DENIED *** ");

// here you would enter code to run when the switch was unsuccessfully activated

delay(2000);

}

}

voidloop()

{

if(getDistance()<10)

{

lcd.clear();

checkPIN();

}

lcd.setCursor(0,0);

lcd.print(" ** Ready ** ");

}

To finish the switch, we housed it in the lovely enclosure from adafruit:

And for the final demonstration of the switch in action. Note that the delays between actions have been added for visual effect – you can always change them to suit yourself:

So there you have it – the base example for a different type of combination switch. I hope someone out there found this interesting or slightly useful.

In the meanwhile have fun and keep checking into tronixstuff.com. Why not follow things on twitter, Google+, subscribe for email updates or RSS using the links on the right-hand column? And join our friendly Google Group – dedicated to the projects and related items on this website. Sign up – it’s free, helpful to each other – and we can all learn something.

Whilst being a passenger in a vehicle with a ‘reversing sensors’, I became somewhat curious as to how the sensors operated and how we can make use of them. So for this chapter we will investigate an ultrasonic sensor from Parallax called the Ping)))™ Ultrasonic Distance Sensor. It can measure distances between ~2cm and ~3m in length. Here is our example sensor:

Parallax have done a lot of work, the board contains not just the bare sensor hardware but controller circuitry as well:

Which is great as it leaves us with only three pins – 5V, GND and signal. More on those in a moment, but first…

How does it work?

Good question. The unit sends out an ultrasonic (a sound that has a frequency which is higher than can be heard by the human ear) burst of sound from one transducer (the round silver things) and waits for it bounce off an object and return – which is detected by the other transducer. The board will then return to us the period of time taken for this process to take, which we can interpret to determine the distance between the sensor and the object from which the ultrasonic sound bounced from.

The Ping))) only measures a distance when requested – to do this we send a very short HIGH pulse of five microseconds to the signal pin. After a brief moment a pulse will come from the board on the same signal pin. The period of this second pulse is the amount of time the sound took to travel out and back from the sensor – so we divide it by two to calculate the distance. Finally, as the the speed of sound is 340 metres per second, the Arduino sketch can calculate the distance to whatever units required.

It may sound complex, but it is not – so let’s run through the theory of operation with an example. Using our digital storage oscillscope we have measured the waveforms on the signal pin during a typical measurement. Consider the following example of measuring a distance of 12cm:

You can see the 5uS pulse in the centre and the pulse returned from the sensor board on the right. Now to zoom in on the returned pulse:

Without being too picky the pulse is roughly 720uS (microseconds) long – the duration of ultrasonic sound’s return trip from the sensor board. So we divide this by two to find the time to travel the distance – 360uS. Recall the speed of sound is 340 metres per second – which converts to 29.412 uS per centimetre. So, 360uS divided by 29.412 uS gives 12.239902081… centimetres. Rounded that gives us 12 centimetres. Easy!

Finally, there are some limitations to using the Ping))) sensor. Download the data sheet (pdf) and read pages three to five for information on how to effectively mount the sensor and the sensitivity results from factory resting.

How do we use it with Arduino?

As described previously we first need to send a 5uS pulse, then listen for the return pulse. The following sketch does just that, then converts the data to centimetres and displays the result on the serial monitor. The code has been commented to explain each step.

Arduino

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

// Example 45.1 - tronixstuff.com - CC by-sa-nc

// Connect Ping))) signal pin to Arduino digital 8

intsignal=8;

intdistance;

unsignedlongpulseduration=0;

voidsetup()

{

pinMode(signal,OUTPUT);

Serial.begin(9600);

}

voidmeasureDistance()

{

// set pin as output so we can send a pulse

pinMode(signal,OUTPUT);

// set output to LOW

digitalWrite(signal,LOW);

delayMicroseconds(5);

// now send the 5uS pulse out to activate Ping)))

digitalWrite(signal,HIGH);

delayMicroseconds(5);

digitalWrite(signal,LOW);

// now we need to change the digital pin

// to input to read the incoming pulse

pinMode(signal,INPUT);

// finally, measure the length of the incoming pulse

pulseduration=pulseIn(signal,HIGH);

}

voidloop()

{

// get the raw measurement data from Ping)))

measureDistance();

// divide the pulse length by half

pulseduration=pulseduration/2;

// now convert to centimetres. We're metric here people...

distance=int(pulseduration/29);

// Display on serial monitor

Serial.print("Distance - ");

Serial.print(distance);

Serial.println(" cm");

delay(500);

}

And the results of some hand-waving in the serial monitor:

So there you have it – you can now measure distance with a degree of accuracy. However that image above isn’t very exciting – instead let’s use a 7-segment display shield to get things up in lights. The shield uses the NXP SAA1064 LED display driver IC (explained quite well here). You can download the demonstration sketch from here. And now for the video:

So there you have it – now the use of the sensor is up to your imagination. Stay tuned using the methods below to see what we get up to with this sensor in the future.

Have fun and keep checking into tronixstuff.com. Why not follow things on twitter, Google+, subscribe for email updates or RSS using the links on the right-hand column, or join our Google Group – dedicated to the projects and related items on this website. Sign up – it’s free, helpful to each other – and we can all learn something.