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.


Wearable project. Glove.

Wearable project. Glove.

Project description:

A glove with five buttons and an LCD screen.
each button has a value and when pressed an array with letters in it is accessed and displayed on the LCD screen (on the second line). once you have the letter you want you can press the fifth button to store that letter in a new array. the second array is then displayed on the first line of the LCD screen.

Fritzing layout:


Video of it working:



 

Arduino Code:

#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12,11,5,4,3,2);

#define LCD_LIGHT_PIN A4
const int oneButtonPin = 6; 
const int twoButtonPin = 7;   
const int threeButtonPin = 8;   
const int fourButtonPin = 9; 
const int fiveButtonPin = 10;
    
int button1State = 0;
int button2State = 0;
int button3State = 0;
int button4State = 0;
int button5State = 0;

//Set output number
int output = 0;
//set sentance size
const int sentSize = 20;
//Init sentence
char chosenSentance[sentSize];
//Init position
int position =0;

void setup() {
  Serial.begin(9600);
    // Setup the number of columns and rows that are available on the LCD. 
  lcd.begin(16, 2);
  lcd.noDisplay();
  
  // Set the button pins as an input.
  pinMode(oneButtonPin, INPUT);
  pinMode(twoButtonPin, INPUT);
  pinMode(threeButtonPin, INPUT);
  pinMode(fourButtonPin, INPUT);
  pinMode(fiveButtonPin, INPUT);
   // Set the LCD display backlight pin as an output.
  pinMode(LCD_LIGHT_PIN, OUTPUT);

  // Turn off the LCD backlight.
  digitalWrite(LCD_LIGHT_PIN, LOW);
}

void loop() { 
  readState();
  char alphabet[16] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'};
  char chosen;
  button5State = digitalRead(fiveButtonPin);
  if (output >=1){

    lcd.setCursor(0,1);
    lcd.print(alphabet[output-=1]);
    //lcd.print(output);
    digitalWrite(LCD_LIGHT_PIN, HIGH);
    lcd.display();
    if (button5State == HIGH){
      chosen = (alphabet[output]);
      lcd.setCursor(position,0);
      lcd.print(chosen);
      //Add letter to sentence
      chosenSentance[position++]=chosen;
      Serial.println(chosenSentance);
      delay(500);
    }
    output = 0;
  }

  if (position>=sentSize){
    position = 0;
  }  
}

int readState(){ 
  //Read buttons
  button1State = digitalRead(oneButtonPin);
  button2State = digitalRead(twoButtonPin);
  button3State = digitalRead(threeButtonPin);
  button4State = digitalRead(fourButtonPin);
  
  //Encode to output
  if (button1State == HIGH){
    output+=1;
  }
  if (button2State == HIGH){
    output+=2;
  }
  if (button3State == HIGH){
    output+=4;
  }
  if (button4State == HIGH){
    output+=8;
  } 
  return output;
}

void clear(){
    lcd.clear();
    lcd.setCursor(0, 0);
}

Project reflection:

1) Where did you get the from?
    Years ago I had a dream where I was taught to count in binary on my fingers. Using that idea I thought that if I placed buttons on my fingers I could type out a sentence and display that sentence on an LCD screen that was placed on the back of my hand.
2) Did your original idea change?
    At first I wanted to give the user the ability to choose from all the letters of the alphabet and still can if I developed this idea further. As it sits they can choose 16 letters with 4 buttons, the fifth button is there to confirm that you want to add that letter to the sentence you are constructing.
3) What was hard and easy?
    As I am not a coder I found some parts of the code challenging to get my head around. 
4) What would you do differently next time?
   I would spend more time on the project and add another button so the user can have access to the whole alphabet.
5) Could this project be extended?
    this project could easily be extended for eg adding bluetooth so as to send the chosen sentence to your phone.