Introduction: Mouse Detector Raspberry Pi Ultrasonic Sensor

About: I love making things. I have for as long as I can remember liked to make stuff. Now days I have two kids (Thomas and Emma) and most of the things I do are safe for them! I love electronics and Microchips, I ha…

Rat/Mouse detection system raspberry pi NoIR camera.

This is a bit of a long story so I will try and cut it down. Basically we were watching the birds one day and then noticed a large rat emerging from under my shed. as we watched the rat ran across the grass and climbed up the bird feeder and helped itself to bird seed. Anyway the misses really doesn’t like rats so it had to go.. My personal opinion is to NOT kill animals so I have a humane trap, however after a few days it was obvious that the rat wasn’t having any thing to do with the trap and even worked out that if he moved the trap the food fell out!! So we gave in with that idea and the trap was put in my shed out of the way. A few weeks late I was in my shed and noticed that the seed had gone! at this stage I didn’t know what had eaten the seed and more importantly what was living in my shed!

So I set up the Raspberry pi Rat / Mouse detection unit! (the first basic unit) And so the sarger continued! On the first night the camera was tripped and the next day I looked at the photos and video…. Clear as anything there was a mouse. At first it was scared by the relay controlling the IR light sorce, but very quickly got used to it and helpped itself to bird food!

So this then escalated to see how the mouse was able to fit in and get out of the rat trap. And for this part i set up the 4 sided dectector. The mouse was able to squeeze through the bars fill its mouth with seed and get out again. So I had a look at the trap and spotted that one of the bars was bent and that was where the mouse was getting through. So I straightened it out and set the pi running again. It turned out that the mouse could get through anywhere!

So after each night I reviewed the recordings and then set about making the trap harder to get out off. firstly I turned the trap around so I could see the mouse clearly, however the first video clearly showed that the mouse was able to sqeeze thourgh any gap, but after a short while it did realise the bigger gap was at the front

The circuit originally was just one sensor which the mouse had to go through the gap to start the recording, but I quickly expanded the system to a 4 sided system with the trap in the middle. it took a bit of time to get everything working well and I basically ended up with the raspberry pi taking a measure each side twice then choosing the larger of the two readings and adding all the 4 highest values together and making sure the distance wasn’t any shorter that 175cm. for this to work I had to add a small delay in-between measurements to allow time to let everything settle. If you try to take readings to quickly they sometimes come out short and not very consistent.

I very quickly added bits to the program theses included the following.

1) Take a small picture with date and time logged on the picture.

2) Take a big picture.

3) Take a one minute video.

4) Email the small picture to my inbox (but only 1 picture in 10) 5) Upload a picture to my website via FTP.

Step 1: The Parts of the System.

There are a lot of bits to this project, but all items are easy to get hold off and cheap.

The simple input/output Button/LED was a unit i made a while ago and i still find it very useful. i wrote an instructable about this a while ago so won't go into the detail again. Simple-Raspberry-Pi-Input-Output-Tricopter

The Ultrasonic units are HC-RS04 and are easy to pick up from ebay, you can use as many as you like to cover the required area.

However this device is 5volts so i use a logic level converter to allow 3.3volt to 5volt conversion, whilst it's a bit overkill i use logic level converters on both input and output pins, you could just use a resistor divider network to drop the 5 volts down to 3.3 volts. its up to you!

Next on the list of items is a relay board, again these can be bought from ebay and the ones i like to use are the opto isolating version.

And lastly you will need a raspberry pi with the NOIR camera and an IR light source.

Power supplies are handles by a 5 volt micro usb PSU, but it must be capable of 2 amps. and the IR light source is powered from 12 volts which in my case was a 11.1 Volt LiPo. (hence the need for the relay board)

Step 2: The Python Program.

Firstly i should point out i am NOT a very good programmer. But i am trying so don't judge me!

So the first section of program here is to give out a pulse on the Trigger01. This pulse needs to be 0.00001 seconds long. Once you have done that the ultrasonic module will send out several ultrasonic pulses and then listen for a echo. Then you need to time the Echo01 pin because this time is proportional to the distance. you then need to repeat this step for all the other sensors.

  
while True:
    colourLED(0,1,1,0.1)
    GPIO.output(Trigger01, True)
    time.sleep(0.00001)
    GPIO.output(Trigger01, False)
    while GPIO.input(Echo01)==0:
        pulse_start = time.time()
    while GPIO.input(Echo01)==1:
        pulse_end = time.time()
    time11 = pulse_end - pulse_start

