1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

Merge pull request #9035 from SemjonKerner/driver_sensor_srf04

drivers/srf04: range finder sensor
This commit is contained in:
Hauke Petersen 2018-09-20 16:01:18 +02:00 committed by GitHub
commit ef4bd75412
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 352 additions and 0 deletions

View File

@ -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

View File

@ -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

110
drivers/include/srf04.h Normal file
View File

@ -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 <semjon.kerner@fu-berlin.de>
*/
#ifndef SRF04_H
#define SRF04_H
#include <stdint.h>
#include <stdio.h>
#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 */
/** @} */

1
drivers/srf04/Makefile Normal file
View File

@ -0,0 +1 @@
include $(RIOTBASE)/Makefile.base

View File

@ -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 <semjon.kerner@fu-berlin.de>
*/
#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 */
/** @} */

95
drivers/srf04/srf04.c Normal file
View File

@ -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 <semjon.kerner@fu-berlin.de>
*
* @}
*/
#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;
}

View File

@ -0,0 +1,9 @@
include ../Makefile.tests_common
BOARD ?= nrf52dk
RIOTBASE ?= $(CURDIR)/../..
USEMODULE += srf04
include $(RIOTBASE)/Makefile.include

View File

@ -0,0 +1,17 @@
tests/driver_srf04
================
This example shows the usage of an srf04 module.
The application uses a timer and two gpio pins.
The module is an ultrasonic range finder with a small protocol [1]:
- trigger pin is raised high for 10 us by calling trigger function
- after a sample period of 50 ms the value can be read out
[1] www.robot-electronics.co.uk/htm/srf04tech.htm
Usage
=====
Build, flash and start the application:
export BOARD=your_board
make flash term

48
tests/driver_srf04/main.c Normal file
View File

@ -0,0 +1,48 @@
/*
* 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 tests
* @{
*
* @file
* @brief Test for srf04 ultra sonic range finder driver
*
* @author Semjon Kerner <semjon.kerner@fu-berlin.de>
*
* @}
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "srf04_params.h"
#include "srf04.h"
int main(void)
{
puts("SRF04 range finder example");
srf04_t dev;
if (srf04_init(&dev, &srf04_params[0]) != SRF04_OK) {
puts("Error: initializing");
return 1;
}
while (1) {
int distance = srf04_get_distance(&dev);
if (distance < SRF04_OK) {
puts("Error: no valid data available");
} else {
printf("D: %d mm\n", distance);
}
}
return 0;
}