diff --git a/drivers/include/srf02.h b/drivers/include/srf02.h index 275ac48637..055f855be4 100644 --- a/drivers/include/srf02.h +++ b/drivers/include/srf02.h @@ -34,7 +34,12 @@ extern "C" { /** * @brief Default I2C address of SRF02 sensors */ -#define SRF02_DEFAULT_ADDR (0xe0) +#define SRF02_DEFAULT_ADDR (0xe0) /* 224 decimal */ + +/** + * @brief The datasheet tells us, that ranging takes 70ms + */ +#define SRF02_RANGE_DELAY (70000U) /** * @brief Device descriptor for SRF02 sensors @@ -69,11 +74,38 @@ typedef enum { int srf02_init(srf02_t *dev, i2c_t i2c, uint8_t addr); /** - * @brief Get the distance measured from the SRF02 ultrasonic sensor + * @brief Trigger a new measurement + * + * This function triggers a new ranging operation. After triggering this + * operation, you have to wait at least 70ms for the result to be ready. * * The result of the ranging operation is returned in inches, centimeters or * microseconds - depending on the given @p mode parameter. * + * @param[in] dev device to trigger + * @param[in] 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 srf02_trigger(srf02_t *dev, srf02_mode_t mode); + +/** + * @brief Read the results of the last ranging operation + * + * @param[in] dev device to read from + * + * @return result of the last ranging operation, meaning depends on the mode + * parameter given to the srf02_trigger function + */ +uint16_t srf02_read(srf02_t *dev); + +/** + * @brief Get the distance measured from the SRF02 ultrasonic sensor + * + * This function combines the srf02_trigger and the srf02_read functions for + * simplified usage in simple (single sensor) setups. + * * @param[in] dev device descriptor of an SRF02 sensor * @param[in] mode there are three real ranging modes, which return * the result in inches, centimeters or microseconds. diff --git a/drivers/srf02/srf02.c b/drivers/srf02/srf02.c index d357851e0f..dc7265ff79 100644 --- a/drivers/srf02/srf02.c +++ b/drivers/srf02/srf02.c @@ -31,11 +31,6 @@ #define ENABLE_DEBUG (0) #include "debug.h" -/** - * @brief The datasheet tells us, that ranging takes 70ms - */ -#define RANGE_DELAY (70000U) - /** * @brief Per default use normal speed on the I2C bus */ @@ -78,6 +73,7 @@ int srf02_init(srf02_t *dev, i2c_t i2c, uint8_t addr) /* try to read the software revision (read the CMD reg) from the device */ i2c_read_reg(i2c, dev->addr, REG_CMD, &rev); if (rev == 0 || rev == 255) { + i2c_release(dev->i2c); DEBUG("[srf02] error reading the devices software revision\n"); return -1; } else { @@ -90,18 +86,18 @@ int srf02_init(srf02_t *dev, i2c_t i2c, uint8_t addr) return 0; } -uint16_t srf02_get_distance(srf02_t *dev, srf02_mode_t mode) +void srf02_trigger(srf02_t *dev, srf02_mode_t mode) { - char res[2]; - /* trigger a new measurement by writing the mode to the CMD register */ DEBUG("[srf02] trigger new reading\n"); i2c_acquire(dev->i2c); i2c_write_reg(dev->i2c, dev->addr, REG_CMD, mode); i2c_release(dev->i2c); +} - /* give the sensor the required time for sampling */ - xtimer_usleep(RANGE_DELAY); +uint16_t srf02_read(srf02_t *dev) +{ + char res[2]; /* read the results */ i2c_acquire(dev->i2c); @@ -113,6 +109,16 @@ uint16_t srf02_get_distance(srf02_t *dev, srf02_mode_t mode) return ((((uint16_t)res[0]) << 8) | (res[1] & 0xff)); } +uint16_t srf02_get_distance(srf02_t *dev, srf02_mode_t mode) +{ + /* trigger a new reading */ + srf02_trigger(dev, mode); + /* give the sensor the required time for sampling */ + xtimer_usleep(SRF02_RANGE_DELAY); + /* get the results */ + return srf02_read(dev); +} + void srf02_set_addr(srf02_t *dev, uint8_t new_addr) { /* get access to the bus */ diff --git a/tests/driver_srf02/README.md b/tests/driver_srf02/README.md index 4a4bdeb6f3..5581a38c09 100644 --- a/tests/driver_srf02/README.md +++ b/tests/driver_srf02/README.md @@ -2,9 +2,50 @@ This is a manual test application for the SRF02 ultrasonic ranger driver. # Usage +First you always need to initialize the sensor using the `init` shell command +and the devices address in right-aligned, decimal format (as specified in the +reference manual), e.g.: `init 224`. +If successful (the shell will tell you...), you can sample distance data from +the device, either once (`shoot`) or continuously every second (`sample`). -After initialization, the sensor value is read periodically and printed to the STDOUT. +This test application also allows to re-program the I2C address of SRF02 +devices. For this initialize the device with its current address and then change +to the new address using the `addr` shell command (e.g. `addr 228`). After +calling the `addr` command, this application will automatically re-initialize +the device with the new address, so it is usable right away. Refer to the +datasheet for more information on usable addresses. -To verify the seen value you can focus the sensor against any reflecting object and vary the distance to -see the value changing. +The following sequence shows how to re-program a device. The initial address is +`224`, the new address after the sequence is `228`: + +``` +2016-03-21 15:53:34,049 - INFO # > init 224 +2016-03-21 15:53:34,054 - INFO # Initializing SRF02 sensor at I2C_DEV(0), address is 224 +2016-03-21 15:53:34,079 - INFO # ... [Ok] +2016-03-21 15:53:34,079 - INFO # +shoot +2016-03-21 15:53:37,339 - INFO # > shoot +2016-03-21 15:53:37,411 - INFO # distance = 94 cm +addr 228 +2016-03-21 15:53:41,468 - INFO # > addr 228 +2016-03-21 15:53:41,472 - INFO # Set address to 228 +shoot +2016-03-21 15:53:42,454 - INFO # > shoot +2016-03-21 15:53:42,527 - INFO # distance = 94 cm +init 224 +2016-03-21 15:53:48,933 - INFO # > init 224 +2016-03-21 15:53:48,938 - INFO # Initializing SRF02 sensor at I2C_DEV(0), address is 224 +2016-03-21 15:53:48,962 - INFO # ... [Failed] +shoot +2016-03-21 15:53:50,568 - INFO # > shoot +2016-03-21 15:53:50,641 - INFO # distance = 29703 cm +init 228 +2016-03-21 15:53:53,084 - INFO # > init 228 +2016-03-21 15:53:53,089 - INFO # Initializing SRF02 sensor at I2C_DEV(0), address is 228 +2016-03-21 15:53:53,113 - INFO # ... [Ok] +2016-03-21 15:53:53,113 - INFO # +shoot +2016-03-21 15:53:54,201 - INFO # > shoot +2016-03-21 15:53:54,274 - INFO # distance = 94 cm +``` diff --git a/tests/driver_srf02/main.c b/tests/driver_srf02/main.c index 6e6f71e4fb..8405e132f1 100644 --- a/tests/driver_srf02/main.c +++ b/tests/driver_srf02/main.c @@ -40,15 +40,10 @@ static srf02_t dev; -static void sample_loop(void) +static void sample(void) { - uint32_t wakeup = xtimer_now(); - - while(1) { - uint16_t distance = srf02_get_distance(&dev, TEST_MODE); - printf("distance = %3i cm\n", distance); - xtimer_usleep_until(&wakeup, SAMPLE_PERIOD); - } + uint16_t distance = srf02_get_distance(&dev, TEST_MODE); + printf("distance = %3i cm\n", distance); } static int cmd_init(int argc, char **argv) @@ -62,7 +57,7 @@ static int cmd_init(int argc, char **argv) uint8_t addr = (uint8_t)atoi(argv[1]); - printf("Initializing SRF02 sensor at I2C_DEV(%i), address is 0x%02x\n... ", + printf("Initializing SRF02 sensor at I2C_DEV(%i), address is %i\n... ", TEST_SRF02_I2C, (int)addr); res = srf02_init(&dev, TEST_SRF02_I2C, addr); if (res < 0) { @@ -79,8 +74,22 @@ static int cmd_sample(int argc, char **argv) { (void)argc; (void)argv; - sample_loop(); + uint32_t wakeup = xtimer_now(); + while(1) { + sample(); + xtimer_usleep_until(&wakeup, SAMPLE_PERIOD); + } + + return 0; +} + +static int cmd_shoot(int argc, char **argv) +{ + (void)argc; + (void)argv; + + sample(); return 0; } @@ -95,13 +104,14 @@ static int cmd_set_addr(int argc, char **argv) new_addr = (uint8_t)atoi(argv[1]); srf02_set_addr(&dev, new_addr); - printf("Set address to %i (0x%02x)\n", (int)new_addr, (int)new_addr); + printf("Set address to %i\n", (int)new_addr); return 0; } static const shell_command_t shell_commands[] = { { "init", "initialize a device", cmd_init }, { "sample", "start sampling", cmd_sample }, + { "shoot", "get a single sample", cmd_shoot }, { "addr", "reprogram the devices address", cmd_set_addr }, { NULL, NULL, NULL } }; @@ -109,8 +119,15 @@ static const shell_command_t shell_commands[] = { int main(void) { puts("\nSRF02 Ultrasonic Range Sensor Test\n"); - puts("This test will sample the sensor once per second and display the\n" - "result\n"); + puts("Use the following flow to test your device/setup. First you need to\n" + "initialize your device (e.g. 'init 224'). Next you can sample your \n" + "device continuously ('sample'), or get one value ('shoot').\n\n" + "This application let's you also reprogram your device's I2C" + "address:\n" + " 1. initialize your device -> e.g. 'init 224'\n" + " 2. specify the new address -> e.g.'addr 228'\n" + "The device will be programmed with the new address and it is\n" + "re-initialized with the new address, so you can use it right away\n"); char line_buf[SHELL_DEFAULT_BUFSIZE]; shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE);