2014-04-15 10 views
0

我在做這樣的項目http://grathio.com/2013/11/new-old-project-secret-knock-drawer-lock/


該項目只處理爆震之間的時間間隔,並且我嘗試添加振幅作爲輸入,如果我只是使用上面的鏈接的代碼工作正常但我想增加幅度(響亮和軟敲)作爲輸入
但我的代碼仍然有問題,它無法識別爆震和LED代理怪異。我需要識別爆震時間間隔和爆震振幅。評論'這是我添加'是我自己添加的代碼,但代碼不起作用。 任何人都可以告訴我我的代碼有什麼問題嗎?

下面是代碼:

在祕密敲項目中確定的幅度

#include <EEPROM.h> 
const byte eepromValid = 123; // If the first byte in eeprom is this then the data is valid. 

/*Pin definitions*/ 
const int programButton = 0; // Record A New Knock button. 
const int ledPin = 1;   // The built in LED 
const int knockSensor = 1;  // (Analog 1) for using the piezo as an input device. (aka knock sensor) 
const int audioOut = 2;  // (Digial 2) for using the peizo as an output device. (Thing that goes beep.) 
const int lockPin = 3;   // The pin that activates the solenoid lock. 

/*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 
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 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 maximumKnocks = 20;  // Maximum number of knocks to listen for. 
const int maximumAmp = 20;  // This is what i add 
const int ampLoud = 10;  // This is what i add 
const int ampSoft = 20;  // This is what i add 
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 secretAmp[maximumAmp] = {10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};  // This is what i add 
int knockReadings[maximumKnocks]; // When someone knocks this array fills with the delays between knocks. 
int ampReadings[maximumAmp];  // This is what i add 
int knockSensorValue = 0; // Last reading of the knock sensor. 
int amp = 0;  // This is what i add 
boolean programModeActive = false; // True if we're trying to program a new knock. 

void setup() { 
    pinMode(ledPin, OUTPUT); 
    pinMode(lockPin, OUTPUT); 
    readSecretKnock(); // Load the secret knock (if any) from EEPROM. 
    doorUnlock(500);  // Unlock the door for a bit when we power up. For system check and to allow a way in if the key is forgotten. 
    delay(500);   // This delay is here because the solenoid lock returning to place can otherwise trigger and inadvertent knock. 
} 

void loop() { 
    // Listen for any knock at all. 
    knockSensorValue = analogRead(knockSensor); 

    if (digitalRead(programButton) == HIGH){ // is the program button pressed? 
    delay(100); // Cheap debounce. 
    if (digitalRead(programButton) == HIGH){ 
     if (programModeActive == false){  // If we're not in programming mode, turn it on. 
     programModeActive = true;   // Remember we're in programming mode. 
     digitalWrite(ledPin, HIGH);  // Turn on the red light too so the user knows we're programming. 
     chirp(500, 1500);     // And play a tone in case the user can't see the LED. 
     chirp(500, 1000); 
     } else {        // If we are in programing mode, turn it off. 
     programModeActive = false; 
     digitalWrite(ledPin, LOW); 
     chirp(500, 1000);     // Turn off the programming LED and play a sad note. 
     chirp(500, 1500); 
     delay(500); 
     } 
     while (digitalRead(programButton) == HIGH){ 
     delay(10);       // Hang around until the button is released. 
     } 
    } 
    delay(250); // Another cheap debounce. Longer because releasing the button can sometimes be sensed as a knock. 
    } 


    if (knockSensorValue >= threshold){ 
    if (programModeActive == true){ // Blink the LED when we sense a knock. 
     digitalWrite(ledPin, LOW); 
    } else { 
     digitalWrite(ledPin, HIGH); 
    } 
    knockDelay(); 
    if (programModeActive == true){ // Un-blink the LED. 
     digitalWrite(ledPin, HIGH); 
    } else { 
     digitalWrite(ledPin, LOW); 
    } 
    listenToSecretKnock();   // We have our first knock. Go and see what other knocks are in store... 
    } 

} 

// Records the timing of knocks. 
void listenToSecretKnock(){ 
    int i = 0; 
    int j = 0; 
    // First reset the listening array. 
    for (i=0; i < maximumKnocks; i++){ 
    knockReadings[i] = 0; 
    } 

    for (j=0; j < maximumAmp; j++){  // This is what i add 
    ampReadings[j] = 0; 
    } 

    int currentKnockNumber = 0;    // Position counter for the array. 
    int currentAmpNumber = 0; 
    int startTime = millis();     // Reference for when this knock started. 
    int now = millis(); 

    do {          // Listen for the next knock or wait for it to timeout. 
    knockSensorValue = analogRead(knockSensor); 
    //=========================================================================================================== 
     if(knockSensorValue >=3 && knockSensorValue <=75){  // This is what i add 
      amp = ampSoft;  // This is what i add 
     } 
     if(knockSensorValue >=76){  // This is what i add 
      amp = ampLoud;   // This is what i add 
     } 
     ampReadings[currentAmpNumber] = amp;  // This is what i add 
     currentAmpNumber++;   // This is what i add 
    //=========================================================================================================== 
    if (knockSensorValue >= threshold){     // Here's another knock. Save the time between knocks. 
     now=millis(); 
     knockReadings[currentKnockNumber] = now - startTime; 
     currentKnockNumber ++;        
     startTime = now;   


     if (programModeActive==true){  // Blink the LED when we sense a knock. 
     digitalWrite(ledPin, LOW); 
     } else { 
     digitalWrite(ledPin, HIGH); 
     } 
     knockDelay(); 
     if (programModeActive == true){ // Un-blink the LED. 
     digitalWrite(ledPin, HIGH); 
     } else { 
     digitalWrite(ledPin, LOW); 
     } 
    } 

    now = millis(); 

    // Stop listening if there are too many knocks or there is too much time between knocks. 
    } while ((now-startTime < knockComplete) && (currentKnockNumber < maximumKnocks)); 

    //we've got our knock recorded, lets see if it's valid 
    if (programModeActive == false){   // Only do this if we're not recording a new knock. 
    if (validateKnock() == true){ 
     doorUnlock(lockOperateTime); 
    } else { 
     // knock is invalid. Blink the LED as a warning to others. 
     for (i=0; i < 4; i++){   
     digitalWrite(ledPin, HIGH); 
     delay(50); 
     digitalWrite(ledPin, LOW); 
     delay(50); 
     } 
    } 
    } 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(); 
    } 
} 


// Unlocks the door. 
void doorUnlock(int delayTime){ 
    digitalWrite(ledPin, HIGH); 
    digitalWrite(lockPin, HIGH); 
    delay(delayTime); 
    digitalWrite(lockPin, LOW); 
    digitalWrite(ledPin, LOW); 
    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. 
// Returns true if it's a good knock, false if it's not. 
boolean validateKnock(){ 
    int i = 0; 

    int currentKnockCount = 0; 
    int secretKnockCount = 0; 
    int currentAmpCount = 0;   // This is what i add 
    int secretAmpCount = 0;  // This is what i add 
    int maxKnockInterval = 0; // We use this later to normalize the times. 

    for (i=0;i<maximumKnocks;i++){ 
    if (knockReadings[i] > 0){ 
     currentKnockCount++; 
    } 
    if (secretCode[i] > 0){   
     secretKnockCount++; 
    } 

    if (ampReadings[i] > 0){  // This is what i add 
     currentAmpCount++;  // This is what i add 
    } 
    if (secretAmp[i] > 0){  // This is what i add 
     secretAmpCount++;  // This is what i add 
    } 

    if (knockReadings[i] > maxKnockInterval){ // Collect normalization data while we're looping. 
     maxKnockInterval = knockReadings[i]; 
    } 
    } 

    // If we're recording a new knock, save the info and get out of here. 
    if (programModeActive == true){ 
     for (i=0; i < maximumKnocks; i++){ // Normalize the time between knocks. (the longest time = 100) 
     secretCode[i] = map(knockReadings[i], 0, maxKnockInterval, 0, 100); 
     } 
     for (int j = 0; j < maximumAmp; j++){ 
     secretAmp[j] = ampReadings[j]; 
     } 
     saveSecretKnock();    // save the result to EEPROM 
     programModeActive = false; 
     playbackKnock(maxKnockInterval); 
     return false; 
    } 

    if (currentKnockCount != secretKnockCount && currentAmpCount != secretAmpCount){ // Easiest check first. If the number of knocks is wrong, don't unlock.  // This is what i add 
    return false; 
    } 

    /* Now we compare the relative intervals of our knocks, not the absolute time between them. 
     (ie: if you do the same pattern slow or fast it should still open the door.) 
     This makes it less picky, which while making it less secure can also make it 
     less of a pain to use if you're tempo is a little slow or fast. 
    */ 
    int totaltimeDifferences = 0; 
    int timeDiff = 0; 
    for (i=0; i < maximumKnocks; i++){ // Normalize the times 
    knockReadings[i]= map(knockReadings[i], 0, maxKnockInterval, 0, 100);  
    timeDiff = abs(knockReadings[i] - secretCode[i]); 
    if (timeDiff > rejectValue){  // Individual value too far out of whack. No access for this knock! 
     return false; 
    } 
    totaltimeDifferences += timeDiff; 
    } 
    // It can also fail if the whole thing is too inaccurate. 
    if (totaltimeDifferences/secretKnockCount > averageRejectValue){ 
    return false; 
    } 

    return true; 
} 


