Counter while button is low (FRDM-K22F)

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Counter while button is low (FRDM-K22F)

930 Views
briancavanagh
Contributor III

Hi,

I was looking through the "Components Library"  for a timer but didn't find what I thought would work so I'm looking for some help.

What I'm trying to do is create a counter while a button is pressed (held low).  

If the button is held low for longer than (or equal to) 2 seconds, carryout the remaining code that will follow.

If the button is held low, less than 2 seconds, do nothing and reset the counter.

Can someone help me with this?

Thanks,

Brian

0 Kudos
7 Replies

716 Views
mjbcswitzerland
Specialist V

Brian

I would try (if highest timing accuracy is needed):

1. Configure a port interrupt that reacts to both positive and negative edges.
2. When the button is pressed the interrupt will be executed and you can check the port input state. If it is "pressed" state you can start either a 2s SW or HW timer.
3. If the interrupt fires again and it is found to be in the off state you can reset the HW or SW timer.
4. If the HW or SW timer fires (not reset within the 2 second period - i.e. the button remained pressed) it can carry or, or trigger the execution, of the next routine.

If the accuracy/resolution requirement is not that high and you have a system tick in operation (eg. every 50ms) it can also be used to sample the input state at each Tick point in time and count the number of successive periods where the button remains pressed. When there are 40 samples in a row pressed (counter >= 40) you can execute or trigger execution of the next routine. Every time you sample the button as not pressed simply reset the counter. Below is working code that does this.

The second method is the simplest in a man-machine environment where 2s +/- 50ms is not an issue. It also avoids possible switch bouncing effects in the interrupt case which may require a little caution to avoid race states when sampling the sate after each interrupt.

Regards

Mark

#define TICK_PER_SECOND  20
extern void fnTickCheck(void)
{
    static int iPressInterval = 0;
    if (_READ_PORT_MASK(A, BUTTON) == 0) {        // is key pressed?
        if (++iPressInterval >= (2 * TICK_PER_SECOND)) {  // pressed - count the duration
            if (++iPressInterval == (2 * TICK_PER_SECOND)) {
                fnReactNow();                     // pressed time elapsed - execute routine
            }
            else {
                if (iPressInterval > (2 * TICK_PER_SECOND)) {
                    iPressInterval--;             // peak hold the pressed duration until the key is released
                }
            }
        }
    }
    else {                                        // not pressed
        iPressInterval = 0;                       // reset the press integrator
    }
}

716 Views
briancavanagh
Contributor III

Hi Mark, thanks for the feedback.

When I view _READ_PORT_MASK(A, BUTTON) I don't fully understand that.  I'm still getting started with Kinetis uC's.

My assumptions are as follows:

  •    _READ_PORT_MASK is PORTB that I'm using on the uC that my switch (SW3) is connected to?
  • "A" should represent PTB17, switch SW3 on the FRDM board?
  • The reference to "BUTTON" is my switch SW3 in my code?

To test my understanding, I'll replace:

  • //fnReactNow(); with RED_SetVal(); this will tell me the 2 seconds has elapsed and I'll stay there for ever.  (Just a test for me)
  •  if the RED led is on, I'll change my code to so I'm not there forever.
  • In // peak hold ... I'll set YELLOW_SetVal(); to stay there forever.  (just another test for me).
  • if the Yellow led is on, I'll change my code so I'm not there forever.
  • Finally,   //not pressed I'll set GREEN_SetVal(); to stay there forever.  (just another test for me).

These steps will help me understand how the code is being processing.

If all works correctly I'll place NegVal(); for each color led, in the appropriate locations, and allow the code to run forever and see what happens when I press the button.

My screen capture below shows my code incorrectly written, I was testing some ideas to get a better understanding before I responded.  I've been trying to figure this out myself before asking for help.

 

Thanks,

Brian

pastedImage_9.png

0 Kudos

716 Views
mjbcswitzerland
Specialist V

Brian

_READ_PORT_MASK() is just a macro:

#define _READ_PORT_MASK(ref, mask)         (GPIO##ref##_PDIR & (mask))

_READ_PORT_MASK(B, 0x00020000); is therefore
(GPIOB_PDIR & 0x00020000)
Which is what you need for your input.

I just check on a FRDM-K22F, adding the LEDs more or less as you suggest.Note that the FRDM-K22F has red,green and blue and not yellow (although yellow results when read and green are on).

I did have an error in the original code since there were two lines incrementing the counter. This is the correct code:

    {
        static int iPressInterval = 0;
        if (_READ_PORT_MASK(B, PORTB_BIT17) == 0) {   // is key pressed?
            _SETBITS(A, PORTA_BIT2);                  // green LED off
            if (++iPressInterval >= (2 * TICK_PER_SECOND)) { // pressed - count the duration
                if (iPressInterval == (2 * TICK_PER_SECOND)) {
                    _CLEARBITS(A, PORTA_BIT1);        // red LED on
                }
                else {
                    if (iPressInterval > (2 * TICK_PER_SECOND)) {
                        iPressInterval--;      // peak hold the pressed duration until the key is released
                        _CLEARBITS(D, PORTD_BIT5);    // blue LED on
                        
                    }
                }
            }
        }
        else {                                        // not pressed
            iPressInterval = 0;                       // reset the press integrator
            _CLEARBITS(A, PORTA_BIT2);                // green LED on
            _SETBITS(D, PORTD_BIT5);                  // blue LED off
        }
    }

I have attached a binary for the board showing it in operation plus a simulation (unzip the attached and start the simulation with a double click on uTaskerV1.4.12_FRDM-K22F_ButtonTest2s.exe. When it runs it looks like below and you can click on the button to hold it down and see the LED reacting (same as on the HW).

Regards

Mark

pastedImage_3.png

0 Kudos

716 Views
briancavanagh
Contributor III

You mentioned a binary and a  zip file uTaskerV1.4.12_FRDM-K22F_ButtonTest2s.exe would be attached.

0 Kudos

716 Views
mjbcswitzerland
Specialist V

Brian

They are attached - you may need to be logged in to see them.

Regards

Mark

0 Kudos

716 Views
briancavanagh
Contributor III

Got it!  Thanks

0 Kudos

716 Views
briancavanagh
Contributor III

Great, thanks Mark, I'll give it a go!

0 Kudos