Menu

SRF02 Ultrasonic module - I2C library

Peter
2014-11-07
2014-12-01
  • Peter

    Peter - 2014-11-07

    Hello,

    I've been working on a library for the SRF02 ultrasonic ranging module for a few weeks now. I've tested it as far as I can so I am posting it here for anyone else to use and hoping that someone else will be able to test it. I have been using a 16F914 with version 0.93 of the software I2C library for testing.

    Technical details of the module are here: http://www.robot-electronics.co.uk/htm/srf02tech.htm

    There are some notes at the top of the header file which give a list of the functions that are included which covers everything except resetting the automatic calibration.

    I have also posted a demo program which shows off the main features.

    I have been unable to change the bus address of the device. I have tried a few things and nothing seems to have worked so if anyone can give me some pointers with that I'd be grateful, as it would allow me to test the 'Fake range' and the 'Ping' functions properly.

     
  • Peter

    Peter - 2014-11-07

    Code Listing:

    '   LIBRARY FOR SRF02 ULTRASONIC SENSOR MODULE IN I2C MODE
    '   V0.1 Peter Everett 07/11/2014
    
    '   The SRF02 is a small ultrasonic transeiver with built in calibration and measurement processing
    '   It can be accessed using I2C or SPI (This library is for the I2C mode)
    '   The module has a typical range from 16 cm to 6 m
    '   Information on the module can be found here http://www.robot-electronics.co.uk/htm/srf02tech.htm
    
    '   FUNCTION LIST AND STATUS
    
    '   SRF_Measure           Tested in cm and inches Oct 2014.  uS gives a result so assumed correct.
    '   SRF_FakeMeasure     Untested.  No means to transmit another synchronised burst
    '   SRF_Ping                Part tested Oct 2014.  LED flashes but no means to listen for a reply
    '   SRF_GetResult         Tested Oct 2014
    '   SRF_GetCalib          Tested Nov 2014
    '   SRF_SWVer               Tested Nov 2014
    '   SRF_ChangeAddr      Doesn't work.  Not figured out why so function disabled by default
    '   
    
    'variables
    dim SRF_ver as byte     'Software version
    dim SRF_units as byte   'Units of the measurement
    dim SRF_cmd as byte     'Command to be sent to the module
    dim SRF_rngH as byte    'High byte of the mesurement result
    dim SRF_rngL as byte    'Low byte of the measurement result
    dim SRF_Result as word  '16 bit word for the measurement result
    dim SRF_Calib as word     '16 bit word for the calibration value (minimum distance that can be measured)
    
    Sub SRF_Measure (in SRF_units, optional SRF_Base as byte = 0xE0)
        'Send a pulse and take a measurement
        'SRF_units determines the units of the measurement
        '0 = Inches
        '1 = Centimetres
        '2 = Microseconds
        'The unit will be stored after the reading and can be read by the main program e.g. for adding to the display
        'Taking a reading will blink the LED on the module
    
        Select case SRF_units
        case 0
          SRF_cmd = 0x50
        case 1
          SRF_cmd = 0x51
        case 2
          SRF_cmd = 0x52
        case else
          'this is an 'error' condition if an invalid unit is specified
          SRF_units = 255
        end select
    
        'send the command
        'the result is stored on the chip and must be read back by the main program using the SRF_GetResult function
        I2CStart
        I2CSend SRF_Base      'device in write mode
        I2CSend 0             'register 0 ('command' register)
        I2CSend SRF_cmd       'send command
        I2CStop
    End Sub
    
    Sub SRF_FakeMeasure (in SRF_units, optional SRF_Base as byte = 0xE0)
        'Take a measurement but don't send a pulse
        'This is used if another transmitter sends the pulse and the module is to listen for it.  The send/receive need to be synchronised.
        'SRF_units determines the units of the measurement
        '0 = Inches
        '1 = Centimetres
        '2 = Microseconds
        'The unit will be stored after the reading and can be read by the main program e.g. for adding to the display
        'Taking a reading will blink the LED on the module
        'The code for this function is the same as for SRF_Measure apart from the values of the command that is issued
    
        Select case SRF_units
        case 0
          SRF_cmd = 0x56
        case 1
          SRF_cmd = 0x57
        case 2
          SRF_cmd = 0x58
        case else
          'this is an 'error' condition if an invalid unit is specified
          SRF_units = 255
        end select
    
        'send the command
        'the result is stored on the chip and must be read back by the main program using the SRF_GetResult function
        I2CStart
        I2CSend SRF_Base    'device in write mode
        I2CSend 0           'register 0 ('command' register)
        I2CSend SRF_cmd     'send command
        I2CStop
    End Sub
    
    Sub SRF_Ping (optional SRF_Base as byte = 0xE0)
        'Send a pulse but doesn't take a measurement
        'Sending a pulse will blink the LED on the module
    
        'send the command
        I2CStart
        I2CSend SRF_Base    'device in write mode
        I2CSend 0           'register 0 ('command' register)
        I2CSend 0x5C          'send command
        I2CStop
    End Sub
    
    Sub SRF_GetResult (optional SRF_Base as byte = 0xE0)
      'Reads the result of the last measurement and stores in the SRF_Result variable
      'The units of the measurement are whatever was set in the SRF_Measure command
        I2CStart
        I2CSend SRF_Base          'device in write mode
        I2CSend 2                 'register 2 (start of the measurement registers)
    
        I2CRestart
        I2CSend (SRF_Base + 1)    'device in read mode
        I2CReceive SRF_rngH         'read high byte
        I2CReceive SRF_rngL, nack 'read low byte
        I2CStop
    
        'Combine the high and low bytes to give a 16 bit word as a result
        SRF_Result = (SRF_rngH * 255) + SRF_rngL
    End Sub
    
    Sub SRF_GetCalib (optional SRF_Base as byte = 0xE0)
        'Reads the auto tune result
        'The units of this measurement are the same as the last ranging measurement
        'Therefore this only works if a measurement has been taken
        'The datasheet says that 5-6 measurements need to be taken for the tuning to be completed
        'The code for this function is the same as SRF_GetResult apart from the register location
    
        I2CStart
        I2CSend SRF_Base          'device in write mode
        I2CSend 4                 'register 4 (start of the autotune registers)
    
        I2CRestart
        I2CSend (SRF_Base + 1)        'device in read mode
        I2CReceive SRF_rngH           'read high byte
        I2CReceive SRF_rngL, nack   'read low byte
        I2CStop
    
        'Combine the high and low bytes to give a 16 bit word as a result
        SRF_Calib = (SRF_rngH * 255) + SRF_rngL
    
    End Sub
    
    Sub SRF_SWVer (optional SRF_Base as byte = 0xE0)
        'Reads the software version from the module
    
        I2CStart
        I2CSend SRF_Base          'device in write mode
        I2CSend 1                 'register 1 (start of the autotune registers)
    
        I2CRestart
        I2CSend (SRF_Base + 1)    'device in read mode
        I2CReceive SRF_ver          'read software version
        I2CStop
    
    End Sub
    
    Sub SRF_ChangeAddr (SRF_OldBase, SRF_NewBase)
        'Changes the bus address of the sensor from SRF_OldBase to SRF_NewBase
        'The address is changed by writing values 0xA0 0xA5 and 0xAA to the command register, followed by the new address.
        'The address for the module is 'flashed' on the LED when it is powered up
        'Only the following addresses can be used with the module: E0 (default), E2, E4, E6, E8, EA, EC, EE, F0, F2, F4, F6, F8, FA, FC, FE 
    
        'At present this function doesn't seem to work so it is disabled
        Exit Sub
    
        'check the new address is valid
        If SRF_NewBase > 0xFE then
            Print "Invalid address 1"
            Exit Sub
        End If
        If SRF_NewBase < 0xE0 then
            Print "Invalid address 2"
            Exit Sub
        End If
        'If (SRF_NewBase % 2) = 1 then      ''compiler doesn't recognise % as modulus?
        '   Exit Sub
        'End If
    
        'Output to LCD to verify address
        CLS
        Print "New address: "
        Print SRF_NewBase
        Exit Sub
    
        'Address is valid, continue
        I2CStart
        I2CSend SRF_OldBase     'device in write mode
        I2CSend 0               'register 0 ('command' register)
        I2CSend 0xA0              'send first command
        I2CStop
        I2CStart
        I2CSend SRF_OldBase     'device in write mode
        I2CSend 0               'register 0 ('command' register)
        I2CSend 0xA5              'send second command
        I2CStop
        I2CStart
        I2CSend SRF_OldBase     'device in write mode
        I2CSend 0               'register 0 ('command' register)
        I2CSend 0xAA              'send third command
        I2CStop
        I2CStart
        I2CSend SRF_OldBase     'device in write mode
        I2CSend 0               'register 0 ('command' register)
        I2CSend SRF_NewBase     'send new address
        I2CStop
    
    End Sub
    
     

    Last edit: Peter 2014-11-07
  • Peter

    Peter - 2014-11-07

    Example program:

    Displays the module software version, takes some measurements then reports the calibration data.

    Results are displayed on a 2x16 LCD module.

    ;Chip Settings
    #chip 16F914,8
    #config CP=OFF, MCLRE=ON, PWRTE=ON, WDT=OFF, OSC=INTRC_OSC_NOCLKOUT
    
    ;Include files (Libraries)
    #include <SRF02.h>
    
    ;Defines (Constants)
    #define LCD_IO 8
    #define LCD_RW PORTD.6
    #define LCD_RS PORTD.7
    #define LCD_Enable PORTD.5
    #define LCD_DATA_PORT PORTB
    #define I2C_MODE Master
    #define I2C_DISABLE_INTERRUPTS ON
    #define I2C_DATA PORTC.7
    #define I2C_CLOCK PORTC.6
    
    ;Variables
    Dim i As byte
    Dim j As byte
    Dim unit As string
    
    SRF02_Demo_1
    Wait 1 s
    SRF02_Demo_2
    Wait 1 s
    SRF02_Demo_3
    Wait 1 s
    CLS
    Print "Finished!"
    
    Sub SRF02_Demo_1
        'Read the software version and save in the SRF_ver variable
        SRF_SWVer 0xE0
    
        'Display on the LCD
        CLS
        Print "Software version"
        Locate 1,0
        Print SRF_ver
    End Sub
    
    Sub SRF02_Demo_2
        For i = 0 to 2
            '0 = inches, 1 = cm, 2 = us
            'determine the unit for displaying
            Select Case i
            Case 0
            unit = "in."
            Case 1
            unit = "cm"
            Case 2
            unit = "us"
            End Select
            For j = 1 to 100
    
                'Repeat 100 times
                'Take a measurement and save in the device
                SRF_Measure i, 0xE0
    
                'Read the result from the device and saves in the SRF_Result variable
                SRF_GetResult 0xE0
    
                'Output to the LCD
                CLS
                Print "SRF_Measure "
                Print i
                print " "
                Locate 1,0
                Print SRF_Result
                Print " "
                Print unit
                Wait 100 ms
            Next
        Next
    End Sub
    
    Sub SRF02_Demo_3
        'Set the unit to cm by making a measurement
        SRF_Measure 1, 0xE0
    
        'Wait for this to complete (takes around 66 ms)
        Wait 70 ms
    
        'Read the result and save in the SRF_Calib variable
        SRF_GetCalib 0xE0
    
        'Output to the LCD
        CLS
        Print "Calibration value"
        Locate 1,0
        Print SRF_Calib
        Print " cm"
    End Sub
    
     

    Last edit: Peter 2014-11-07
  • Anobium

    Anobium - 2014-11-09

    @Peter. Very nice.

    May I include this good work in the next release of GCB?

    This is a good addition to the portfolio!

     
  • Peter

    Peter - 2014-11-17

    Yes, no problem including it.

    Hopefully a few more people will play around with it and test it. Being unable to change the module address is a bit of a limitation.

     
  • Peter

    Peter - 2014-11-30

    I have updated my SRF02.h library to version 0.2. Changes are:
    - SRF_ChangeAddr now works and allows the I2C bus address to be changed which allows multiple sensors to be used
    - SRF_Ping and SRF_FakeMeasure have been tested as best as I can and you seem to be able to detect a ping from one sensor on another.

    The new file is attached. There's hardly any change from version 0.1.

     
  • Anobium

    Anobium - 2014-12-01

    @Peter. Thank you again. Can we publish as part of the next GCB release? I will add headers etc. for you.

     
  • Peter

    Peter - 2014-12-01

    Go for it.

    If I find any more bugs in it beforehand I will let you know.

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.