This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Button interrupt , gpiote

HEllo;
I'm working with nrf52832 and sdk15 , and for interrupt button i chose to work with the example "/nRF5_SDK_15.0.0_a53641a/examples/peripheral/pin_change_int/"
, so my question is how we can know its pushed button(push the button two time)  and long press.
and how we can add : three configuration nrf_drv_gpiote_in_config_t in_config = GPIOTE_CONFIG_IN_SENSE_HITOLO(true);/and LOTOHI and toggle , all together. thank you for your help .
and what about consume of the energy is it better to work wirh nrf_gpio_pin_read(30) or this methode of interupt.

Parents
  • so my question is how we can know its pushed button(push the button two time)

     In the pin change int example, you know that button 1 is pushed (a transition happens) when a GPIOTE event is triggered. In the pin_change_int example, the function in_pin_handler() will run in response to this event.

    and long press

     Check out this ticket.

     

    and how we can add : three configuration nrf_drv_gpiote_in_config_t in_config = GPIOTE_CONFIG_IN_SENSE_HITOLO(true);/and LOTOHI and toggle , all together

     I am not sure if I understand what you are asking about here, can you explain it in more details?

     

    and what about consume of the energy is it better to work wirh nrf_gpio_pin_read(30) or this methode of interupt

     It depends on how you use nrf_gpio_pin_read(). If you put it in a while(1) it will definitely use more power than the method using GPIOTE events and interrupt.

    However, if you create a timer that will trigger an interrupt handler periodically and run nrf_gpio_pin_read() in the handler, then the current consumption will be low. The drawback of this method is that it will most definitely loose some pin transitions. I think the initial method is the best one.

    Best regards,

    Simon

  • Hello Simon thank you for your answer.
    I contiue working with the example (examples/peripheral/pin_change_int), and I made this code :

    #include <stdbool.h>
    #include "nrf.h"
    #include "nrf_drv_gpiote.h"
    #include "app_error.h"
    #include "boards.h"
    #include "nrf_delay.h"
    
    #define PIN_IN 30
    #define PIN_OUT 26
    bool HL_state;
    bool LH_state;
    bool First_state;
    bool up_state;
    int HL_counter=0;
    int LH_counter=0;
    int count ;
    int push_counter;
    int up_counter;
    
    
    void in_pin_handlerHL(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
    {
        //nrf_drv_gpiote_out_toggle(PIN_OUT);
        NRF_GPIOTE->EVENTS_IN[0] = 0;
    
    
            if (nrf_gpio_pin_read(30)==0)
            {
                HL_counter ++;
                HL_state=true;
                LH_state=false;
                LH_counter=0;
            }else{
                LH_counter ++;
                LH_state=true;
                HL_state=false;
                HL_counter=0;
            }
    
    }
    // void in_pin_handlerLH(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
    // {
    //     //nrf_drv_gpiote_out_toggle(PIN_OUT);
    //     NRF_GPIOTE->EVENTS_IN[0] = 0;
    //     LH_counter ++;
    
    //         if (nrf_gpio_pin_read(30)==1)
    //         {
    //             LH_state=true;
    //             HL_state=false;
    //             HL_counter=0;
    //         }else{
    //             LH_state=false;
    //         }
    // }
    /**
     * @brief Function for configuring: PIN_IN pin for input, PIN_OUT pin for output,
     * and configures GPIOTE to give an interrupt on pin change.
     */
    static void gpio_init(void)
    {
        ret_code_t err_code;
    
    
        if (!nrf_drv_gpiote_is_init())
        {
            err_code = nrf_drv_gpiote_init();
            APP_ERROR_CHECK(err_code);
        }
    
        nrf_drv_gpiote_out_config_t out_config = GPIOTE_CONFIG_OUT_SIMPLE(false);
    
        // err_code = nrf_drv_gpiote_out_init(PIN_OUT, &out_config);
        // APP_ERROR_CHECK(err_code);
    
        nrf_drv_gpiote_in_config_t in_configHL = GPIOTE_CONFIG_IN_SENSE_TOGGLE(false);
        // nrf_drv_gpiote_in_config_t in_config = GPIOTE_CONFIG_IN_SENSE_TOGGLE(true);
        in_configHL.pull = NRF_GPIO_PIN_PULLUP;
    
        nrf_drv_gpiote_in_config_t in_configLH = GPIOTE_CONFIG_IN_SENSE_LOTOHI(true);
        in_configLH.pull = NRF_GPIO_PIN_PULLUP;
    
        err_code = nrf_drv_gpiote_in_init(PIN_IN, &in_configHL, in_pin_handlerHL);
        APP_ERROR_CHECK(err_code);
    
        // err_code = nrf_drv_gpiote_in_init(PIN_IN, &in_configLH, in_pin_handlerLH);
        // APP_ERROR_CHECK(err_code);
    
        nrf_drv_gpiote_in_event_enable(PIN_IN, true);
    }
    
    /**
     * @brief Function for application main entry.
     */
    int main(void)
    {
        gpio_init();
    
        //printf("HL_state%d\n", HL_state );
        //printf("LH_state%d\n", LH_state );
           // printf("start");
        while (true)
        {
    
            if (HL_state==true)
            {
                //printf("yes\n");
                First_state=true;
                count=0;
    
                push_counter ++;
            }else
            {
                count ++;
                //printf("counter : %d\n", count);
                push_counter=0;
                up_counter ++;
            }
    
            if (1<count && count <5 && First_state==true )
            {
                printf("UP\n");
                up_state=true;
                First_state=false;
                up_counter=0;
    
            }else{
                up_state==false;
    
            }
    
            if (HL_state==true && up_state==true && up_counter < 10)
            {
                printf("double\n");
                up_state=false;
                First_state=false;
                count=0;
                up_counter=0;
    
            }else{
    
            }
    
            if(20<push_counter && push_counter<50 && HL_state==true){
    
                printf("hold_press\n");
                up_state=false;
                First_state=false;
    
    
            }else if(push_counter>50 && HL_state==true){
                printf("long_press\n");
                up_state=false;
                First_state=false;
                push_counter=0;
    
            }else{
    
            }
    
            nrf_delay_ms(100);
    
        }
    
    }
    
    
    /** @} */
    


    is it right ? , my question is can we do the high to lo and lo to high configuration as i commented in my code , cause it dosnt work for me , but for the moment i made it , I think it's right, please give me your feed back about my code. and i hope it will not consume a lot of energy 

  • Before continuing, I would like to ask why you don't use the solution already provided in this thread? That solution is based on a timer, which makes it more accurate and energy-efficient. 

    Best regards,

    Simon

  • I would like to ask why you don't use the solution already provided in this thread?

    I think its not simple as i did, and its based on DK other wise Im using a custom borad. I'll use timer in my application (based on ble_hrs example)

Reply Children
  • I am sorry for the delay, I have been quite busy lately. I am currently looking into your problem and will provide you with an answer asap.

    Best regards,

    Simon

  • Hello SImon I just want to remember you of answering me if you d like of course

  • achraf said:
    I think its not simple as i did

     I think it should be quite straightforward:

    • First you call call timers_init() and buttons_init() in main()
      • timers_init() will simply initialize application timer (read more about it here)
      • buttons_init() will initialize the buttons and start the timer.
        • It will implement a button callback that starts when button 1 is pressed
        • It will implement a timeout handler, that will trigger rapid and continuously after the button is pressed, that checks whether a long or short button press occurred (based on value of cnt)
    • You can ignore most of the other code present (except for power management, some includes and defines)

     If anything is unclear, or if you would like me to explain anything in detail, please ask.

    achraf said:
    its based on DK other wise Im using a custom borad

     I think the solution should work with a custom board as well. Why do you think that matters?


    Some other comments about your solution:

    • Since you are putting the code in a loop, it is hard to know the duration of respectively a long and a short button press. In the timer-based method, you will.
    • The solution will consume a lot of power since you are constantly polling and the CPU will always run, even when calling nrf_delay_ms() a lot of current will be drawn.
      • In the timer-based method, you can put the CPU in sleep, between the increments of the counter variable cnt

    Best regards,

    Simon

Related