简体   繁体   中英

Servo motor control by knocking

I am working on a project with arduino. Basically what i want is to open a door by recognising the the knocking pattern of the person ie the door will unlock only when the knock of person matches with that stored in the arduino. Now to unlock the door i am using the servo motor. I want to run the motor only when the person enters the correct knock otherwise not,But when i run the code , the servo motor begins to run as soon as the code execute without waiting for the correct knock. Can anyone help me to troubleshoot the mistake i am making in the code.Following is the code:

const int knockSensor = 0;         // Piezo sensor on pin 0.
const int programSwitch = 2;       // If this is high we program a new code.        
const int lockMotor = 3;           // Gear motor used to turn the lock.
const int redLED = 4;              // Status LED
const int greenLED = 5;            // Status LED

// Tuning constants.  Could be made vars and hoooked to potentiometers for soft      configuration, etc.
const int threshold = 10;           // Minimum signal from the piezo to register as a      knock
const int rejectValue = 25;        // If an individual knock is off by this percentage  of a knock we don't unlock..
const int averageRejectValue = 15; // If the average timing of the knocks is off by this percent we don't unlock.
const int knockFadeTime = 150;     // milliseconds we allow a knock to fade before we  listen for another one. (Debounce timer.)
const int lockTurnTime = 500;      // milliseconds that we run the motor to get it to go a half turn.

const int maximumKnocks = 50;       // 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.


// Variables.
 int 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 delays  between knocks.
 int knockSensorValue = 0;           // Last reading of the knock sensor.
 int programButtonPressed = false;   // Flag so we remember the programming button setting at the end of the cycle.

#include <Servo.h>
Servo myservo;  // create servo object to control a servo 
            // a maximum of eight servo objects can be created 


int pos = 0; 
void setup() {
pinMode(lockMotor, OUTPUT);
pinMode(redLED, OUTPUT);
pinMode(greenLED, OUTPUT);
pinMode(programSwitch, INPUT);
myservo.attach(8);  // attaches the servo on pin 9 to the servo object 

Serial.begin(9600);                         // Uncomment the Serial.bla lines for debugging.
Serial.println("Program start.");           // but feel free to comment them out after it's working right.

digitalWrite(greenLED, HIGH);      // Green LED on, everything is go.
}

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

if (digitalRead(programSwitch)==HIGH){  // is the program button pressed?
programButtonPressed = true;          // Yes, so lets save that state
digitalWrite(redLED, HIGH);           // and turn on the red light too so we know we're programming.
} else {
programButtonPressed = false;
digitalWrite(redLED, LOW);
} 

if (knockSensorValue >=threshold){
listenToSecretKnock();
} 
 } 

// Records the timing of knocks.
void listenToSecretKnock(){
Serial.println("knock starting");   

int i = 0;
 // First lets reset the listening array.
for (i=0;i<maximumKnocks;i++){
knockReadings[i]=0;
} 

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

digitalWrite(greenLED, LOW);                // we blink the LED for a bit as a visual indicator of the knock.
if (programButtonPressed==true){
 digitalWrite(redLED, LOW);                         // and the red one too if we're programming a new knock.
}
delay(knockFadeTime);                                   // wait for this peak to fade before we listen to the next one.
digitalWrite(greenLED, HIGH);  
if (programButtonPressed==true){
 digitalWrite(redLED, HIGH);                        
}
do {
//listen for the next knock or wait for it to timeout. 
knockSensorValue = analogRead(knockSensor);
if (knockSensorValue >=threshold){                   //got another knock...
  //record the delay time.
  Serial.println("knock.");
  now=millis();
  knockReadings[currentKnockNumber] = now-startTime;
  currentKnockNumber ++;                             //increment the counter
  startTime=now;          
  // and reset our timer for the next knock
  digitalWrite(greenLED, LOW);  
  if (programButtonPressed==true){
    digitalWrite(redLED, LOW);                       // and the red one too if we're programming a new knock.
  }
  delay(knockFadeTime);                              // again, a little delay to let the knock decay.
  digitalWrite(greenLED, HIGH);
  if (programButtonPressed==true){
    digitalWrite(redLED, HIGH);                         
  }
  }

 now=millis();

//did we timeout or run out of knocks?
} while ((now-startTime < knockComplete) && (currentKnockNumber < maximumKnocks));

 //we've got our knock recorded, lets see if it's valid
if (programButtonPressed==false){             // only if we're not in progrmaing mode.
 if (validateKnock() == true){
  triggerDoorUnlock(); 
 } else {
  Serial.println("Secret knock failed.");
  digitalWrite(greenLED, LOW);          // We didn't unlock, so blink the red LED as visual feedback.
  for (i=0;i<4;i++){                    
    digitalWrite(redLED, HIGH);
    delay(100);
    digitalWrite(redLED, LOW);
    delay(100);
  }
  digitalWrite(greenLED, HIGH);
  }
  } else { // if we're in programming mode we still validate the lock, we just don't do anything with the lock
validateKnock();
// and we blink the green and red alternately to show that program is complete.
 Serial.println("New lock stored.");
 digitalWrite(redLED, LOW);
 digitalWrite(greenLED, HIGH);
 for (i=0;i<3;i++){
  delay(100);
  digitalWrite(redLED, HIGH);
  digitalWrite(greenLED, LOW);
  delay(100);
  digitalWrite(redLED, LOW);
  digitalWrite(greenLED, HIGH);      
  }
   }
     }


 // Runs the motor (or whatever) to unlock the door.
 void triggerDoorUnlock(){
 Serial.println("Door unlocked!");
  int i=0;

 // turn the motor on for a bit.
  for(pos = 0; pos < 180; pos += 1)  // goes from 0 degrees to 180 degrees 
 {                                  // in steps of 1 degree 
  myservo.write(pos);              // tell servo to go to position in variable 'pos' 
  delay (5000);                    // Wait a bit.

  }  

 digitalWrite(greenLED, HIGH);            // And the green LED too.


 for(pos = 180; pos>=1; pos-=1)     // goes from 180 degrees to 0 degrees 
 {                                
 myservo.write(pos);              // tell servo to go to position in variable 'pos' 
 delay(5000);                       // waits 15ms for the servo to reach the position 
 }            // Turn the motor off.

  // Blink the green LED a few times for more visual feedback.
  for (i=0; i < 5; i++){   
  digitalWrite(greenLED, LOW);
  delay(100);
  digitalWrite(greenLED, HIGH);
  delay(100);
   }

   }

Not being familiar with Arduino, I can't say for sure if you're missing anything specific to the API, but the only way I see it being possible for voltage to be applied to the servo is if your knock validation returns true, or the servo object isn't set up completely correctly.

The documentation for servos suggests fairly straightforward setup.

I would also verify the validateKnock() method and make sure it isn't always returning true - maybe step through it by hand with some sample code. I see that your validateKnock method isn't posted, so it's impossible to say why it might not be working if that is the issue.

Are you sure a voltage isn't being applied to the servo as soon as you bind the object to the pin? Does the servo object have some properties you are forgetting to set on init?

change your 0 degree to 1 degree and 180 degrees to 179 degrees. It should stop it from running. if your using a 180 degree servo. It can't reach it's min/max limits.

Have you tried to calibrate the piezo sensor? Because, most arduino boards use 10 bit ADC meaning 1024 divisions of voltage range (0-5000mV) and looking into your code, it seems like you activate the sensor as soon as the level goes above 10 (ie approx. 50 mV) while this contributes to the sensitivity of the sensor, it also means that any little noise would be registered unless you use an appropriately calibrated Piezo Sensor. Also, you need to show the validateKnock code in order to help us help you...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM