Tomat-O-Mat

From Wurst-Wasser.net
Revision as of 09:40, 31 August 2013 by Heiko (talk | contribs) (→‎Parts list)
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

The Idea

Since I'm too lazy[1] to water my tomatoes, I thought it would be nice if a Pi would take care of that.

How It Works

A RaspberryPi is connected to a Sony Playstation Camera, a DHT11, some level switches, a relay and a solenoid valve.
TomatOMatSchematics.png

Parts list

  • RaspberryPi Rev 2
  • Power supply for the Pi
  • Power supply for the pump/solenoid valve (12V, 2A)
  • Sony Playstation Camera
  • DHT11 (side project RaspberryPi Humidity and Temperature Sensor)
  • DS18B20 (side project RaspberryPi Temperature Sensor)
  • Lower watermark level switches like this (vertically mounted)
  • Upper watermark level switches like this (horizontally mounted)
  • Pump (bought on eBay, model DC40A-1215 (12V, 350mA, 400l/h (6l/min), 1.5m delivery head, 30.000h lifetime) like this), better yet[2]: Solenoid valve like this
  • Relay board (5V, low-triggered, 2-channel, this)
  • some resistors, cables, wires, boards, and the usual soldering equipment

Sources

00_check_and_init.sh

#!/bin/bash
#set -x

# File: 00_check_and_init.sh
# Author: Heiko Kretschmer, watering-o-matic at wurst-wasser.net
# Purpose: Checking wether the gpio are set up, and if not, setting 'em up.

# Globals
GDIRBASE="/home/pi/Development/giess-o-mat"

# UnMain
"${GDIRBASE}/"01_check_init.sh || sudo "${GDIRBASE}/"02_init.sh

# EOF

01_check_init.sh

#!/bin/bash
#set -x

# Author: tomatomat at wurst-wasser.net
# Purpose: Checking wether GPIO pins are set up

#############
# Check GPIOs
#############

if [ ! -f "/sys/class/gpio/gpio8/value" ]; then
  echo "control file for gpio8 is missing, need to call 02_init.sh!"
  exit 1
fi

if [ ! -f "/sys/class/gpio/gpio17/value" ]; then
  echo "control file for gpio17 is missing, need to call 02_init.sh!"
  exit 1
fi

#if [ ! -f "/sys/class/gpio/gpio21/value" ]; then
#   echo "control file for gpio21 is missing, need to call 02_init.sh!"
#   exit 1
#fi

if [ ! -f "/sys/class/gpio/gpio22/value" ]; then
  echo "control file for gpio22 is missing, need to call 02_init.sh!"
  exit 1
fi

if [ ! -f "/sys/class/gpio/gpio23/value" ]; then
  echo "control file for gpio23 is missing, need to call 02_init.sh!"
  exit 1
fi

if [ ! -f "/sys/class/gpio/gpio24/value" ]; then
  echo "control file for gpio24 is missing, need to call 02_init.sh!"
  exit 1
fi

if [ ! -f "/sys/class/gpio/gpio25/value" ]; then
  echo "control file for gpio25 is missing, need to call 02_init.sh!"
  exit 1
fi

exit 0

# EOF

02_init.sh

#!/bin/bash
#set -x

# File: 02_init.sh
# Author: tomatomat at wurst-wasser.net
# Purpose: Initiating GPIO pins for in-/output
# Important note: MUST be run as root at boot-time - the "device"-files disappear on reboot!

# GPIO numbers should be from this list
# 0, 1, 4, 7, 8, 9, 10, 11, 14, 15, 17, 18, 21, 22, 23, 24, 25

# Note that the GPIO numbers that you program here refer to the pins
# of the BCM2835 and *not* the numbers on the pin header. 
# So, if you want to activate Pin 07 on the header you should be 
# using GPIO4 in this script. Likewise if you want to activate Pin 11
# on the header you should be using GPIO17 here.

# Check permissions (Actually, just export as root, then set permissions for device files, done)
test "`whoami`" != "root" && echo "Must be root (or use sudo)." && exit 1

