knock sensor/Reading it/06. The first read
Reading it · 06 of 10

The first read

Three wires, no library and a sketch that reads the pin as fast as loop() can go and prints a line every time it changes to HIGH. Knock the table once and several lines appear, a few milliseconds apart: that is the spring ringing, and the rest of the book is about it.

Three wires

Three wires
Your board
Wires
3
VCC to
3V3
SIGNAL to
GPIO 4
GND to GND, VCC to 3V3, SIGNAL to GPIO 4. VCC is the voltage your pin receives during a knock, so on a 3.3 V board it has to be 3V3, never 5V. GPIO 4 is a plain input that the ESP32-S3 does not read at boot, so a knock while it powers up cannot change how it starts.

GND to GND. VCC to your board's logic supply: 5V on an Uno, 3V3 on the three 3.3 V boards. SIGNAL to a digital pin. NC stays unconnected.

The input pin is the same in every sketch in this book, and the same as the TK17 collision sensor's: D2 on an Uno, GPIO 25 on an ESP32, GPIO 4 on an ESP32-S3, GP15 on a Pico. None of them is read by the chip at boot or tied up with its flash memory, so a knock while the board starts cannot stop it starting. On an Uno, D2 is also one of the two pins that can raise an interrupt, which a later sketch needs.

The sketch

pinMode(KNOCK_PIN, INPUT) makes the pin an input with nothing of its own switched on, because the block already has its pull-down. digitalRead(KNOCK_PIN) returns HIGH or LOW: HIGH is the spring touching the rod.

The sketch prints only when the reading changes from LOW to HIGH, the start of a pulse, and it never waits. Both matter. A sketch that printed on every pass while SIGNAL is HIGH would print dozens of lines per pulse; a sketch with a delay(100) in it would be asleep for almost every pulse, because each one lasts about a millisecond.

What you should see

Open the serial monitor at 115200 and knock the table next to the block, firmly, once. Then once more. Something like this, though your times and counts will differ:

4212 ms  pulse 1
4214 ms  pulse 2
4217 ms  pulse 3
4220 ms  pulse 4
6031 ms  pulse 5
6033 ms  pulse 6
6036 ms  pulse 7

Two knocks, seven lines. The first four came within ten milliseconds of each other; that is one knock, with the spring touching the rod four times. The next article counts each burst as one.

The code

No library. pinMode makes the pin an input and digitalRead returns HIGH or LOW. The sketch remembers the last reading, so it can print on the change to HIGH rather than on every pass while SIGNAL is HIGH. Change KNOCK_PIN to the pin you wired SIGNAL to.

knock_first_read.ino
/*
  Knock Sensor - first read                              TK28 / /p/tk28

  Wiring. Count from the square pad on the TinkerBlock board, switch
  at the top, header at the bottom:

    GND    -> GND
    VCC    -> 5V on an Uno; 3V3 on an ESP32, ESP32-S3 or Pico
              (during a knock, SIGNAL gives your pin whatever VCC is)
    NC     -> nothing   (unconnected on the board)
    SIGNAL -> D2 on an Uno, GPIO 25 on an ESP32, GPIO 4 on an
              ESP32-S3, GP15 on a Raspberry Pi Pico

  Arduino IDE
    Tools > Board                 your board, e.g. ESP32S3 Dev Module
    Tools > Port                  the one that appears when you plug in
    Tools > USB CDC On Boot       Enabled   (ESP32-S3 only)
    No library needed.
*/

// The GPIO number SIGNAL is wired to.
// Uno: 2. ESP32: 25. ESP32-S3: 4. Pico: 15.
const int KNOCK_PIN = 4;

int last = LOW;                 // the reading last time round
unsigned long pulses = 0;

void setup() {
  Serial.begin(115200);
  pinMode(KNOCK_PIN, INPUT);    // the block has its own pull-down
}

void loop() {
  int level = digitalRead(KNOCK_PIN);

  if (level == HIGH && last == LOW) {   // a change to HIGH: a pulse
    pulses++;
    Serial.print(millis());
    Serial.print(" ms  pulse ");
    Serial.println(pulses);
  }
  last = level;                 // never waits: a pulse is about 1 ms
}

INPUT, not INPUT_PULLUP: the block has its own 10 kΩ pull-down, and the chip's pull-up would fight it. There is no delay() anywhere: a pulse lasts about a millisecond, and a sketch that sleeps misses it.

When it does not work

Nothing prints when I knock.

Watch the red LED while you knock the board itself firmly. If it never flickers, VCC or GND is not connected, or the cable is one pin over. If it flickers, SIGNAL is on a different pin from the one KNOCK_PIN names: the number is the GPIO number printed beside the pin, not its position along the header.

One knock prints three, five, sometimes ten lines.

That is right, and it is the point of this sketch. The spring swings back and forth and touches the rod several times for one knock, and each touch is a separate change to HIGH. The next article counts a knock once.

I added a delay() to slow the output down and now it misses knocks.

Each pulse lasts about a millisecond. A loop that sleeps for 100 ms reads the pin ten times a second and is asleep for almost all of every pulse. Keep loop() free of delay(), or move the reading into an interrupt, which is the article after next.

The serial monitor stays empty on my ESP32-S3.

Set Tools > USB CDC On Boot to Enabled and upload again. Without it the S3's USB port does not bring up a serial port at boot, so the sketch runs with nowhere to print. The red LED flickering tells you the block itself is fine.

Where this goes next

Counting a knock once, with a hold-off.

One knock is many pulses

Edit this page — content/books/knock-sensor/the-first-read.mdx

Community

Questions about this product

See what other owners have asked, and read their solutions.

Ask a question ↗

Knock Sensor

Loading discussions…

Discuss this article

Ask about this page. The answer stays here, on the page it belongs to, for whoever hits the same wall next.

Browse Modules and blocks on the forum