Library for interfacing the SRF08 ultrasonic range sensor. Most functions of the SRF08 are covered, including interrupt-based waiting for the ranging process to finish
Fork of SRF08 by
Diff: SRF08.cpp
- Revision:
- 2:ca82f89f415d
- Parent:
- 1:76fb116fa28d
- Child:
- 3:c43cd24ec7e7
--- a/SRF08.cpp Tue Jul 10 08:48:02 2012 +0000 +++ b/SRF08.cpp Wed Jul 11 07:53:50 2012 +0000 @@ -1,6 +1,5 @@ - /* -Copyright (c) 2010 Chris Styles ( chris dot styles at mbed dot org ) +Copyright (c) 2012 Brent Dekker Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -25,31 +24,16 @@ /* * Constructor: SRF08 - * Args: PinName sda: Data pin of I2C bus to which module is connected - * PinName scl: Clock pin of I2C bus to which module is connected - * int addr: address of module on the I2C bus + * Args: * Returns: void * Description: Creates an instance of the SRF08 to communicate with a sRF08 module */ -SRF08::SRF08(PinName sda, PinName scl, int addr) : - m_i2c(sda, scl), m_addr(addr), rangeBuf(), rangeBufIndex(0) { - char cmd[2]; - // Set up SRF08 max range and receiver sensitivity over I2C bus - cmd[0] = 0x02; // Range register - cmd[1] = 0xFF; - m_i2c.write(m_addr, cmd, 2); - cmd[0] = 0x01; // Receiver gain register - cmd[1] = 0x1F; // Set max receiver gain - m_i2c.write(m_addr, cmd, 2); -} - -/* - * Destructor: ~SRF08 - * Args: void - * Returns: void - * Description: Destroys instance of SRF08 class - */ -SRF08::~SRF08() { +SRF08::SRF08(PinName SDA, PinName SCL, int i2cAddress) : + i2cMod(SDA, SCL), + i2cAddress(i2cAddress), + rangeTimeout(), + rangingBusy(false), + debugPC(USBTX, USBRX) { } @@ -59,11 +43,14 @@ * Returns: void * Description: Sends command to module to start ranging. */ -void startRanging() { - // Send Tx burst command over I2C bus - cmd[0] = 0x00; // Command register - cmd[1] = 0x51; // Ranging results in cm - m_i2c.write(m_addr, cmd, 2); // Send ranging burst +void SRF08::startRanging() { + //Create a two byte command. The first first byte is the register address + // on the SRF08 to write to. The second byte is the command which is written + // to that address ("Start ranging in cm" in this case). + const char command[] = {0x00, 0x51}; + i2cMod.write(i2cAddress, command, 2); + this->rangingBusy = true; + rangeTimeout.attach(this, &SRF08::setRangingFinished, 0.07); } /* @@ -72,12 +59,8 @@ * Returns: Bool: whether ranging is finished * Description: Checks if the ranging process on the module is finished */ -bool rangingFinished() { - char cmd = 0x00; //Software revision register - char echo; - m_i2c.write(m_addr, cmd, 1, 1); //Send address of software rev register - m_i2c.read(m_addr, echo, 1); //Read 1 byte echo result - if (echo == 0xFF) return false; +bool SRF08::rangingFinished() { + if(this->rangingBusy) return false; return true; } @@ -87,63 +70,31 @@ * Returns: int range * Description: Range in cm. This function should only be called when ranging is finished, otherwise previous value is returned */ -void getRange() { - char cmd[2]; - char echo[2]; - // Read range over I2C bus - cmd[0] = 0x02; // Address of first echo - m_i2c.write(m_addr, cmd, 1, 1); // Send address of first echo - m_i2c.read(m_addr, echo, 2); // Read two-byte echo result - // Generate PWM mark/space ratio from range data - int range = (echo[0]<<8)+echo[1]; - return range; +int SRF08::getRange() { + //while (!rangingFinished() ) wait(0.01); //Wait until ranging is finished + const char command[] = {0x02}; //Address of range register + char response[] = {0x00, 0x00}; + i2cMod.write(i2cAddress, command, 1, 1); //Send command + i2cMod.read(i2cAddress, response, 2); //Read 16bits result + int range = (response[0]<<8)+response[1]; //Shift two bytes into int + return range; //Return int range } /* - * Function: readRange + * Function: readLightIntensity * Args: void - * Returns: int range - * Description: Reads the range register and converts it to a usable value + * Returns: int lightIntensity + * Description: Reads the lightIntensity from the module + * The light intensity is updated if a range command is sent, so don't use + * this function only */ -int SRF08::readRange() { - char cmd[2]; - char echo[2]; - - // Get range data from SRF08 - // Send Tx burst command over I2C bus - cmd[0] = 0x00; // Command register - cmd[1] = 0x51; // Ranging results in cm - m_i2c.write(m_addr, cmd, 2); // Send ranging burst - - wait(0.07); // Wait for return echo - - // Read back range over I2C bus - cmd[0] = 0x02; // Address of first echo - m_i2c.write(m_addr, cmd, 1, 1); // Send address of first echo - m_i2c.read(m_addr, echo, 2); // Read two-byte echo result - - // Generate PWM mark/space ratio from range data - int range = (echo[0]<<8)+echo[1]; - - return range; -} - -/* - * Function: readBufRange - * Args: void - * Returns: int range - * Description: Reads the range register, adds it to an array and converts it to a filtered value - */ -//int SRF08::readBufRange() { - -//} - -int SRF08::getAverageBufRange() { - int total = 0; - for (int i = 0; i < RANGEBUFSIZE; i++) { - total += rangeBuf[i]; - } - return (int)total/RANGEBUFSIZE; +int SRF08::getLightIntensity() { + const char command[] = {0x01}; //Light intensity register + char response[] = {0x00}; + i2cMod.write(i2cAddress, command, 1, 1); //Send command + i2cMod.read(i2cAddress, response, 1); //Read response + int lightIntensity = response[0]; + return lightIntensity; } /* @@ -154,11 +105,18 @@ * The range is ((rangeVal x 43mm) + 43mm) * The max range is about six meters */ -void SRF08::setRangeRegister(char rangeVal) { - char cmd[2]; - cmd[0] = 0x02; //Range register - cmd[1] = rangeVal; //Range value - m_i2c.write(m_addr, cmd, 2); +void SRF08::setRangeRegister(unsigned char rangeVal) { + while (!rangingFinished() ) wait(0.01); //Wait until ranging is finished + char command[] = {0x02, rangeVal}; //Range register + i2cMod.write(i2cAddress, command, 2); //Send command +} + + +//Function setMaxGainRegister +void SRF08::setMaxGainRegister(unsigned char gainVal) { + while (!rangingFinished() ) wait(0.01); //Wait until ranging is finished + char command[] = {0x01, gainVal}; //Max gain register + i2cMod.write(i2cAddress, command, 2); //Send command } /* @@ -169,37 +127,21 @@ * The address can have the following values: * E0 | E2 | E4 | E6 ... FC | FE */ -void SRF08::setAddress(char address) { - char cmd[2]; - cmd[0] = 0x00; - cmd[1] = 0xA0; - m_i2c.write(m_addr, cmd, 2); - cmd[1] = 0xAA; - m_i2c.write(m_addr, cmd, 2); - cmd[1] = 0xA5; - m_i2c.write(m_addr, cmd, 2); - cmd[1] = address; - m_i2c.write(m_addr, cmd, 2); - m_addr = address; +void SRF08::setAddress(int address) { + //Send address change sequence + char command[] = {0x00, 0xA0}; + i2cMod.write(i2cAddress, command, 2); + command[1] = 0xAA; + i2cMod.write(i2cAddress, command, 2); + command[1] = 0xA5; + i2cMod.write(i2cAddress, command, 2); + command[1] = address; + i2cMod.write(i2cAddress, command, 2); + //Save the updated address + i2cAddress = address; } -/* - * Function: readLightIntensity - * Args: void - * Returns: int lightIntensity - * Description: Reads the lightIntensity from the module - * The light intensity is updated if a range command is sent, so don't use - * this function only - */ -int SRF08::readLightIntensity() { - char cmd[1]; - char echo[1]; - - cmd[0] = 0x01; // Address of light intensity value - m_i2c.write(m_addr, cmd, 1, 1); // Send address of first echo - m_i2c.read(m_addr, echo, 2); // Read two-byte echo result - - int lightIntensity = echo[0]; - - return lightIntensity; -} +//Small helper function +void SRF08::setRangingFinished() { + this->rangingBusy = false; +} \ No newline at end of file