Introduction: Knock Block

Knock Block: a modern knocking framework

Man has long wrestled with Time. Also, with knocking on things and not getting the time of day. We propose a knocking platform through which these fundamental needs are met. This is illustrated with the Knock Block KUI and accompanying Clock Knock Block application. The Knock Block possesses realistic knocking action with a human-like variation in frequency and amplitude of knocks.

Just knock on the Knock Block, or even the surface on which it's resting, and it will knock back the time to you. First it will knock the number of hours, and then the quarter hours.

If you knock several times, the Mock Knock Block application will take over, and repeat back your knocking pattern.

Video: http://www.vimeo.com/6713094

Step 1: Inside the Knock Block

What's inside that rich mahogany exterior? An Arduino that reads vibrations from a piezoelectric sensor and relays back information with a solenoid tapping against the resonant lid of the block. It's all powered by one or two 9V batteries.

Parts list:
- any Arduino can handle this
- a TIP31C high current transistor for the switch
- the exotically named Jameco 191172-001 solenoid, prized for its low price ($3!) and current
- a Measurement Specialties DT-series piezo film element (pretty sure that's the model)
- a 1M ohm resistor (your mileage may vary)
- 9V battery
- block case of your choice

Step 2: Choose Your Block

Exactly how you make your case is up to you, but ours was carved from a block of mahogany by a ShopBot CNC machine. Our design was simple so we made a 2D file and just set depths for the machine to cut (our DXF file is attached below). After routing, we handsanded the whole thing, but especially the edges to make them nice and rounded.We designed the lid to pressfit onto the body so there are no fasteners.

As long as it's hard and has some space to allow the knocking to reverbrate through the body, you're fine. We also cut an acrylic bracket that holds the parts (especially the solenoid) in place and away from the sides where they might dampen the sound.

We gave it a tongue for a nice tone, with the idea that we could make several blocks each with a different size tongue for a variety of tones.

Step 3: Wire the Circuit (piezo)

Tape the piezo at the base to something hard, so it can vibrate more freely. A cheap substitute for the piezo element is an old speaker, which also can produce voltage in response to vibrations.

Schematic for wiring to an Arduino is attached.

Step 4: Wire the Circuit (solenoid)

You'll need to get a high-current transistor (we used a TIP31C) to act as a switch for the solenoid - if it's connected directly to the Arduino it may reset the whole thing every time it activates, since it draws too much current for the Arduino to supply. Then the Arduino is only turning the base on and off, and the collector/emitter circuit is sourced by the 9V directly. The solenoid we used was designed for 12V but it has some tolerance for lower voltage at the cost of knocking volume.

Schematic and board overview attached. Notes:
- We wired the battery right into the Vin and GND pins on the Arduino (right under the resistor).
- The middle pin of the transistor is bent out so it's not in the Arduino, and is only connected to the solenoid via the blue wire.

Step 5: The Arduino Code

// Arduino code for Knock Block
// 2009: ReeD Martin, Ned Burns, Jon Ward, John Kestner
// constants:
const int ledPin = 12; // the solenoid circuit is connected to digital pin 12
const int knockSensor = 0; // the piezo is connected to analog pin 0
const int threshold = 20; // threshold value to decide when the detected sound is a knock or not;
// change this to adjust sensitivity on your own block

int sensorReading = 0; // variable to store the value read from the sensor pin
int ledState = LOW; // variable used to st4re the last LED status, to toggle the light

// Current Time
int current_millis_value = 0;
int previous_millis_value = 0;
int m = 0;
int seconds = 0;
int minutes = 45; // manually set the minutes it starts from when turned on
int hours = 6; // manually set the hours it starts from when turned on

// Initialize Knock-Tracking Variables
long lastKnock = 0;
long curKnock = 0;
int lastIntensity = 0;
int shouldKnock = 0;
long knockSpaces[100];

void setup() {
pinMode(ledPin, OUTPUT); // declare the ledPin as as OUTPUT
pinMode(knockSensor, INPUT);
Serial.begin(9600); // use the serial port
Serial.println("Welcome to the Knock Clock Block!");
}

void loop() {
// Manage time
current_millis_value = millis();
m += current_millis_value - previous_millis_value;
seconds += m / 1000;
m = m % 1000;
minutes += seconds / 60;
seconds = seconds % 60;
hours += minutes / 60;
minutes = minutes % 60;
hours = hours % 24;
previous_millis_value = current_millis_value;

// read the sensor and store it in the variable sensorReading:
sensorReading = analogRead(knockSensor);

curKnock = millis();

// if the sensor reading is greater than the threshold, count it as a knock
if (sensorReading >= threshold) {

if((curKnock - lastKnock) < 1000) {
knockSpaces[shouldKnock] = (curKnock - lastKnock);
shouldKnock++;
}

lastKnock = curKnock;
lastIntensity = sensorReading;

delay(150); // avoid accidentally triggering more than once

// if it isn't, check to see if 1000 ms has elapsed, and begin knocking:
} else if((curKnock - lastKnock) > 1000 && shouldKnock >= 1) {

if(shouldKnock < 5) {

// Reset Knocks
shouldKnock = 0;
lastKnock = 0;
lastIntensity = 0;

// Knock Hours
for (int y = 0; y < hours; y++) {
Serial.println("Knock! (Hours)");
knockOut(round((max(sensorReading,lastIntensity) / 50)*18));
delay(200 + random(90));
}

delay(900);

// Knock Minutes (15 min increments)
for (int y = 0; y < floor(minutes / 15); y++) {
Serial.println("Knock! (Minutes)");
knockOut(round((max(sensorReading,lastIntensity) / 50)*18));
delay(900 + random(200));
}

} else {

// Knock Back
for (int y = 0; y < shouldKnock; y++) {
Serial.println("Knock! (Fun!)");
knockOut(0);
delay((knockSpaces[y] - 20));
}

// Reset Knocks
shouldKnock = 0;
lastKnock = 0;
lastIntensity = 0;

knockOut(0);

delay(150); // avoid accidentally triggering more than once
}

delay(100); // avoid accidentally triggering more than once
}
}

// Perform a knock
void knockOut(int tVolume) {
ledState = HIGH;
digitalWrite(ledPin, ledState);
delay(20 + random(tVolume)); // Randomize intensity
ledState = LOW;
digitalWrite(ledPin, ledState);
}

Step 6: Stock Your Block

Here you can see the battery resting on one side of the acrylic bracket, the Arduino on the other side with the transistor for the solenoid sticking in it at an angle, and the solenoid in the middle - screwed into a block of MDF to hold it steady - and the piezo sensor taped to the MDF block. Some calibration was necessary to make sure the solenoid hit the tongue of the lid well, and we put a piece of felt under the solenoid hammer to keep it at the right height.

Step 7: Put the Lid On

... and enjoy your Knock Block.