Arduino Workshop @ The Forge

Jeff, Karen & Bob

Blink on knock. No Delays. Only millis().

Piezo Knock Physical Image

Notes and explanations

Delays are often problematic. If you use a delay and your program is trying to run a repetitive piece of code such as the use of a sensor you will most likely lose a portion of the sensor hits during the delay pause. The way around this is with millis(). Millis() is a free running timer. You may either start and stop along a timeline or reset millis() to control an action. Keep in mind that sometime, someday your millis() will run out unless you have an end or reset programmed in. You can use either the built in LED or a wired LED with a resistor. The schematic does not show the LED.

Parts & Symbols

8 ohm speaker
1 M resister

Piezo Knock Schematic

Copy & Paste the following code to the Arduino IDE.

/* Blink without Delay upon Knock

Turns on and off a light emitting diode(LED) connected to a digital
pin, without using the delay() function. This means that other code
can run at the same time without being interrupted by the LED code.

The circuit:
* LED attached from pin 13 to ground.
* Note: on most Arduinos, there is already an LED on the board
that's attached to pin 13, so no hardware is needed for this example.

created 2005
by David A. Mellis
modified 8 Feb 2010
by Paul Stoffregen
modified 14 Sept 2013
by Karen Niemczyk

This example code is in the public domain.

// constants won't change. Used here to
// set pin numbers:
const int ledPin = 13; // the number of the LED pin
const int knockSensor = A0; // the piezo is connected to analog pin 0
const int threshold = 100; // threshold value to decide when the detected sound is a knock or not

// Variables will change:
// these variables will change:
int sensorReading = 0; // variable to store the value read from the sensor pin
int ledBlink = LOW;
int ledState = LOW; // variable used to store the last LED status, to toggle the light
long previousMillis = 0; // will store last time LED was updated

// the follow variables is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long interval = 1000; // interval at which to blink (milliseconds)

void setup() {
// set the digital pin as output:
pinMode(ledPin, OUTPUT);
Serial.begin(9600); // use the serial port

void loop()
// here is where you put code that needs to be running all the time. In this case it reads the sensor
// read the sensor and store it in the variable sensorReading:
sensorReading = analogRead(knockSensor);

// if the sensor reading is greater than the threshold:
if (sensorReading >= threshold) {
// toggle the status of the ledPin:
ledBlink = !ledBlink;

if (ledBlink == HIGH) {
// check to see if it's time to blink the LED; that is, if the
// difference between the current time and last time you blinked
// the LED is bigger than the interval at which you want to
// blink the LED.
unsigned long currentMillis = millis();

if(currentMillis - previousMillis > interval) {
// save the last time you blinked the LED
previousMillis = currentMillis;

// if the LED is off turn it on and vice-versa:
if (ledState == LOW)
ledState = HIGH;
ledState = LOW;

// set the LED with the ledState of the variable:
digitalWrite(ledPin, ledState);