diff --git a/README.md b/README.md index 611e3a22..b23b5c31 100644 --- a/README.md +++ b/README.md @@ -232,6 +232,7 @@ or [GitLab examples](https://gitlab.com/UncleRus/esp-idf-lib/tree/master/example | Component | Description | License | Supported on | Thread safety | |--------------------------|----------------------------------------------------------------------------------|---------|--------------------|---------------| +| **anemometer** | Driver for impulse wind speed sensors(anemometers) | BSD-3-Clause | esp32, esp8266, esp32s2, esp32c3 | no | | **ds3502** | Driver for nonvolatile digital potentiometer DS3502 | BSD-3-Clause | esp32, esp8266, esp32s2, esp32c3 | yes | | **example** | An example component | ISC | esp32, esp8266, esp32s2, esp32c3 | n/a | | **hd44780** | Driver for HD44780 compatible LCD text displays | BSD-3-Clause | esp32, esp8266, esp32s2, esp32c3 | no | @@ -320,7 +321,7 @@ or [GitLab examples](https://gitlab.com/UncleRus/esp-idf-lib/tree/master/example - [Grupo de Pesquisa em Cultura Digital](http://gepid.upf.br/): `mpu6050` - GrzegorzH: `ds18x20` - [Gunar Schorcht](https://github.com/gschorcht): `bme680` `ccs811` `sht3x` `sts3x` -- [Jakub Turek](https://github.com/QB4-dev): `l3gx` `lsm303` +- [Jakub Turek](https://github.com/QB4-dev): `anemometer` `l3gx` `lsm303` - [Jan Veeh](https://github.com/janveeh): `icm42670` - [Jeff Rowberg](https://www.i2cdevlib.com/): `mpu6050` - [Jose Manuel Perez](https://github.com/jmpmscorp): `lc709203f` `sgm58031` diff --git a/components/anemometer/.eil.yml b/components/anemometer/.eil.yml new file mode 100644 index 00000000..ede80ae3 --- /dev/null +++ b/components/anemometer/.eil.yml @@ -0,0 +1,22 @@ +name: anemometer +description: Driver for impulse wind speed sensors(anemometers) +version: 1.0.0 +groups: + - misc +code_owners: + - qb4-dev +depends: + - i2cdev + - log + - esp_idf_lib_helpers +thread_safe: no +targets: + - esp32 + - esp8266 + - esp32s2 + - esp32c3 +license: BSD-3 +copyrights: + - name: qb4-dev + year: 2024 + diff --git a/components/anemometer/CMakeLists.txt b/components/anemometer/CMakeLists.txt new file mode 100644 index 00000000..0b7ee61a --- /dev/null +++ b/components/anemometer/CMakeLists.txt @@ -0,0 +1,13 @@ +if(${IDF_TARGET} STREQUAL esp8266) + set(req esp8266 freertos esp_idf_lib_helpers esp_timer) +elseif(${IDF_VERSION_MAJOR} STREQUAL 4 AND ${IDF_VERSION_MINOR} STREQUAL 1 AND ${IDF_VERSION_PATCH} STREQUAL 3) + set(req driver freertos esp_idf_lib_helpers) +else() + set(req driver freertos esp_idf_lib_helpers esp_timer) +endif() + +idf_component_register( + SRCS anemometer.c + INCLUDE_DIRS . + REQUIRES ${req} +) diff --git a/components/anemometer/LICENSE b/components/anemometer/LICENSE new file mode 100644 index 00000000..4971fd65 --- /dev/null +++ b/components/anemometer/LICENSE @@ -0,0 +1,26 @@ +Copyright (c) 2024 Jakub Turek + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of itscontributors +may be used to endorse or promote products derived from this software without +specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/components/anemometer/anemometer.c b/components/anemometer/anemometer.c new file mode 100644 index 00000000..801a5a9d --- /dev/null +++ b/components/anemometer/anemometer.c @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2024 Jakub Turek + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of itscontributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file anemometer.c + * + * ESP-IDF driver for impulse wind speed sensors(anemometers) + * + * Ported from esp-open-rtos + * + * Copyright (c) 2024 Jakub Turek + * + * BSD Licensed as described in the file LICENSE + */ +#include "anemometer.h" + +#include +#include +#include +#include + +#ifdef CONFIG_IDF_TARGET_ESP32 +static portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED; +#define PORT_ENTER_CRITICAL portENTER_CRITICAL(&mux) +#define PORT_EXIT_CRITICAL portEXIT_CRITICAL(&mux) + +#elif CONFIG_IDF_TARGET_ESP8266 +#define PORT_ENTER_CRITICAL portENTER_CRITICAL() +#define PORT_EXIT_CRITICAL portEXIT_CRITICAL() + +#else +#error cannot identify the target +#endif + +#define CHECK_ARG(VAL) do { if (!(VAL)) return ESP_ERR_INVALID_ARG; } while (0) +#define RETURN_CRITICAL(RES) do { PORT_EXIT_CRITICAL; return RES; } while(0) + +typedef struct { + gpio_num_t input_pin; //!< GPIO input pin + float sf; //!< scale factor + uint32_t pps; //!< measured pulses count per second + TickType_t init_tick; //!< measurement init tick +} anemometer_priv_t; + +static inline void pps_iterate(anemometer_priv_t *priv, TickType_t ticks) +{ + if(ticks - priv->init_tick > pdMS_TO_TICKS(1000)){ + priv->init_tick = ticks; + priv->pps = 0; + } +} + +static void IRAM_ATTR gpio_isr_handler(void* arg) +{ + anemometer_priv_t *priv = (anemometer_priv_t *)arg; + TickType_t ticks = xTaskGetTickCountFromISR(); + pps_iterate(arg,ticks); + priv->pps++; +} + +anemometer_t anemometer_init(const anemometer_config_t *conf) +{ + gpio_config_t io_conf; + anemometer_priv_t *priv; + + priv = (anemometer_priv_t *)calloc(1,sizeof(anemometer_priv_t)); + if(priv == NULL){ + return NULL; + } + + priv->input_pin = conf->input_pin; + priv->sf = conf->scale_factor ? conf->scale_factor : ANEMOMETER_DEFAULT_SF; + + /* setup GPIO */ + io_conf.intr_type = GPIO_INTR_POSEDGE; + io_conf.pin_bit_mask = (1 << priv->input_pin); + io_conf.mode = GPIO_MODE_INPUT; + io_conf.pull_up_en = GPIO_PULLUP_ENABLE; + gpio_config(&io_conf); + + /* enable interrupts */ + gpio_install_isr_service(0); + gpio_isr_handler_add(priv->input_pin, gpio_isr_handler, (void *) priv); + return priv; +} + +esp_err_t anemometer_deinit(anemometer_t *anemometer) +{ + CHECK_ARG(anemometer); + anemometer_priv_t *priv = (anemometer_priv_t *)anemometer; + + gpio_isr_handler_remove(priv->input_pin); + free(priv); + return ESP_OK; +} + +esp_err_t anemometer_get_wind_speed(anemometer_t *anemometer, float *speed) +{ + CHECK_ARG(anemometer); + CHECK_ARG(speed); + anemometer_priv_t *priv = (anemometer_priv_t *)anemometer; + TickType_t ticks = xTaskGetTickCount(); + + PORT_ENTER_CRITICAL; + pps_iterate(priv,ticks); + *speed = priv->sf * priv->pps; + PORT_EXIT_CRITICAL; + return ESP_OK; +} + + + + diff --git a/components/anemometer/anemometer.h b/components/anemometer/anemometer.h new file mode 100644 index 00000000..5403700d --- /dev/null +++ b/components/anemometer/anemometer.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2024 Jakub Turek + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of itscontributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file anemometer.h + * @defgroup misc wind + * @{ + * + * ESP-IDF driver for impulse wind speed sensors(anemometers) + * + * Copyright (c) 2024 Jakub Turek + * + * BSD Licensed as described in the file LICENSE + */ +#ifndef __ANEMOMETER_H__ +#define __ANEMOMETER_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define ANEMOMETER_DEFAULT_SF (1.75/20) //!< 1.75 m/s = 20 pps + +/** + * Device descriptor + */ + +typedef void *anemometer_t; + +typedef struct +{ + gpio_num_t input_pin; //!< GPIO input pin + const float scale_factor; //!< scale factor +} anemometer_config_t; + +/** + * @brief Init anemometer sensor + * + * @param config Pointer to the device config + * @return anemometer device or NULL if failed + */ +anemometer_t anemometer_init(const anemometer_config_t *config); + +/** + * @brief Deinit anemometer sensor + * + * @param anemometer Pointer to the anemometer device + * @return `ESP_OK` on success + */ +esp_err_t anemometer_deinit(anemometer_t *anemometer); + +/** + * @brief Deinit anemometer sensor + * + * @param anemometer Pointer to the anemometer device + * @param[out] speed calculated wind speed in [m/s] + * @return `ESP_OK` on success + */ +esp_err_t anemometer_get_wind_speed(anemometer_t *anemometer, float *speed); + + +#ifdef __cplusplus +} +#endif + +/**@}*/ + +#endif /* __ANEMOMETER_H__ */ diff --git a/components/anemometer/component.mk b/components/anemometer/component.mk new file mode 100644 index 00000000..6ddb74a0 --- /dev/null +++ b/components/anemometer/component.mk @@ -0,0 +1,7 @@ +COMPONENT_ADD_INCLUDEDIRS = . + +ifdef CONFIG_IDF_TARGET_ESP8266 +COMPONENT_DEPENDS = esp8266 freertos +else +COMPONENT_DEPENDS = driver freertos +endif diff --git a/examples/anemometer/default/CMakeLists.txt b/examples/anemometer/default/CMakeLists.txt new file mode 100644 index 00000000..f581ab54 --- /dev/null +++ b/examples/anemometer/default/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four lines of boilerplate have to be in your project's CMakeLists +# in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + +set(EXTRA_COMPONENT_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../../../components) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(example-anemometer) diff --git a/examples/anemometer/default/Makefile b/examples/anemometer/default/Makefile new file mode 100644 index 00000000..2751be41 --- /dev/null +++ b/examples/anemometer/default/Makefile @@ -0,0 +1,10 @@ +#V := 1 +PROJECT_NAME := example-anemometer + +EXTRA_COMPONENT_DIRS := $(CURDIR)/../../../components + +#ifdef CONFIG_IDF_TARGET_ESP8266 +EXCLUDE_COMPONENTS := max7219 ads130e08 mcp23x17 led_strip max31865 ls7366r max31855 encoder +#endif + +include $(IDF_PATH)/make/project.mk diff --git a/examples/anemometer/default/README.md b/examples/anemometer/default/README.md new file mode 100644 index 00000000..964da8f8 --- /dev/null +++ b/examples/anemometer/default/README.md @@ -0,0 +1,18 @@ +# Example for `anemometer` driver + +## What it does + +It shows anemometer impulse wind sensor sensor data in a loop. + +## Wiring + +Connect `DATA` pin to the following pins with appropriate pull-up +resistors. + +| Name | Description | Defaults | +|------|-------------|----------| +| `CONFIG_EXAMPLE_ANEMOMETER_GPIO` | GPIO number for `DATA` | "5" for `esp8266`, "6" for `esp32c3`, "19" for `esp32`, `esp32s2`, and `esp32s3` | + +## Notes + +`CONFIG_NEWLIB_LIBRARY_LEVEL_NORMAL` must be `y` on `esp8266`. diff --git a/examples/anemometer/default/main/CMakeLists.txt b/examples/anemometer/default/main/CMakeLists.txt new file mode 100644 index 00000000..cf2c455c --- /dev/null +++ b/examples/anemometer/default/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "main.c" + INCLUDE_DIRS ".") diff --git a/examples/anemometer/default/main/Kconfig.projbuild b/examples/anemometer/default/main/Kconfig.projbuild new file mode 100644 index 00000000..ecf32336 --- /dev/null +++ b/examples/anemometer/default/main/Kconfig.projbuild @@ -0,0 +1,10 @@ +menu "Example configuration" + config EXAMPLE_ANEMOMETER_GPIO + int "SCL GPIO Number" + default 2 if IDF_TARGET_ESP8266 + default 6 if IDF_TARGET_ESP32C3 + default 19 if IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 + help + GPIO number for anemometer sensor DATA line. + +endmenu diff --git a/examples/anemometer/default/main/component.mk b/examples/anemometer/default/main/component.mk new file mode 100644 index 00000000..7700ea99 --- /dev/null +++ b/examples/anemometer/default/main/component.mk @@ -0,0 +1 @@ +COMPONENT_ADD_INCLUDEDIRS = . include/ diff --git a/examples/anemometer/default/main/main.c b/examples/anemometer/default/main/main.c new file mode 100644 index 00000000..690d8987 --- /dev/null +++ b/examples/anemometer/default/main/main.c @@ -0,0 +1,41 @@ +/* WiFi station 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static const char *TAG="APP"; + +void app_main() +{ + float val; + anemometer_config_t config = { + .input_pin = CONFIG_EXAMPLE_ANEMOMETER_GPIO, + .scale_factor = ANEMOMETER_DEFAULT_SF + }; + + anemometer_t wind_sensor = anemometer_init(&config); + + while(1){ + anemometer_get_wind_speed(wind_sensor,&val); + ESP_LOGI(TAG, "Wind speed = %.2f m/s", val); + vTaskDelay(1000 / portTICK_RATE_MS); + } +} diff --git a/examples/anemometer/default/sdkconfig.defaults.esp8266 b/examples/anemometer/default/sdkconfig.defaults.esp8266 new file mode 100644 index 00000000..79a53171 --- /dev/null +++ b/examples/anemometer/default/sdkconfig.defaults.esp8266 @@ -0,0 +1 @@ +CONFIG_NEWLIB_LIBRARY_LEVEL_NORMAL=y