Updated comments
This commit is contained in:
@@ -1,7 +1,6 @@
|
|||||||
/* Secret Knock Trinket
|
/* Secret Knock Sensor
|
||||||
Code for running a secret knock lock on the Adafruit Trinket.
|
|
||||||
|
|
||||||
See full instructions here:
|
See original instructions here (note: The MySensors adopted code might differ in wiring. The instructions below is correct):
|
||||||
https://learn.adafruit.com/secret-knock-activated-drawer-lock/
|
https://learn.adafruit.com/secret-knock-activated-drawer-lock/
|
||||||
Version 13.10.31 Built with Arduino IDE 1.0.5
|
Version 13.10.31 Built with Arduino IDE 1.0.5
|
||||||
|
|
||||||
@@ -16,48 +15,50 @@
|
|||||||
Pin 0: Program button used for recording a new Knock (connect Pin0 -> button -> GND)
|
Pin 0: Program button used for recording a new Knock (connect Pin0 -> button -> GND)
|
||||||
Pin 1: Optional: Connect LED here (remember resisor in series)
|
Pin 1: Optional: Connect LED here (remember resisor in series)
|
||||||
Pin 2: Optional: Piezo element (for beeps).
|
Pin 2: Optional: Piezo element (for beeps).
|
||||||
Pin A1 (Analog 1): A sound sensor for sensing knocks. See MySensors purchase guide. I used this: http://rover.ebay.com/rover/1/711-53200-19255-0/1?icep_ff3=2&pub=5575069610&toolid=10001&campid=5337433187&customid=&icep_item=200941260251&ipn=psmain&icep_vectorid=229466&kwid=902099&mtid=824&kw=lg
|
Pin 1: A sound sensor (digital output) for sensing knocks. See MySensors purchase guide. I used this: http://rover.ebay.com/rover/1/711-53200-19255-0/1?icep_ff3=2&pub=5575069610&toolid=10001&campid=5337433187&customid=&icep_item=200941260251&ipn=psmain&icep_vectorid=229466&kwid=902099&mtid=824&kw=lg
|
||||||
Pin 4: Connects to a 1. Relay which open door or lock or 2. transistor or that opens a solenoid lock when HIGH (see adafruit guide for this option).
|
Pin 4: Connects to either 1. Relay which open door or lock or
|
||||||
|
2. transistor that opens a solenoid lock when HIGH (see adafruit guide for this option).
|
||||||
|
|
||||||
|
|
||||||
Connect radio according as usual(you can skip IRQ pin)
|
Connect radio according as usual(you can skip IRQ pin)
|
||||||
http://www.mysensors.org/build/connect_radio
|
http://www.mysensors.org/build/connect_radio
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <MySensor.h>
|
#include <MySensor.h>
|
||||||
#include <SPI.h>
|
#include <SPI.h>
|
||||||
|
|
||||||
|
|
||||||
#define CHILD_ID 99 // Id of the sensor child
|
#define CHILD_ID 99 // Id of the sensor child
|
||||||
|
|
||||||
const byte eepromValid = 121; // If the first byte in eeprom is this then the data is valid.
|
const byte eepromValid = 121; // If the first byte in eeprom is this then the data is valid.
|
||||||
|
|
||||||
/*Pin definitions*/
|
/*Pin definitions*/
|
||||||
const int programButton = 0; // (Digital 0) Record A New Knock button.
|
const int programButton = 0; // (Digital 0) Record A New Knock button.
|
||||||
const int ledPin = 1; // (Digital 1) The LED pin (if any)
|
const int ledPin = 1; // (Digital 1) The LED pin (if any)
|
||||||
const int knockSensor = 5; // (Digital 5) for using the microphone digital output (tune knob to register knock)
|
const int knockSensor = 5; // (Digital 5) for using the microphone digital output (tune knob to register knock)
|
||||||
const int audioOut = 2; // (Digital 2) for using the peizo as an output device. (Thing that goes beep.)
|
const int audioOut = 2; // (Digital 2) for using the peizo as an output device. (Thing that goes beep.)
|
||||||
const int lockPin = 4; // (Digital 4) The pin that activates the relay/solenoid lock.
|
const int lockPin = 4; // (Digital 4) The pin that activates the relay/solenoid lock.
|
||||||
|
|
||||||
/*Tuning constants. Changing the values below changes the behavior of the device.*/
|
/*Tuning constants. Changing the values below changes the behavior of the device.*/
|
||||||
int threshold = 3; // Minimum signal from the piezo to register as a knock. Higher = less sensitive. Typical values 1 - 10
|
int threshold = 3; // Minimum signal from the piezo to register as a knock. Higher = less sensitive. Typical values 1 - 10
|
||||||
const int rejectValue = 25; // If an individual knock is off by this percentage of a knock we don't unlock. Typical values 10-30
|
const int rejectValue = 25; // If an individual knock is off by this percentage of a knock we don't unlock. Typical values 10-30
|
||||||
const int averageRejectValue = 15; // If the average timing of all the knocks is off by this percent we don't unlock. Typical values 5-20
|
const int averageRejectValue = 15; // If the average timing of all the knocks is off by this percent we don't unlock. Typical values 5-20
|
||||||
const int knockFadeTime = 150; // Milliseconds we allow a knock to fade before we listen for another one. (Debounce timer.)
|
const int knockFadeTime = 150; // Milliseconds we allow a knock to fade before we listen for another one. (Debounce timer.)
|
||||||
const int lockOperateTime = 2500; // Milliseconds that we operate the lock solenoid latch before releasing it.
|
const int lockOperateTime = 2500; // Milliseconds that we operate the lock solenoid latch before releasing it.
|
||||||
const int maximumKnocks = 20; // Maximum number of knocks to listen for.
|
const int maximumKnocks = 20; // Maximum number of knocks to listen for.
|
||||||
const int knockComplete = 1200; // Longest time to wait for a knock before we assume that it's finished. (milliseconds)
|
const int knockComplete = 1200; // Longest time to wait for a knock before we assume that it's finished. (milliseconds)
|
||||||
|
|
||||||
byte secretCode[maximumKnocks] = {50, 25, 25, 50, 100, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // Initial setup: "Shave and a Hair Cut, two bits."
|
byte secretCode[maximumKnocks] = {50, 25, 25, 50, 100, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // Initial setup: "Shave and a Hair Cut, two bits."
|
||||||
int knockReadings[maximumKnocks]; // When someone knocks this array fills with the delays between knocks.
|
int knockReadings[maximumKnocks]; // When someone knocks this array fills with the delays between knocks.
|
||||||
int knockSensorValue = 0; // Last reading of the knock sensor.
|
int knockSensorValue = 0; // Last reading of the knock sensor.
|
||||||
boolean programModeActive = false; // True if we're trying to program a new knock.
|
boolean programModeActive = false; // True if we're trying to program a new knock.
|
||||||
|
|
||||||
bool lockStatus;
|
bool lockStatus;
|
||||||
MySensor gw;
|
MySensor gw;
|
||||||
MyMessage lockMsg(CHILD_ID, V_LOCK_STATUS);
|
MyMessage lockMsg(CHILD_ID, V_LOCK_STATUS);
|
||||||
|
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
|
|
||||||
pinMode(ledPin, OUTPUT);
|
pinMode(ledPin, OUTPUT);
|
||||||
pinMode(knockSensor, INPUT);
|
pinMode(knockSensor, INPUT);
|
||||||
@@ -79,9 +80,9 @@ void setup() {
|
|||||||
setLockState(lockStatus, true); // Now set the last known state and send it to controller
|
setLockState(lockStatus, true); // Now set the last known state and send it to controller
|
||||||
|
|
||||||
delay(500); // This delay is here because the solenoid lock returning to place can otherwise trigger and inadvertent knock.
|
delay(500); // This delay is here because the solenoid lock returning to place can otherwise trigger and inadvertent knock.
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
gw.process(); // Process incomming messages
|
gw.process(); // Process incomming messages
|
||||||
// Listen for any knock at all.
|
// Listen for any knock at all.
|
||||||
knockSensorValue = digitalRead(knockSensor);
|
knockSensorValue = digitalRead(knockSensor);
|
||||||
@@ -123,10 +124,10 @@ void loop() {
|
|||||||
listenToSecretKnock(); // We have our first knock. Go and see what other knocks are in store...
|
listenToSecretKnock(); // We have our first knock. Go and see what other knocks are in store...
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Records the timing of knocks.
|
// Records the timing of knocks.
|
||||||
void listenToSecretKnock(){
|
void listenToSecretKnock(){
|
||||||
int i = 0;
|
int i = 0;
|
||||||
// First reset the listening array.
|
// First reset the listening array.
|
||||||
for (i=0; i < maximumKnocks; i++){
|
for (i=0; i < maximumKnocks; i++){
|
||||||
@@ -186,11 +187,11 @@ void listenToSecretKnock(){
|
|||||||
} else { // If we're in programming mode we still validate the lock because it makes some numbers we need, we just don't do anything with the return.
|
} else { // If we're in programming mode we still validate the lock because it makes some numbers we need, we just don't do anything with the return.
|
||||||
validateKnock();
|
validateKnock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Unlocks the door.
|
// Unlocks the door.
|
||||||
void setLockState(bool state, bool send){
|
void setLockState(bool state, bool send){
|
||||||
if (state)
|
if (state)
|
||||||
Serial.println("open lock");
|
Serial.println("open lock");
|
||||||
else
|
else
|
||||||
@@ -203,11 +204,11 @@ void setLockState(bool state, bool send){
|
|||||||
gw.saveState(0,state);
|
gw.saveState(0,state);
|
||||||
lockStatus = state;
|
lockStatus = state;
|
||||||
delay(500); // This delay is here because releasing the latch can cause a vibration that will be sensed as a knock.
|
delay(500); // This delay is here because releasing the latch can cause a vibration that will be sensed as a knock.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks to see if our knock matches the secret.
|
// Checks to see if our knock matches the secret.
|
||||||
// Returns true if it's a good knock, false if it's not.
|
// Returns true if it's a good knock, false if it's not.
|
||||||
boolean validateKnock(){
|
boolean validateKnock(){
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
int currentKnockCount = 0;
|
int currentKnockCount = 0;
|
||||||
@@ -263,11 +264,11 @@ boolean validateKnock(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// reads the secret knock from EEPROM. (if any.)
|
// reads the secret knock from EEPROM. (if any.)
|
||||||
void readSecretKnock(){
|
void readSecretKnock(){
|
||||||
byte reading;
|
byte reading;
|
||||||
int i;
|
int i;
|
||||||
reading = gw.loadState(1);
|
reading = gw.loadState(1);
|
||||||
@@ -276,20 +277,20 @@ void readSecretKnock(){
|
|||||||
secretCode[i] = gw.loadState(i+2);
|
secretCode[i] = gw.loadState(i+2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//saves a new pattern too eeprom
|
//saves a new pattern too eeprom
|
||||||
void saveSecretKnock(){
|
void saveSecretKnock(){
|
||||||
gw.saveState(1, 0); // clear out the signature. That way we know if we didn't finish the write successfully.
|
gw.saveState(1, 0); // clear out the signature. That way we know if we didn't finish the write successfully.
|
||||||
for (int i=0; i < maximumKnocks; i++){
|
for (int i=0; i < maximumKnocks; i++){
|
||||||
gw.saveState(i+2, secretCode[i]);
|
gw.saveState(i+2, secretCode[i]);
|
||||||
}
|
}
|
||||||
gw.saveState(1, eepromValid); // all good. Write the signature so we'll know it's all good.
|
gw.saveState(1, eepromValid); // all good. Write the signature so we'll know it's all good.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Plays back the pattern of the knock in blinks and beeps
|
// Plays back the pattern of the knock in blinks and beeps
|
||||||
void playbackKnock(int maxKnockInterval){
|
void playbackKnock(int maxKnockInterval){
|
||||||
digitalWrite(ledPin, LOW);
|
digitalWrite(ledPin, LOW);
|
||||||
delay(1000);
|
delay(1000);
|
||||||
digitalWrite(ledPin, HIGH);
|
digitalWrite(ledPin, HIGH);
|
||||||
@@ -304,22 +305,22 @@ void playbackKnock(int maxKnockInterval){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
digitalWrite(ledPin, LOW);
|
digitalWrite(ledPin, LOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deals with the knock delay thingy.
|
// Deals with the knock delay thingy.
|
||||||
void knockDelay(){
|
void knockDelay(){
|
||||||
int itterations = (knockFadeTime / 20); // Wait for the peak to dissipate before listening to next one.
|
int itterations = (knockFadeTime / 20); // Wait for the peak to dissipate before listening to next one.
|
||||||
for (int i=0; i < itterations; i++){
|
for (int i=0; i < itterations; i++){
|
||||||
delay(10);
|
delay(10);
|
||||||
analogRead(knockSensor); // This is done in an attempt to defuse the analog sensor's capacitor that will give false readings on high impedance sensors.
|
analogRead(knockSensor); // This is done in an attempt to defuse the analog sensor's capacitor that will give false readings on high impedance sensors.
|
||||||
delay(10);
|
delay(10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Plays a non-musical tone on the piezo.
|
// Plays a non-musical tone on the piezo.
|
||||||
// playTime = milliseconds to play the tone
|
// playTime = milliseconds to play the tone
|
||||||
// delayTime = time in microseconds between ticks. (smaller=higher pitch tone.)
|
// delayTime = time in microseconds between ticks. (smaller=higher pitch tone.)
|
||||||
void chirp(int playTime, int delayTime){
|
void chirp(int playTime, int delayTime){
|
||||||
long loopTime = (playTime * 1000L) / delayTime;
|
long loopTime = (playTime * 1000L) / delayTime;
|
||||||
pinMode(audioOut, OUTPUT);
|
pinMode(audioOut, OUTPUT);
|
||||||
for(int i=0; i < loopTime; i++){
|
for(int i=0; i < loopTime; i++){
|
||||||
@@ -328,11 +329,11 @@ void chirp(int playTime, int delayTime){
|
|||||||
digitalWrite(audioOut, LOW);
|
digitalWrite(audioOut, LOW);
|
||||||
}
|
}
|
||||||
pinMode(audioOut, INPUT);
|
pinMode(audioOut, INPUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void incomingMessage(const MyMessage &message) {
|
void incomingMessage(const MyMessage &message) {
|
||||||
// We only expect one type of message from controller. But we better check anyway.
|
// We only expect one type of message from controller. But we better check anyway.
|
||||||
if (message.type==V_LOCK_STATUS) {
|
if (message.type==V_LOCK_STATUS) {
|
||||||
// Change relay state
|
// Change relay state
|
||||||
@@ -342,5 +343,5 @@ void incomingMessage(const MyMessage &message) {
|
|||||||
Serial.print("Incoming lock status:");
|
Serial.print("Incoming lock status:");
|
||||||
Serial.println(message.getBool());
|
Serial.println(message.getBool());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user