I recall having problems getting the Arduino Knock Lock to work properly. I’ve added my own modified code below – hopefully somebody finds it of use. The issue with the code seemed to be the speed at which the knock evaluations were taking place (meaning that one knock counted as more than one), and the sound sensitivity values in the code that caused the smallest sounds to be counted as knocks.
By modifying the delay() times and the quietKnock and loudKnock values, you should approach a more usable setup. The code could be improved further of course — but this will suffice.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
#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 = 90; const int loudKnock = 5500; boolean locked = false; int numberOfKnocks = 0; void setup() { // put your setup code here, to run once: 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() { // put your main code here, to run repeatedly: 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 > 0) { 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"); delay(2000); numberOfKnocks = 0; } } } boolean checkForKnock(int value) { if(value > quietKnock && value < loudKnock) { digitalWrite(yellowLed, HIGH); delay(250); digitalWrite(yellowLed, LOW); Serial.print("Valid knock of value "); Serial.println(value); return true; } else { Serial.print("Bad knock value"); Serial.println(value); return false; } } |
Thank you so much for your code improvements. My project works now.
Thanks, the key for me was in adding a delay after incrementing numberOfKnocks:
if (checkForKnocks(knockVal) == true) { // Validate the vibration as knocks with a custom function.
numberOfKnocks++; // if they’re valid knocks, then increment the knockCounter.
delay(200); // This was key to reducing in the noise and making it detect knocks
}
I ended up using these for the knock detection thresholds:
int quietKnock = 150;
int loudKnock = 5500;
Forgot to mention, I just built the circuit on the breadboard, rather than attaching the piezo directly to anything. The upshot of that is you need to make sure the breadboard isn’t moving around, and then produce a defined tap on the piezo, probably with something metallic or rigid plastic. For me, tapping it with tweezers worked, but not my finger for instance.
Hey, thank you for putting this up. I couldn’t get piezo to register anything at all and i couldn’t find where the code was wrong. I pasted yours in and kept comparing with mine until I found the extra = sign somewhere. Thanks for the help!