본문 바로가기

Sensor/sonic

SRF02 초음파센서




SRF02 Ultrasonic range finder 
Technical Specification

I2C Mode
For Serial mode click here

I2C Communication
To use the SRF02 in I2C mode, make sure nothing is connected to the mode pin, it must be left unconnected.
The I2C bus is available on popular controllers such as the OOPic, Stamp BS2p, PicAxe etc. as well as a wide variety of micro-controllers. To the programmer the SRF02 behaves in the same way as the ubiquitous 24xx series EEPROM's, except that the I2C address is different. The default shipped address of the SRF02 is 0xE0. It can bechanged by the user to any of 16 addresses E0, E2, E4, E6, E8, EA, EC, EE, F0, F2, F4, F6, F8, FA, FC or FE, therefore up to 16 sonar's can be used.

Connections
The connections to the SRF02 are identical to the SRF08 and SRF10 rangers. The "Mode" pin should be left unconnected, it has an internal pull-up resistor. The SCL and SDA lines should each have a pull-up resistor to +5v somewhere on the I2C bus. You only need one pair of resistors, not a pair for every module. They are normally located with the bus master rather than the slaves. The SRF02 is always a slave - never a bus master. If you need them, I recommend 1.8k resistors. Some modules such as the OOPic already have pull-up resistors and you do not need to add any more.  



Registers
 The SRF02 appears as a set of 6 registers.

Location

Read

Write

0

Software Revision

Command Register

1

Unused (reads 0x80)

N/A 

2

Range High Byte

N/A

3

Range Low Byte

N/A

4 Autotune Minimum - High Byte N/A
5 Autotune Minimum - Low Byte N/A

Only location 0 can be written to. Location 0 is the command register and is used to start a ranging session. It cannot be read. Reading from location 0 returns the SRF02 software revision.  The ranging lasts up to 65mS, and the SRF02 will not respond to commands on the I2C bus whilst it is ranging.

Locations, 2 and 3, are the 16bit unsigned result from the latest ranging - high byte first. The meaning of this value depends on the command used, and is either the range in inches, or the range in cm or the flight time in uS. A value of 0 indicates that no objects were detected. Do not initiate a ranging faster than every 65mS to give the previous burst time to fade away.

Locations, 4 and 5, are the 16bit unsigned minimum range. This is the approximate closest range the sonar can measure to. See the Autotune section below for full details. 

Commands
The are three commands to initiate a ranging (80 to 82), to return the result in inches, centimeters or microseconds. Another set of three commands (86 to 88) do the same, but without transmitting the burst. These are used where the burst has been transmitted by another sonar. It is up to you to synchronize the commands to the two sonar's. There is a command (92) to transmit a burst without doing the ranging and also a set of commands to change the I2C address.

Command Action
Decimal Hex
80 0x50 Real Ranging Mode - Result in inches 
81 0x51 Real Ranging Mode - Result in centimeters
82 0x52 Real Ranging Mode - Result in micro-seconds
     
86 0x56 Fake Ranging Mode - Result in inches 
87 0x57 Fake Ranging Mode - Result in centimeters
88 0x58 Fake Ranging Mode - Result in micro-seconds
     
92 0x5C Transmit an 8 cycle 40khz burst - no ranging takes place
     
96 0x60 Force Autotune Restart - same as power-up. You can ignore this command.
     
160 0xA0 1st in sequence to change I2C address
165 0xA5 3rd in sequence to change I2C address
170 0xAA 2nd in sequence to change I2C address

Ranging
To initiate a ranging, write one of the above commands to the command register and wait the required amount of time for completion and read the result. The echo buffer is cleared at the start of each ranging. The ranging lasts up to 66mS, after this the range can be read from locations 2 and 3.

Checking for Completion of Ranging
You do not have to use a timer on your own controller to wait for ranging to finish. You can take advantage of the fact that the SRF02 will not respond to any I2C activity whilst ranging. Therefore, if you try to read from the SRF02 (we use the software revision number a location 0) then you will get 255 (0xFF) whilst ranging. This is because the I2C data line (SDA) is pulled high if nothing is driving it. As soon as the ranging is complete the SRF02 will again respond to the I2C bus, so just keep reading the register until its not 255 (0xFF) anymore. You can then read the sonar data. Your controller can take advantage of this to perform other tasks while the SRF02 is ranging. The SRF02 will always be ready 70mS after initiating the ranging.

LED
The red LED is used to flash out a code for the I2C address on power-up (see below). It also gives a brief flash during the "ping" whilst ranging.

Changing the I2C Bus Address
To change the I2C address of the SRF02 you must have only one sonar on the bus. Write the 3 sequence commands in the correct order followed by the address. Example; to change the address of a sonar currently at 0xE0 (the default shipped address) to 0xF2, write the following to address 0xE0; (0xA0, 0xAA, 0xA5, 0xF2 ). These commands must be sent in the correct sequence to change the I2C address, additionally, No other command may be issued in the middle of the sequence. The sequence must be sent to the command register at location 0, which means 4 separate write transactions on the I2C bus. When done, you should label the sonar with its address, however if you do forget, just power it up without sending any commands. The SRF02 will flash its address out on the LED. One long flash followed by a number of shorter flashes indicating its address. The flashing is terminated immediately on sending a command the SRF02.

Address Long Flash Short flashes
Decimal Hex
224 E0 1 0
226 E2 1 1
228 E4 1 2
230 E6 1 3
232 E8 1 4
234 EA 1 5
236 EC 1 6
238 EE 1 7
240 F0 1 8
242 F2 1 9
244 F4 1 10
246 F6 1 11
248 F8 1 12
250 FA 1 13
252 FC 1 14
254 FE 1 15

Take care not to set more than one sonar to the same address, there will be a bus collision and very unpredictable results.

Note - there is only one module address stored in the SRF02. If you change it, the equivalent Serial Mode address will also change:
0xE0, 0xE2, 0xE4, 0xE6, 0xE8, 0xEA, 0xEC, 0xEE, 0xF0, 0xF2, 0xF4, 0xF6, 0xF8, 0xFA, 0xFC, 0xFE I2C addresses
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F Equivalent Serial addresses
 

