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

Dependents:   DISCO-F746NG_LCDTS_demo Srf08Test

/media/uploads/brentdekker/ultrasonic-range-finder-srf08.jpg

SRF08

Warning

Don't forget to add the pullup resistors from 5v to SDA and SCL!

Information on the SRF08 can be found here: http://www.robot-electronics.co.uk/htm/srf08tech.shtml

Example program

#include "mbed.h"
#include "SRF08.h"

Serial PC(USBTX, USBRX);       //Debug port to PC
SRF08 rangeMod1(p28, p27, 0xE4); //SRF08 ranging module 1
SRF08 rangeMod2(p28, p27, 0xE2); //SRF08 ranging module 2

int main() {
    PC.printf("Start ranging test \n");
    rangeMod1.setAddress(0xE4); //Factory default is 0xE0
    while(1) {
        rangeMod1.startRanging();
        while (!rangeMod1.rangingFinished() ) wait(0.01);
        int range1 = rangeMod1.getRange();
        int light1 = rangeMod1.getLightIntensity();
        rangeMod2.startRanging();
        while (!rangeMod2.rangingFinished() ) wait(0.01);
        int range2 = rangeMod2.getRange();
        PC.printf(" Range_1: %i", range1);
        PC.printf(" Range_2: %i", range2);
        PC.printf(" Light_1: %i", light1);
        PC.printf("\n");
    }
}

Library

Import library

Public Member Functions

SRF08 (PinName SDA, PinName SCL, int i2cAddress)
Create a SRF08 object connected to the specified I2C pins and address.
void startRanging ()
Send the "Start ranging in cm" command via I2C.
bool rangingFinished ()
Checks if the module has finished ranging.
int getRange ()
Gets the measured range from the module.
int getLightIntensity ()
Gets the measured light intensity from the module.
void setRangeRegister (unsigned char rangeVal)
Sets the range register of the SRF08 for faster ranging.
void setMaxGainRegister (unsigned char gainVal)
Sets the max gain register of the SRF08 .
void setAddress (int i2cAddress)
Changes the I2C address of the SRF08 .
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