Project – Ultrasonic Combination Switch

Hello Readers

Time for a follow-up to the Single Button Combination Lock by 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 required hardware for this project is minimal and shown below – a Freetronics Arduino-compatible board, thePing))) sensor, and for display purposes we have an I2C-interface LCD module:

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 (download sketch):

// Ultrasonic combination lock - distance display // John Boxall - December 2011 // tronixstuff.wordpress.com/projects | CC by-sa-nc
#include "Wire.h" #include "LiquidCrystal_I2C.h" // for I2C bus LCD module http://bit.ly/eNf7jM LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x27 for a 16 chars and 2 line display
int signal=8;
void setup() { pinMode(signal, OUTPUT); lcd.init(); // initialize the lcd lcd.backlight(); // turn on LCD backlight }
int getDistance() // returns distance from Ping))) sensor in cm { int distance; unsigned long pulseduration=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); return distance; }
void loop() { 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].

Question – What is an ultrasonic sound? 

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 (download):

// Ultrasonic combination lock // John Boxall - December 2011 // tronixstuff.wordpress.com/projects | CC by-sa-nc
int pin[]={ 20, 15, 20, 25}; // this is the "PIN" distances in cm
#include "Wire.h" #include "LiquidCrystal_I2C.h" // for I2C bus LCD module http://bit.ly/eNf7jM LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x27 for a 16 chars and 2 line display
int signal=8; // digital pin for Ping))) signal
void setup() { pinMode(signal, OUTPUT); lcd.init(); // initialize the lcd lcd.backlight(); // turn on LCD backlight Serial.begin(9600); // for debug }
int getDistance() // returns distance from Ping))) sensor in cm { int distance; unsigned long pulseduration=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); return distance; }
void checkPIN() { int attempt[4]; // stores user's attempt values int accept=0; // used for checking resulting user entry int t=5; // +/- tolerance int adel=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 (int z=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); } else if (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); } }
void loop() { if (getDistance()<10) { lcd.clear(); checkPIN(); } lcd.setCursor(0,0); lcd.print(" ** Ready ** "); }

To finish the switch, a housing of some sort is required. adafruit industries sell a housing which has mounts for an Arduino-form board and 16×2 LCD which is convenient, so we use it for the finished example as shown below:

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 :)

Have fun and keep checking into tronixstuff.com. Why not follow things on twitterGoogle+, 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.

Advertisements
By John Boxall

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s