Code: Select all
global raising_time, falling_time, delay
Code: Select all
global raising_time, falling_time, delay
Thank you very much for this feedback.pythoncoder wrote:The best way to use interrupt handlers is to have variables accessible to both the handler and the main program. Typically the main program executes a loop which runs forever. The interrupt handler updates the variables and sets a flag to tell the main loop it has done so. The main loop reads the data and clears the flag. As a start I'd re-jig your test program to work that way, moving all the print statements into the main loop. The interrupt handler then becomes very simple indeed.
The flag and shared data can be global variables, but in programs of any complexity it's better to create a class. The shared data is in bound variables and the interrupt handler is a bound method. The latter "just works" with no special coding required.
If interrupts occur at a high rate you may need to think about the case where a subsequent interrupt occurs before the main loop has cleared the flag. If it's liable to occur and how you handle it depends on the application: sometimes all that's required is for the interrupt handler simply to do nothing if the flag is set on entry - i.e. just discard the sample.
Code: Select all
import time
import machine
from machine import Pin, RTC
RTC_USEC_POS = 6
RTC_SEC_POS = 5
RTC_MIN_POS = 4
MIN_TO_SEC = 60
SEC_TO_USEC = 1000
TRIGGER_TIME = 10
TRIGGER_PIN = 'GP11'
ECHO_PIN = 'GP12'
LOW = 0
HIGH = 1
class DistanceSensor:
def __init__(self, triggerGPIO, echoGPIO):
self.triggerPin = Pin(triggerGPIO, mode = Pin.OUT)
self.echoPin = Pin(echoGPIO, mode = Pin.IN)
self.rtc = machine.RTC()
self.delay = 0
def changingEdge(self, pin):
print("Changing Edge ")
print(self)
print(pin)
flags = pin.irq().flags()
print(flags)
if flags & Pin.IRQ_RISING:
self.raising_time = self.rtc.now()
print(self.raising_time)
elif flags & Pin.IRQ_FALLING:
self.falling_time = self.rtc.now()
print(self.falling_time)
ellapsed_minutes = self.falling_time[RTC_MIN_POS] - self.raising_time[RTC_MIN_POS]
ellapsed_seconds = self.falling_time[RTC_SEC_POS] - self.raising_time[RTC_SEC_POS]
ellapsed_useconds = self.falling_time[RTC_USEC_POS] - self.raising_time[RTC_USEC_POS]
self.delay = ellapsed_minutes * MIN_TO_SEC * SEC_TO_USEC + ellapsed_seconds * SEC_TO_USEC + ellapsed_useconds
print("Delay: %d" % self.delay)
distanceSensor = DistanceSensor(TRIGGER_PIN, ECHO_PIN)
callback = distanceSensor.echoPin.irq(trigger = Pin.IRQ_RISING | Pin.IRQ_FALLING, handler = distanceSensor.changingEdge)
print(callback.flags())
callback()
while distanceSensor.delay==0:
input("Press Enter to trigger...")
distanceSensor.triggerPin.value(HIGH)
time.sleep_us(TRIGGER_TIME)
distanceSensor.triggerPin.value(LOW)
Thank you for thatpythoncoder wrote:@Gabi the definitive guide is here http://docs.micropython.org/en/latest/p ... rules.html
Code: Select all
import time
import machine
import micropython
from machine import Pin, RTC
micropython.alloc_emergency_exception_buf(100)
RTC_USEC_POS = 6
RTC_SEC_POS = 5
RTC_MIN_POS = 4
MIN_TO_SEC = 60
SEC_TO_USEC = 1000
TRIGGER_TIME = 100000
TRIGGER_PIN = 'GP11'
ECHO_PIN = 'GP12'
LOW = 0
HIGH = 1
class DistanceSensor:
def __init__(self, triggerGPIO, echoGPIO):
self.triggerPin = Pin(triggerGPIO, mode = Pin.OUT)
self.echoPin = Pin(echoGPIO, mode = Pin.OUT)
self.rtc = machine.RTC()
self.delay = 0
def getEchoPin(self):
return self.echoPin
def setEchoPin(self, newValue):
self.echoPin.value(newValue)
def changingEdge(self, pin):
global callback
print("Changing Edge ")
print(callback)
print(pin)
flags = callback.flags()
print(flags)
print(Pin.IRQ_RISING)
print(Pin.IRQ_FALLING)
if flags & Pin.IRQ_RISING:
self.raising_time = self.rtc.now()
print(self.raising_time)
elif flags & Pin.IRQ_FALLING:
self.falling_time = self.rtc.now()
print(self.falling_time)
ellapsed_minutes = self.falling_time[RTC_MIN_POS] - self.raising_time[RTC_MIN_POS]
ellapsed_seconds = self.falling_time[RTC_SEC_POS] - self.raising_time[RTC_SEC_POS]
ellapsed_useconds = self.falling_time[RTC_USEC_POS] - self.raising_time[RTC_USEC_POS]
self.delay = ellapsed_minutes * MIN_TO_SEC * SEC_TO_USEC + ellapsed_seconds * SEC_TO_USEC + ellapsed_useconds
print("Delay: %d" % self.delay)
distanceSensor = DistanceSensor(TRIGGER_PIN, ECHO_PIN)
callback = distanceSensor.echoPin.irq(trigger = Pin.IRQ_RISING | Pin.IRQ_FALLING, handler = distanceSensor.changingEdge)
Code: Select all
import time
import machine
import micropython
from machine import Pin
micropython.alloc_emergency_exception_buf(100)
RTC_USEC_POS = 6
RTC_SEC_POS = 5
RTC_MIN_POS = 4
MIN_TO_SEC = 60
SEC_TO_USEC = 1000
TRIGGER_TIME = 10
TRIGGER_PIN = 'GP11'
ECHO_PIN = 'GP12'
LOW = 0
HIGH = 1
class DistanceSensor:
def __init__(self, triggerGPIO, echoGPIO):
self.triggerPin = Pin(triggerGPIO, mode = Pin.OUT)
self.echoPin = Pin(echoGPIO, mode = Pin.IN)
self.mm_decimal = ""
self.mm = -1
self.cm = -1
def isDistanceCalculated(self):
return self.mm != -1 & self.cm != -1
def setTriggerPinValue(self, value):
self.triggerPin.value(value)
def getDistanceString(self):
return str(self.cm) + "," + self.mm_decimal + str(self.mm) + "cm"
def changingEdge(self, pin):
global callback
flags = callback.flags()
if flags & Pin.IRQ_RISING:
self.raising_time = time.ticks_us()
elif flags & Pin.IRQ_FALLING:
self.falling_time = time.ticks_us()
delay = time.ticks_diff(self.raising_time, self.falling_time)
#We use 17 instead of 0,017
distance = delay * 17
#We rescale the distance in cm by separating cm and mm
self.cm = distance // 1000
self.mm = distance % 1000
#in case we have a distance like 49028
# cm = 49
# mm = 028 but the 0 would be discared so we check it
if distance % 100 == distance % 1000:
self.mm_decimal = "0"
distanceSensor = DistanceSensor(TRIGGER_PIN, ECHO_PIN)
callback = distanceSensor.echoPin.irq(trigger = Pin.IRQ_RISING | Pin.IRQ_FALLING, handler = distanceSensor.changingEdge)
distanceSensor.setTriggerPinValue(LOW)
time.sleep(1)
distanceSensor.setTriggerPinValue(HIGH)
time.sleep_us(TRIGGER_TIME)
distanceSensor.setTriggerPinValue(LOW)
while distanceSensor.isDistanceCalculated() == False:
time.sleep_us(50000)
pass
print(distanceSensor.getDistanceString())