diff --git a/drivers/Makefile.dep b/drivers/Makefile.dep index cf30a71667..e5a0c9991d 100644 --- a/drivers/Makefile.dep +++ b/drivers/Makefile.dep @@ -405,6 +405,12 @@ ifneq (,$(filter srf02,$(USEMODULE))) USEMODULE += xtimer endif +ifneq (,$(filter srf04,$(USEMODULE))) + USEMODULE += xtimer + FEATURES_REQUIRED += periph_gpio + FEATURES_REQUIRED += periph_gpio_irq +endif + ifneq (,$(filter srf08,$(USEMODULE))) FEATURES_REQUIRED += periph_i2c USEMODULE += xtimer diff --git a/drivers/Makefile.include b/drivers/Makefile.include index 11cc60b374..83c994ef37 100644 --- a/drivers/Makefile.include +++ b/drivers/Makefile.include @@ -222,6 +222,10 @@ ifneq (,$(filter soft_spi,$(USEMODULE))) USEMODULE_INCLUDES += $(RIOTBASE)/drivers/soft_spi/include endif +ifneq (,$(filter srf04,$(USEMODULE))) + USEMODULE_INCLUDES += $(RIOTBASE)/drivers/srf04/include +endif + ifneq (,$(filter sx127x,$(USEMODULE))) USEMODULE_INCLUDES += $(RIOTBASE)/drivers/sx127x/include endif diff --git a/drivers/include/srf04.h b/drivers/include/srf04.h new file mode 100644 index 0000000000..3856b34f0f --- /dev/null +++ b/drivers/include/srf04.h @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2018 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @defgroup drivers_srf04 srf04 ultra sonic range finder + * @ingroup drivers_sensors + * @brief Device driver for the srf04 ultra sonic range finder + * @{ + * + * @file + * @brief Device driver for the srf04 ultra sonic range finder + * + * @author Semjon Kerner + */ + +#ifndef SRF04_H +#define SRF04_H + +#include +#include + +#include "periph/gpio.h" +#include "xtimer.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Status and error return codes + */ +enum { + SRF04_OK = 0, /**< exit without error */ + SRF04_ERR_INVALID = -1, /**< error no valid measurement available*/ + SRF04_ERR_MEASURING = -2, /**< error sensor is measuring*/ + SRF04_ERR_GPIO = -3, /**< error initializing gpio*/ +}; + +/** + * @brief GPIO pins for srf04 device + */ +typedef struct { + gpio_t trigger; /**< GPIO Port the trigger pin is connected to */ + gpio_t echo; /**< GPIO Port the echo pin is connected to */ +} srf04_params_t; + +/** + * @brief Device descriptor for srf04 sensor + */ +typedef struct { + srf04_params_t p; /**< GPIO Ports of device */ + int distance; /**< raw time of flight distance */ + uint32_t time; /**< timestamp of trigger or echo */ +} srf04_t; + +/** + * @brief Initialize gpio and interrupt + * + * @param[out] dev device descriptor of sensor to initialize + * @param[in] params init param struct holding gpio trigger and echo pins + * + * @return SRF04_OK on success + * @return SRF04_GPIO on gpio init failure + */ +int srf04_init(srf04_t *dev, const srf04_params_t *params); + +/** + * @brief Triggers measurement + * + * @param[in] dev device descriptor of sensor + */ +void srf04_trigger(const srf04_t *dev); + +/** + * @brief Returns time of flight in ms + * + * @note should not be invoked within 50 ms after triggering + * + * @param[in] dev device descriptor of sensor + * + * @return time of flight in ms + * @return SRF04_MEASURING if measurement is in progress + * @return SRF04_INVALID if no valid measurement is available + */ +int srf04_read(const srf04_t* dev); + +/** + * @brief Convenience function triggers a measurement and returns distance + * + * @note This function will return after 50 ms once new data is available + * + * @param[in] dev device descriptor of sensor + * + * @return time of flight in mm + * @return SRF04_MEASURING if measurement is in progress + * @return SRF04_INVALID if no valid measurement is available + */ +int srf04_get_distance(const srf04_t* dev); + +#ifdef __cplusplus +} +#endif + +#endif /* SRF04_H */ +/** @} */ diff --git a/drivers/srf04/Makefile b/drivers/srf04/Makefile new file mode 100644 index 0000000000..48422e909a --- /dev/null +++ b/drivers/srf04/Makefile @@ -0,0 +1 @@ +include $(RIOTBASE)/Makefile.base diff --git a/drivers/srf04/include/srf04_params.h b/drivers/srf04/include/srf04_params.h new file mode 100644 index 0000000000..fddcfd046d --- /dev/null +++ b/drivers/srf04/include/srf04_params.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2018 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup drivers_srf04 + * + * @{ + * @file + * @brief Default configuration for srf04 devices + * + * @author Semjon Kerner + */ + +#ifndef SRF04_PARAMS_H +#define SRF04_PARAMS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "board.h" +#include "srf04.h" + +/** + * @name Default configuration parameters for SRF04 device + * @{ + */ +#ifndef SRF04_PARAM_TRIGGER +#define SRF04_PARAM_TRIGGER GPIO_PIN(0,13) +#endif +#ifndef SRF04_PARAM_ECHO +#define SRF04_PARAM_ECHO GPIO_PIN(0,14) +#endif + +#ifndef SRF04_PARAMS +#define SRF04_PARAMS \ + { .trigger = SRF04_PARAM_TRIGGER, \ + .echo = SRF04_PARAM_ECHO, \ + } +#endif +/** @} */ + +/** + * @brief SRF04 configuration + */ +static const srf04_params_t srf04_params[] = { + SRF04_PARAMS +}; + +#define SRF04_NUMOF (sizeof(srf04_params) / sizeof(srf04_params[0])) + +#ifdef __cplusplus +} +#endif + +#endif /* SRF04_PARAMS_H */ +/** @} */ diff --git a/drivers/srf04/srf04.c b/drivers/srf04/srf04.c new file mode 100644 index 0000000000..d828ed7d85 --- /dev/null +++ b/drivers/srf04/srf04.c @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2018 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup drivers_srf04 + * @{ + * + * @file + * @brief driver for srf04 ultra sonic range finder + * + * @author Semjon Kerner + * + * @} + */ + +#include "srf04.h" +#include "srf04_params.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +#define SRF04_DISTANCE (584U) +#define SRF04_SAMPLE_PERIOD (50U * US_PER_MS) + +static void _cb(void *arg) +{ + uint32_t t = xtimer_now_usec(); + + srf04_t* dev = (srf04_t*)arg; + if (dev->distance > SRF04_ERR_MEASURING) { + dev->distance = SRF04_ERR_MEASURING; + dev->time = t; + } else { + gpio_irq_disable(dev->p.echo); + dev->distance = (t - dev->time); + } +} + +int srf04_init(srf04_t* dev, const srf04_params_t *params) +{ + dev->p = *params; + + dev->distance = SRF04_ERR_INVALID; + dev->time = 0; + + if (gpio_init(dev->p.trigger, GPIO_OUT) != 0) { + DEBUG("[srf04] Error: could not initialize GPIO trigger pin\n"); + return SRF04_ERR_GPIO; + } + + if (gpio_init_int(dev->p.echo, GPIO_IN, GPIO_BOTH, _cb, (void*)dev) != 0) { + DEBUG("[srf04] Error: could not initialize GPIO echo pin\n"); + return SRF04_ERR_GPIO; + } + + gpio_irq_disable(dev->p.echo); + + return SRF04_OK; +} + +void srf04_trigger(const srf04_t* dev) +{ + if (dev->distance == SRF04_ERR_MEASURING) { + return; + } + + gpio_irq_enable(dev->p.echo); + + gpio_set(dev->p.trigger); + xtimer_usleep(10); + gpio_clear(dev->p.trigger); +} + +int srf04_read(const srf04_t* dev) +{ + return dev->distance; +} + +int srf04_get_distance(const srf04_t* dev) +{ + /* trigger new reading */ + srf04_trigger(dev); + /* give the sensor the required time for sampling */ + xtimer_usleep(SRF04_SAMPLE_PERIOD); + /* get the result */ + if (dev->distance >= SRF04_OK) { + return ((dev->distance * 100) / SRF04_DISTANCE); + } + return dev->distance; +}