Monday, 6 June 2016

Major project. Self resetting mouse trap

Major project. Self resetting mouse trap

Project description:

A mouse trap that resets after a mouse has been captured. What the trap does is takes 10 readings of the ambient light and stores the average, it then turns on the laser and takes readings and stores the average of that. the average of both averages becomes the trigger point meaning that if the laser light level drops below the trigger point then the servo method is called opening the trap floor and closing it again, next the trap gets re-calibrated again and becomes set.  

Fritzing layout:



Video of it working:



Arduino Code:


#include <StackArray.h>
#include <Servo.h>

int laserPin = 13;
int LDRPin = A0;
int switchPin = 3;
int servoPin = 9;
Servo myservo; 
#define TURN_TIME 290  
#define TURN_TIME_MINUS 300     
// minimum difference needed between ambient light level and laser calibration
const int min_diff = 200;   
// Larger values make it LESS sensitive
const int LASER_SENSITIVITY = 30;

const int AMBIENT_SAMPLE_DELAYSTART = 400;
const int NUM_AMBIENT_SAMPLES = 10;
const int TOTAL_LASER_SAMPLES = 15;
const int GOOD_LASER_SAMPLES = 5;

// variable for the armed state
boolean isArmed = false; 
// has the wire been tripped     
boolean isTriggered = false;
// variable set by the calibration process 
int threshold = 0; 

// variable to store the servo position
int pos = 0;  

void setup() {
  //serial communication at 9600 bits per second:
  Serial.begin(9600);

  myservo.attach(9);  // attaches the servo on pin 9 to the servo object
  myservo.write(90);
  // make the LDR's pin an input:
  pinMode(LDRPin, INPUT);
  //make the laser's pin an output:
  pinMode(laserPin, OUTPUT);
  //turn laser on
  digitalWrite(laserPin, HIGH); 

  // set initial state
  setLaser( false ) ;
  // intial 'test' to be sure working
  setLaser( false ) ;  delay(500);  setLaser( false ) ; 

  // start unarmed
  setArmedState(false);  

  // calibrate the laser light level in the current environment
  calibrate();
}



void loop() {
  //TODO get the average of LDR sample and laser sample then set as threshold
  
  // read the LDR sensor
  int sample = analogRead(LDRPin);
  //Serial.print("Sample = ");  Serial.println(sample);

  // check to see if the laser beam is interrupted based on the threshold
  if ( sample < threshold ) {
    Serial.print("Triggering Sample: " ) ; Serial.println( sample ) ;
    isTriggered = true;
  }

  if (isTriggered) {
    servo();
    isTriggered=false;
  }
  
}

// function to flip the armed state of the trip wire
void setArmedState( bool setArmed ){
  setLaser( setArmed ) ;
  isTriggered = false ;
  isArmed = setArmed ;

  if (!setArmed){
    Serial.println("Disarmed") ;
  } else {
    Serial.println("Armed") ;
  } 
}

void calibrate(){
  StackArray<int> stack;
  
  int sample = 0;              
  unsigned int ambSampleTotal = 0;
  unsigned int lasSampleTotal = 0;
  int ambBaseline = 0; 
  int lasThreshold = 0; 
  int sum = 0;         
  
  setLaser( false ) ;     // ensure Laser is off
  
  // Take the average of N readings for our ambient light ambBaseline
  ambSampleTotal = 0;
  delay(AMBIENT_SAMPLE_DELAYSTART) ;  // Considerable bounce when first reading
  Serial.println("Sampling ambient light levels") ;
  for (int i=0; i<NUM_AMBIENT_SAMPLES; i++){
    sample = analogRead(LDRPin); 
    //Serial.print("Ambient Sample: " ) ;  Serial.println( sample ) ;

    ambSampleTotal += sample ; // take reading and add it to the sample

  }
  ambBaseline = ambSampleTotal / NUM_AMBIENT_SAMPLES;
  Serial.print("Ambient light level = ");  Serial.println(ambBaseline);  


  Serial.println("Sampling Laser light levels.") ;
  delay (2000);
  setLaser( true ) ;  // Turn on laser
  lasSampleTotal = 0;
  do
  {
    sample = analogRead(LDRPin);      
//    Serial.print("Laser-On Sample: " ) ;  Serial.println( sample ) ;
    
    if (sample > ambBaseline + min_diff){
//      Serial.print("In-Tolerance Sample: " ) ;  Serial.println( sample ) ;
      stack.push(sample) ;
      
    } else {
      if( !stack.isEmpty() ) {
        Serial.print( "Reset...  Sample=" ) ; Serial.println( sample ) ;
        while( !stack.isEmpty() ) stack.pop() ;  // Clear out the stack when reading drops
      }
    }
  } while (stack.count() < TOTAL_LASER_SAMPLES);  // Need 'N' in-tolerance samples in a row

  for( int n=0; n < GOOD_LASER_SAMPLES; n++ )
        lasSampleTotal += stack.pop() ;

  //we need to correctly set the lasThreshold as it now hold the sum of 3 samples
  lasThreshold = (lasSampleTotal/GOOD_LASER_SAMPLES) - LASER_SENSITIVITY;
  Serial.print("Laser light level = ");  Serial.println(lasThreshold);
  //now we set sum by adding lasThreshold and ambBaseline
  sum = (lasThreshold + ambBaseline);

  //lastly we find the average (trigering point)
  threshold = (sum/2);

  Serial.print("Trigger threshold= ");  Serial.println(threshold);
  Serial.print("Armed");
  setLaser( true ) ;
}    

void setLaser( bool setOn ) {
  if( setOn ) digitalWrite(laserPin, HIGH);  
  else        digitalWrite(laserPin, LOW);    
}

void servo(){
 
   // Start turning anticlockwise
    myservo.write(180);
    // Go on turning for the right duration
    delay(TURN_TIME);
    // Stop turning
    myservo.write(90);
    delay(2000);
    // Start turning clockwise
    myservo.write(0);
    // Go on turning for the right duration
    delay(TURN_TIME_MINUS);
    // Stop turning
    myservo.write(90);
    // Wait for 1 second
    delay(1000);
  calibrate();
}


Project reflection:

1) Where did you get the idea from?
     I wanted to make a self resetting possum trap this year though didn't have the money to build one so I decided to scale it down.
2) Did your original idea change?
    Once I made the decision to down scale the project there was little I could change. I first made the trap out of two Tupperware containers and then a friend gave me a Weet-bix tin so I then transferred everything across.
3) What was hard and easy?
    The most frustrating thing was the servo, I had a small position based servo that wasn't strong enough to hold the trap floor and a mouse though it did close to the right place each time. The other servo I had was a time based servo, I found this servo could easily hold the weight of the floor and about 3 mice but it wouldn't close to the same place each time.
4) What would you do differently next time?
    I would get a stronger position based servo. other than that this project went as go as one can expect.
5) Could this project be extended?
    As I am in third year this year and doing a LoRaWan project, this trap will become a node (end-device) for that project. Other things that you could do is use this idea for other pests eg possums, stray cats or rats.
6) Side note:
    I really enjoyed making this mouse trap and found I have a love for arduino and the vast things that can be accomplished if one was to think outside the square.


No comments:

Post a Comment