Introduction: CPB Plant Monitor W/ Handmade Planter

I really love plants, so for my final project at Boston College in my Physical Computing class I decided to make a planter (thanks to my ceramics class) with a plant monitor attached! It can detect the moisture level of the soil, the light level in the room, any violent shaking of the plant, and the temperature of the room.

Supplies

Ceramics

  • clay
  • potter's wheel
  • clay tools
  • kiln
  • glaze
  • time

Electronics

  • Circuit Playground Bluefruit
  • Alligator clip
  • Alligator to pin wire x2
  • button with pin connector
  • nail
  • data transfer cord
  • battery pack

Other

  • tape/putty
  • Audacity software
  • Mu IDE

Step 1: Make Your Ceramic Planter Pot

I'm currently taking a ceramics class at Boston College as well, so I decided to learn how to throw a planter pot. I started with a softball sized lump of clay on the wheel, centering it, opening up the center, and bringing up the sides to create a tall bowl shape. I poked three holes into the bottom so it can drain water as well. I also threw a small plate that sits underneath the planter to catch any water drainage. I trimmed the bowl shape to be more refined and trimmed a thin foot onto the bottom of the plate after the clay had partially dried. I glazed both in a glaze called "Nelson Red" which is actually a light yellow-green. This process took a few weeks to complete, as it had to go through both a bisque fire and glaze fire to finish.

Step 2: Gather Electronics and Assemble

This project was relatively simple in terms of electronic parts because the CPB has so many sensors built into it already. I used an alligator clip to one of the capacitive touch pads and connected it to a nail that is conductive to measure moisture in the soil. I used another two pin to alligator clips to connect an extra button to the CPB, but this could have easily just used two alligator clips as well. I connected the button to GND and one of the capacitive touch pads that are also digital input/output. The light sensor and accelerometer are both built into the CPB already.

Step 3: Gather Sounds

I used sounds to add to my plant monitor. If the moisture level of the plant is less than 50% of the designated range, I had it say "Water me!". If the light level of the plant is less than 50% of the designated range, I had it say "It's kind of dark in here...". If the accelerometer detects shaking, I had it say "Stop shaking me!". Feel free to add your own sounds as you like.

I used https://online-voice-recorder.com/ to record my voice for the monitor. I then used the free Audacity software to format the sounds into WAV files in mono and 22khz. I put these files on my CPB in separate folder.

I attached a speaker to the CPB to emit these sounds - this is optional if you do not want sounds on your plant monitor.

Step 4: Code

The code mostly involves setting up the various sensors and buttons available on the CPB. I used the light sensor, accelerometer, temperature sensor, a touchpad, and two built-in buttons on the CPB. I also attached an additional button that uses another touchpad.

The while True loop involves checking for each button press or a combination of the two buttons on the CPB to denote a reset in the lights. It then maps the moisture or light levels to a percentage of the 10 pixels on the CPB and lights it up accordingly in different colors.

Another part of the code involves converting the temperature in Fahrenheit to binary so that it can be displayed in a readable way on the board in neopixel lights. It uses a simple algorithm for converting decimal numbers to binary and represents it in red lights on the board, using a white light to denote the end of the binary number.

I manually calibrated the bottom and top values of the range for moisture and light - you will also need to edit these values to fit your scenario.

See my GitHub Gist below for details, feel free to edit to fit your needs.

plant-monitor.py

