The following information is a single lesson in a larger project. Find more great projects here.

Lesson Overview:

Now we'll write our knock sensing code!

## Step 1: Introduction

In this lesson you will write the program that interprets knocks with the piezo component and unlocks a box with a rotating servo motor. If someone nocks the correct number of times, the lock opens.

1. Like the last servo motor project (Mood Cue) you will use the Servo.h library to simplify the motor control.

2. You will also write your own Arduino function called checkForKnock(). checkForKnock takes the volume of the knock as an argument and increases the knock counting variable if your knock is loud enough!

3. Our version of the Knock Lock project is in the Workplane. It should look similar to the circuit that you built in the previous lesson.

4. Continue to the next step.

## Step 2: Include Servo Library

Just as in the Mood Cue project, you’ll need to import the Servo library and create an instance to use the motor.

1. Copy the code below into the Code Editor. #include Servo myServo;

2. Continue to the next step.

## Step 3: Create Constants

Next create constants to name your inputs and outputs. This includes the piezo knock sensor, lock button, and LEDs. You'll initialize the servo motor later.

1. Copy the code below into the Code Editor. const int piezo = A0; const int switchPin = 2; const int yellowLed = 3; const int greenLed = 4; const int redLed = 5;

2. Continue to the next step.

## Step 4: Switch and Piezo Variables

Create variables to hold the values from your switch and piezo. These variables both use the integer datatype.

1. Copy the code below into the Code Editor. int knockVal; int switchVal;

2. Continue to the next step.

## Step 5: Set Knock Thresholds

Set up some constants to use as thresholds for the knock maximum and minimum levels. These numbers fall well within the 0-1023 scale that the analogRead() function will return for pin A0.

1. Copy the code into the Code Editor. const int quietKnock = 10; const int loudKnock = 100;

2. Continue to the next step.

## Step 6: Knock Variables

The locked variable will let you know if the lock is engaged or not. A boolean is a data type that can only be true (1) or false (0). You should start out the program with the servo unlocked.

The global variable numberOfKnocks will hold the number of valid knocks you have. Give it a value of 0 initially.

1. Copy the code below into the Code Editor. boolean locked = false; int numberOfKnocks = 0;

2. Copy the code into the Code Editor.

3. Stuck? HINT: Recall that global variables are defined in the header. They are valid for every section of the code.

## Step 7: Set Up Servo and Digital Pins

In your setup(), attach the servo to pin 9. Set the LED pins as outputs and the switch pin as an input.

1. Copy the code below into the Code Editor. void setup(){ myServo.attach(9); pinMode(yellowLed, OUTPUT); pinMode(redLed, OUTPUT); pinMode(greenLed, OUTPUT); pinMode(switchPin, INPUT).

2. Continue to the next step.

## Step 8: Start Serial Communication

Initialize serial communication with the computer so you can monitor the knock volume, what the current state of the lock is, and how many more knocks you have to go.

1. Copy the code below into the Code Editor. Serial.begin(9600);

2. Continue to the next step.

## Step 9: Unlock the Box

You will want the box to be unlocked initially. Turn on the green LED, move the servo to the unlocked position, and print the current lock status to the serial monitor.

1. Copy the code below into the Code Editor. digitalWrite(greenLed, HIGH); myServo.write(0); Serial.println("The box is unlocked!"); } //end of setup()

2. Continue to the next step.

## Step 10: Check Lock Status: FALSE

In the loop() function, you’ll first check to see if the box is locked or not. This will determine what happens in the rest of the program. If it is locked, read the switch value.

You will check the lock status in an if() statement.