// reads the secret knock from EEPROM. (if any.) 
void readSecretKnock(){ 
    byte reading; 
    int i; 
    int j; 
    reading = EEPROM.read(0); 
    if (reading == eepromValid){ // only read EEPROM if the signature byte is correct. 
    for (int i=0; i < maximumKnocks ;i++){ 
     secretCode[i] = EEPROM.read(i+1); 
    } 
    for (int j=0; j < maximumAmp ;j++){  // This is what i add 
     secretAmp[j] = EEPROM.read(j+1);  // This is what i add 
    } 
    } 
} 


//saves a new pattern too eeprom 
void saveSecretKnock(){ 
    EEPROM.write(0, 0); // clear out the signature. That way we know if we didn't finish the write successfully. 
    for (int i=0; i < maximumKnocks; i++){ 
    EEPROM.write(i+1, secretCode[i]); 
    EEPROM.write(i+1, secretAmp[i]);  // This is what i add 
    } 
    EEPROM.write(0, 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 
void playbackKnock(int maxKnockInterval){ 
     digitalWrite(ledPin, LOW); 
     delay(1000); 
     digitalWrite(ledPin, HIGH); 
     chirp(200, 1800); 
     for (int i = 0; i < maximumKnocks ; i++){ 
     digitalWrite(ledPin, LOW); 
     // only turn it on if there's a delay 
     if (secretCode[i] > 0){         
      delay(map(secretCode[i], 0, 100, 0, maxKnockInterval)); // Expand the time back out to what it was. Roughly. 
      digitalWrite(ledPin, HIGH); 
      chirp(200, 1800); 
     } 
     } 
     digitalWrite(ledPin, LOW); 
} 

// Deals with the knock delay thingy. 
void knockDelay(){ 
    int itterations = (knockFadeTime/20);  // Wait for the peak to dissipate before listening to next one. 
    for (int i=0; i < itterations; i++){ 
    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. 
    delay(10); 
    } 
} 

// Plays a non-musical tone on the piezo. 
// playTime = milliseconds to play the tone 
// delayTime = time in microseconds between ticks. (smaller=higher pitch tone.) 
void chirp(int playTime, int delayTime){ 
    long loopTime = (playTime * 1000L)/delayTime; 
    pinMode(audioOut, OUTPUT); 
    for(int i=0; i < loopTime; i++){ 
    digitalWrite(audioOut, HIGH); 
    delayMicroseconds(delayTime); 
    digitalWrite(audioOut, LOW); 
    } 
    pinMode(audioOut, INPUT); 
} 
+0

,什麼是問題? –

+0

@MichaelWalz,問題是爲什麼我的代碼不工作,如果我也添加幅度作爲輸入。 'This is what I add'是我添加的代碼。我的代碼有什麼問題導致它無法工作? – user3110542

回答

1

我猜你是想記錄敲模式,並在同一時間敲卷。所以敲擊更輕或更響的類似模式不會激活鎖定。如果是這種情況,我建議你讓數組mySecretKnock成爲一個二維數組。 然後使用兩個變量記錄模擬和數字輸入。

在相同的控制結構中一個接一個地捕獲它們。

即,如果一個值足夠高以觸發if語句,則只需在下一行代碼中記錄另一個的值即可。

請記住,如果數字後一個處理的模擬輸入會更低,所以你可能需要調整你的閥值號