When you have all the times then you add them all up and check the distance.

    pulse_duration01 = time11
    pulse_duration02 = time21
    pulse_duration03 = time31
    pulse_duration04 = time41
    #time11 = round((time11 * 17150),1)
    #time21 = round((time21 * 17150),1)
    #time31 = round((time31 * 17150),1)
    #time41 = round((time41 * 17150),1)
    #dis01 = round((pulse_duration01 * 17150),1)
    #dis02 = round((pulse_duration02 * 17150),1)
    #dis03 = round((pulse_duration03 * 17150),1)
    #dis04 = round((pulse_duration04 * 17150),1)
    distance = pulse_duration01 + pulse_duration02 + pulse_duration03 + pulse_duration04
    distance = distance * 17150
    distance = round(distance,1)
    #print("Total = ")+str(distance)
    #print("dis ")+str(dis01)+(" ")+str(dis02)+(" ")+str(dis03)+(" ")+str(dis04)
    checkInput('none')
    if (distance < 190):
        #print("tripped ")+str(time11)+(" ")+str(time12)+(" ")+str(time21)+(" ")+str(time22)+(" ")+str(time31)+(" ")+str(time32)+(" ")+str(time41)+(" ")+str(time42)
        #print("dis ")+str(dis01)+(" ")+str(dis02)+(" ")+str(dis03)+(" ")+str(dis04)

You can see from the above code there was a lot of experimenting with this project. Printing out distances was useful to check the cage was aligned correctly.

So if the distance was shorter than 190 (cm) then the following happened...

        GPIO.output(Lights, True)
        time.sleep(2)
        takePictureSmall(B)
        takePictureLarge(B)
        takeVideo(B)
        GPIO.output(Lights, False)
        B = B + 1

First step is to turn on the infrared light source and then give it a couple of seconds to settle. Next take a small picture then take a big picture, followed by a two minute video. Finally turn the IR light off and increment the file number.

So let's have a look at these steps in more detail. firstly the take small picture which also include emailing the picture and uploading to my webpage.

def takePictureSmall(fileNumber):
    filename = ("pic_")+str(fileNumber)+(".jpg")
    params = (" -w 640 -h 480 -a 12 -p 100,100,300,200")
    partA=("/media/pi/KINGSTON/PhotoSmall")
    os.chdir(partA)
    command = ("sudo raspistill -t 2000 -o ")
    os.system(command + filename + params)
    if (fileNumber%10 == 0):
       print"sending email"
       sendEmail(filename)
    print (filename)
    send2FTP(filename)
    os.chdir("/home/pi")

def sendEmail(img2Send):
    me = "oneemailaddress.com"
    you = "secondemailaddress.com"
    msg = MIMEMultipart('alternative')
    msg['Subject'] = "Rat Attack"
    msg['From'] = me
    msg['To'] = you
    fp = open(img2Send, 'rb')
    img = MIMEImage(fp.read())
    fp.close()
    msg.attach(img)
    try:
        s = smtplib.SMTP('smtp.**********')#your smtp address.
        s.sendmail(me, you, msg.as_string())
        print "Email sent"
    except:
        print "Unable to send"

def send2FTP(img2Send):
    ftp = ftplib.FTP()
    try:
        print"logging in to FTP..."
        ftp.connect('ftpaddress.com','21')
        ftp.login("username.com", "userpassword")
        ftp.cwd("htdocs/rats")
        file = open(img2Send,'rb')
        command = ('STOR '+img2Send)
        ftp.storbinary(command, file)
        file.close()
        ftp.quit()
    except:
        print "failed to login"

The next bit to look at is easy compared with the above. Just take a big picture. But i have also included in this section the part which checks to see if the USB stick is installed and creates folders if they are missing.

def takePictureLarge(fileNumber):
    filename = ("pic_")+str(fileNumber)+(".jpg")
    partA=("/media/pi/KINGSTON/PhotoLarge")
    os.chdir(partA)
    command = ("sudo raspistill -t 2000 -o ")
    os.system(command + filename)
    os.chdir("/home/pi")

def checkMedia():
    checkMediaUSB = os.path.isdir("/media/pi/KINGSTON")
    if checkMediaUSB == True:
        checkFolder = os.path.isdir("/media/pi/KINGSTON/PhotoSmall")
        if checkFolder == False:
            os.mkdir("/media/pi/KINGSTON/PhotoSmall")
            os.mkdir("/media/pi/KINGSTON/PhotoLarge")
            os.mkdir("/media/pi/KINGSTON/Video")

Lastly we are going to take a 2 minute video.

