Read and count only when button is pressed

Hello,

Trying to use a code from the DevAcademy on buttons below but having a bit of trouble with modifying it.

My aim is a counter that reads how many buttons pressed I made so far but it seems to count indefinitely.

May I ask assistance with it?

/*
 * Copyright (c) 2016 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 * Note: 
 * Tested on nRF Connect SDK Version : 2.0
 */

#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/gpio.h>

/* STEP 9 - Increase the sleep time from 100ms to 10 minutes  */
// #define SLEEP_TIME_MS   10*60*1000
#define SLEEP_TIME_MS   1

/* SW0_NODE is the devicetree node identifier for the node with alias "sw0" */
#define SW0_NODE	DT_ALIAS(sw0) 
static const struct gpio_dt_spec button = GPIO_DT_SPEC_GET(SW0_NODE, gpios);

/* LED0_NODE is the devicetree node identifier for the node with alias "led0". */
#define LED0_NODE	DT_ALIAS(led0)
static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(LED0_NODE, gpios);


/* STEP 4 - Define the callback function */
int button_pressed(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
{
    gpio_pin_toggle_dt(&led);
	if (gpio_pin_get_dt(&led)) {
		return 1;
	}
	return 0;
}
/* STEP 5 - Define a variable of type static struct gpio_callback */
static struct gpio_callback button_cb_data;

void main(void)
{
	int ret;
	int count = 0;

	if (!device_is_ready(led.port)) {
		return;
	}

	if (!device_is_ready(button.port)) {
		return;
	}

	ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE);
	if (ret < 0) {
		return;
	}

	ret = gpio_pin_configure_dt(&button, GPIO_INPUT);
	if (ret < 0) {
		return;
	}
	/* STEP 3 - Configure the interrupt on the button's pin */
	ret = gpio_pin_interrupt_configure_dt(&button, GPIO_INT_EDGE_TO_ACTIVE );

	/* STEP 6 - Initialize the static struct gpio_callback variable   */
    gpio_init_callback(&button_cb_data, button_pressed, BIT(button.pin)); 	
	
	/* STEP 7 - Add the callback function by calling gpio_add_callback()   */
	 gpio_add_callback(button.port, &button_cb_data);
	

	if (led.port) {
		while (1) {
			if (gpio_pin_get_dt(&button)==1) {
				count++;
				printk("%d\n", count);
			}
			k_msleep(SLEEP_TIME_MS);
		}
	}
	// while (1) {
	// 	/* STEP 8 - Remove the polling code */

    //     k_msleep(SLEEP_TIME_MS);
	// }

}

Board: nrf52840dk

Parents
  • Hi,

    As the code is written now, count will be incremented as long the button is pressed. What you want instead, is that count to be incremented only once per button press. 

    You have already configured a GPIO event to be triggered on pin state change to logical level 1. This means that every time the GPIO pin is changed to a logical 1 the callback handler will be called. You should therefore move the count ++ line to the button_pressed callback handler. If you're using the button on the devkit, then the pin will be at logical 1 when you release the button, if you want the callback handler to be called once you push the button and not release, you have to change GPIO_INT_EDGE_TO_ACTIVE to GPIO_INT_EDGE_TO_INACTIVE. 

    regards

    Jared 

  • Wait, that works!

    /*
     * Copyright (c) 2016 Intel Corporation
     *
     * SPDX-License-Identifier: Apache-2.0
     * Note: 
     * Tested on nRF Connect SDK Version : 2.0
     */
    
    #include <zephyr/kernel.h>
    #include <zephyr/device.h>
    #include <zephyr/devicetree.h>
    #include <zephyr/drivers/gpio.h>
    
    /* STEP 9 - Increase the sleep time from 100ms to 10 minutes  */
    // #define SLEEP_TIME_MS   10*60*1000
    #define SLEEP_TIME_MS   1
    
    /* SW0_NODE is the devicetree node identifier for the node with alias "sw0" */
    #define SW0_NODE	DT_ALIAS(sw0) 
    static const struct gpio_dt_spec button = GPIO_DT_SPEC_GET(SW0_NODE, gpios);
    
    /* LED0_NODE is the devicetree node identifier for the node with alias "led0". */
    #define LED0_NODE	DT_ALIAS(led0)
    static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(LED0_NODE, gpios);
    
    int count = 0;
    
    
    /* STEP 4 - Define the callback function */
    int button_pressed(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
    {
        // gpio_pin_toggle_dt(&led);
    	// if (gpio_pin_get_dt(&led)) {
    	// 	return 1;
    	// }
    	// return 0;
    	count++;
    	printk("%d\n", count);
    	return 0;
    }
    /* STEP 5 - Define a variable of type static struct gpio_callback */
    static struct gpio_callback button_cb_data;
    
    void main(void)
    {
    	int ret;
    	
    
    	if (!device_is_ready(led.port)) {
    		return;
    	}
    
    	if (!device_is_ready(button.port)) {
    		return;
    	}
    
    	ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE);
    	if (ret < 0) {
    		return;
    	}
    
    	ret = gpio_pin_configure_dt(&button, GPIO_INPUT);
    	if (ret < 0) {
    		return;
    	}
    	/* STEP 3 - Configure the interrupt on the button's pin */
    	ret = gpio_pin_interrupt_configure_dt(&button, GPIO_INT_EDGE_TO_INACTIVE );
    
    	/* STEP 6 - Initialize the static struct gpio_callback variable   */
        gpio_init_callback(&button_cb_data, button_pressed, BIT(button.pin)); 	
    	
    	/* STEP 7 - Add the callback function by calling gpio_add_callback()   */
    	 gpio_add_callback(button.port, &button_cb_data);
    	
    
    	if (led.port) {
    		while (1) {
    			if (gpio_pin_get_dt(&button)==1) {
    				
    			}
    			k_msleep(SLEEP_TIME_MS);
    		}
    	}
    	// while (1) {
    	// 	/* STEP 8 - Remove the polling code */
    
        //     k_msleep(SLEEP_TIME_MS);
    	// }
    
    }

    but what does GPIO_INT_EDGE_TO_INACTIVE in a nutshell?

  • al_ns said:
    Wait, that works!

    Good!

    al_ns said:
    but what does GPIO_INT_EDGE_TO_INACTIVE in a nutshell?

    Configures GPIO interrupt to be triggered on pin state change to logical level 0 and enables it.

    regards

    Jared

  • I think one thing I noticed is that it "slips" like sometimes the count does twice or thrice at times.

    Is there a way to prevent that?

Reply Children
Related