This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Show hidden characters
# Megan Costello
# final project plant monitor
importpwmio,board,digitalio,touchio, neopixel, random, analogio, time, simpleio, busio, adafruit_lis3dh, adafruit_thermistor
fromaudiopwmioimportPWMAudioOutasAudioOut
fromaudiocoreimportWaveFile
WHITE= (255,255,255)
BLACK= (0,0,0)
RED= (255,0,0)
GREEN= (0,255,0)
BLUE= (0,0,255)
YELLOW= (255,150,0)
pixels_pin=board.NEOPIXEL
pixels_num_of_lights=10
pixels=neopixel.NeoPixel(pixels_pin, pixels_num_of_lights, brightness=0.2, auto_write=True)
touchpad_A1=touchio.TouchIn(board.A1)
speaker=digitalio.DigitalInOut(board.SPEAKER_ENABLE)
speaker.direction=digitalio.Direction.OUTPUT
speaker.value=True
audio=AudioOut(board.SPEAKER)
button_A=digitalio.DigitalInOut(board.BUTTON_A)
button_A.switch_to_input(pull=digitalio.Pull.DOWN)
button_B=digitalio.DigitalInOut(board.BUTTON_B)
button_B.switch_to_input(pull=digitalio.Pull.DOWN)
redbutton=digitalio.DigitalInOut(board.A3)
redbutton.direction=digitalio.Direction.INPUT
redbutton.pull=digitalio.Pull.UP
i2c=busio.I2C(board.ACCELEROMETER_SCL, board.ACCELEROMETER_SDA)
int1=digitalio.DigitalInOut(board.ACCELEROMETER_INTERRUPT)
accelerometer=adafruit_lis3dh.LIS3DH_I2C(i2c, address=0x19, int1=int1)
accelerometer.range=adafruit_lis3dh.RANGE_8_G
accelerometer.set_tap(2,20)
thermistor=adafruit_thermistor.Thermistor(board.TEMPERATURE, 10000, 10000, 25, 3950)
path="monitor-sounds/"
defplay_file(filename):
withopen(path+filename, "rb") aswave_file:
wave=WaveFile(wave_file)
audio.play(wave)
whileaudio.playing:
pass
defconvertBinary(num):
bin= []
whilenum>0:
bin.append(num%2)
num=int(num/2)
bin.reverse()
print(bin)
returnbin
pixels.fill(BLACK)
DRY_VALUE=200
WET_VALUE=1000
light=analogio.AnalogIn(board.LIGHT)
whileTrue:
moisture_level=touchpad_A1.raw_value
print("moisture is ", moisture_level)
pixels_wet=int(simpleio.map_range(moisture_level, DRY_VALUE, WET_VALUE, 1, 10))
time.sleep(1)
light_level=light.value
pixels_light=int(simpleio.map_range(light_level, 0, 2000, 1, 10))
print("light is ", light_level)
temp_f=round(thermistor.temperature*9/5+32)
pixels_temp=int(simpleio.map_range(temp_f, 50, 90, 1, 10))
print("temp is ", temp_f)
time.sleep(0.5)
ifbutton_A.valueandbutton_B.value:
print("reset")
pixels.fill(BLACK)
elifbutton_A.value:
print("blue lights on ")
#pixels[0:pixels_wet] = BLUE * pixels_wet
foriinrange(10):
ifi<=pixels_wet:
print("blue ", i)
pixels[i] =BLUE
time.sleep(0.1)
ifpixels_wet<5:
play_file("waterme.wav")
elifbutton_B.value:
print("yellow lights on ")
#pixels[0:pixels_light] = YELLOW * pixels_light
foriinrange(10):
ifi<=pixels_light:
print("yellow ", i)
pixels[i] =YELLOW
time.sleep(0.1)
ifpixels_light<5:
play_file("dark.wav")
elifnotredbutton.value:
print("temp reading")
binNum=convertBinary(temp_f)
foriinrange(len(binNum)):
ifbinNum[i] ==1:
pixels[i] =RED
else:
pixels[i] =BLACK
time.sleep(0.1)
pixels[len(binNum)] =WHITE
elifaccelerometer.shake(shake_threshold=10):
print("stop shaking!")
play_file("stopshaking.wav")

Step 5: Test and Complete

At this stage, you should have a working plant monitor! It took me a few tries to calibrate the ranges for light and moisture how I wanted them, be sure to test these. I attached a battery pack so that the monitor can run independently. I also attached the CPB to the side of my planter using wall putty. Have fun monitoring your plant!