Log knocks on a web page

Detect knocks on a door or desk with the knock sensor and list each one with the time on your phone.
  • Level:Intermediate
  • Duration: 45 min
  • Ages 12+
  • Platform: ESP32

Tools for this lesson

Helpful for this build. Open a tool to see tips and more projects that use it.

Log knocks on a web page – EEMENTOR STEM™ lesson

Did someone knock while you had headphones on? Fix the knock sensor to a door or desk, and the ESP32 records every knock with the time and shows the list on your phone. The LED flashes with each knock too.

What you'll learn

  • How a knock (vibration) sensor works
  • How to keep a list of recent events
  • How to get the real time from the internet (NTP)

What you need

  • ESP32 board, expansion board and USB cable (ESP32 IoT Starter Kit)
  • Knock sensor module (45-in-1 Sensor Kit)
  • 1 LED and 1 resistor, 220 Ω
  • A 2.4 GHz Wi-Fi network
  • Breadboard and jumper wires (ESP32 IoT Starter Kit)

Wiring

Breadboard wiring diagram: Log knocks on a web page
Breadboard view. Check each connection against the wiring table below.
From To
Knock sensor S ESP32 GPIO 27
Knock sensor + 3V3
Knock sensor − GND
ESP32 GPIO 26 220 Ω resistor, then the LED's long leg
LED short leg GND

Sensor modules from different makers can label and order their pins differently. Always follow the labels printed on your module.

The sketch

Replace YOUR_WIFI_NAME and YOUR_WIFI_PASSWORD with your own network details (2.4 GHz only). Open the Serial Monitor at 115200 baud to see the address, then open it on a phone or computer on the same Wi-Fi.

Some versions of this module switch their output to HIGH when they trigger, others to LOW. The sketch reads the output when it starts (keep things quiet and still for a moment) and treats any change from that resting state as a trigger, so it works with both.

#include <WiFi.h>
#include <WebServer.h>
#include <time.h>

const char* WIFI_NAME = "YOUR_WIFI_NAME";
const char* WIFI_PASSWORD = "YOUR_WIFI_PASSWORD";
const char* TIME_ZONE = "EET-2EEST,M3.5.0/3,M10.5.0/4"; // Estonia; change for your country

const int KNOCK_PIN = 27;
const int LED_PIN = 26;

WebServer server(80);
int restState;
unsigned long lastKnock = 0;

const int LOG_SIZE = 15;
String knocks[LOG_SIZE];
int knockCount = 0;
long total = 0;

String timeNow() {
  struct tm t;
  if (getLocalTime(&t, 10)) {
    char text[20];
    strftime(text, sizeof(text), "%H:%M:%S", &t);
    return String(text);
  }
  return String(millis() / 1000) + " s after start";
}

String page() {
  String html = "<!DOCTYPE html><html><head><meta charset='utf-8'>";
  html += "<meta name='viewport' content='width=device-width, initial-scale=1'>";
  html += "<meta http-equiv='refresh' content='3'><title>Knock log</title></head>";
  html += "<body style='font-family:sans-serif;padding:16px'><h1>Knock log</h1>";
  html += "<p>Total knocks: <b>" + String(total) + "</b></p>";
  if (knockCount == 0) html += "<p>No knocks yet.</p>";
  for (int i = 0; i < knockCount; i++) html += "<p>" + knocks[i] + "</p>";
  html += "</body></html>";
  return html;
}

void setup() {
  Serial.begin(115200);
  pinMode(KNOCK_PIN, INPUT);
  pinMode(LED_PIN, OUTPUT);
  delay(300);
  restState = digitalRead(KNOCK_PIN);

  WiFi.begin(WIFI_NAME, WIFI_PASSWORD);
  while (WiFi.status() != WL_CONNECTED) delay(500);
  Serial.print("Open http://");
  Serial.println(WiFi.localIP());
  configTzTime(TIME_ZONE, "pool.ntp.org");

  server.on("/", []() { server.send(200, "text/html", page()); });
  server.begin();
}

void loop() {
  server.handleClient();

  if (digitalRead(KNOCK_PIN) != restState && millis() - lastKnock > 300) {
    lastKnock = millis();
    total++;
    for (int i = LOG_SIZE - 1; i > 0; i--) knocks[i] = knocks[i - 1];  // newest first
    knocks[0] = timeNow();
    if (knockCount < LOG_SIZE) knockCount++;
    Serial.println("Knock!");
    digitalWrite(LED_PIN, HIGH);
  }
  if (millis() - lastKnock > 150) digitalWrite(LED_PIN, LOW);
}

How it works

The knock sensor contains a tiny spring that touches a contact when it's shaken, so a knock briefly changes the signal. The ESP32 checks the pin thousands of times a second and treats each change as a knock, ignoring anything within 300 ms so that one knock isn't counted twice. The time comes from an internet time server, and the 15 most recent knocks are kept in a list for the web page.

Try this next

  • Recognise a secret knock pattern, such as knock-knock … knock.
  • Show how many knocks there were in the last hour.
  • Sound the buzzer from the ESP32 kit on every knock.

Troubleshooting

  • Knocks aren't detected: fix the sensor firmly to the surface with tape; it has to feel the vibration.
  • One knock counts several times: increase 300 to 500 ms.
  • The time shows "s after start": the ESP32 hasn't reached the time server yet; wait a minute.

Build it yourself

Everything used in this lesson comes in one kit, with parts tested by our engineers.

ESP32 IoT Starter Kit | Arduino IDE Compatible | Free Tutorials $57.00

Shop the kit