1. Copy the code into the Code Editor. void loop(){ if(locked == false){ switchVal = digitalRead(switchPin);

2. Notice that this is not the end of the if() statement. It will continue in the next step!

3. Continue to the next step.

## Step 11: Lock the Box

The following activity will take place if the button is closed (meaning that you are currently pressing it):

Change the locked variable to true, indicating the lock is engaged.

Turn the green LED off, and the red LED on to create a visual indicator that the project is locked

Move the servo into the lock position

Print out a message to the serial monitor indicating the box is now locked.

Finally, add a delay so the lock has plenty of time to move into place.

1. Copy the code into the Code Editor. if(switchVal == HIGH){ locked = true; digitalWrite(greenLed, LOW); digitalWrite(redLed, HIGH); myServo.write(90); Serial.println("The box is locked!"); delay(1000); } //end of nested if() } //end of outer if()

2. Continue to the next step.

## Step 12: Check Lock Status: TRUE

Now we'll see what happens if the locked variable is true (i.e. the lock is engaged). Read the value of the vibration of the piezo and store it in knockVal.

1. Copy the code into the Code Editor. if(locked == true){ knockVal = analogRead(piezo);

2. Continue to the next step.

## Step 13: Count Only Valid Knocks

The next statement checks to see if you have fewer than three valid knocks, AND there is some vibration on the sensor (i.e. you are currently knocking). If these are both true, the program will do the following: check to see if this current knock is valid and increment the numberOfKnocks variable.

This is where you’ll call your custom functioncheckForKnocks(), which you will actually be writing at the end of the sketch! After checking your function, print out the number of knock stillneeded.

1. Copy the code below into the Code Editor. if(numberOfKnocks < 3 && knockVal > 0){ if(checkForKnock(knockVal) == true){ numberOfKnocks ++; } //subtract knocks made so far from three Serial.print(3-numberOfKnocks); Serial.print(" more knocks to go"); }

2. The text in the serial monitor will look like (for example): 2 more knocks to go

3. Continue to the next step.

## Step 14: Unlock the Box

The next if() statement checks to see if you have three or more valid knocks.

If this is true, then the secret code has been broken! The program will do the following:

Change the locked variable to false

Move the servo to the unlocked position.

Wait for a few milliseconds to let it start moving, with the delay() function

Change the status of the green and red LEDs.

Print out a status message to the serial monitor, indicating the box is unlocked!

1. Copy the code below into the Code Editor. if(numberOfKnocks >=3){ locked = false; myServo.write(0); delay(20); digitalWrite(greenLed, HIGH); digitalWrite(redLed, LOW); Serial.println("The box is unlocked!"); } //end of if(numberOfKnocks...) } //end of if(locked==true) } //end of loop

2. Remember to close up the else statement and the loop() with curly brackets.

3. Continue to the next step.

## Step 15: Write a Function to Verify Knocks

Now it’s time to write the function checkForKnock().

When you write your own functions, you need to decide whether it returns a value or not. If it does not return a value, you declare it as type void, like the loop() and setup() functions. If it does return a value, you will declare what kind (int, long, float, etc.). In this function, you’re checking to see if a knock is valid (true) or not valid (false), so declare the function as type boolean.

You also need to decide if the function takes an argument between the parentheses. This function will be using information from knockVal, which is an integer. Let's use the variable 'value' while writing the function.

1. Copy the code below into the Code Editor. boolean checkForKnock(int value){

2. Continue to the next step.

## Step 16: Check Validity of Knock

In your function, whenever you refer to value it will use whatever number it receives as an argument in the main program. Remember that when you called the function it looked like: checkForKnock(knockVal);

Check to see whether the argument 'value' is greater than your quiet knock, and less than your loud knock, using an if() statement.

1. Copy the code below into the Code Editor. if(value > quietKnock && value < loudKnock){

2. Continue to the next step.

## Step 17: Function Returns TRUE

If the value falls within that range, it’s a valid knock! Blink the yellow LED once and print the value of the knock to the serial monitor.

To let the main program know what the outcome of the comparison is, you use the command return. The return command also terminates the function: once it executes, you go back to the main program. In this case, you would return a value of "true."

1. Copy the code into the Code Editor. digitalWrite(yellowLed, HIGH); delay(50); digitalWrite(yellowLed, LOW); Serial.print("Valid knock of value "); Serial.println(value); return true; }

2. Copy the code into the Code Editor.

## Step 18: Function Returns FALSE

If value is either too quiet or too loud, print it out to the serial monitor and have the function return false.

Remember to close up your function with one more curly bracket. This is the end of the program.

1. Copy the code into the Code Editor. else{ Serial.print("Bad knock value "); Serial.println(value); return false; } }

2. Remember to include all {curly brackets.} This is the end of the program!

3. Continue to the next step.

## Step 19: Use It! (simulator -1)

Unfortunately, the piezo buzzer can't be used as an input in the simulator right now. But you can still test the virtual circuit!

Before running the code, replace the buzzer with another input: the pushbutton. You should also change the value of the pulldown resistor to 10 k-ohm, which you have used in other button projects. We have a suggested circuit layout in the picture below.

1. Replace the piezo with a pushbutton, and change the value of the pulldown resistor to 10 k-ohm.

2. Continue to the next step.

## Step 20: Use It! (simulator -2)

Now you can try "knocking" with the button. (Maybe you can think of this as ringing a doorbell!)

1. Upload & Run the code in the simulator. Open up the serial monitor as well.
2. When you start the program, you will see the green LED come on and the servo move to the unlocked position. The message "The box is unlocked" will appear in the serial monitor.
3. Press the button on the left to lock the project. The servo moves into the locked position and the red LED comes on. The serial monitor reads "The box is locked!"

## Step 21: Use It! (simulator -3)

Try pressing the button. You should get a message in the Serial Monitor that says:

3 more knocks to go Bad Value 1023 The button will always provide the maximum analog signal to pin A0. This is well outside the range of what you would sense with the piezo knock sensor! In order to get this to work, you'll need to change your conditions for a loud knock to be greater than 1023. We suggest using the code pictured below:

1. Continue to the next step.

2. Try making the following change in the code: const int loudKnock = 100; to: const int loudKnock = 1053;

## Step 22: Use It! (simulator - 4)

Now you can try simulating the circuit again! What happens after you knock three times? (see hint.)

1. After uploading the new code, press the button the right to lock the servo and turn on the red LED.

2. Try pressing the knock button again. When you make a valid knock, the yellow light flashes, and the Serial Monitor reads: "Valid knock of 1023, 2 more knocks to go."

3. Try pressing the button a total of three times to see how the LEDs and piezo react. (see hint)

4. Make sure you change your loudKnock threshold back to 100 before transferring the sketch to Arduino IDE and uploading to your Arduino Uno.

5. Continue to the next step.

6. Stuck? HINT: After 3 valid knocks, the green light comes on and the servo motor turns 90 degrees.

## Step 23: Use It! (Arduino Kit - 1)

Now you can try using your Arduino kit to sense a real knock!

Again, when you upload and run the code on your Arduino Uno, you can open up the serial monitor to see what values pin A0 is interpreting. The green LED will turn on, and the servo will lock.

1. Plug in the Arduino Uno and upload the sketch.

2. Press the button to move the servo into the locked position and turn the red LED on.

3. Continue to the next step.

## Step 24: Use It! (Arduino Kit - 2)

Finally, you will see what happens when the piezo detects a knock.

1. Try knocking soft and hard to see what intensity of knock triggers your checkForKnock function. You'll know it's working when the yellow LED flashes and the serial monitor tells you that you have a valid knock. It will also tell you how many more knocks are needed before the lock opens.
2. Depending on what kind of surface your piezo is attached to, your knock values might be outside of our 10-100 range! You can go back to into the code and change the range of acceptable values to fit your project (like we did with the button input in the simulator).
3. Once you you make three valid knocks, the green light will come on and the servo arm will swing open!
4. Continue to the next step.

## Step 25: Interpreting Knock Values

As you work with the knock sensor, observe the knock values reported in the serial monitor. How do these values compare to the 0-1023 scale that analogRead() can return? What does this say about the voltages generated at pin A0 when the piezo senses a knock?

1. Continue to the next step.

## Step 26: Review

Congratulations, you have created a knock-sensitive locking mechanism, using a piezo as an analog input!

A main skill that you have used in this lesson is creating your own function. ￼Writing your own functions not only allows you to control the flow of your code more easily, it also helps keep it readable as your projects become larger and larger.

As you continue write more code, you may find you have a large number of functions you can re-use in different projects. You should keep track of the functions that you write so you can use them in all of your projects, or share them with other students!

1. Continue to the next lesson to learn how to make a locking box for this project.

Next Lesson:Building a Locked Box