Hello,
I completed the Knock Lock in the project book using all of the pieces that came with the Arduino Starter Kit and I wanted to try and clean it up a little bit. Reading the serial monitor was a bit tricky, because it was cluttered with too much noise, so I changed the code so that it only checked for valid knocks if the knock value was greater than 2 instead of greater than 0. This worked well and eliminated all of the random knock values of 1.
The next thing I wanted to clean up was the problem of checking the same knock twice. Understandably, the table was still vibrating after the initial check and I would get a second (lower) value printed to the serial monitor. This could potentially cause a malfunction in your lock if the second value was high enough to be counted as a second valid knock. I decided to add a quarter second delay after checking for a valid knock to prevent this.
First I added a 200 ms delay right before returning true in the checkForKnock function and a 250 millisecond delay right before returning false. I choose a 200 ms delay for the true half of the if/else statement because that half already has a 50 ms delay when it flashes the yellow led. This worked perfectly and eliminated double checks for a single knock.
(See good.png, I couldn't figure out how to embed the image)
However, when I decided to just increase the delay of the flashing yellow light from 50 ms to 250 ms and remove the second delay (in the true half) the serial monitor starting showing a second check with a value of 3 after every valid knock. Why is this happening?
(See faulty.png)
I understand that the error doesn't really affect the operation of the lock, but I would really like to understand what is going on. Any thoughts are appreciated. Thank you!
Here is the full code:
#include <Servo.h>
Servo myServo;
const int piezo = A0;
const int switchPin = 2;
const int yellowLed = 3;
const int greenLed = 4;
const int redLed = 5;
int knockVal;
int switchVal;
const int quietKnock = 10;
const int loudKnock = 100;
boolean locked = false;
int numberOfKnocks = 0;
void setup() {
myServo.attach(9);
pinMode(yellowLed, OUTPUT);
pinMode(greenLed, OUTPUT);
pinMode(redLed, OUTPUT);
pinMode(switchPin, INPUT);
Serial.begin(9600);
digitalWrite(greenLed, HIGH);
myServo.write(0);
Serial.println("The box is unlocked!");
}
void loop() {
if (locked == false) {
switchVal = digitalRead(switchPin);
if (switchVal == HIGH) {
locked = true;
digitalWrite(greenLed, LOW);
digitalWrite(redLed, HIGH);
myServo.write(90);
Serial.println("The box is locked!");
delay(1000);
}
}
if (locked == true) {
knockVal = analogRead(piezo);
if (numberOfKnocks < 3 && knockVal > 2) {
if (checkForKnock(knockVal) == true) {
numberOfKnocks++;
}
Serial.print(3 - numberOfKnocks);
Serial.println(" more knocks to go");
}
if (numberOfKnocks >= 3) {
locked = false;
myServo.write(0);
delay(20);
digitalWrite(greenLed, HIGH);
digitalWrite(redLed, LOW);
Serial.println("The box is unlocked!");
numberOfKnocks = 0;
}
}
}
boolean checkForKnock(int value) {
if (value > quietKnock && value < loudKnock) {
digitalWrite(yellowLed, HIGH);
delay(50);
digitalWrite(yellowLed, LOW);
Serial.print("Valid knock of value: ");
Serial.println(value);
delay(200); //not sure why but splitting up the delay works better
return true;
}
else {
Serial.print("Bad knock value ");
Serial.println(value);
delay(250);
return false;
}
}