diff --git a/drivers/include/srf02.h b/drivers/include/srf02.h index 82f3506e0c..275ac48637 100644 --- a/drivers/include/srf02.h +++ b/drivers/include/srf02.h @@ -34,7 +34,7 @@ extern "C" { /** * @brief Default I2C address of SRF02 sensors */ -#define SRF02_DEFAULT_ADDR 112 +#define SRF02_DEFAULT_ADDR (0xe0) /** * @brief Device descriptor for SRF02 sensors @@ -85,6 +85,14 @@ int srf02_init(srf02_t *dev, i2c_t i2c, uint8_t addr); */ uint16_t srf02_get_distance(srf02_t *dev, srf02_mode_t mode); +/** + * @brief Program the given device with a new bus address + * + * @param[in] dev device to program + * @param[in] new_addr new address to program the given device to + */ +void srf02_set_addr(srf02_t *dev, uint8_t new_addr); + #ifdef __cplusplus } #endif diff --git a/drivers/srf02/srf02.c b/drivers/srf02/srf02.c index 953cdd7cf7..d357851e0f 100644 --- a/drivers/srf02/srf02.c +++ b/drivers/srf02/srf02.c @@ -28,7 +28,7 @@ #include "srf02.h" #include "periph/i2c.h" -#define ENABLE_DEBUG (0) +#define ENABLE_DEBUG (0) #include "debug.h" /** @@ -52,10 +52,20 @@ #define REG_AUTO_LOW (0x05) /** @} */ +/** + * @brief Some additional SRF02 commands + * @{ + */ +#define CMD_ADDR_SEQ1 (0xa0) +#define CMD_ADDR_SEQ2 (0xaa) +#define CMD_ADDR_SEQ3 (0xa5) +/** @} */ + + int srf02_init(srf02_t *dev, i2c_t i2c, uint8_t addr) { dev->i2c = i2c; - dev->addr = addr; + dev->addr = (addr >> 1); /* internally we right align the 7-bit addr */ char rev; /* Acquire exclusive access to the bus. */ @@ -66,7 +76,7 @@ int srf02_init(srf02_t *dev, i2c_t i2c, uint8_t addr) return -1; } /* try to read the software revision (read the CMD reg) from the device */ - i2c_read_reg(i2c, addr, REG_CMD, &rev); + i2c_read_reg(i2c, dev->addr, REG_CMD, &rev); if (rev == 0 || rev == 255) { DEBUG("[srf02] error reading the devices software revision\n"); return -1; @@ -102,3 +112,21 @@ uint16_t srf02_get_distance(srf02_t *dev, srf02_mode_t mode) /* compile result - TODO: fix for different host byte order other than LE */ return ((((uint16_t)res[0]) << 8) | (res[1] & 0xff)); } + +void srf02_set_addr(srf02_t *dev, uint8_t new_addr) +{ + /* get access to the bus */ + i2c_acquire(dev->i2c); + + DEBUG("[srf02] reprogramming device address to 0x%02x\n", (int)new_addr); + + /* write the new address, for this we need to follow a certain sequence */ + i2c_write_reg(dev->i2c, dev->addr, REG_CMD, CMD_ADDR_SEQ1); + i2c_write_reg(dev->i2c, dev->addr, REG_CMD, CMD_ADDR_SEQ2); + i2c_write_reg(dev->i2c, dev->addr, REG_CMD, CMD_ADDR_SEQ3); + i2c_write_reg(dev->i2c, dev->addr, REG_CMD, new_addr); + dev->addr = (new_addr >> 1); + + /* release the bus */ + i2c_release(dev->i2c); +} diff --git a/tests/driver_srf02/Makefile b/tests/driver_srf02/Makefile index 19548d23a0..54fdfd4f5d 100644 --- a/tests/driver_srf02/Makefile +++ b/tests/driver_srf02/Makefile @@ -5,6 +5,7 @@ FEATURES_REQUIRED = periph_i2c USEMODULE += xtimer USEMODULE += srf02 +USEMODULE += shell # set default device parameters in case they are undefined TEST_SRF02_I2C ?= I2C_0 diff --git a/tests/driver_srf02/main.c b/tests/driver_srf02/main.c index ec0ff502fa..6e6f71e4fb 100644 --- a/tests/driver_srf02/main.c +++ b/tests/driver_srf02/main.c @@ -21,6 +21,14 @@ * @} */ +#include +#include +#include + +#include "shell.h" +#include "xtimer.h" +#include "srf02.h" + #ifndef TEST_SRF02_I2C #error "TEST_SRF02_I2C not defined" #endif @@ -28,26 +36,35 @@ #error "TEST_MODE not defined" #endif -#include +#define SAMPLE_PERIOD (100 * 1000U) -#include "xtimer.h" -#include "srf02.h" -#include "periph/i2c.h" +static srf02_t dev; -#define SAMPLE_PERIOD (1000 * 1000U) - -int main(void) +static void sample_loop(void) { - int res; - srf02_t dev; uint32_t wakeup = xtimer_now(); - puts("\nSRF02 Ultrasonic Range Sensor Test\n"); - puts("This test will sample the sensor once per second and display the\n" - "result\n"); + while(1) { + uint16_t distance = srf02_get_distance(&dev, TEST_MODE); + printf("distance = %3i cm\n", distance); + xtimer_usleep_until(&wakeup, SAMPLE_PERIOD); + } +} - printf("Initializing SRF02 sensor at I2C_%i... ", TEST_SRF02_I2C); - res = srf02_init(&dev, TEST_SRF02_I2C, SRF02_DEFAULT_ADDR); +static int cmd_init(int argc, char **argv) +{ + int res; + + if (argc < 2) { + printf("usage: %s \n", argv[0]); + return 1; + } + + uint8_t addr = (uint8_t)atoi(argv[1]); + + printf("Initializing SRF02 sensor at I2C_DEV(%i), address is 0x%02x\n... ", + TEST_SRF02_I2C, (int)addr); + res = srf02_init(&dev, TEST_SRF02_I2C, addr); if (res < 0) { puts("[Failed]"); return 1; @@ -55,10 +72,46 @@ int main(void) else { puts("[Ok]\n"); } - - while(1) { - xtimer_usleep_until(&wakeup, SAMPLE_PERIOD); - uint16_t distance = srf02_get_distance(&dev, TEST_MODE); - printf("distance = %i cm\n", distance); - } + return 0; +} + +static int cmd_sample(int argc, char **argv) +{ + (void)argc; + (void)argv; + sample_loop(); + + return 0; +} + +static int cmd_set_addr(int argc, char **argv) +{ + uint8_t new_addr; + + if (argc < 2) { + printf("usage: %s \n", argv[0]); + return 1; + } + + 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); + return 0; +} + +static const shell_command_t shell_commands[] = { + { "init", "initialize a device", cmd_init }, + { "sample", "start sampling", cmd_sample }, + { "addr", "reprogram the devices address", cmd_set_addr }, + { NULL, NULL, NULL } +}; + +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"); + + char line_buf[SHELL_DEFAULT_BUFSIZE]; + shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE); }