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 Raspberry Pi Software
We are using this button in the new product, 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