C 秘密敲打工程中的振幅识别

C 秘密敲打工程中的振幅识别,c,arrays,arduino,arduino-ide,arduino-uno,C,Arrays,Arduino,Arduino Ide,Arduino Uno,我正在做这样的项目该项目只处理敲打之间的时间间隔,我尝试添加振幅作为输入,如果我只使用上面链接中的代码,它工作正常,但我也想添加振幅(响亮和柔和的敲打)作为输入。但我的代码仍然存在问题,它无法识别敲打和LED表现怪异。我需要识别爆震时间间隔和爆震幅度。注释“这是我添加的”是我自己添加的代码,但代码不起作用。谁能告诉我我的代码有什么问题吗? 下面是代码: #include <EEPROM.h> const byte eepromValid = 123; // If the fir

我正在做这样的项目

该项目只处理敲打之间的时间间隔,我尝试添加振幅作为输入,如果我只使用上面链接中的代码,它工作正常,但我也想添加振幅(响亮和柔和的敲打)作为输入。
但我的代码仍然存在问题,它无法识别敲打和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);
}
#包括
常量字节eepromValid=123;//如果eeprom中的第一个字节为该字节,则数据有效。
/*引脚定义*/
常量int programButton=0;//记录一个新的敲击按钮。
常数int ledPin=1;//内置LED
常数int knockSensor=1;//(模拟1)用于将压电元件用作输入设备。(aka爆震传感器)
常数int audioOut=2;//(数字2)用于将peizo用作输出设备。(发出嘟嘟声的东西。)
常数int lockPin=3;//激活电磁阀锁的销。
/*调整常数。更改以下值会更改设备的行为*/
int threshold=3;//压电元件发出的最小信号,记录为爆震。较高=较不敏感。典型值1-10
常数int rejectValue=25;//如果单个爆震按此爆震百分比关闭,我们不会解锁。典型值10-30
const int averageRejectValue=15;//如果所有敲打的平均时间偏离这个百分比,我们不会解锁。典型值5-20
常量int knockFadeTime=150;//在我们听到另一个敲击声之前,我们会让敲击声消失几毫秒。(去盎司计时器。)
常数int lockOperateTime=2500;//在释放锁电磁阀闩锁之前,我们操作锁电磁阀闩锁的毫秒数。
const int maximumnocks=20;//要侦听的最大敲打次数。
常量int最大值为20;//这就是我要补充的
常数int安培云=10;//这就是我要补充的
常数int ampSoft=20;//这就是我要补充的
常量int knockComplete=1200;//在我们认为敲门声结束之前等待敲门声的最长时间。(毫秒)
字节secretCode[maximumKnocks]={50,25,25,50,100,50,0,0,0,0,0,0,0,0,0,0,0,0};//初始设置:“剃须和理发,两位。”
字节secretAmp[maximumAmp]={10,10,10,10,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0};//这就是我要补充的
int knockReads[最大敲打次数];//当有人敲门时,这个数组充满了敲门之间的延迟。
整数安培读数[最大值];//这就是我要补充的
int knockSensorValue=0;//爆震传感器的最后读数。
int amp=0;//这就是我要补充的
布尔programModeActive=false;//如果我们正在尝试编程一个新的敲门,则为True。
无效设置(){
引脚模式(LED引脚,输出);
引脚模式(锁定引脚,输出);
readSecretKnock();//从EEPROM加载秘密敲门(如果有)。
doorUnlock(500);//通电时,先打开车门一点。用于系统检查,并在忘记钥匙时允许进入。
延迟(500);//之所以出现此延迟,是因为电磁阀锁返回原位会触发意外爆震。
}
void循环(){
//听有没有敲门声。
knockSensor值=模拟读数(knockSensor);
如果(digitalRead(programButton)=高){//程序按钮按下了吗?
延迟(100);//便宜的去盎司。
如果(数字读取(编程按钮)=高){
如果(programModeActive==false){//如果我们没有处于编程模式,请打开它。
programModeActive=true;//请记住我们处于编程模式。
digitalWrite(发光二极管,高);//也打开红灯,以便用户知道我们正在编程。
啁啾声(5001500);//并播放音调,以防用户看不到LED。
啁啾(5001000);
}否则{//如果我们处于编程模式,请将其关闭。
programModeActive=false;
数字写入(ledPin,低电平);
啁啾声(5001000);//关闭编程LED并播放悲伤的音符。
啁啾(5001500);
延迟(500);
}
while(数字读取(编程按钮)=高){
延迟(10);//等待按钮松开。
} 
}
延迟(250);//又一次廉价的去盎司。时间更长,因为释放按钮有时会感觉到敲击声。
}
如果(knockSensorValue>=阈值){
如果(programModeActive==true){//当我们感觉到爆震时,LED闪烁。
数字写入(ledPin,低电平);
}否则{
数字写入(ledPin,高电平);
}
敲除延迟();
如果(programModeActive==true){//取消闪烁LED。
数字写入(ledPin,高电平);
}否则{
数字写入(ledPin,低电平);
}
listenToSecretKnock();//我们有了第一次敲门。去看看还有什么其他的敲门。。。
}
} 
//记录敲击的时间。
void listenToSecretKnock(){
int i=0;
int j=0;
//首先重置侦听数组。
对于(i=0;i=3&&knockSensorValue=76){//这是我添加的内容
amp=amplound;//这是我添加的内容
}
安培读数[当前安培数值]