Problem using utime.tick_ms()

Discussion related to "under the hood" OpenMV topics.
bogflap
Posts: 40
Joined: Mon Apr 16, 2018 10:03 am

Problem using utime.tick_ms()

Postby bogflap » Tue Nov 20, 2018 1:21 pm

Have been trying to get this code working

Code: Select all

import pyb
import utime

import micropython
micropython.alloc_emergency_exception_buf(500)

# Global constants
buttonShortPressTime = 20    # milliseconds

# Ring buffer implementation
ringTail = 0
ringHead = 0
ringSize = 10000
ringFull = False
msRingBuffer = None
trRingBuffer = None

# Global variables
buttonPin = None
extInt = None
lowButtonTime = None

# button pressed flag
buttonPressed = False

# button transition ISR
def buttonTransitionISR(line):
    global buttonPin
    global trRingBuffer
    global msRingBuffer
    global ringHead
    global ringFull

    if ringFull == False:
        trRingBuffer[ringHead] = buttonPin.value()
        msRingBuffer[ringHead] = utime.ticks_ms()
        localRingHead = (ringHead + 1) % ringSize
        if localRingHead == ringTail:
            ringFull = True
        else:
            ringHead = localRingHead
    # else: do nothing

def initialiseInterrupts():
    global buttonPin
    global buttonClock
    global extInt
    global trRingBuffer
    global msRingBuffer

    # Initialise ring buffer
    trRingBuffer = bytearray(ringSize)
    msRingBuffer = bytearray()
    # Have to do this as we do not know what utime.ticks_ms() returns
    for index in range(0,ringSize):
        msRingBuffer.append(utime.ticks_ms())

    # experimental button pin
    buttonPin = pyb.Pin('P0', pyb.Pin.IN)

    # set up ISR for button press
    extInt = pyb.ExtInt(buttonPin, pyb.ExtInt.IRQ_RISING_FALLING, pyb.Pin.PULL_UP, buttonTransitionISR)

# check for button pressed condition
def buttonPressedCheck():
    global trRingBuffer
    global msRingBuffer
    global lowButtonTime
    global buttonPressed
    global ringHead
    global ringTail

    # Reset button pressed indication
    # Calling functions will only see it set the once
    buttonPressed = False;

    while(True):
        # Start peeling stuff out of the ring buffer
        if ringHead == ringTail:
            # head == tail implies buffer empty
            break

        # Will only see button pressed indication if the ring is empty
        # If we are to slow calling this function then intermediate button
        # presses will be discarded
        buttonPressed = False;

        if lowButtonTime == None:
            # Initialisation requires that we see a low pin first
            if trRingBuffer[ringTail] == 0:
                lowButtonTime = msRingBuffer[ringTail]
                print ("initialising lowButtonTime = ", lowButtonTime)
        elif trRingBuffer[ringTail] == 0:
            # Get ms value for low button
            lowButtonTime = msRingBuffer[ringTail]
            print ("lowButtonTime = ", lowButtonTime)
        else:
            # Got ms value for high button
            thisButtonTime = msRingBuffer[ringTail]
            buttonPressedTime = utime.ticks_diff(thisButtonTime, lowButtonTime)
            print ("thisButtonTime = ", thisButtonTime, " lowButtonTime = ", lowButtonTime, " buttonPressedTime = ", buttonPressedTime)
            if buttonPressedTime >= buttonShortPressTime:
                buttonPressed = True

        # Increment tail
        ringTail = (ringTail + 1) % ringSize

        # end of while(True)

# Initialise interrupt handlers
initialiseInterrupts()

green_led = pyb.LED(2)

# start with LED off
green_led.off()

while(True):
    buttonPressedCheck()
    if buttonPressed == True:
        green_led.toggle()