def takeVideo(fileNumber):
    filename = ("vid_")+str(fileNumber)+(".h264")
    partA=("/media/pi/KINGSTON/Video")
    os.chdir(partA)
    command = ("sudo raspivid -t 120000 -o ")
    os.system(command + filename)
    os.chdir("/home/pi")

Easy!

So Below is the whole program. Like i said it could do with a very big clean up, but this was a quick program (get it working and get it in the shed)

import smtplib
import ftplib
import math
import time
import datetime as dt
import RPi.GPIO as GPIO
import os
import sys

from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
Red = 10
Blue = 9
Green = 11
Button = 5
Trigger01 = 17
Echo01  = 27
Trigger02 = 19
Echo02  = 26
Trigger03 = 6
Echo03  = 13
Trigger04 = 20
Echo04  = 21

Lights = 22

GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)

GPIO.setup(Trigger01, GPIO.OUT)
GPIO.setup(Echo01, GPIO.IN)
GPIO.setup(Trigger02, GPIO.OUT)
GPIO.setup(Echo02, GPIO.IN)
GPIO.setup(Trigger03, GPIO.OUT)
GPIO.setup(Echo03, GPIO.IN)
GPIO.setup(Trigger04, GPIO.OUT)
GPIO.setup(Echo04, GPIO.IN)

GPIO.setup(Lights, GPIO.OUT)
GPIO.setup(Red, GPIO.OUT)
GPIO.setup(Blue, GPIO.OUT)
GPIO.setup(Green, GPIO.OUT)
GPIO.setup(Button, GPIO.IN)

def delayTime():
    time.sleep(0.1)

def sendEmail(img2Send):
    me = "oneemailaddress"
    you = "secondemailaddress"
    msg = MIMEMultipart('alternative')
    msg['Subject'] = "Rat Attack"
    msg['From'] = me
    msg['To'] = you
    fp = open(img2Send, 'rb')
    img = MIMEImage(fp.read())
    fp.close()
    msg.attach(img)
    try:
        s = smtplib.SMTP('smtp.address')
        s.sendmail(me, you, msg.as_string())
        print "Email sent"
    except:
        print "Unable to send"

def send2FTP(img2Send):
    ftp = ftplib.FTP()
    try:
        print"logging in to FTP..."
        ftp.connect('FTPaddress','21')
        ftp.login("username", "passord")
        ftp.cwd("htdocs/rats")
        file = open(img2Send,'rb')
        command = ('STOR '+img2Send)
        ftp.storbinary(command, file)
        file.close()
        ftp.quit()
    except:
        print "failed to login"


def takePictureSmall(fileNumber):
    filename = ("pic_")+str(fileNumber)+(".jpg")
    params = (" -w 640 -h 480 -a 12 -p 100,100,300,200")
    partA=("/media/pi/KINGSTON/PhotoSmall")
    os.chdir(partA)
    command = ("sudo raspistill -t 2000 -o ")
    os.system(command + filename + params)
    if (fileNumber%10 == 0):
       print"sending email"
       sendEmail(filename)
    print (filename)
    send2FTP(filename)
    os.chdir("/home/pi")
    
def takePictureLarge(fileNumber):
    filename = ("pic_")+str(fileNumber)+(".jpg")
    partA=("/media/pi/KINGSTON/PhotoLarge")
    os.chdir(partA)
    command = ("sudo raspistill -t 2000 -o ")
    os.system(command + filename)
    os.chdir("/home/pi")

def takeVideo(fileNumber):
    filename = ("vid_")+str(fileNumber)+(".h264")
    partA=("/media/pi/KINGSTON/Video")
    os.chdir(partA)
    command = ("sudo raspivid -t 120000 -o ")
    os.system(command + filename)
    os.chdir("/home/pi")
    
def checkMedia():
    checkMediaUSB = os.path.isdir("/media/pi/KINGSTON")
    if checkMediaUSB == True:
        checkFolder = os.path.isdir("/media/pi/KINGSTON/PhotoSmall")
        if checkFolder == False:
            os.mkdir("/media/pi/KINGSTON/PhotoSmall")
            os.mkdir("/media/pi/KINGSTON/PhotoLarge")
            os.mkdir("/media/pi/KINGSTON/Video")

def quickFlash():
    for x in range(0,8):
        colourLED(1,1,0,0.1)
        colourLED(0,1,1,0.1)
        colourLED(1,0,1,0.1)
    colourLED(1,1,1,1)

