Are you new to using CircuitPython? No worries, there is a full getting started guide here.
To edit the CircuitPython code and receive realtime data from our sensors in the REPL, Adafruit suggests using the Mu Editor. You can learn about Mu and installation in this tutorial.
Open up the Mu editor or an editor of your choice with a REPL. (REPL = read-evaluate-print-loop, and it's what we'll need to use to access the values of our moisture and temperature levels so we can calibrate our sensors).
Import Libraries and Initialize Values
We'll begin the program by importing the necessary libraries and initialize the variables we'll be using.
If you think you might be missing a library, you'll be covered by installing the whole library package. Find out how in the CircuitPython Essentials Guide on CircuitPlayground Libraries.
- DRY_VALUE and WET_VALUE should be calibrated and will be slightly different for everyone. We'll talk about how to calibrate this later.
- tempThreshhold is in Celcius and is the minimum temperature needed for ideal compost conditions. Feel free to change this to room temperature when testing the prototype to make sure everything works. Don't forget to change back to 43!
# Author: Isaac Wellish # Code adapted from Tony Dicola's CircuitPython code on using the DS18x20 temperature sensor- # as well as John Park's CircuitPython code on determining soil moisture from nails from adafruit_onewire.bus import OneWireBus from adafruit_ds18x20 import DS18X20 import time import board import simpleio import touchio import neopixel import analogio from simpleio import map_range #Initialize neopixels pixels = neopixel.NeoPixel(board.NEOPIXEL, 10, brightness=.1) #set variables for capacitive touch inputs, later used for soil moisture variables touch = touchio.TouchIn(board.A1) touch2 = touchio.TouchIn(board.A2) DRY_VALUE = 3100 # calibrate this by hand! WET_VALUE = 4000 # calibrate this by hand! tempThreshhold = 43 #celius temperature of threshold for ideal compost temperature # Initialize one-wire bus on board pin A3. ow_bus = OneWireBus(board.A3) # Scan for sensors and grab the first one found. ds18 = DS18X20(ow_bus, ow_bus.scan()[0]) #Initialize the light senor on board to use for neopixel brightness later light = analogio.AnalogIn(board.LIGHT)
The Main Program Loop: Finding the Average Soil Moisture & Temperature Levels
- To have a more accurate representation of what the moisture level is in the compost, we place the nails in separate locations in the compost and take the average of both moisture readings.
- Print average moisture and temperature levels.
# Main loop while True: ###SOIL MOISTURE READINGS #set variables for capacitive touch inputs for nails to take in soil moisture levels value_A1 = touch.raw_value value_A2 = touch2.raw_value #take the average of both moisture levels avgMoist = value_A1 + value_A2 / 2 print("Moisture level:",(avgMoist,)) ###TEMPERATURE READINGS #variable for temperature compostTemp = ds18.temperature #print the temperature print('Temperature: {0:0.3f}C'.format(compostTemp))
Determining the State of the Compost with NeoPixels
- We will be using the on board NeoPixels as visual feedback for the information the temperature and moisture sensors are giving us. The colors let us know how to best help the compost.
- Ideally we would throw in a wifi module and make the project Internet of Things friendly to be able to see the real sensor data without having to look at a box on the compost bin but I wanted to keep this project a little more simple. I will most likely be adding IoT functionality to this project later!
- When the compost is not hot enough and too dry, the colors yellow and red will be displayed alternating. This color combination means you must add food scraps to counterbalance the dryness. You must also turn the compost to mix in the new food scraps as well as give the organisms inside some oxygen so they can better breakdown the compost, releasing heat and increasing the temperature.
- When the compost is not hot enough and too wet, the colors yellow and blue will be displayed alternating. This color combination means you must add dry carbon-based material like leaves and wood chips to counterbalance the wet stuff. You must turn the compost as well for the same reasons as above.
- When the compost is not hot enough but at the right moisture level (so close!), the colors yellow and green will be displayed alternating. This color combination means the moisture is at the ideal level however the compost isn't hot enough. Give the compost a couple turns to bring some oxygen to those hungry organisms in there!
- When the compost is at the ideal temperature level, regardless of moisture, all the NeoPixels will be green. We have ideal conditions! This means you don't have to do anything!
###IF STATEMENTS TO DETERMINE STATE OF COMPOST #RED & YELLOW = TOO COLD & TOO DRY if((compostTemp<tempThreshhold) and (avgMoist<DRY_VALUE)): pixels[0] = (255,0,0) # red pixels[1] = (255,255,0) #yellow pixels[2] = (255,0,0) pixels[3] = (255,255,0) pixels[4] = (255,0,0) pixels[5] = (255,255,0) pixels[6] = (255,0,0) pixels[7] = (255,255,0) pixels[8] = (255,0,0) pixels[9] = (255,255,0) print("Not hot enough, too dry") #BLUE & YELLOW = TOO COLD & TOO WET elif((compostTemp<tempThreshhold) and (avgMoist>WET_VALUE)): pixels[0] = (0,0,255) # blue pixels[1] = (255,255,0) #yellow pixels[2] = (0,0,255) pixels[3] = (255,255,0) pixels[4] = (0,0,255) pixels[5] = (255,255,0) pixels[6] = (0,0,255) pixels[7] = (255,255,0) pixels[8] = (0,0,255) pixels[9] = (255,255,0) print("Not hot enough, too wet") #GREEN & YELLOW = TOO COLD & MOISTURE LEVEL OPTIMUM elif((compostTemp<tempThreshhold) and (avgMoist >DRY_VALUE and avgMoist<WET_VALUE)): pixels[0] = (0,255,0) # green pixels[1] = (255,255,0) #yellow pixels[2] = (0,255,0) pixels[3] = (255,255,0) pixels[4] = (0,255,0) pixels[5] = (255,255,0) pixels[6] = (0,255,0) pixels[7] = (255,255,0) pixels[8] = (0,255,0) pixels[9] = (255,255,0) print("Not hot enough, right moisture level") #ALL GREEN = COMPOST AT OPTIMUM TEMPERATURE & MOISTURE elif(compostTemp>tempThreshhold): pixels.fill((0,255,0))# green print("Compost Ready")
Using The Light Sensor to Dim or Brighten NeoPixels
- To decrease the amount of power needed for running this program on the CPX (Circuit Playground Express) and make it easier on the eyes to see the NeoPixel colors, we will use the on board light sensor to brighten the NeoPixels when it's brighter out and dim the NeoPixels when it's darker out.
- We'll use a mapping function to map the range of the light sensor to the range of NeoPixel brightness.
- We then use that mapped value as the level of brightness for the NeoPixels to show on the board.
- Lastly we pause the program for three seconds to save power. We don't need to be updating the program and sensor data any more than this. If you'd like to save power even more, feel free to change this amount of time!
*It would make sense to show the NeoPixels ("pixels.show()") at the end of the program but for some reason the NeoPixels would only update correctly if the show() function was executed before updating the brightness level. This works fine with a three second pause in between while loop runs but will become more and more faulty once the update time is greatly increased. The brightness should update well enough as long as the update time is less than a minute or so. Please let us know if you have figured out a better fix!
###LIGHTING CONFIGURATION #print value of light sensor print((light.value,)) #map light snesor range to neopixel brightness range peak = map_range(light.value, 2000, 62000, 0.01, 0.3) #print neopixel brightness levels print(peak) #show neopixels pixels.show() #update neopixel brightness based on level of exposed light pixels = neopixel.NeoPixel(board.NEOPIXEL, 10, brightness=peak) #pause for three seconds time.sleep(3) ###END PROGRAM
# SPDX-FileCopyrightText: 2018 Isaac Wellish for Adafruit Industries # # SPDX-License-Identifier: MIT # Author: Isaac Wellish # Code adapted from Tony Dicola's CircuitPython code using the DS18x20 temp sensor # as well as John Park's CircuitPython code determining soil moisture from nails import time from adafruit_onewire.bus import OneWireBus from adafruit_ds18x20 import DS18X20 import board import touchio import neopixel import analogio from simpleio import map_range # Initialize neopixels pixels = neopixel.NeoPixel(board.NEOPIXEL, 10, brightness=.1) # set variables for capacitive touch inputs, later used for soil moisture variables touch = touchio.TouchIn(board.A1) touch2 = touchio.TouchIn(board.A2) DRY_VALUE = 3100 # calibrate this by hand! WET_VALUE = 4000 # calibrate this by hand! tempThreshhold = 43 #celius temperature of threshold for ideal compost temperature # Initialize one-wire bus on board pin A3. ow_bus = OneWireBus(board.A3) # Scan for sensors and grab the first one found. ds18 = DS18X20(ow_bus, ow_bus.scan()[0]) # Initialize the light senor on board to use for neopixel brightness later light = analogio.AnalogIn(board.LIGHT) # Main loop while True: # SOIL MOISTURE READINGS # set capacitive touch inputs for nails to take in soil moisture levels value_A1 = touch.raw_value value_A2 = touch2.raw_value # take the average of both moisture levels avgMoist = value_A1 + value_A2 / 2 print("Moisture level:",(avgMoist,)) # TEMPERATURE READINGS # variable for temperature compostTemp = ds18.temperature # print the temperature print('Temperature: {0:0.3f}C'.format(compostTemp)) # IF STATEMENTS TO DETERMINE STATE OF COMPOST # RED & YELLOW = TOO COLD & TOO DRY if((compostTemp<tempThreshhold) and (avgMoist<DRY_VALUE)): pixels[0] = (255,0,0) # red pixels[1] = (255,255,0) # yellow pixels[2] = (255,0,0) pixels[3] = (255,255,0) pixels[4] = (255,0,0) pixels[5] = (255,255,0) pixels[6] = (255,0,0) pixels[7] = (255,255,0) pixels[8] = (255,0,0) pixels[9] = (255,255,0) print("Not hot enough, too dry") # BLUE & YELLOW = TOO COLD & TOO WET elif((compostTemp<tempThreshhold) and (avgMoist>WET_VALUE)): pixels[0] = (0,0,255) # blue pixels[1] = (255,255,0) # yellow pixels[2] = (0,0,255) pixels[3] = (255,255,0) pixels[4] = (0,0,255) pixels[5] = (255,255,0) pixels[6] = (0,0,255) pixels[7] = (255,255,0) pixels[8] = (0,0,255) pixels[9] = (255,255,0) print("Not hot enough, too wet") # GREEN & YELLOW = TOO COLD & MOISTURE LEVEL OPTIMUM elif((compostTemp<tempThreshhold) and (avgMoist >DRY_VALUE and avgMoist<WET_VALUE)): pixels[0] = (0,255,0) # green pixels[1] = (255,255,0) # yellow pixels[2] = (0,255,0) pixels[3] = (255,255,0) pixels[4] = (0,255,0) pixels[5] = (255,255,0) pixels[6] = (0,255,0) pixels[7] = (255,255,0) pixels[8] = (0,255,0) pixels[9] = (255,255,0) print("Not hot enough, right moisture level") # ALL GREEN = COMPOST AT OPTIMUM TEMPERATURE & MOISTURE elif compostTemp > tempThreshhold: pixels.fill((0,255,0)) # green print("Compost Ready") # LIGHTING CONFIGURATION # print value of light sensor print((light.value,)) # map light snesor range to neopixel brightness range peak = map_range(light.value, 2000, 62000, 0.01, 0.3) # print neopixel brightness levels print(peak) # show neopixels pixels.show() # update neopixel brightness based on level of exposed light pixels = neopixel.NeoPixel(board.NEOPIXEL, 10, brightness=peak) # pause for three seconds time.sleep(3) # END PROGRAM
Text editor powered by tinymce.