and get the following results
initialising lowButtonTime = 231
thisButtonTime = 141 lowButtonTime = 231 buttonPressedTime = -90
thisButtonTime = 141 lowButtonTime = 231 buttonPressedTime = -90
lowButtonTime = 141
thisButtonTime = 142 lowButtonTime = 141 buttonPressedTime = 1
lowButtonTime = 142
lowButtonTime = 142
thisButtonTime = 142 lowButtonTime = 142 buttonPressedTime = 0
lowButtonTime = 142
thisButtonTime = 143 lowButtonTime = 142 buttonPressedTime = 1
lowButtonTime = 143
thisButtonTime = 143 lowButtonTime = 143 buttonPressedTime = 0
lowButtonTime = 144
thisButtonTime = 144 lowButtonTime = 144 buttonPressedTime = 0
lowButtonTime = 145
thisButtonTime = 145 lowButtonTime = 145 buttonPressedTime = 0
lowButtonTime = 145
thisButtonTime = 146 lowButtonTime = 145 buttonPressedTime = 1
lowButtonTime = 146
thisButtonTime = 146 lowButtonTime = 146 buttonPressedTime = 0
lowButtonTime = 146
thisButtonTime = 102 lowButtonTime = 146 buttonPressedTime = -44
lowButtonTime = 103
lowButtonTime = 103
lowButtonTime = 103
lowButtonTime = 103
lowButtonTime = 103
lowButtonTime = 103
thisButtonTime = 103 lowButtonTime = 103 buttonPressedTime = 0
lowButtonTime = 103
thisButtonTime = 103 lowButtonTime = 103 buttonPressedTime = 0
lowButtonTime = 54
lowButtonTime = 54
thisButtonTime = 72 lowButtonTime = 54 buttonPressedTime = 18
lowButtonTime = 165
lowButtonTime = 165
thisButtonTime = 215 lowButtonTime = 165 buttonPressedTime = 50
thisButtonTime = 157 lowButtonTime = 165 buttonPressedTime = -8
thisButtonTime = 157 lowButtonTime = 165 buttonPressedTime = -8
thisButtonTime = 157 lowButtonTime = 165 buttonPressedTime = -8
lowButtonTime = 157
thisButtonTime = 157 lowButtonTime = 157 buttonPressedTime = 0
thisButtonTime = 158 lowButtonTime = 157 buttonPressedTime = 1
lowButtonTime = 158
lowButtonTime = 158
lowButtonTime = 158
thisButtonTime = 158 lowButtonTime = 158 buttonPressedTime = 0
lowButtonTime = 158
lowButtonTime = 158
thisButtonTime = 158 lowButtonTime = 158 buttonPressedTime = 0
lowButtonTime = 158
lowButtonTime = 159
thisButtonTime = 159 lowButtonTime = 159 buttonPressedTime = 0
lowButtonTime = 159
lowButtonTime = 160
thisButtonTime = 226 lowButtonTime = 160 buttonPressedTime = 66
lowButtonTime = 50
thisButtonTime = 50 lowButtonTime = 50 buttonPressedTime = 0
lowButtonTime = 51
lowButtonTime = 108
lowButtonTime = 109
lowButtonTime = 132
lowButtonTime = 132
lowButtonTime = 134
lowButtonTime = 134
lowButtonTime = 137
lowButtonTime = 99
thisButtonTime = 99 lowButtonTime = 99 buttonPressedTime = 0
lowButtonTime = 99
lowButtonTime = 99
lowButtonTime = 99
thisButtonTime = 100 lowButtonTime = 99 buttonPressedTime = 1
lowButtonTime = 100
lowButtonTime = 100
lowButtonTime = 100
thisButtonTime = 100 lowButtonTime = 100 buttonPressedTime = 0
lowButtonTime = 100
thisButtonTime = 100 lowButtonTime = 100 buttonPressedTime = 0
lowButtonTime = 100
thisButtonTime = 101 lowButtonTime = 100 buttonPressedTime = 1
lowButtonTime = 60
lowButtonTime = 60
lowButtonTime = 131
lowButtonTime = 131
thisButtonTime = 131 lowButtonTime = 131 buttonPressedTime = 0
lowButtonTime = 35
lowButtonTime = 35
lowButtonTime = 35
thisButtonTime = 35 lowButtonTime = 35 buttonPressedTime = 0
lowButtonTime = 35
thisButtonTime = 234 lowButtonTime = 35 buttonPressedTime = 199
thisButtonTime = 234 lowButtonTime = 35 buttonPressedTime = 199
lowButtonTime = 186
thisButtonTime = 186 lowButtonTime = 186 buttonPressedTime = 0
lowButtonTime = 186
lowButtonTime = 186
lowButtonTime = 186
lowButtonTime = 187
lowButtonTime = 187
lowButtonTime = 187
lowButtonTime = 187
lowButtonTime = 187
lowButtonTime = 187
thisButtonTime = 124 lowButtonTime = 187 buttonPressedTime = -63
lowButtonTime = 50
lowButtonTime = 50
lowButtonTime = 50
thisButtonTime = 50 lowButtonTime = 50 buttonPressedTime = 0
lowButtonTime = 50
lowButtonTime = 50
lowButtonTime = 50
lowButtonTime = 50
lowButtonTime = 50
lowButtonTime = 50
thisButtonTime = 204 lowButtonTime = 50 buttonPressedTime = 154
lowButtonTime = 95
lowButtonTime = 95
lowButtonTime = 95
lowButtonTime = 95
lowButtonTime = 95
lowButtonTime = 96
lowButtonTime = 96
lowButtonTime = 96
lowButtonTime = 96
lowButtonTime = 49
thisButtonTime = 49 lowButtonTime = 49 buttonPressedTime = 0
lowButtonTime = 5
thisButtonTime = 33 lowButtonTime = 5 buttonPressedTime = 28
thisButtonTime = 33 lowButtonTime = 5 buttonPressedTime = 28
lowButtonTime = 37
thisButtonTime = 37 lowButtonTime = 37 buttonPressedTime = 0
lowButtonTime = 37
lowButtonTime = 37
lowButtonTime = 37
lowButtonTime = 37
thisButtonTime = 37 lowButtonTime = 37 buttonPressedTime = 0
thisButtonTime = 37 lowButtonTime = 37 buttonPressedTime = 0
lowButtonTime = 37
thisButtonTime = 37 lowButtonTime = 37 buttonPressedTime = 0
lowButtonTime = 37
thisButtonTime = 37 lowButtonTime = 37 buttonPressedTime = 0
lowButtonTime = 37
thisButtonTime = 37 lowButtonTime = 37 buttonPressedTime = 0
thisButtonTime = 37 lowButtonTime = 37 buttonPressedTime = 0
thisButtonTime = 37 lowButtonTime = 37 buttonPressedTime = 0
thisButtonTime = 37 lowButtonTime = 37 buttonPressedTime = 0
lowButtonTime = 37
lowButtonTime = 37
lowButtonTime = 37
thisButtonTime = 37 lowButtonTime = 37 buttonPressedTime = 0
thisButtonTime = 37 lowButtonTime = 37 buttonPressedTime = 0
thisButtonTime = 37 lowButtonTime = 37 buttonPressedTime = 0
lowButtonTime = 37
thisButtonTime = 38 lowButtonTime = 37 buttonPressedTime = 1
thisButtonTime = 40 lowButtonTime = 37 buttonPressedTime = 3
thisButtonTime = 40 lowButtonTime = 37 buttonPressedTime = 3
lowButtonTime = 40
lowButtonTime = 40
thisButtonTime = 40 lowButtonTime = 40 buttonPressedTime = 0
lowButtonTime = 40
thisButtonTime = 40 lowButtonTime = 40 buttonPressedTime = 0
thisButtonTime = 40 lowButtonTime = 40 buttonPressedTime = 0
lowButtonTime = 40
lowButtonTime = 40
lowButtonTime = 40
thisButtonTime = 40 lowButtonTime = 40 buttonPressedTime = 0
lowButtonTime = 40
lowButtonTime = 40
lowButtonTime = 40
thisButtonTime = 40 lowButtonTime = 40 buttonPressedTime = 0
thisButtonTime = 40 lowButtonTime = 40 buttonPressedTime = 0
thisButtonTime = 40 lowButtonTime = 40 buttonPressedTime = 0
thisButtonTime = 40 lowButtonTime = 40 buttonPressedTime = 0
lowButtonTime = 42
lowButtonTime = 42
thisButtonTime = 42 lowButtonTime = 42 buttonPressedTime = 0
thisButtonTime = 42 lowButtonTime = 42 buttonPressedTime = 0
lowButtonTime = 43
lowButtonTime = 43
thisButtonTime = 43 lowButtonTime = 43 buttonPressedTime = 0
lowButtonTime = 43
lowButtonTime = 43
lowButtonTime = 43
lowButtonTime = 43
lowButtonTime = 43
lowButtonTime = 43
lowButtonTime = 43
lowButtonTime = 43
lowButtonTime = 43
lowButtonTime = 43
lowButtonTime = 43
thisButtonTime = 43 lowButtonTime = 43 buttonPressedTime = 0
lowButtonTime = 43
lowButtonTime = 43
lowButtonTime = 43
lowButtonTime = 43
thisButtonTime = 43 lowButtonTime = 43 buttonPressedTime = 0
lowButtonTime = 43
thisButtonTime = 43 lowButtonTime = 43 buttonPressedTime = 0
lowButtonTime = 43
lowButtonTime = 44
thisButtonTime = 44 lowButtonTime = 44 buttonPressedTime = 0
lowButtonTime = 47
thisButtonTime = 47 lowButtonTime = 47 buttonPressedTime = 0
thisButtonTime = 47 lowButtonTime = 47 buttonPressedTime = 0
lowButtonTime = 47
lowButtonTime = 47
thisButtonTime = 47 lowButtonTime = 47 buttonPressedTime = 0
lowButtonTime = 47
lowButtonTime = 47
lowButtonTime = 49
lowButtonTime = 50
lowButtonTime = 50
lowButtonTime = 50
lowButtonTime = 50
thisButtonTime = 50 lowButtonTime = 50 buttonPressedTime = 0
thisButtonTime = 50 lowButtonTime = 50 buttonPressedTime = 0
lowButtonTime = 50
lowButtonTime = 50
thisButtonTime = 51 lowButtonTime = 50 buttonPressedTime = 1
lowButtonTime = 51
lowButtonTime = 52
lowButtonTime = 52
lowButtonTime = 52
lowButtonTime = 52
lowButtonTime = 53
lowButtonTime = 53
thisButtonTime = 54 lowButtonTime = 53 buttonPressedTime = 1
lowButtonTime = 54
thisButtonTime = 63 lowButtonTime = 54 buttonPressedTime = 9
lowButtonTime = 64
lowButtonTime = 64
lowButtonTime = 64
lowButtonTime = 64
lowButtonTime = 64
lowButtonTime = 64
lowButtonTime = 64
lowButtonTime = 64
lowButtonTime = 64
lowButtonTime = 64
lowButtonTime = 64
lowButtonTime = 64
lowButtonTime = 64
lowButtonTime = 64
lowButtonTime = 64
lowButtonTime = 64
lowButtonTime = 70
lowButtonTime = 70
lowButtonTime = 71
lowButtonTime = 71
lowButtonTime = 71
lowButtonTime = 71
lowButtonTime = 71
lowButtonTime = 71
lowButtonTime = 71
lowButtonTime = 71
lowButtonTime = 71
lowButtonTime = 71
lowButtonTime = 71
lowButtonTime = 71
lowButtonTime = 71
lowButtonTime = 71
lowButtonTime = 72
lowButtonTime = 72
lowButtonTime = 72
lowButtonTime = 73
thisButtonTime = 73 lowButtonTime = 73 buttonPressedTime = 0
lowButtonTime = 73
lowButtonTime = 112
thisButtonTime = 112 lowButtonTime = 112 buttonPressedTime = 0
thisButtonTime = 112 lowButtonTime = 112 buttonPressedTime = 0
thisButtonTime = 112 lowButtonTime = 112 buttonPressedTime = 0
lowButtonTime = 112
thisButtonTime = 112 lowButtonTime = 112 buttonPressedTime = 0
lowButtonTime = 232
lowButtonTime = 232
lowButtonTime = 232
lowButtonTime = 232
thisButtonTime = 232 lowButtonTime = 232 buttonPressedTime = 0
lowButtonTime = 232
thisButtonTime = 232 lowButtonTime = 232 buttonPressedTime = 0
thisButtonTime = 232 lowButtonTime = 232 buttonPressedTime = 0
lowButtonTime = 232
thisButtonTime = 232 lowButtonTime = 232 buttonPressedTime = 0
lowButtonTime = 233
thisButtonTime = 233 lowButtonTime = 233 buttonPressedTime = 0
lowButtonTime = 233
thisButtonTime = 233 lowButtonTime = 233 buttonPressedTime = 0
thisButtonTime = 233 lowButtonTime = 233 buttonPressedTime = 0
thisButtonTime = 233 lowButtonTime = 233 buttonPressedTime = 0
thisButtonTime = 233 lowButtonTime = 233 buttonPressedTime = 0
lowButtonTime = 233
lowButtonTime = 233
lowButtonTime = 234
lowButtonTime = 234
lowButtonTime = 234
thisButtonTime = 74 lowButtonTime = 234 buttonPressedTime = -160
I seem to get a lot of low values without any intervening high values i.e. falling edges without any intervening rising edges. I assume that the ISR is not fast enough to catch the rising edges?
Also I get negative values from utime.tick_diff() which I assumed would take into account roll over of values?
Finally can you tell me how long a period utime.tick_ms will give me before rolloing over?

