add gpio buttons and adc buttons

pull/190/head
yuanjiong 2021-10-20 20:12:08 +08:00
parent c1ed67e99b
commit 83b414dd0d
4 changed files with 269 additions and 0 deletions

View File

@ -0,0 +1,110 @@
/* ADC1 Example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include <stdlib.h>
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/adc_common.h"
#include "esp_adc_cal.h"
#include "who_adc_button.h"
//ADC Channels
#define ADC1_EXAMPLE_CHAN0 ADC1_CHANNEL_0
//ADC Attenuation
#define ADC_EXAMPLE_ATTEN ADC_ATTEN_DB_11
//ADC Calibration
#if CONFIG_IDF_TARGET_ESP32
#define ADC_EXAMPLE_CALI_SCHEME ESP_ADC_CAL_VAL_EFUSE_VREF
#elif CONFIG_IDF_TARGET_ESP32S2
#define ADC_EXAMPLE_CALI_SCHEME ESP_ADC_CAL_VAL_EFUSE_TP
#elif CONFIG_IDF_TARGET_ESP32C3
#define ADC_EXAMPLE_CALI_SCHEME ESP_ADC_CAL_VAL_EFUSE_TP
#elif CONFIG_IDF_TARGET_ESP32S3
#define ADC_EXAMPLE_CALI_SCHEME ESP_ADC_CAL_VAL_EFUSE_TP_FIT
#endif
#define PRESS_INTERVAL 500000
static uint32_t voltage = 0;
static const char *TAG = "ADC SINGLE";
static esp_adc_cal_characteristics_t adc1_chars;
button_adc_config_t *adc_buttons;
int adc_button_num;
static QueueHandle_t xQueueKeyStateO = NULL;
static bool adc_calibration_init(void)
{
esp_err_t ret;
bool cali_enable = false;
ret = esp_adc_cal_check_efuse(ADC_EXAMPLE_CALI_SCHEME);
if (ret == ESP_ERR_NOT_SUPPORTED)
{
ESP_LOGW(TAG, "Calibration scheme not supported, skip software calibration");
}
else if (ret == ESP_ERR_INVALID_VERSION)
{
ESP_LOGW(TAG, "eFuse not burnt, skip software calibration");
}
else if (ret == ESP_OK)
{
cali_enable = true;
esp_adc_cal_characterize(ADC_UNIT_1, ADC_EXAMPLE_ATTEN, ADC_WIDTH_BIT_DEFAULT, 0, &adc1_chars);
}
else
{
ESP_LOGE(TAG, "Invalid arg");
}
return cali_enable;
}
void adc_button_task(void *arg)
{
int last_button_pressed = -1;
int button_pressed = -1;
int64_t backup_time = esp_timer_get_time();
int64_t last_time = esp_timer_get_time();
//ADC1 config
ESP_ERROR_CHECK(adc1_config_width(ADC_WIDTH_BIT_DEFAULT));
ESP_ERROR_CHECK(adc1_config_channel_atten(ADC1_EXAMPLE_CHAN0, ADC_EXAMPLE_ATTEN));
while (1)
{
voltage = adc1_get_raw(ADC1_EXAMPLE_CHAN0);
backup_time = esp_timer_get_time();
for (int i = 0; i < adc_button_num; ++i)
{
if ((voltage >= adc_buttons[i].min) && (voltage <= adc_buttons[i].max))
{
button_pressed = adc_buttons[i].button_index;
if ((button_pressed != last_button_pressed) || ((backup_time - last_time) > PRESS_INTERVAL))
{
last_button_pressed = button_pressed;
last_time = backup_time;
xQueueOverwrite(xQueueKeyStateO, &button_pressed);
break;
}
}
}
vTaskDelay(pdMS_TO_TICKS(10));
}
}
void register_adc_button(button_adc_config_t *buttons_ptr, int button_num, const QueueHandle_t key_state_o)
{
xQueueKeyStateO = key_state_o;
adc_buttons = buttons_ptr;
adc_button_num = button_num;
xTaskCreatePinnedToCore(adc_button_task, "adc_button_scan_task", 1024, NULL, 5, NULL, 0);
}

View File

@ -0,0 +1,30 @@
#pragma once
#include "esp_event_loop.h"
#include "soc/system_reg.h"
#include "driver/gpio.h"
#include "esp_log.h"
#ifdef __cplusplus
extern "C"
{
#endif
typedef struct
{
int button_index; /**< button index on the channel */
int min; /**< min voltage in mv corresponding to the button */
int max; /**< max voltage in mv corresponding to the button */
} button_adc_config_t;
/**
* @brief initialize adc button
*
* @param buttons_ptr the pointer of adc button configuration
* @param button_num the numbers of adc buttons
* @param key_state_o the queue to send which button is pressed
*/
void register_adc_button(button_adc_config_t *buttons_ptr, int button_num, const QueueHandle_t key_state_o);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,100 @@
#include <stdio.h>
#include <stdlib.h>
#include "who_button.h"
typedef struct
{
gpio_num_t io_num;
key_state_t state;
} key_scan_state_t;
#define LONG_PRESS_THRESH 700000
#define DOUBLE_CLICK_THRESH 300000
static xQueueHandle gpio_evt_queue = NULL;
static QueueHandle_t xQueueKeyStateO = NULL;
static void IRAM_ATTR gpio_isr_handler_key(void *arg)
{
uint32_t gpio_num = (uint32_t)arg;
xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
}
int key_scan(TickType_t ticks_to_wait)
{
gpio_num_t io_num;
BaseType_t press_key = pdFALSE;
BaseType_t lift_key = pdFALSE;
int64_t backup_time = 0;
int64_t interval_time = 0;
static int64_t last_time = 0;
for (;;)
{
xQueueReceive(gpio_evt_queue, &io_num, ticks_to_wait);
if (gpio_get_level(io_num) == 0)
{
press_key = pdTRUE;
backup_time = esp_timer_get_time();
interval_time = backup_time - last_time;
}
else if (press_key)
{
lift_key = pdTRUE;
last_time = esp_timer_get_time();
backup_time = last_time - backup_time;
}
if (press_key & lift_key)
{
press_key = pdFALSE;
lift_key = pdFALSE;
if (backup_time > LONG_PRESS_THRESH)
{
return KEY_LONG_PRESS;
}
else
{
if ((interval_time < DOUBLE_CLICK_THRESH) && (interval_time > 0))
return KEY_DOUBLE_CLICK;
else
return KEY_SHORT_PRESS;
}
}
}
}
void key_trigger(void *arg)
{
int ret = 0;
while (1)
{
ret = key_scan(portMAX_DELAY);
xQueueOverwrite(xQueueKeyStateO, &ret);
}
vTaskDelete(NULL);
}
void key_init(gpio_num_t gpio_num)
{
gpio_config_t io_conf = {0};
io_conf.mode = GPIO_MODE_INPUT;
io_conf.intr_type = GPIO_INTR_ANYEDGE;
io_conf.pin_bit_mask = 1LL << gpio_num;
io_conf.pull_up_en = GPIO_PULLUP_ENABLE;
gpio_config(&io_conf);
gpio_evt_queue = xQueueCreate(5, sizeof(uint32_t));
gpio_install_isr_service(0);
gpio_isr_handler_add(gpio_num, gpio_isr_handler_key, (void *)gpio_num);
}
void register_button(const gpio_num_t key_io_num, const QueueHandle_t key_state_o)
{
xQueueKeyStateO = key_state_o;
key_init(key_io_num);
xTaskCreatePinnedToCore(key_trigger, "key_scan_task", 1024, NULL, 5, NULL, 0);
}

View File

@ -0,0 +1,29 @@
#pragma once
#include "esp_event_loop.h"
#include "soc/system_reg.h"
#include "driver/gpio.h"
#include "esp_log.h"
typedef enum
{
KEY_SHORT_PRESS = 1,
KEY_LONG_PRESS,
KEY_DOUBLE_CLICK,
} key_state_t;
#ifdef __cplusplus
extern "C"
{
#endif
/**
* @brief initialize gpio button
*
* @param key_io_num the gpio number of the button
* @param key_state_o the queue to send the button state
*/
void register_button(const gpio_num_t key_io_num, const QueueHandle_t key_state_o);
#ifdef __cplusplus
}
#endif