# The Pins we use, and how: (Details man gpio)
#
# GPIO 8 (Pin 24) - Input (k), reading signal upper water level measurement of reservoir
# GPIO 17 (Pin 11) - Output (c), delivering signal for the pump / solenoid valve
# GPIO 22 (Pin 15) - Input (e), reading signal for lower water level measurement of reservoir
# GPIO 23 (Pin 16) - Input (h), reading signal for upper water level measurement of flowerbed
# GPIO 24 (Pin 18) - Input (a), reading signal for lower water level measurement of flowerbed
# GPIO 25 (Pin 22) - Input (g), reading signal for middle water level measurement of reservoir

echo "Initializing GPIOs..."

#############
# Setup GPIOs
#############

# Set up GPIO 8 (Pin 24) and set to input (should read 0, if water over mark)
NR="8"
echo "${NR}" > /sys/class/gpio/export
echo "in" > /sys/class/gpio/gpio${NR}/direction

# Set up GPIO 17 (Pin 11) and set to output (Pump starts if 0)
echo 17 > /sys/class/gpio/export
echo "out" > /sys/class/gpio/gpio17/direction
chown pi /sys/class/gpio/gpio17/value

# Set up GPIO 25 (Pin 22) and set to input (should read 0, if water over mark)
NR="25"
echo "${NR}" > /sys/class/gpio/export
echo "in" > /sys/class/gpio/gpio${NR}/direction

# Set up GPIO 22 (Pin 15) and set to input (should read 0, if water over mark)
NR="22"
echo "${NR}" > /sys/class/gpio/export
echo "in" > /sys/class/gpio/gpio${NR}/direction

# Set up GPIO 23 (Pin 16) and set to input (should read 0, if water over mark)
NR="23"
echo "${NR}" > /sys/class/gpio/export
echo "in" > /sys/class/gpio/gpio${NR}/direction

# Set up GPIO 24 (Pin 18) and set to input (should read 0, if water over mark)
NR="24"
echo "${NR}" > /sys/class/gpio/export
echo "in" > /sys/class/gpio/gpio${NR}/direction

############
# Init GPIOs
############

# Set output to default (disabling pump/solenoid valve, since the relay triggers on low signal)
echo "1" > /sys/class/gpio/gpio17/value # Pin 11 -> High, Pump/solenoid valve disabled

# Clean up
#echo "17" > /sys/class/gpio/unexport
#echo "21" > /sys/class/gpio/unexport
#echo "22" > /sys/class/gpio/unexport
#echo "23" > /sys/class/gpio/unexport
#echo "24" > /sys/class/gpio/unexport

# EOF

04_check_uninit.sh

#!/bin/bash
#set -x

# Author: tomatomat at wurst-wasser.net
# Purpose: Checking wether GPIO pins are set up

#############
# Check GPIOs
#############

if [ ! -f "/sys/class/gpio/gpio8/value" -a ! -f "/sys/class/gpio/gpio17/value" -a ! -f "/sys/class/gpio/gpio22/value" -a ! -f "/sys/class/gpio/gpio23/value" -a ! -f "/sys/class/gpio/gpio24/value" ! -f "/sys/class/gpio/gpio25/value" -a ]; then
 exit 0 # All GPIOs are gone
fi

exit 1 # One ore more GPIOs are still there

# EOF

09_uninit.sh

#!/bin/bash
#set -x

# File: 09_uninit.sh
# Author: tomatomat at wurst-wasser.net
# Purpose: Un-Initiating GPIO pins for in-/output
# Important note: MUST be run as root!

# Globals
GDIRBASE="/home/pi/Development/giess-o-mat"

# UnMain
"${GDIRBASE}/"04_check_uninit.sh && echo "We already did uninit. Exiting." && exit 1

# Check permissions (Actually, just export as root, then set permissions for device files, done)
test "`whoami`" != "root" && echo "Must be root (or use sudo)." && exit 1

# Set output to default (disabling pump and putting safety on, since the relay triggers on low signal)
echo "1" > /sys/class/gpio/gpio17/value # Pin 11 -> High

# Clean up (Levels on GPIO output pins remain unchanged)
echo "8" > /sys/class/gpio/unexport
echo "17" > /sys/class/gpio/unexport
echo "22" > /sys/class/gpio/unexport
echo "23" > /sys/class/gpio/unexport
echo "24" > /sys/class/gpio/unexport
echo "25" > /sys/class/gpio/unexport

# EOF

10_check_level.sh

#!/bin/bash
#set -x

# File: 10_check_levels.sh
# Author: Heiko Kretschmer, tomatomat at wurst-wasser.net
# Purpose: Reading GPIO pins to get current water level

# Globals
GDIRBASE="/home/pi/Development/giess-o-mat"

# Check if we already set up the GPIOs
"${GDIRBASE}/"00_check_and_init.sh

# Read from level-input (lower and upper water mark of reservoir)
RESERVOIRUPPERWATERMARKVALUE="`cat /sys/class/gpio/gpio25/value`"
RESERVOIRMIDDLEWATERMARKVALUE="`cat /sys/class/gpio/gpio8/value`"
RESERVOIRLOWERWATERMARKVALUE="`cat /sys/class/gpio/gpio22/value`"

# Read from level-input (lower water mark of flowerbed)
FLOWERBEDLOWERWATERMARKVALUE="`cat /sys/class/gpio/gpio24/value`"
FLOWERBEDUPPERWATERMARKVALUE="`cat /sys/class/gpio/gpio23/value`"

# Say what's up!
echo ""
echo "Reservoir water level:"
echo "----------------"
echo "RESERVOIRUPPERWATERMARKVALUE: ${RESERVOIRUPPERWATERMARKVALUE} (0=water higher, 1=water lower than watermark)"
echo "RESERVOIRMIDDLEWATERMARKVALUE: ${RESERVOIRMIDDLEWATERMARKVALUE} (0=water higher, 1=water lower than watermark)"
echo "RESERVOIRLOWERWATERMARKVALUE: ${RESERVOIRLOWERWATERMARKVALUE} (0=water higher, 1=water lower than watermark)"
echo ""
echo "Flowerbed water level:"
echo "----------------------"
echo "FLOWERBEDUPPERWATERMARKVALUE: ${FLOWERBEDUPPERWATERMARKVALUE} (0=water higher, 1=water lower than watermark)"
echo "FLOWERBEDLOWERWATERMARKVALUE: ${FLOWERBEDLOWERWATERMARKVALUE} (0=water higher, 1=water lower than watermark)"
echo ""

# EOF

16_pump_10s_if_necessary.sh

#!/bin/bash
#set -x

# Script: 16_pump_10s_if_necessary.sh
# Author: tomatomat at wurst-wasser.net
# Purpose: Set GPIO pins to start pump

# Globals
GFOLDERBASE="/home/pi/Development/giess-o-mat"
GTIMESTAMPFORMAT="%H:%M:%S"
#GTIMESTAMPFORMAT="%Y-%m-%d_%H:%M:%S"
GTIMESTAMPDATE="`date +%Y-%m-%d`" # ISO8601
GFOLDERLOGS="${GFOLDERBASE}/logs"
GLOGPUMP="${GFOLDERLOGS}/pump_${GTIMESTAMPDATE}.log"

# Check if we already set up the GPIOs
"${GFOLDERBASE}/"00_check_and_init.sh

# Check permissions (Actually, just export as root, then set permissions for device files, done)
#test "`whoami`" != "root" && echo "Must be root (or use sudo)." && exit 1

# Read levels
FLOWERBEDLOWERWATERMARKVALUE="`\"${GFOLDERBASE}/\"11_read_FLOWERBEDLOWERWATERMARKVALUE.sh`"
FLOWERBEDUPPERWATERMARKVALUE="`\"${GFOLDERBASE}/\"12_read_FLOWERBEDUPPERWATERMARKVALUE.sh`"
RESERVOIRLOWERWATERMARKVALUE="`\"${GFOLDERBASE}/\"13_read_RESERVOIRLOWERWATERMARKVALUE.sh`"
RESERVOIRMIDDLEWATERMARKVALUE="`\"${GFOLDERBASE}/\"14_read_RESERVOIRMIDDLEWATERMARKVALUE.sh`"
RESERVOIRUPPERWATERMARKVALUE="`\"${GFOLDERBASE}/\"15_read_RESERVOIRUPPERWATERMARKVALUE.sh`"
#echo "RESERVOIRLOWERWATERMARKVALUE: ${RESERVOIRLOWERWATERMARKVALUE}"