By the way I am touching P0 to ground with a wire so I would expect this t be a worse case scenario for debouncing. Also the green led does toggles sometimes but not what I would call reliably.
bogflap
Posts: 40
Joined: Mon Apr 16, 2018 10:03 am

Re: Problem using utime.tick_ms()

Postby bogflap » Wed Nov 21, 2018 6:16 am

To answer my own question. Using array.array(('B') and array.array{'L') instead of bytearray for buffer allocations seems to cure my immediate problems.
I used pyb.millis() instead of utime.tick_ms() but it is not immediately clear whether this helped.
At least the documentation tells me what the return type for pyb.millis() is.
Now I have to cope with consecutive trailing falling edge interrupts after the single rising edge interrupt on button release.
I would not recommend this implementation for switch debouncing.
User avatar
kwagyeman
Posts: 2462
Joined: Sun May 24, 2015 2:10 pm

Re: Problem using utime.tick_ms()

Postby kwagyeman » Wed Nov 21, 2018 9:46 am

Hi, traveling for thanksgiving. Hard for me to answer quickly. Glad to hear you worked it out.
Nyamekye,
bogflap
Posts: 40
Joined: Mon Apr 16, 2018 10:03 am

Re: Problem using utime.tick_ms()

Postby bogflap » Wed Nov 21, 2018 12:41 pm

So the following is my best endeavours to date. If anyone has any ideas for improvements please let me know.

Code: Select all

import pyb
import array

import micropython
micropython.alloc_emergency_exception_buf(200)


class ButtonMonitor():
    __ringTail = 0
    __ringHead = 0
    __ringOverflow = False
    __msRingBuffer = None
    __trRingBuffer = None
    __buttonPin = None
    __extInt = None
    __lowButtonTime = None

    __RING_SIZE = 100
    __BUTTON_SHORT_PRESS_TIME = 20    # milliseconds
    __BUTTON_LONG_PRESS_TIME = 1500    # milliseconds
    # Basically an enum
    __NO_PRESS = 0
    __SHORT_PRESS = 1
    __LONG_PRESS = 2

    # button transition ISR
    def buttonTransitionISR(self, line):
        if self.__ringOverflow == False:
            self.__trRingBuffer[self.__ringHead] = self.__buttonPin.value()
            self.__msRingBuffer[self.__ringHead] = pyb.millis()
            localRingHead = (self.__ringHead + 1) % self.__RING_SIZE
            if localRingHead == self.__ringTail:
                self__ringOverflow = True
            else:
                self.__ringHead = localRingHead
        # else: do nothing for now

    # Constructor
    def __init__(self, port):
        # Initialise ring buffer
        self.__trRingBuffer = array.array('B')
        self.__msRingBuffer = array.array('l')
        # Size the byte arrays according to there expected content
        for index in range(0,self.__RING_SIZE):
            self.__trRingBuffer.append(False)
            self.__msRingBuffer.append(pyb.millis())

        # experimental button pin
        self.__buttonPin = pyb.Pin(port, pyb.Pin.IN)

        # set up ISR for button press
        self.__extInt = pyb.ExtInt(   self.__buttonPin,
                                    pyb.ExtInt.IRQ_RISING_FALLING,
                                    pyb.Pin.PULL_UP,
                                    self.buttonTransitionISR)

    # check for button pressed condition
    def buttonPressedCheck(self):
        # Reset button pressed indication
        # Calling functions will only see it set the once
        self.buttonPressed = self.__NO_PRESS;

        while(True):
            # Start peeling stuff out of the ring buffer
            if self.__ringHead == self.__ringTail:
                # head == tail implies buffer empty
                break

            if self.__lowButtonTime == None:
                # Initialisation requires that we see a low pin first
                if self.__trRingBuffer[self.__ringTail] == 0:
                    self.__lowButtonTime = self.__msRingBuffer[self.__ringTail]
            elif self.__trRingBuffer[self.__ringTail] == 0:
                # Get ms value for low button
                self.__lowButtonTime = self.__msRingBuffer[self.__ringTail]
            else:
                # Got ms value for high button
                thisButtonTime = self.__msRingBuffer[self.__ringTail]
                buttonPressedTime = thisButtonTime - self.__lowButtonTime
                if buttonPressedTime >= self.__BUTTON_SHORT_PRESS_TIME:
                    if buttonPressedTime >= self.__BUTTON_LONG_PRESS_TIME:
                        self.buttonPressed = self.__LONG_PRESS
                    else:
                        self.buttonPressed = self.__SHORT_PRESS

            # Increment tail
            self.__ringTail = (self.__ringTail + 1) % self.__RING_SIZE

            # end of while(True)

    # diagnostic function
    def dumpQueue(self):
        while(True):
            # Start peeling stuff out of the ring buffer
            if self.__ringHead == self.__ringTail:
                # head == tail implies buffer empty
                break

            print (self.__trRingBuffer[self.__ringTail], " ", self.__msRingBuffer[self.__ringTail])

            # Increment tail
            self.__ringTail = (self.__ringTail + 1) % self.__RING_SIZE

# Initialise button monitors
P0Monitor = ButtonMonitor('P0')

red_led = pyb.LED(1)
green_led = pyb.LED(2)

# start with LEDs off
green_led.off()
red_led.off()

while(True):
    P0Monitor.buttonPressedCheck()
    if P0Monitor.buttonPressed == P0Monitor.__SHORT_PRESS:
        print("Short press")
        red_led.off()
        green_led.toggle()
    if P0Monitor.buttonPressed == P0Monitor.__LONG_PRESS:
        print("Long press")
        green_led.off()
        red_led.toggle()

Return to “Technical Discussion”

Who is online

Users browsing this forum: No registered users and 4 guests