mcervi
05-09-2010, 04:35 PM
Hello,
I'm having a problem with pin wakeup functions on the RF Engine (RF100PC6), using firmware 2.2.16.
On the SN171 proto board, there is a button attached to GPIO5. GPIO5 has its internal pullup enabled, and the button connects GPIO5 to GND when it is pressed. So, GPIO5 is low when the button is pressed, and high otherwise.
I call monitorPin(GPIO5, True) to enable monitoring of that pin. Then, I call wakeupOn(GPIO5, True, False) to enable pin wakeup on a falling edge (i.e. when the button is pressed down).
My HOOK_GPIN code pulses an LED and makes a long beep when the button goes down, and makes a short beep (no LED) when the button goes up. So, it's easy to tell if the HOOK_GPIN code has run and what type of event has occurred.
LED2 is lit whenever the device is awake (so it's easy to tell if it is sleeping).
If I put the unit to sleep from Portal by calling my function gotoSleep(), then it will sleep and wake up when the button is pressed down (falling edge). It sees the button press and executes the HOOK_GPIN code as soon as it wakes up. This all works as expected and is 100% reliable.
However, if I:
1) Press the button and keep the button held down while calling gotoSleep()
2) release the button after it's asleep
3) press the button again
it stays asleep when the button is released (step 2), which is correct, and it wakes up on the button press (step 3), but it does NOT call the HOOK_GPIN function in step 3. :confused:
If I then:
4) release the button
it does call the HOOK_GPIN function for the button release.
This is also 100% reliable - it never wakes up on the next falling edge of a monitored pin if it goes to sleep while that pin is low. I tried this on GPIO9 too just in case it was something funny with GPIO5.
I know it sees the falling edge on that pin, because it wakes itself up from sleep mode. But then why doesn't it call the HOOK_GPIN code?
My application needs to do something as soon as a user presses the button, and go to sleep immediately thereafter. If the user happens to hold the button longer than it takes for the device to complete its task and start sleeping, then the device won't work at all the next time the user presses the button - this would be bad! :(
I'm not sure how to fix this... this is my first project with these devices, so it's quite possible that I have made a mistake in my code.
Any help or suggestions would be greatly appreciated! :)
My test code is below... This can be tested using the SN171 proto board with the LED jumpers on, the switch-GPIO5 jumper set, the RS232 jumpers removed, and a beeper/buzzer between GPIO17 and GND.
from synapse.pinWakeup import *
# Initialization Code
# Pin assignments
LED1_PIN = GPIO_1
LED2_PIN = GPIO_2
BEEPER_PIN = GPIO_17
BUTTON1_PIN = GPIO_5
buttonPressed = 0
secondCounter = 0
@setHook(HOOK_STARTUP)
def startupEvent():
""" This is hooked into the HOOK_STARTUP event """
# Detect and initialize the hardware
initProtoHw()
# Set up wakeup Pin
monitorPin(BUTTON1_PIN, True)
setRate(2)
wakeupOn(BUTTON1_PIN, True, False)
lightLed2()
@setHook(HOOK_100MS)
def timer100msEvent(currentMs):
"""Hooked into the HOOK_100MS event"""
global secondCounter
global buttonPressed
secondCounter = secondCounter + 1
# If master hasn't contacted unit in 200 ticks (20s) then go to sleep to save batteries.
# Unit won't wake up again until the button is pressed or it is power-cycled.
@setHook(HOOK_GPIN)
def wakeUpOnButton(pinNum,isSet):
""" set to wake up by interrupt pin controlled by Microprocessor ... triggered falling edge """
global buttonPressed
# Buttons go to 0 when pressed and are 1 (due to internal pullup) when idle
if (isSet == False):
pulsePin(LED1_PIN, 800, True)
pulsePin(BEEPER_PIN, 250, True)
buttonPressed = 1
else:
pulsePin(BEEPER_PIN, 125, True)
# This code is called from master via RPC.
def gotoSleep(dur):
"""commands nodes to go to sleep"""
global secondCounter
if rpcSourceAddr() != localAddr():
# Reset counter when master contacts this unit.
secondCounter = 0
wakeupOn(BUTTON1_PIN, True, False)
ledsOff()
sleep(1, dur)
#afterSleep()
lightLed2()
# This code is called from master via RPC.
# It only clears the button press request if the master acknowledges receipt
# by calling this function via RPC.
def clearButtonPress():
global secondCounter
global buttonPressed
# Reset counter when master contacts this unit.
secondCounter = 0
buttonPressed = 0
# LED control functions
def ledsOff():
"""Turn off all LEDs"""
writePin(LED1_PIN, False)
writePin(LED2_PIN, False)
# Not technically an LED, but it makes sense to do this here
writePin(BEEPER_PIN, False)
def lightLed1():
"""Light the first LED"""
writePin(LED1_PIN, True)
def lightLed2():
"""Light the second LED"""
writePin(LED2_PIN, True)
# Initialization Code
def initProtoHw():
setPinDir(LED1_PIN, True)
setPinDir(LED2_PIN, True)
setPinDir(BEEPER_PIN, True)
# Button1 is input with pullup
setPinDir(BUTTON1_PIN, False)
setPinPullup(BUTTON1_PIN, True)
# Turn LEDs and beeper off
ledsOff()
I'm having a problem with pin wakeup functions on the RF Engine (RF100PC6), using firmware 2.2.16.
On the SN171 proto board, there is a button attached to GPIO5. GPIO5 has its internal pullup enabled, and the button connects GPIO5 to GND when it is pressed. So, GPIO5 is low when the button is pressed, and high otherwise.
I call monitorPin(GPIO5, True) to enable monitoring of that pin. Then, I call wakeupOn(GPIO5, True, False) to enable pin wakeup on a falling edge (i.e. when the button is pressed down).
My HOOK_GPIN code pulses an LED and makes a long beep when the button goes down, and makes a short beep (no LED) when the button goes up. So, it's easy to tell if the HOOK_GPIN code has run and what type of event has occurred.
LED2 is lit whenever the device is awake (so it's easy to tell if it is sleeping).
If I put the unit to sleep from Portal by calling my function gotoSleep(), then it will sleep and wake up when the button is pressed down (falling edge). It sees the button press and executes the HOOK_GPIN code as soon as it wakes up. This all works as expected and is 100% reliable.
However, if I:
1) Press the button and keep the button held down while calling gotoSleep()
2) release the button after it's asleep
3) press the button again
it stays asleep when the button is released (step 2), which is correct, and it wakes up on the button press (step 3), but it does NOT call the HOOK_GPIN function in step 3. :confused:
If I then:
4) release the button
it does call the HOOK_GPIN function for the button release.
This is also 100% reliable - it never wakes up on the next falling edge of a monitored pin if it goes to sleep while that pin is low. I tried this on GPIO9 too just in case it was something funny with GPIO5.
I know it sees the falling edge on that pin, because it wakes itself up from sleep mode. But then why doesn't it call the HOOK_GPIN code?
My application needs to do something as soon as a user presses the button, and go to sleep immediately thereafter. If the user happens to hold the button longer than it takes for the device to complete its task and start sleeping, then the device won't work at all the next time the user presses the button - this would be bad! :(
I'm not sure how to fix this... this is my first project with these devices, so it's quite possible that I have made a mistake in my code.
Any help or suggestions would be greatly appreciated! :)
My test code is below... This can be tested using the SN171 proto board with the LED jumpers on, the switch-GPIO5 jumper set, the RS232 jumpers removed, and a beeper/buzzer between GPIO17 and GND.
from synapse.pinWakeup import *
# Initialization Code
# Pin assignments
LED1_PIN = GPIO_1
LED2_PIN = GPIO_2
BEEPER_PIN = GPIO_17
BUTTON1_PIN = GPIO_5
buttonPressed = 0
secondCounter = 0
@setHook(HOOK_STARTUP)
def startupEvent():
""" This is hooked into the HOOK_STARTUP event """
# Detect and initialize the hardware
initProtoHw()
# Set up wakeup Pin
monitorPin(BUTTON1_PIN, True)
setRate(2)
wakeupOn(BUTTON1_PIN, True, False)
lightLed2()
@setHook(HOOK_100MS)
def timer100msEvent(currentMs):
"""Hooked into the HOOK_100MS event"""
global secondCounter
global buttonPressed
secondCounter = secondCounter + 1
# If master hasn't contacted unit in 200 ticks (20s) then go to sleep to save batteries.
# Unit won't wake up again until the button is pressed or it is power-cycled.
@setHook(HOOK_GPIN)
def wakeUpOnButton(pinNum,isSet):
""" set to wake up by interrupt pin controlled by Microprocessor ... triggered falling edge """
global buttonPressed
# Buttons go to 0 when pressed and are 1 (due to internal pullup) when idle
if (isSet == False):
pulsePin(LED1_PIN, 800, True)
pulsePin(BEEPER_PIN, 250, True)
buttonPressed = 1
else:
pulsePin(BEEPER_PIN, 125, True)
# This code is called from master via RPC.
def gotoSleep(dur):
"""commands nodes to go to sleep"""
global secondCounter
if rpcSourceAddr() != localAddr():
# Reset counter when master contacts this unit.
secondCounter = 0
wakeupOn(BUTTON1_PIN, True, False)
ledsOff()
sleep(1, dur)
#afterSleep()
lightLed2()
# This code is called from master via RPC.
# It only clears the button press request if the master acknowledges receipt
# by calling this function via RPC.
def clearButtonPress():
global secondCounter
global buttonPressed
# Reset counter when master contacts this unit.
secondCounter = 0
buttonPressed = 0
# LED control functions
def ledsOff():
"""Turn off all LEDs"""
writePin(LED1_PIN, False)
writePin(LED2_PIN, False)
# Not technically an LED, but it makes sense to do this here
writePin(BEEPER_PIN, False)
def lightLed1():
"""Light the first LED"""
writePin(LED1_PIN, True)
def lightLed2():
"""Light the second LED"""
writePin(LED2_PIN, True)
# Initialization Code
def initProtoHw():
setPinDir(LED1_PIN, True)
setPinDir(LED2_PIN, True)
setPinDir(BEEPER_PIN, True)
# Button1 is input with pullup
setPinDir(BUTTON1_PIN, False)
setPinPullup(BUTTON1_PIN, True)
# Turn LEDs and beeper off
ledsOff()