# Check water level in reservoir, so we don't run dry!
if [ "${RESERVOIRLOWERWATERMARKVALUE}" -eq 0 ]; then # 0=higher than mark, 1=lower than mark

  # Check water level in flowerbed, so we don't drown it (and the tomatoes start to rot)
  if [ "${FLOWERBEDUPPERWATERMARKVALUE}" -eq 1 ]; then # 0=higher than mark, 1=lower than mark

     # Check water level in flowerbed, so we don't drown it (and the tomatoes start to rot)
     if [ "${FLOWERBEDLOWERWATERMARKVALUE}" -eq 1 ]; then # 0=higher than mark, 1=lower than mark

        # Start pump
        echo "0" > /sys/class/gpio/gpio17/value # start pump

        # Log it so we can generate nice graphs afterwards
        GTIMESTAMP="`date +${GTIMESTAMPFORMAT}`"
        printf "${GTIMESTAMP}\t1\n" >> "${GLOGPUMP}"

        # Run for 10 Seconds
        sleep 10

        # Stop Pump
        echo "1" > /sys/class/gpio/gpio17/value # stop pump

        # Log it so we can generate nice graphs afterwards
        GTIMESTAMP="`date +${GTIMESTAMPFORMAT}`"
        printf "${GTIMESTAMP}\t0\n" >> "${GLOGPUMP}"
        echo "`date '+%Y-%m-%d, %H:%M:%S'`: Pumped for 10 seconds (approx. 1l)"

     else
        echo "`date '+%Y-%m-%d, %H:%M:%S'`: Flowerbeds's lower watermark already reached, pump not started, we don't want to drown the tomatoes..."
     fi

  else
     echo "`date '+%Y-%m-%d, %H:%M:%S'`: Flowerbeds's upper watermark already reached, pump not started, we don't want to drown the tomatoes..."
  fi

else
  echo "`date '+%Y-%m-%d, %H:%M:%S'`: Reservoir's lower watermark reached, pump not started."
fi

# Just for the logs, not necessary for this script
FLOWERBEDLOWERWATERMARKVALUE="`\"${GFOLDERBASE}/\"11_read_FLOWERBEDLOWERWATERMARKVALUE.sh`"
FLOWERBEDUPPERWATERMARKVALUE="`\"${GFOLDERBASE}/\"12_read_FLOWERBEDUPPERWATERMARKVALUE.sh`"
RESERVOIRLOWERWATERMARKVALUE="`\"${GFOLDERBASE}/\"13_read_RESERVOIRLOWERWATERMARKVALUE.sh`"
RESERVOIRMIDDLEWATERMARKVALUE="`\"${GFOLDERBASE}/\"14_read_RESERVOIRMIDDLEWATERMARKVALUE.sh`"
RESERVOIRUPPERWATERMARKVALUE="`\"${GFOLDERBASE}/\"15_read_RESERVOIRUPPERWATERMARKVALUE.sh`"

#EOF

MORE LATER ToDo-List:

  • Scripts 11..15
  • cronjobs

Some thoughts

FAQ

Choice of programming language
  • Q: Why don't you use python, C or any other higher language?
  • A: I wanted to KISS. Shell is easy to code, easy to maintain, easy to learn, and easy to automate[3]
GPIO protection
  • Q: Why do you connect the GPIOs directly? You should use something like GertBoard to protect your Pi!
  • A: You are so right. I see this as a PoC, next time I will do better, I promise. Next winter comes[TM].

  1. ...and I tend to forget...
  2. Ookay, why should you use a valve instead of a pump? The valve will use more power and is more expensive...but it has one big advantage: It is closed when inactive. What? Oookay. I admit it: My reservoir is on a higher level than the flowerbed, as a result the water kept running after the pump stopped. That lead to a bit much water in the flowerbed. In short: IF your reservoir is on higher level -> use solenoid valve. IF your reservoir is lower than flowerbed -> use pump.
  3. Okay, if you need more exact timing, shell is not the environment of choice, but in this case it fits perfectly.
  • Tags: RaspberryPi, Raspberry Pi, RasPi, GPIO, Farm, Farming, Tomato, Tomatoes, Water, Flowerbed, Level, Water, Grow, Robot, Automatic, Automated, Valve, Lines, Fertilizer