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

drivers/srf08: initial import of the updated ultrasonic driver

This commit is contained in:
PeterKietzmann 2014-12-11 16:13:49 +01:00
parent 2feb6423a7
commit 46fdcf64c1
8 changed files with 399 additions and 320 deletions

View File

@ -1,162 +0,0 @@
/*
* Copyright (C) 2013 Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
*
* 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 <zkasmi@inf.fu-berlin.de>
*/
#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_ */

164
drivers/include/srf08.h Normal file
View File

@ -0,0 +1,164 @@
/*
* Copyright (C) 2013 Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
*
* 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 <zkasmi@inf.fu-berlin.de>
* @author Peter Kietzmann <peter.kietzmann@haw-hamburg.de>
*/
#ifndef SRF08_H_
#define SRF08_H_
#include <stdint.h>
#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_ */

View File

@ -1 +1,3 @@
MODULE = srf08
include $(RIOTBASE)/Makefile.base

View File

@ -1,158 +0,0 @@
/*
* srf08-ultrasonic-sensor.c - Driver for the SRF08 ultrasonic ranger via the
* i2c interface.
*
* Copyright (C) 2013 Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
*
* 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 <zkasmi@inf.fu-berlin.de>
* @version $Revision: 3857 $
*
* @note $Id: srf08-ultrasonic-sensor.c 3857 2013-09-05 14:45:13 kasmi $
*
*/
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#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;
}
}
}

117
drivers/srf08/srf08.c Normal file
View File

@ -0,0 +1,117 @@
/*
* Copyright (C) 2013 Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
*
* 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 <zkasmi@inf.fu-berlin.de>
* @author Peter Kietzmann <peter.kietzmann@haw-hamburg.de>
*
* @}
*/
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#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;
}

View File

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

View File

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

78
tests/driver_srf08/main.c Normal file
View File

@ -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 <peter.kietzmann@haw-hamburg.de>
*
* @}
*/
#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 <stdio.h>
#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);
}
}
}