Tutorial: Using a Grove Button on Smart Plant Pi Kickstarter – Raspberry Pi

Tutorial:  Using a Grove Button on Smart Plant Pi Kickstarter – Raspberry Pi

This is an article about how  to use a Grove Button using Python on the Raspberry Pi.   This button is a part of the Smart Plant Pi new Kickstarter.

SmartPlantPi Features

[list]

[list_item size=”small” icon=”icon-beaker” hex_color=””]Measure your Temperature![/list_item]

[list_item size=”small” icon=”icon-beaker” hex_color=””]Measured your Soil Moisture![/list_item]

[list_item size=”small” icon=”icon-beaker” hex_color=””]Measure your Sunlight![/list_item]

[list_item size=”small” icon=”icon-beaker” hex_color=””]Show your results on the Internet![/list_item]

[list_item size=”small” icon=”icon-beaker” hex_color=””]Even connect your plant to the Amazon Echo/Alexa![/list_item]

[/list]

[callout size=”col-12″ title=”Checkout the SmartPlantPi Kickstarter” button_title=”Go to Kickstarter” button_link=”https://www.kickstarter.com/projects/sunair/1801490632?token=c7277b31″  button_size=”normal” button_rounded=”true” button_color=”red”]

[section]

SmartPlantPi

This is a perfect project kit for kids with some help from the adults and for adults trying to learn some new things.   We have done this before with our successful OurWeather kickstarter so we know what we are talking about.   People all over the world have built the OurWeather weather station with great success.   This project has no soldering involved and uses Grove connectors to wire everything up!  You can’t reverse them and blow things up.   Here is our tutorial on the Grove system.

Easy to build.  Easy to learn about the IOT (Internet Of Things) and the Raspberry Pi.

SwitchDoc Labs is building on the strength and reception of our last successful No Soldering Kickstarter Project – OurWeather.

 

Just want a single button?   You can buy one in our SwitchDoc Labs store here or on Amazon.com.

 

The Grove Button (P) – P for Panel

This Grove button contains one independent button, which is configured with pull-down resistor. Ready for use with our microcontrollers as digital input. The button signals the SIG wire, with the second SIG wire being a no-connect.

What does “P” mean? “P” is for “panel mount” in this product. . The  Grove connecter is moved to the back so that you can easily use it as a neat and wire-free interface button.

The Grove  Button (P) is a momentary push button. It contains one  “momentary on/off” button. “Momentary” means that the button rebounds on its own after it is released. The button outputs a HIGH signal when pressed, and LOW when released. The button signals the SIG Pin of the Grove Interface.

The Video

The Raspberry Pi Software

We are using this button in the new Kickstarter, SmartPlantPi.   The button has three functions.   Press it once (all within two seconds), it will tell the computer that you have filled the water basin (SmartPlantPi knows that the basin is empty by looking at the flow meter sensor).   Press it twice (again all within two seconds), it will set the Moisture Threshold (the percent soil moisture to start watering the plant) to the current soil moisture of the plant.   It’s a handy way of setting the Moisture Threshold when you have your plant with just the perfect amount of water for the plant.   Three presses and SmartPlant Pi sets the Moisture Threshold to the default value (currently 65%).

The Interrupt Driver

When you press the button, the software is set up such that you interrupt the processor and the software counts the number of presses and sets a time out (using apscheduler – a fabulous easy to use Python based scheduler package)

Following is the GPIO initialization line of code and the two Interrupt service routines.  The first is called  by the button press and the second routine is called by the 2 second timeout by apscheduler.

 

###############
# button sensor setup
###############
GPIO.setup(config.buttonClick, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

# set up interrupts to handle buttonClick
GPIO.add_event_detect(config.buttonClick,GPIO.FALLING,callback=buttonClickEventHandler, bouncetime=100)

# handle the button click event
def buttonClickEventHandler (pin):
    global buttonPush, buttonInProgress, buttonState, buttonStartTime, scheduler
    print "handling button Click event. preBS=",buttonState
    if (buttonPush == False):
        if (buttonInProgress == False):
                buttonInProgress = True
                buttonPush = False
                buttonState = 1
                buttonStartTime = time.time()
                endTime = datetime.now() + timedelta(seconds=2)
                scheduler.add_job(buttonSampleEnd, 'date', run_date=endTime)
                state.SPP_State = state.SPP_States.Button
                return
        else:
                buttonState = buttonState +1
                # limit to 3
                if (buttonState > 3):
                        buttonState = 3
                return


def buttonSampleEnd():
        global buttonPush, buttonInProgress, buttonState, buttonStartTime

        buttonInProgress = False
        buttonPush = True
        state.SPP_State = state.SPP_States.Monitor




buttonPush = False
buttonInProgress = False
buttonState = 0
buttonStartTime =  0

Note how the interrupt routine counts up to three key presses in two seconds. That is how we determine what we are being told to do.

The Button Interpretation Code

Next is the code in the main line section of SmartPlantPi that specifically handles the Button Press and writes out the results to the Grove OLED screen on SmartPlantPi.   Note the use of the threading lock OLEDLock to keep this OLED writing code from interfering with other status output.

 

 #############
                # Standalone Button Interface
                #############
                if (buttonPush == True):
                        # deal with the button Push
                        print "button State = ", buttonState
                        buttonPush = False
                        OLEDLock.acquire()
                        list = startStatementDisplay(display)
                        # one button push = water now full
                        if (buttonState == 1):
                                makeStatementDisplay(list, 1,"    Water Filled" )
                                state.Pump_Water_Full = 1
                                state.Last_Event = "Water set to Full "+time.strftime("%Y-%m-%d %H:%M:%S")

                        # two button push = set moisture threshold to current reading of moisture_sensor
                        if (buttonState == 2):
                                makeStatementDisplay(list, 1,"    Soil Moisture")
                                makeStatementDisplay(list, 2,"      Threshold")
                                state.Moisture_Limit =  state.Moisture_Humidity
                                makeStatementDisplay(list, 3,"    Set to=%6.1f%%" % state.Moisture_Limit)
                                state.Last_Event = ("Moisture Lim Set to %6.1f: " % state.Moisture_Limit)+time.strftime("%Y-%m-%d %H:%M:%S")


                        # three button push, set moisture threshold to default (65%)
                        if (buttonState == 3):
                                makeStatementDisplay(list, 1,"    Soil Moisture")
                                makeStatementDisplay(list, 2,"      Threshold")
                                makeStatementDisplay(list, 3,"  Set to default=65%")
                                state.Moisture_Limit = 65.0
                                state.Last_Event = ("Moisture Lim Set to %6.1f: " % state.Moisture_Limit)+time.strftime("%Y-%m-%d %H:%M:%S")

                        finishStatementDisplay(display,list)
                        OLEDLock.release()
                        buttonPush = False

Works like a champ. Next up, the code for the combo Rotary Dial and Button input device.