In the previous project, we were creating an accelerometer game that recorded each time the CREATOR Kit is tapped. The result of the program was a list of times that the user tapped on the CREATOR Kit.

In this project, we'll make this a bit more useful — we'll create a secret knock. In this case the user will have to tap on the kit with a very specific rhythm. If the their rhythm is reasonably close to our "secret" rhythm, then they've corrected entered the secret knock.

A secret knock could be used to gain access to a room, to start another program, to send a message over the network, or in many other ways!

You'll need to wire up only the accelerometer and speaker as done in previous projects. Here is what your breadboard should look like:

Here is what the code for this project should look like at this point (with new changes highlighted with arrows):

from rstem.accel import Accel from rstem.sound import Note import time accel = Accel() # Calibrate z_rest = 0 SAMPLES = 100 for i in range(SAMPLES): x, y, z = accel.forces() z_rest += z time.sleep(0.01) z_rest /= SAMPLES # Beep to tell user we're starting recording beep = Note('A6') beep.play(0.2).wait() # Record taps TOTAL_TICKS = 2000 raw_tap_ticks = [] for i in range(TOTAL_TICKS): x, y, z = accel.forces() if abs(z_rest-z) > 0.1: raw_tap_ticks.append(i) time.sleep(0.001) # Beep to tell user we've stopped recording beep.play(0.2).wait() # Convert raw ticks to filtered ticks filtered_tap_ticks = [] previous_tick = None for tick in raw_tap_ticks: if previous_tick == None or tick - previous_tick > 20: filtered_tap_ticks.append(tick) previous_tick = tick # Convert filtered ticks to relative ticks relative_tap_ticks = [] previous_tick = filtered_tap_ticks[0] for tick in filtered_tap_ticks: relative_tap_ticks.append(tick - previous_tick) previous_tick = tick *# Print actual taps *chars_per_tick = TOTAL_TICKS/80 *print("Actual Knock:", relative_tap_ticks) *if len(relative_tap_ticks) == 0: * print("No taps!") *elif len(relative_tap_ticks) == 1: * print("Just one tap!") *else: * for tap_tick in relative_tap_ticks: * spaces = int(80*tap_tick/TOTAL_TICKS) * print(" " * spaces + "*", end="") * print() * *# Print the expected taps of the "secret knock" *secret_knock = [0, 100, 300, 300] *print("Secret Knock:", secret_knock) * *# Compare actual taps to secret knock taps *knock_passed = False *if len(relative_tap_ticks) == len(secret_knock): * knock_passed = True * for i in range(len(relative_tap_ticks)): * if abs(relative_tap_ticks[i] - secret_knock[i]) > secret_knock[i] * 0.5: * knock_passed = False * *if knock_passed: * print("Access granted!") *else: * print("Access DENIED!")

The new additions we've made highlighted above are:

- On Lines 48 through 58, we print out the rhythm (with stars ('*')). To do this, we first eliminate a two special cases: if there's no taps or if there's just one tap, we just let the user know. When there are two or more taps, for each tap, we print the relative amount of spaces from the previous tap, followed by a star.

- On Lines 61 and 62, we define a secret knock that the user must reproduce.

- On Lines 65 through 70, we test to see if the user's taps match our `secret_knock`. To match, the two lists must be the same length, and each user tap time must be close to the secret knock time.

- On Lines 72 through 75, we simply print out whether or not the user correctly entered the secret knock.

The secret knock in the code above is 2 quick knocks followed by 2 slightly slower knocks: KNOCK KNOCK KNOCK KNOCK.

If your timing is off, take a look at the numbers that print out in the Output Window (the first set is your knocks and the second set is the secret knock) and then try adjusting until you get the pattern. It might take a couple tries...

1. Can you make a more complicated secret knock?

2. Having trouble replicating the knock in the code? Try doing your own knock, copy of the numbers of your knock from the Output Window back into your code, and then you'll just have to replicate your own knock!