def colourLED(r,b,g,t):
    if r==1:
        GPIO.output(Red, True)
    else:
        GPIO.output(Red, False)
    if b==1:
        GPIO.output(Blue, True)
    else:
        GPIO.output(Blue, False)
    if g==1:
        GPIO.output(Green, True)
    else:
        GPIO.output(Green, False)
    time.sleep(t);

def checkInput(colour):
    if GPIO.input(Button)==1:
        quickFlash()
        for x in range(0,2):
            colourLED(0,1,1,3)
            if GPIO.input(Button)==1:
                quickFlash()
                print"Pause program while USB stick removed" 
                while (GPIO.input(Button)==0):
                    colourLED(0,1,1,1)
                    colourLED(1,1,1,1)
		quickFlash()
            colourLED(1,0,1,3)
            if GPIO.input(Button)==1:
                quickFlash()
                print"Stop the program"
                sys.exit()
            colourLED(1,1,0,3)
            if GPIO.input(Button)==1:
                quickFlash()
                print"Shut down the PI"
                os.system('sudo halt')
            colourLED(1,1,1,0)
 
        
GPIO.output(Trigger01, False)
GPIO.output(Trigger02, False)
GPIO.output(Trigger03, False)
GPIO.output(Trigger04, False)
GPIO.output(Lights, False)
GPIO.output(Red, True)
GPIO.output(Blue, True)
GPIO.output(Green, True)
quickFlash()
B = 0
time.sleep(20)
checkMedia()

while True:
    colourLED(0,1,1,0.1)
    GPIO.output(Trigger01, True)
    time.sleep(0.00001)
    GPIO.output(Trigger01, False)
    while GPIO.input(Echo01)==0:
        pulse_start = time.time()
    while GPIO.input(Echo01)==1:
        pulse_end = time.time()
    time11 = pulse_end - pulse_start
    #delayTime()#1
    colourLED(1,0,1,0.1)
    GPIO.output(Trigger02, True)
    time.sleep(0.00001)
    GPIO.output(Trigger02, False)
    while GPIO.input(Echo02)==0:
        pulse_start = time.time()
    while GPIO.input(Echo02)==1:
        pulse_end = time.time()
    time21 = pulse_end - pulse_start
    #delayTime()#2
    colourLED(1,1,0,0.1)
    GPIO.output(Trigger03, True)
    time.sleep(0.00001)
    GPIO.output(Trigger03, False)
    while GPIO.input(Echo03)==0:
        pulse_start = time.time()
    while GPIO.input(Echo03)==1:
        pulse_end = time.time()
    time31 = pulse_end - pulse_start
    #delayTime()#3
    colourLED(1,1,1,0.1)
    GPIO.output(Trigger04, True)
    time.sleep(0.00001)
    GPIO.output(Trigger04, False)
    while GPIO.input(Echo04)==0:
        pulse_start = time.time()
    while GPIO.input(Echo04)==1:
        pulse_end = time.time()
    time41 = pulse_end - pulse_start
    #delayTime()#4
    pulse_duration01 = time11
    pulse_duration02 = time21
    pulse_duration03 = time31
    pulse_duration04 = time41
    #time11 = round((time11 * 17150),1)
    #time21 = round((time21 * 17150),1)
    #time31 = round((time31 * 17150),1)
    #time41 = round((time41 * 17150),1)
    #dis01 = round((pulse_duration01 * 17150),1)
    #dis02 = round((pulse_duration02 * 17150),1)
    #dis03 = round((pulse_duration03 * 17150),1)
    #dis04 = round((pulse_duration04 * 17150),1)
    distance = pulse_duration01 + pulse_duration02 + pulse_duration03 + pulse_duration04
    distance = distance * 17150
    distance = round(distance,1)
    #print("Total = ")+str(distance)
    #print("dis ")+str(dis01)+(" ")+str(dis02)+(" ")+str(dis03)+(" ")+str(dis04)
    checkInput('none')
    if (distance < 190):
        #print("tripped ")+str(time11)+(" ")+str(time12)+(" ")+str(time21)+(" ")+str(time22)+(" ")+str(time31)+(" ")+str(time32)+(" ")+str(time41)+(" ")+str(time42)
        #print("dis ")+str(dis01)+(" ")+str(dis02)+(" ")+str(dis03)+(" ")+str(dis04)
        GPIO.output(Lights, True)
        time.sleep(2)
        takePictureSmall(B)
        takePictureLarge(B)
        takeVideo(B)
        GPIO.output(Lights, False)
        B = B + 1
    #time.sleep(1)
LED Contest

Participated in the
LED Contest