✨ add gpio buttons and adc buttons
parent
c1ed67e99b
commit
83b414dd0d
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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
|
Loading…
Reference in New Issue