An automatic plant watering system is a project that's been on my back burner for years. I'd like to be able to go on vacation and not worry about whatever houseplant I'm fruitlessly nursing at the moment. (I have the opposite of a green thumb -- I have very little luck growing plants -- but I keep trying, and if nothing else, I can make sure lack of watering isn't the problem.)
I've had all the parts sitting around for quite some time,
and had tried them all individually,
but never seemed to make the time to put them all together.
Today's "Raspberry Pi Jam" at Los Alamos Makers seemed like
the ideal excuse.
Sensing Soil Moisture
First step: the moisture sensor. I used a little moisture sensor that I found on eBay. It says "YL-38" on it. It has the typical forked thingie you stick into the soil, connected to a little sensor board.
The board has four pins: power, ground, analog and digital outputs. The digital output would be the easiest: there's a potentiometer on the board that you can turn to adjust sensitivity, then you can read the digital output pin directly from the Raspberry Pi.
But I had bigger plans: in addition to watering, I wanted to keep track of how fast the soil dries out, and update a web page so that I could check my plant's status from anywhere. For that, I needed to read the analog pin.
Raspberry Pis don't have a way to read an analog input. (An Arduino would have made this easier, but then reporting to a web page would have been much more difficult.) So I used an ADS1115 16-bit I2sup>C Analog to Digital Converter board from Adafruit, along with Adafruit's ADS1x15 library. It's written for CircuitPython, but it works fine in normal Python on Raspbian.
It's simple to use. Wire power, ground, SDA and SDC to the appropriate Raspberry Pi pins (1, 6, 3 and 5 respectively). Connect the soil sensor's analog output pin with A0 on the ADC. Then
# Initialize the ADC i2c = busio.I2C(board.SCL, board.SDA) ads = ADS.ADS1015(i2c) adc0 = AnalogIn(ads, ADS.P0) # Read a value value = adc0.value voltage = adc0.voltage
With the probe stuck into dry soil, it read around 26,500 value, 3.3 volts. Damp soil was more like 14528, 1.816V. Suspended in water, it was more like 11,000 value, 1.3V.
Driving a Water Pump
The pump also came from eBay. They're under $5; search for terms like "Mini Submersible Water Pump 5V to 12V DC Aquarium Fountain Pump Micro Pump". As far as driving it is concerned, treat it as a motor. Which means you can't drive it directly from a Raspberry Pi pin: they don't generate enough current to run a motor, and you risk damaging the Pi with back-EMF when the motor stops.
Instead, my go-to motor driver for small microcontroller projects is a SN754410 SN754410 H-bridge chip. I've used them before for driving little cars with a Raspberry Pi or with an Arduino. In this case the wiring would be much simpler, because there's only one motor and I only need to drive it in one direction. That means I could hardwire the two motor direction pins, and the only pin I needed to control from the Pi was the PWM motor speed pin. The chip also needs a bunch of ground wires (which it uses as heat sinks), a line to logic voltage (the Pi's 3.3V pin) and motor voltage (since it's such a tiny motor, I'm driving it from the Pi's 5v power pin).
Here's the full wiring diagram.
Driving a single PWM pin is a lot simpler than the dual bidirectional motor controllers I've used in other motor projects.
GPIO.setmode(GPIO.BCM) GPIO.setup(23, GPIO.OUT) pump = GPIO.PWM(PUMP_PIN, 50) pump.start(0) # Run the motor at 30% for 2 seconds, then stop. pump.ChangeDutyCycle(30) time.sleep(2) pump.ChangeDutyCycle(0)
The rest was just putting together some logic: check the sensor, and if it's too dry, pump some water -- but only a little, then wait a while for the water to soak in -- and repeat. Here's the full plantwater.py script. I haven't added the website part yet, but the basic plant waterer is ready to use -- and ready to demo at tonight's Raspberry Pi Jam.
[ 13:50 Feb 27, 2020 More hardware | permalink to this entry | ]