From 46fdcf64c122716f8db8c3ff93fd136167e25e60 Mon Sep 17 00:00:00 2001 From: PeterKietzmann Date: Thu, 11 Dec 2014 16:13:49 +0100 Subject: [PATCH] drivers/srf08: initial import of the updated ultrasonic driver --- drivers/include/srf08-ultrasonic-sensor.h | 162 --------------------- drivers/include/srf08.h | 164 ++++++++++++++++++++++ drivers/srf08/Makefile | 2 + drivers/srf08/srf08-ultrasonic-sensor.c | 158 --------------------- drivers/srf08/srf08.c | 117 +++++++++++++++ tests/driver_srf08/Makefile | 28 ++++ tests/driver_srf08/README.md | 10 ++ tests/driver_srf08/main.c | 78 ++++++++++ 8 files changed, 399 insertions(+), 320 deletions(-) delete mode 100644 drivers/include/srf08-ultrasonic-sensor.h create mode 100644 drivers/include/srf08.h delete mode 100644 drivers/srf08/srf08-ultrasonic-sensor.c create mode 100644 drivers/srf08/srf08.c create mode 100644 tests/driver_srf08/Makefile create mode 100644 tests/driver_srf08/README.md create mode 100644 tests/driver_srf08/main.c diff --git a/drivers/include/srf08-ultrasonic-sensor.h b/drivers/include/srf08-ultrasonic-sensor.h deleted file mode 100644 index 2a89370092..0000000000 --- a/drivers/include/srf08-ultrasonic-sensor.h +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (C) 2013 Zakaria Kasmi - * - * 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 srf08 SRF08 - * @ingroup drivers - * @brief Driver for the SRF08 ultrasonic range sensor - * - * The connection between the MCU and the SRF08 is based on the i2c-interface. - * - * @{ - * - * @file - * @internal - * @brief Driver definitions for the SRF08 ultrasonic. - * - * The communication between the MCU and SRF08 is via the i2c interface. - * - * @author Zakaria Kasmi - */ - -#ifndef SRF08_ULTRASONIC_SENSOR_I2C_H_ -#define SRF08_ULTRASONIC_SENSOR_I2C_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/** @brief The sensors default I2C address */ -#define SRF08_DEFAULT_ADDR 112 - - -/** @brief The sensors command register (write) */ -#define SRF08_COMMAND_REG 0x0 - -/** @brief Max. gain register (write) */ -#define SRF08_GAIN_REG 0x1 - -/** @brief The sensors range register (write) */ -#define SRF08_RANGE_REG 0x2 - -/** @brief The upper measurement byte (read) */ -#define SRF08_RANGE_HIGH_BYTE 0x2 - -/** @brief The lower measurement byte (read)*/ -#define SRF08_RANGE_LOW_BYTE 0x3 - - -/** @brief Measure in inch mode */ -#define SRF08_REAL_RANGING_MODE_CM 0x50 - -/** @brief Measure in cm mode */ -#define SRF08_REAL_RANGING_MODE_CM 0x51 - -/** @brief Measure in micro-seconds mode */ -#define SRF08_REAL_RANGING_MODE_CM 0x52 - - -/** @brief Number of highest register */ -#define SRF08_MAX_REGISTER_NUMBER 35 - -/** @brief Maximum number of echos from more distant objects */ -#define SRF08_MAX_ECHO_NUMBER 17 - - -/** @brief Define the used I2C Interface */ -#define SRF08_I2C_INTERFACE I2C2 /* P0.10 SDA2, P0.11 SCL2 */ - - -/** - * @brief Initialize the SRF08 ultrasonic sensor. - * - * @param[in] i2c_interface the i2c interface, several interfaces can be - * selected: i2c0, i2c1 and i2c2. - * @param[in] baud_rate the baud rate. - * - * @return true if the SRF08 is successfully initialized, otherwise false. - * - */ -bool srf08_init(uint8_t i2c_interface, uint32_t baud_rate); - - -/** - * @brief Start a continuous distance ranging with the SRF08 ultrasonic - * range-finder. - * The ranging results are given over the RS232-Interface. - * - * @param[in] ranging_mode there are three real ranging modes, which return - * the result in inches, centimeters or microseconds. - * Another set of three fake ranging modes do the same - * but without transmitting the burst. - * - */ -void srf08_start_ranging(uint8_t ranging_mode); - - -/** - * @brief Set the maximum range of the SRF08. - * - * @param[in] max_range the adjusted maximal range is: - * max_range = (max_rangex43mm) + 43mm. - * - */ -void srf08_set_range(uint8_t max_range); - - -/** - * @brief Set the maximum of the analog stages. - * - * @param[in] max_gain the maximal gain value. - * - */ -void srf08_set_gain(uint8_t max_gain); - - -/** - * @brief Get the maximal range. - * - * - * @return the maximal range value. - */ -uint8_t srf08_get_range(void); - - -/** - * @brief Get the maximal analog gain. - * - * - * @return the maximal gain value. - */ -uint8_t srf08_get_gain(void); - - -/** - * @brief Get all distances measured from the SRF08 ultrasonic sensor. - * The results of a ranging can be returned in inches, centimeters - * or microseconds. The SRF08 can detect up to targets. - * This function prints the distance values over the rs232 - * interface - * - * @param[in] range_array a pointer to a buffer holding the ranging results. - * @param[in] ranging_mode there are three real ranging modes, which return - * the result in inches, centimeters or microseconds. - * Another set of three fake ranging modes do the same - * but without transmitting the burst. - * - * @return -1 if the write/read action from the i2c-interface is failed, - * otherwise the number of the detected targets is delivered. - */ -int32_t srf08_get_distances(uint32_t *range_array, uint8_t ranging_mode); - -#ifdef __cplusplus -} -#endif - -/** @} */ -#endif /* SRF08_ULTRASONIC_SENSOR_I2C_H_ */ diff --git a/drivers/include/srf08.h b/drivers/include/srf08.h new file mode 100644 index 0000000000..c41d8812d8 --- /dev/null +++ b/drivers/include/srf08.h @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2013 Zakaria Kasmi + * + * 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 driver_srf08 SRF08 ultrasonic range sensor + * @ingroup drivers + * @brief Driver for the SRF08 ultrasonic range sensor + * + * The connection between the MCU and the SRF08 is based on the i2c-interface. + * + * @{ + * + * @file srf08.h + * @brief Driver definitions for the SRF02 ultrasonic ranger. + * + * The connection between the SRF08 and the MCU is based on the i2c interface. + * + * @author Zakaria Kasmi + * @author Peter Kietzmann + */ + +#ifndef SRF08_H_ +#define SRF08_H_ + +#include +#include "periph/i2c.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief The sensors default I2C address */ +#define SRF08_DEFAULT_ADDR 112 + +/** @brief The sensors command register (write) */ +#define SRF08_COMMAND_REG 0x0 + +/** @brief Max. gain register (write) */ +#define SRF08_GAIN_REG 0x1 + +/** @brief The sensors range register (write) */ +#define SRF08_RANGE_REG 0x2 + +/** @brief The upper measurement byte (read) */ +#define SRF08_RANGE_HIGH_BYTE 0x2 + +/** @brief The lower measurement byte (read)*/ +#define SRF08_RANGE_LOW_BYTE 0x3 + +/** @brief Number of highest register */ +#define SRF08_MAX_REGISTER_NUMBER 35 + +/** @brief Maximum number of echos from more distant objects */ +#define SRF08_MAX_ECHO_NUMBER 17 + +/** @brief Maximum range the sensor can measure (6m) */ +#define SRF08_MAX_RANGE_6M 0x8C + +/** @brief Maximum gain of the sensor (1025)*/ +#define SRF08_MAX_GAIN 0x25 + +/** + * @brief Device descriptor for SRF08 sensors + */ +typedef struct { + i2c_t i2c; /**< I2C device the sensor is connected to */ + uint8_t addr; /**< I2C bus address of the sensor */ +} srf08_t; + +/** + * @brief Possible measurement modes for the SRF08 sensor + */ +typedef enum { + SRF08_MODE_INCH = 0x50, /**< result in inches */ + SRF08_MODE_CM = 0x51, /**< result in centimeters */ + SRF08_MODE_MICRO_SEC = 0x52, /**< result in centimeters */ + SRF08_ANN_MODE_INCH = 0x53, /**< synchronous measurement in inches */ + SRF08_ANN_MODE_CM = 0x54, /**< synchronous measurement in centimeters */ + SRF08_ANN_MODE_MICRO_SEC = 0x55 /**< synchronous measurement in microseconds */ +}srf08_mode_t; + +/** + * @brief Initialize the SRF08 ultrasonic sensor + * + * @param[in] dev device descriptor of an SRF08 sensor + * @param[in] i2c I2C device the sensor is connected to + * @param[in] addr I2C address of the sensor + * @param[in] speed I2C speed mode + * + * @return 0 on successful initialization + * @return -1 on undefined device given + * @return -2 on unsupported speed value + * @return -3 on max. range error + * @return -4 on max. gain error + * + */ +int srf08_init(srf08_t *dev, i2c_t i2c, uint8_t addr, i2c_speed_t speed); + +/** + * @brief Set the maximum range of the SRF08. + * + * @param[in] dev device descriptor of an SRF08 sensor + * @param[in] max_range the adjusted maximal range is: + * max_range = (max_range x 43mm) + 43mm. + * The hardware limit is 6m. + * + * @return 1 on success + * @return -1 on undefined device given + * + */ +int srf08_set_max_range(srf08_t *dev, uint8_t max_range); + +/** + * @brief Set the maximum of the analog stages. + * + * @ note + * This value is just a limitation of the maximum amplification and not the actual. + * While measuing, this value starts at its minimum and increases approx. each 75 us + * until the maximum value is reached. + * + * @param[in] dev device descriptor of an SRF08 sensor + * @param[in] max_gain the maximal gain value. + * + * @return 1 on success + * @return -1 on undefined device given + * + */ +int srf08_set_max_gain(srf08_t *dev, uint8_t max_gain); + +/** + * @brief Get all distances measured from the SRF08 ultrasonic sensor. + * The results of a ranging can be returned in inches, centimeters + * or microseconds. The SRF08 can detect up to 17 targets. + * + * + * @param[in] dev device descriptor of an SRF08 sensor + * @param[in] range_array a pointer to a buffer holding the ranging results. + * @param[in] num_echos number of stored measurements (echos) + * @param[in] ranging_mode there are three real ranging modes, which return + * the result in inches, centimeters or microseconds. + * Another set of three fake ranging modes do the same + * but without transmitting the burst. + * + * @return number of measured echos on success + * @return -1 on ranging mode errors + * @return -2 if num_echos exceeds the max. number of + possible measurements + * @return -3 if i2c read high byte failed + * @return -4 if i2c read low byte failed + * + */ +int srf08_get_distances(srf08_t *dev, uint16_t *range_array, int num_echos, srf08_mode_t ranging_mode); + +#ifdef __cplusplus +} +#endif + +/** @} */ +#endif /* SRF08_H_ */ diff --git a/drivers/srf08/Makefile b/drivers/srf08/Makefile index 48422e909a..27fe8b7acd 100644 --- a/drivers/srf08/Makefile +++ b/drivers/srf08/Makefile @@ -1 +1,3 @@ +MODULE = srf08 + include $(RIOTBASE)/Makefile.base diff --git a/drivers/srf08/srf08-ultrasonic-sensor.c b/drivers/srf08/srf08-ultrasonic-sensor.c deleted file mode 100644 index 914234d4c1..0000000000 --- a/drivers/srf08/srf08-ultrasonic-sensor.c +++ /dev/null @@ -1,158 +0,0 @@ -/* - * srf08-ultrasonic-sensor.c - Driver for the SRF08 ultrasonic ranger via the - * i2c interface. - * - * Copyright (C) 2013 Zakaria Kasmi - * - * 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. - */ - -/** - * @file - * @internal - * @brief Driver for the SRF08 ultrasonic ranger using the i2c interface. - * - * @author Zakaria Kasmi - * @version $Revision: 3857 $ - * - * @note $Id: srf08-ultrasonic-sensor.c 3857 2013-09-05 14:45:13 kasmi $ - * - */ - -#include -#include -#include -#include "hwtimer.h" -#include "srf08-ultrasonic-sensor.h" -#include "i2c.h" - -bool srf08_init(uint8_t i2c_interface, uint32_t baud_rate) -{ - if (i2c_initialize(i2c_interface, (uint32_t) I2CMASTER, 0, baud_rate, NULL) - == false) { /* initialize I2C */ - puts("fatal error happened in i2c_initialize()\n"); - return false; - } - else { - i2c_enable_pull_up_resistor(i2c_interface); - //i2c_disable_pull_up_resistor(i2c_interface); - return true; - } -} - -void srf08_set_range(uint8_t max_range) -{ - uint8_t tx_buff[1]; - - tx_buff[0] = max_range; - i2c_write(SRF08_I2C_INTERFACE, SRF08_DEFAULT_ADDR, SRF08_RANGE_REG, tx_buff, - 1); -} - -void srf08_set_gain(uint8_t gain) -{ - uint8_t tx_buff[1]; - - tx_buff[0] = gain; - i2c_write(SRF08_I2C_INTERFACE, SRF08_DEFAULT_ADDR, SRF08_GAIN_REG, tx_buff, - 1); -} - -uint8_t srf08_get_range(void) -{ - uint8_t rx_buff[1]; - - i2c_read(SRF08_I2C_INTERFACE, SRF08_DEFAULT_ADDR, SRF08_RANGE_REG, rx_buff, - 1); - return rx_buff[0]; -} - -uint8_t srf08_get_gain(void) -{ - uint8_t rx_buff[1]; - - i2c_read(SRF08_I2C_INTERFACE, SRF08_DEFAULT_ADDR, SRF08_GAIN_REG, rx_buff, - 1); - return rx_buff[0]; -} - - -int32_t srf08_get_distances(uint32_t *range_array, uint8_t ranging_mode) -{ - bool status; - uint8_t reg_size = 1; - uint8_t rx_buff[reg_size]; - uint8_t tx_buff[reg_size]; - uint8_t register_location; - uint8_t echo_number = 0; - - tx_buff[0] = ranging_mode; - status = i2c_write(SRF08_I2C_INTERFACE, SRF08_DEFAULT_ADDR, - SRF08_COMMAND_REG, tx_buff, reg_size); - if (!status) { - puts("Write the ranging command to the i2c-interface is failed"); - return -1; - } - hwtimer_wait(HWTIMER_TICKS(70000)); - - // Read all echo buffers - for (register_location = 2; register_location < SRF08_MAX_REGISTER_NUMBER; - register_location += 2) { - //read the high echo byte - status = i2c_read(SRF08_I2C_INTERFACE, SRF08_DEFAULT_ADDR, - register_location, rx_buff, reg_size); - if (!status) { - puts("Read the high echo byte from the i2c-interface is failed"); - return -1; - } - uint8_t range_high_byte = rx_buff[0]; - //read the low echo byte - status = i2c_read(SRF08_I2C_INTERFACE, SRF08_DEFAULT_ADDR, - register_location + 1, rx_buff, reg_size); - if (!status) { - puts("Read the low echo byte from the i2c-interface is failed"); - return -1; - } - uint8_t range_low_byte = rx_buff[0]; - if ((range_high_byte == 0) && (range_low_byte == 0)) { - break; - } - else { - uint32_t distance = (range_high_byte << 8) | range_low_byte; - range_array[(register_location - 2) / 2] = distance; - echo_number++; - printf("distance = %4lu cm , echo%d\n", - distance, register_location / 2); - } - hwtimer_wait(HWTIMER_TICKS(500000)); - } - puts("--------------------------------------------"); - return echo_number; -} - -void srf08_start_ranging(uint8_t ranging_mode) -{ - uint32_t range_array[SRF08_MAX_ECHO_NUMBER]; - uint8_t i; - - puts("Ultrasonic SRF08 engine is started"); - //wait due to calibration - hwtimer_wait(HWTIMER_TICKS(700000)); - printf("Actual range = %d\n", srf08_get_range()); - printf("Actual gain = %d\n", srf08_get_gain()); - - while (1) { - puts("--------------------------------------------"); - uint8_t echo_number = srf08_get_distances(range_array, ranging_mode); - if (echo_number > 0) { - for (i = 0; i < echo_number; i++) { - printf("stored distance = %4lu cm , echo%d\n", range_array[i], i + 1); - } - } - else { - break; - } - } -} diff --git a/drivers/srf08/srf08.c b/drivers/srf08/srf08.c new file mode 100644 index 0000000000..2c178b82ff --- /dev/null +++ b/drivers/srf08/srf08.c @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2013 Zakaria Kasmi + * + * 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 driver_srf08 + * @{ + * + * @file srf08.c + * @brief Driver for the SRF08 ultrasonic ranger. + * The connection between the MCU and the SRF08 is based on the + * i2c-interface. + * + * @author Zakaria Kasmi + * @author Peter Kietzmann + * + * @} + */ + + +#include +#include +#include +#include "hwtimer.h" +#include "srf08.h" +#include "periph/i2c.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + + +int srf08_init(srf08_t *dev, i2c_t i2c, uint8_t addr, i2c_speed_t speed) +{ + dev->i2c = i2c; + dev->addr = addr; + + /* initialize i2c interface */ + if(i2c_init_master(i2c, speed) < 0) { + return -1; + } + /* set the maximum range */ + if (srf08_set_max_range(dev, SRF08_MAX_RANGE_6M) < 0) { + return -3; + } + /* set the maximum gain */ + if (srf08_set_max_gain(dev, SRF08_MAX_GAIN) < 0) { + return -4; + } + + return 0; +} + + +int srf08_set_max_range(srf08_t *dev, uint8_t max_range) +{ + return i2c_write_reg(dev->i2c, dev->addr, SRF08_RANGE_REG, max_range); +} + + +int srf08_set_max_gain(srf08_t *dev, uint8_t gain) +{ + return i2c_write_reg(dev->i2c, dev->addr, SRF08_GAIN_REG, gain); +} + + +int srf08_get_distances(srf08_t *dev, uint16_t *range_array, int num_echos, srf08_mode_t ranging_mode) +{ + int status; + int echo_number = 0; + char range_bytes[sizeof(uint16_t)]; + char register_location; + char max_reg_no_read = (num_echos * sizeof(range_bytes)) +1; + + /* set ranging mode */ + status = i2c_write_reg(dev->i2c, dev->addr, SRF08_COMMAND_REG, ranging_mode); + + if (!status) { + DEBUG("Write the ranging command to the i2c-interface is failed"); + return -1; + } + + if(max_reg_no_read > SRF08_MAX_REGISTER_NUMBER) { + DEBUG("Too many echos requested. Max. is 17"); + return -2; + } + + hwtimer_wait(HWTIMER_TICKS(70000)); + + /* read all echo buffers */ + for (register_location = 2; register_location < max_reg_no_read; + register_location += sizeof(range_bytes)) { + + /* read the echo bytes */ + status = i2c_read_regs(dev->i2c, dev->addr, register_location, range_bytes, sizeof(range_bytes)); + + if (!status) { + DEBUG("Read the echo bytes from the i2c-interface is failed"); + return -3; + } + + if (range_bytes == 0) { + break; + } + + else { + uint16_t distance = (range_bytes[0] << 8) | range_bytes[1]; + range_array[(register_location - 2) / 2] = distance; + echo_number++; + } + } + + return echo_number; +} diff --git a/tests/driver_srf08/Makefile b/tests/driver_srf08/Makefile new file mode 100644 index 0000000000..0eb8b32fc1 --- /dev/null +++ b/tests/driver_srf08/Makefile @@ -0,0 +1,28 @@ +APPLICATION = driver_srf08 +include ../Makefile.tests_common + +FEATURES_REQUIRED = periph_i2c + +USEMODULE += vtimer +USEMODULE += srf08 + +# Define default settings +export TEST_SRF08_I2C ?= I2C_0 +export TEST_SRF08_SPEED ?= I2C_SPEED_NORMAL +export TEST_MODE ?= SRF08_MODE_CM +export TEST_NUM_ECHOS?= 3 + +include $(RIOTBASE)/Makefile.include + +ifneq (,$(TEST_SRF08_I2C)) +export CFLAGS += -DTEST_SRF08_I2C=$(TEST_SRF08_I2C) +endif +ifneq (,$(TEST_SRF08_SPEED)) +export CFLAGS += -DTEST_SRF08_SPEED=$(TEST_SRF08_SPEED) +endif +ifneq (,$(TEST_MODE)) +export CFLAGS += -DTEST_MODE=$(TEST_MODE) +endif +ifneq (,$(TEST_NUM_ECHOS)) +export CFLAGS += -DTEST_NUM_ECHOS=$(TEST_NUM_ECHOS) +endif diff --git a/tests/driver_srf08/README.md b/tests/driver_srf08/README.md new file mode 100644 index 0000000000..d12a114580 --- /dev/null +++ b/tests/driver_srf08/README.md @@ -0,0 +1,10 @@ +# About +This is a manual test application for the SRF08 ultrasonic ranger driver. + +# Usage + + +After initialization, the sensor values are read periodically and printed to the STDOUT. Here, three echos are stored. + +To verify the seen values you can focus the sensor against any reflecting object and vary the distance to +see especially the first measured value changing. diff --git a/tests/driver_srf08/main.c b/tests/driver_srf08/main.c new file mode 100644 index 0000000000..41f3465b1d --- /dev/null +++ b/tests/driver_srf08/main.c @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2014 Hamburg University of Applied Sciences + * + * 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 application for the SRF08 ultrasonic range sensor + * + * @author Peter Kietzmann + * + * @} + */ +#ifndef TEST_SRF08_I2C +#error "TEST_SRF08_I2C not defined" +#endif +#ifndef TEST_SRF08_SPEED +#error "TEST_SRF08_SPEED not defined" +#endif +#ifndef TEST_MODE +#error "TEST_MODE not defined" +#endif +#ifndef TEST_NUM_ECHOS +#error "TEST_NUM_ECHOS not defined" +#endif + +#include + +#include "vtimer.h" +#include "srf08.h" +#include "periph/i2c.h" + + #define SLEEP (1000 * 1000U) + + static srf08_t srf08_0; + +int main(void) +{ + puts("SRF08 ultrasonic ranger test application\n"); + printf("Initializing SRF08 sensor at I2C_%i... ", TEST_SRF08_I2C); + + int res; + uint16_t range_array[TEST_NUM_ECHOS]; + + res = srf08_init(&srf08_0, TEST_SRF08_I2C, SRF08_DEFAULT_ADDR, TEST_SRF08_SPEED); + + if (res < 0) { + printf("[Failed]"); + return 1; + } + + else { + puts("[Ok]\n"); + + while(1) { + + int echo_number = srf08_get_distances(&srf08_0, range_array, TEST_NUM_ECHOS, TEST_MODE); + + if (echo_number > 0) { + for (int i = 0; i < echo_number; i++) { + printf("stored distance = %i cm , echo%i\n", range_array[i], i + 1); + } + puts("--------------------------------------------"); + } + + else { + puts("An error occured"); + } + vtimer_usleep(SLEEP); + } + } +}