AutoTune
The SRF02 does not require any user calibration. You power up and go right ahead and use the SRF02.
Internally, there are tuning cycles happening automatically in the background. After the ultrasonic burst has been transmitted, the transducer keeps on ringing for a period of time. It is this ringing which limits the closest range the SRF02 can measure. This time period varies with temperature and from transducer to transducer, but is normally the equivalent of 11 to 16cm (4" to 6"), a bit more if the transducer is warm. The SRF02 is able to detect the transducer ring time and move its detection threshold right up to it, giving the SRF02 the very best performance possible. On power up, the detection threshold is set to 28cm (11"). The tuning algorithms quickly back this right up to the transducer ring. This happens within 5-6 ranging cycles - less than half a second at full scan speed. After this the tuning algorithms continue to monitor the transducer, backing the threshold up even further when possible or easing it out a bit when necessary. The tuning algorithms work automatically, in the background and with no impact on scan time.
The minimum range can be checked, if required by reading registers 4 and 5. This value is returned in uS, cm or inches, the same as the range. It is also possible to make the SRF02 re-tune by writing command 96 but you can ignore this command. It is used during our testing.

 

SRF02 Ultrasonic range finder 
Technical Specification

Serial Mode
For I2C mode click here

Serial Communication
To use the SRF02 in Serial mode, make sure the Mode pin is connected to 0v Ground.
Serial data is fixed at 9600 baud 1 start, 2 stop and no parity bits. Serial data is a TTL level signal - It is NOT RS232. Do not connect the SRF02 to an RS232 port - you will destroy the module! If you would like to connect the SRF02 to your PC's RS232 port, you must use a MAX232 or similar device. It can also be used (in I2C mode) with the USBI2C module to make a self powered USB ranger, see the examples page for details. Many small controllers such as the OOPic, Stamp BS2p, PicAxe etc. as well as a wide variety of micro-controllers have serial ports. To communicate with the SRF02, you simply need to send two bytes, the address of the SRF02 (factory default is 0) and the command. The default shipped address can be changed by the user to any of 16 addresses 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, or 15, therefore up to 16 sonar's can be used.

Connections
The connections to the SRF02 are shown below. The "Mode" pin must be connected to 0v ground to place the SRF02 in serial mode. The Rx pin is data into the SRF02 and should be connected to the Tx pin on your controller. The Tx pin is data out of the SRF02 and should be connected to the Rx pin on your controller. If you're using multiple SRF02's, you can connect them all up to the same serial port on your controller. Connect the Tx from your controller to all the Rx pins on the SRF02's and connect the Rx pin on your controller to all the Tx pins on the SRF02's. This works because the Tx pins are high impedance (just a weak pull-up to 5v), except when actually sending data. Just make sure all the SRF02's are programmed to different addresses.

Commands
To send a command to the SRF02, you need to send two bytes. The first is the SRF02's address 0 to 15, (0x00 to 0x0F) and then the actual command itself - see below. The are three commands to initiate a ranging (80 to 82), to produce the result in inches, centimeters or microseconds. These three commands don't Tx the result back to your controller. You should wait 70mS and then use command 94 to get the result of the ranging. Another set of three commands (83 to 85) do the same, but also transmits the result of the ranging back to your controller as soon as it is available. Together, these six commands (80 - 85) are called "Real" because they perform a complete ranging. There is another set of six commands (86 - 91) called "Fake". They are the same as the "Real" commands except that they do not send the 8-cycle burst out. These are used where the burst has been transmitted by another sonar. It is up to you to synchronize the commands to the two sonar's. There is a command (92) to transmit a burst without doing the ranging.
Command 93 is used to get the firmware revision of the SRF02.
Command 94 gets returns two bytes (high byte first) from the most recent ranging. Put them together to make a 16-bit result.
Commands 95 and 96 are used by the Autotune algorithms - See the Autotune section below for details.

Command Action
Decimal Hex
80 0x50 Real Ranging Mode - Result in inches 
81 0x51 Real Ranging Mode - Result in centimeters
82 0x52 Real Ranging Mode - Result in micro-seconds
83 0x53 Real Ranging Mode - Result in inches, automatically Tx range back to controller as soon as ranging is complete.
84 0x54 Real Ranging Mode - Result in centimeters, automatically Tx range back to controller as soon as ranging is complete.
85 0x55 Real Ranging Mode - Result in micro-seconds, automatically Tx range back to controller as soon as ranging is complete.
     
86 0x56 Fake Ranging Mode - Result in inches 
87 0x57 Fake Ranging Mode - Result in centimeters
88 0x58 Fake Ranging Mode - Result in micro-seconds
89 0x59 Fake Ranging Mode - Result in inches, automatically Tx range back to controller as soon as ranging is complete.
90 0x5A Fake Ranging Mode - Result in centimeters, automatically Tx range back to controller as soon as ranging is complete.
91 0x5B Fake Ranging Mode - Result in micro-seconds, automatically Tx range back to controller as soon as ranging is complete.
     
92 0x5C Transmit an 8 cycle 40khz burst - no ranging takes place
93 0x5D Get software version - sends a single byte back to the controller
94 0x5E Get Range, returns two bytes (high byte first) from the most recent ranging.
95 0x5F Get Minimum, returns two bytes (high byte first) of the closest range measurable - see Autotune section
96 0x60 Force Autotune Restart - same as power-up. You can ignore this command.
     
160 0xA0 1st in sequence to change I2C address
165 0xA5 3rd in sequence to change I2C address
170 0xAA 2nd in sequence to change I2C address

LED
The red LED is used to flash out a code for the I2C address on power-up (see below). It also gives a brief flash during the "ping" whilst ranging.

Changing the SRF02 Address
To change the address of the SRF02 you must have only one sonar connected. Write the 3 sequence commands in the correct order followed by the address. Example; to change the address of a sonar currently at 0 (the default shipped address) to 5, write the following to address 0; (0xA0, 0xAA, 0xA5, 0x05 ). These commands must be sent in the correct sequence to change the I2C address, additionally, No other command may be issued in the middle of the sequence. The sequence must be sent as four separate commands to the current address of the sonar. i.e. 0x00, 0xA0 then 0x00, 0xAA, then 0x00, 0xA5 and finally 0x00, 0x05. When done, you should label the sonar with its new address, however if you do forget, just power it up without sending any commands. The SRF02 will flash its address out on the LED. One long flash followed by a number of shorter flashes indicating its address. The flashing is terminated immediately on sending a command the SRF02.

Address Long Flash Short flashes
Decimal Hex
0 00 1 0
1 01 1 1
2 02 1 2
3 03 1 3
4 04 1 4
5 05 1 5
6 06 1 6
7 07 1 7
8 08 1 8
9 09 1 9
10 0A 1 10
11 0B 1 11
12 0C 1 12
13 0D 1 13
14 0E 1 14
15 0F 1 15

Take care not to set more than one sonar to the same address, there will be a bus collision and very unpredictable results.

Note - there is only one module address stored in the SRF02. If you change it, the equivalent I2C address will also change:
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F Serial addresses
0xE0, 0xE2, 0xE4, 0xE6, 0xE8, 0xEA, 0xEC, 0xEE, 0xF0, 0xF2, 0xF4, 0xF6, 0xF8, 0xFA, 0xFC, 0xFE Equivalent I2C addresses

AutoTune
The SRF02 does not require any user calibration. You power up and go right ahead and use the SRF02.
Internally, there are tuning cycles happening automatically in the background. After the ultrasonic burst has been transmitted, the transducer keeps on ringing for a period of time. It is this ringing which limits the closest range the SRF02 can measure. This time period varies with temperature and from transducer to transducer, but is normally the equivalent of 11 to 16cm (4" to 6"), a bit more if the transducer is warm. The SRF02 is able to detect the transducer ring time and move its detection threshold right up to it, giving the SRF02 the very best performance possible. On power up, the detection threshold is set to 28cm (11"). The tuning algorithms quickly back this right up to the transducer ring. This happens within 5-6 ranging cycles - less than half a second at full scan speed. After this the tuning algorithms continue to monitor the transducer, backing the threshold up even further when possible or easing it out a bit when necessary. The tuning algorithms work automatically, in the background and with no impact on scan time.
The minimum range can be checked, if required by sending command 95. This will return the closest measurable range in uS, cm or inches, the same as the range. It is also possible to make the SRF02 re-tune by writing command 96 but you can ignore this command. It is used during our testing.







 Connecting the ATMEGA32 to LCD03, CMPS03 and the SRF02 

 

Introduction
The following example demonstrates how to connect the LCD03, CMPS03 and SRF02 to the ATMEGA32 from Atmel. It provides a connection diagram and also generic I2C routines that can be easily adapted to communicate with any Robot Electronics product that operates on the I2C bus.
For the example I used the following free software:

WinAVR - Open source C compiler for a range of Atmel devices, available at    http://winavr.sourceforge.net/
AVR Studio - IDE ( text editor and graphical option select for WinAVR). available from    www.atmel.com/dyn/products/tools_card.asp?tool_id=2725 

A programmer will also be required for the ATMEGA32, I elected to use the AVR ISP mk2 which runs from the USB bus, requires no external power and programming is integrated into AVR Studio. There are plenty of other options available though.

Source code for ATMEGA32

//**************************************************************************
//* I2C routines for the ATMEGA32 and example using LCD03,CMPS03 and SRF02 *
//* Written by C Clarke                                                    *
//* 29/10/2007                                                             *
//**************************************************************************

#include <inttypes.h>                                            // these four library headers are part of WinAVR compiler
#include <stdio.h>
#include <stdlib.h>
#include <avr/io.h>

void setup(void);
void i2c_transmit(char,char,char);

char i2c_read(char,char);
char s[21];

#define DEGREE 0xDF                                              // this is taken from ascii char sheet for lcd03


void main(void)
{
char x;
unsigned int range,angle;
long delay;

   setup();
   for(delay=0; delay<30000L; delay++);                          // the LCD03 takes a small delay to init
   i2c_transmit(0xc6,0,12);                                      // clear lcd03 screen
   i2c_transmit(0xc6,0,4);                                       // hide lcd03 cursor
   while(1){
      for(delay=0; delay<30000L; delay++);                       // just a refresh rate delay
      i2c_transmit(0xE0,0,0x51);                                 // srf02 ping command, result in cm
      i2c_transmit(0xC6,0,2);                                    // set cursor to position(1-80)
      i2c_transmit(0xC6,0,21);                                   // at position 21
      range = i2c_read(0xE0,2) <<8;                              // read srf02 range, high byte
      range += i2c_read(0xE0,3);                                 // read srf02 range, low byte
      sprintf(s,"SRF02 Range = %d.%dm",range/100,range%100);     // fills char string s with srf02 line text and data
      for(x=0; s[x]!=0; x++) i2c_transmit(0xc6,0,s[x]);          // buffer s chars sent one at a time to LCD03, ends on null from sprintf

      angle = i2c_read(0xC0,2) <<8;                              // read cmps03 angle, high byte
      angle += i2c_read(0xC0,3);                                 // read cmps03 angle, low byte
      i2c_transmit(0xC6,0,2);                                    // set cursor to position(1-80)
      i2c_transmit(0xC6,0,41);                                   // at position 41
      sprintf(s,"CMPS03 = %3d.%d",angle/10,angle%10);            // fills char string s with CMPS03 line text and data
      for(x=0; s[x]!=0; x++) i2c_transmit(0xc6,0,s[x]);          // buffer s chars sent one at a time to LCD03, ends on null from sprintf
      i2c_transmit(0xc6,0,DEGREE);                               // add my degree symbol at string end
   }
}

char i2c_read(char address, char reg)
{
char read_data = 0;

   TWCR = 0xA4;                                                  // send a start bit on i2c bus
   while(!(TWCR & 0x80));                                        // wait for confirmation of transmit  
   TWDR = address;                                               // load address of i2c device
   TWCR = 0x84;                                                  // transmit 
   while(!(TWCR & 0x80));                                        // wait for confirmation of transmit
   TWDR = reg;                                                   // send register number to read from
   TWCR = 0x84;                                                  // transmit
   while(!(TWCR & 0x80));                                        // wait for confirmation of transmit

   TWCR = 0xA4;                                                  // send repeated start bit
   while(!(TWCR & 0x80));                                        // wait for confirmation of transmit 
   TWDR = address+1;                                             // transmit address of i2c device with readbit set
   TWCR = 0xC4;                                                  // clear transmit interupt flag
   while(!(TWCR & 0x80));                                        // wait for confirmation of transmit
   TWCR = 0x84;                                                  // transmit, nack (last byte request)
   while(!(TWCR & 0x80));                                        // wait for confirmation of transmit 
   read_data = TWDR;                                             // and grab the target data
   TWCR = 0x94;                                                  // send a stop bit on i2c bus
   return read_data;

}

void i2c_transmit(char address, char reg, char data)
{
   TWCR = 0xA4;                                                  // send a start bit on i2c bus
   while(!(TWCR & 0x80));                                        // wait for confirmation of transmit 
   TWDR = address;                                               // load address of i2c device
   TWCR = 0x84;                                                  // transmit
   while(!(TWCR & 0x80));                                        // wait for confirmation of transmit
   TWDR = reg;
   TWCR = 0x84;                                                  // transmit
   while(!(TWCR & 0x80));                                        // wait for confirmation of transmit
   TWDR = data;
   TWCR = 0x84;                                                  // transmit
   while(!(TWCR & 0x80));                                        // wait for confirmation of transmit
   TWCR = 0x94;                                                  // stop bit
}

void setup(void)
{
   TWBR = 32;                                                    // 100khz i2c bus speed
}

 

 


 실험소스

 

//**************************************************************************
//* I2C routines for the ATMEGA32 and example using LCD03,CMPS03 and SRF02 *
//* Written by C Clarke                                                    *
//* 29/10/2007                                                             *
//**************************************************************************
#include <avr/io.h>
#include "main.h"
#include "uart.h"
#include "delay.h"

 

//값 읽어 오는 함수
char i2c_read(char address, char reg)
{
 char read_data = 0;

 TWCR = 0xA4;                                                  // send a start bit on i2c bus
 while(!(TWCR & 0x80));                                        // wait for confirmation of transmit 
 TWDR = address;                                               // load address of i2c device
 TWCR = 0x84;                                                  // transmit
 while(!(TWCR & 0x80));                                        // wait for confirmation of transmit
 TWDR = reg;                                                   // send register number to read from
 TWCR = 0x84;                                                  // transmit
 while(!(TWCR & 0x80));                                        // wait for confirmation of transmit
 TWCR = 0xA4;                                                  // send repeated start bit
 while(!(TWCR & 0x80));                                        // wait for confirmation of transmit
 TWDR = address+1;                                             // transmit address of i2c device with readbit set
 TWCR = 0xC4;                                                  // clear transmit interupt flag
 while(!(TWCR & 0x80));                                        // wait for confirmation of transmit
 TWCR = 0x84;                                                  // transmit, nack (last byte request)
 while(!(TWCR & 0x80));                                        // wait for confirmation of transmit
 read_data = TWDR;                                             // and grab the target data
 TWCR = 0x94;                                                  // send a stop bit on i2c bus
 return read_data;

}

 //레지스터데 명령 내리는 함수

void i2c_transmit(char address, char reg, char data)
{
 TWCR = 0xA4;                                                  // send a start bit on i2c bus
 while(!(TWCR & 0x80));                                        // wait for confirmation of transmit
 TWDR = address;                                               // load address of i2c device
 TWCR = 0x84;                                                  // transmit
 while(!(TWCR & 0x80));                                        // wait for confirmation of transmit
 TWDR = reg;
 TWCR = 0x84;                                                  // transmit
 while(!(TWCR & 0x80));                                        // wait for confirmation of transmit
 TWDR = data;
 TWCR = 0x84;                                                  // transmit
 while(!(TWCR & 0x80));                                        // wait for confirmation of transmit
 TWCR = 0x94;                                                  // stop bit
}

 

void i2c_init(void)
{
 TWBR = 12;                                                    // 통신속도 100khz
 TWDR = 0xFF;      //dummy data
}

 

//SRF02 센서 어드레스 바꾸는 함수 

void SRF02_change_address(unsigned char src, unsigned char dst)
{
  i2c_transmit(src, 0, 0xA0);
  i2c_transmit(src, 0, 0xAA);
  i2c_transmit(src, 0, 0xA5);
  i2c_transmit(src, 0, dst);
}


int main(void)
{
 int range;

 UART_0_init();
 i2c_init();

 while(1){
  delay_ms(250);
  i2c_transmit(0xE0, 0, 0x51);   //--> (add, command reg, command)


  

  range = i2c_read(0xE0,2) <<8;                              // read srf02 range, high byte
  range += i2c_read(0xE0,3);                                 // read srf02 range, low byte

  uart_0_debug("Range",range);

 

 }

}