Chicken CoopCam and Environment Sensor

So I recently built a chicken coop for our 4 chickens. I wanted to keep track of the weather conditions and view what is going on inside the coop. I put together a small Raspberry Pi project using Python and motion to get everything working.

I purchased a powered USB hub, Raspberry Pi Zero, 32Gb sd card, wifi module, SenseHat and NoIR camera. I used the USB hub to power the Raspberry Pi and in the future to power some infrared LEDs for night time viewing. I also used a empty box that my Garmin vivosmart came in to enclose the device with cutouts for the camera (small diamond on the left and the larger opening for the SenseHat. I mounted it using a small piece of lattice wood and velcro so I could easily take it down and perform service.

After setting up the basics like installing Rapsbian Jessie(do not use Stretch) and running raspi-config to enable SSH, 144Mb for GPU under split memory and the camera module, updating & upgrading, and configuring wifi on the Raspberry Pi I moved on to installing motion to create the streaming webcam server.


sudo apt-get update && sudo apt-get upgrade
sudo apt-get install -y cmake git libjpeg-dev libavformat56 libavformat-dev libavcodec56 libavcodec-dev libavutil54 libavutil-dev libc6-dev zlib1g-dev libmysqlclient18 libmysqlclient-dev libpq5 libpq-dev
git clone https://github.com/raspberrypi/userland
git clone https://github.com/lowflyerUK/motion.git
cd motion/
git checkout mmal-test
USERLANDPATH=/home/pi/userland cmake .
make

Thanks to lowflyer

Here is the Python code used to collect information from the sensors and run the graph. The following came mostly from blogmywiki with some modifications for calculating Fahrenheit, tuning the temperature, and removing the FTP as I am sending the graph and video output files directly to a NAS using a mounted share. Install matplotlib first with sudo pip3 install matplotlib.


#!/usr/bin/python

import matplotlib
matplotlib.use('Agg')   # used as running headless without windows
import matplotlib.pyplot as plt
from time import sleep
from sense_hat import SenseHat
import time
from datetime import datetime
import os

def getCPUtemperature():
 res = os.popen('vcgencmd measure_temp').readline()
 return(res.replace("temp=","").replace("'C\n",""))

sense = SenseHat()

interval_min = 5 # measurement interval in minutes
hrs_shown = 24  # number of hours covered by chart
chart_span = int(hrs_shown*(60/interval_min)) # calculate number of readings to show

# uncomment these lines to write headers to CSV file
#fd = open('logging.csv','a')
#fd.write('time,pressure,temperature,humidity\n')
#fd.close()

while True:
    pressure_list = []
    temp_list = []
    humidity_list = []
    x = []
    a = 0
    daily_max_humidity = 0
    daily_max_temp = 0
    daily_max_pressure = 0
    daily_min_humidity = 2000
    daily_min_temp = 2000
    daily_min_pressure = 2000

    for a in range (chart_span):
        sense.clear()
        fd = open('/mnt/envmon/logging.csv','a')
        #convpress = round(sense.get_pressure() * 0.0295299830714,1)
        pressure = sense.get_pressure()*0.0295299830714
        pressure_list.append(pressure)
# attempt to calculate ambient temperature
# based on dgaust in https://www.raspberrypi.org/forums/viewtopic.php?f=104&t=111457
        cpuTemp=int(float(getCPUtemperature()))
        ambient = sense.get_temperature_from_pressure()
#        calctemp = ambient - ((cpuTemp - ambient)/ 1.5)
        temp_c = sense.get_temperature()
        calctemp = (temp_c - ((cpuTemp - temp_c)/0.32))*9/5+32
        temp_list.append(calctemp)

        humidity = sense.get_humidity()*(2.5-0.01*temp_c)
        humidity_list.append(humidity)

        timestamp = str(datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
        fd.write(timestamp+','+str(pressure)+','+str(calctemp)+','+str(humidity)+'\n')
        fd.close()
#        print(timestamp, pressure, calctemp, humidity)

        x.append(a)
        a += 1

        if humidity > daily_max_humidity:
            daily_max_humidity = humidity
        if calctemp > daily_max_temp:
            daily_max_temp = calctemp
        if pressure > daily_max_pressure:
            daily_max_pressure = pressure
        if humidity < daily_min_humidity:
            daily_min_humidity = humidity
        if calctemp < daily_min_temp:
            daily_min_temp = calctemp
        if pressure < daily_min_pressure:
            daily_min_pressure = pressure

        print('max humidity '+str(daily_max_humidity))
        print('max temp '+str(daily_max_temp))
        print('max pressure '+str(daily_max_pressure))
        print('min humidity '+str(daily_min_humidity))
        print('min temp '+str(daily_min_temp))
        print('min pressure '+str(daily_min_pressure))

        fig = plt.figure()
        plt.plot(x,humidity_list)
        plt.plot(x,temp_list,'r')
        plt.plot(x,pressure_list,'g')
        plt.title('SenseHAT WX '+timestamp)
        plt.figtext(0, 0.9, "max "+str(round(daily_max_humidity,0))+"%",color='blue',fontsize=8)
        plt.figtext(0, 0.85, "min "+str(round(daily_min_humidity,0))+"%",color='blue',fontsize=8)
        plt.figtext(0, 0.8, "max "+str(round(daily_max_temp,0))+"F",color='red',fontsize=8)
        plt.figtext(0, 0.75, "min "+str(round(daily_min_temp,0))+"F",color='red',fontsize=8)
        plt.figtext(0, 0.7, "max "+str(round(daily_max_pressure,0))+"in",color='green',fontsize=8)
        plt.figtext(0, 0.65, "min "+str(round(daily_min_pressure,0))+"in",color='green',fontsize=8)
        plt.figtext(0, 0.04, "current ",color='black',fontsize=10)
        plt.figtext(0.08, 0.04, "humidity "+str(round(humidity,0))+"%",color='blue',fontsize=10)
        plt.figtext(0.3, 0.04, "temp "+str(round(calctemp,1))+"$^\circ$F",color='red',fontsize=10)
        plt.figtext(0.44, 0.04, "pressure "+str(round(pressure,1))+" in",color='green',fontsize=10)
        fig.savefig('/mnt/envmon/wx_chart6.png')
        
        sense.show_message(".", text_colour=[0,80,0])
        sleep(interval_min*60)
        plt.close(fig)

Lastly I updated my fstab to mount the drives on boot using systemd


//192.168.128.201/WebCam/Monitor /mnt/camshare cifs username=,password=,iocharset=utf8,file_mode=0777,dir_mode=0777,x-systemd.automount 0 0
//192.168.128.201/ContainerStation/container-station-data/lib/docker/volumes/b0ce997730fdbc24d0754b4e489c5f781e9bae573109ad2be1ac8337b7e9f474/_data/wp-content/uploads/2017/02 /mnt/envmon cifs username=,password=,iocharset=utf8,file_mode=0777,dir_mode=0777,x-systemd.automount 0 0

And created a startup script to start the python program and motion (don't forget to chmod +x the file, place in /etc/init.d/ and "sudo update-rc.d env-motion.sh defaults")


#! /bin/sh
### BEGIN INIT INFO
# Provides:          env-motion.sh
# Required-Start:    $all
# Required-Stop:     
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Startup script to chart environmental monitoring and start motion web cam
### END INIT INFO

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin

. /lib/init/vars.sh
. /lib/lsb/init-functions
# If you need to source some other scripts, do it here

case "$1" in
  start)
    log_begin_msg "Starting to monitor environments and capture chicken videos"
    nohup python3 /home/pi/Scripts/senseplot.py &
    /home/pi/motion/motion -c /home/pi/motion/configs/motion-mmalcam-both.conf
    log_end_msg $?
    exit 0
    ;;
  stop)
    log_begin_msg "Stopping the service"

    # do something to kill the service or cleanup or nothing

    log_end_msg $?
    exit 0
    ;;
  *)
    echo "Usage: /etc/init.d/env-motion.sh {start|stop}"
    exit 1
    ;;
esac

Here are the results.

And the live video stream using motion.
Chicken Coop WebCam (CoopCam)

Next step is to add some servo motors to automatically open the doors in the morning and close them at night, and add a 40 pin ribbon cable between the SenseHat and Pi to provide some distance between the CPU which runs hot. Then I can remove the calculations for temperature and humidity.

Leave a Reply