Quellcode

Firmware des Windmessers, welche auf dem Chip läuft

 

#include <avr/interrupt.h>
#include <util/atomic.h>
#include <EEPROM.h>

#define NUM_CALIB 20

// Sends a burst at the specified Transmitter
float measureBurst (char t, char r);

// Measure burst-time between Transmitter and receiver
void startPhaseDifference (char t, char r);

// Stops measuring phase difference
int stopPhaseDifference (void);

// Calibrate the system; ATTENTION: Calibration must be executed in still air!
// If no calibration is launched at startup, old calibration values will be taken
void calibrate (unsigned int T);

// Delays a specified amount of time
void _delay (unsigned long del);


/*
Burst delay

Distance d/cm	Delay t/µs      Delaydifference dt/µs = t - d/c

1,1		110		78
3,5		206		105
8,4		367		124
14,6		568		146
21,6		795		171
30,6		1081	197
*/

/*
Phase delay

Varying

*/


/*
TimerBurstDiff

32 Cycles ^= 2µs

*/

// Global variables
const int cycleDiff = 4;                                           // Cycle difference between Timer0 and Timer1
const int cycleOffset = 6;
int b_x1 = 0, b_x2 = 0, b_y1 = 0, b_y2 = 0;                        // Burstoffsets -/ delays, d = 252mm (are set by calibrate)
int p_x1 = 0, p_x2 = 0, p_y1 = 0, p_y2 = 0;                        // Phaseoffsets (are set by calibrate)
int phase_x = 0, phase_y = 0;
const int d = 252;                                                 // Distance of receiver and transmitter [mm]
int burstTime = 0;
int burstCount = 0;
char transmitter = 0;
char tMaskB = 0, tMaskC = 0;
char interrupt_mode = 0;


// Main Program
//
//
//
void setup() {

  // Declarations
  
  // Measurevalues
  float c, v, a, T;
  float t_x1, t_x2, v_x;
  float t_y1, t_y2, v_y;
  int p_m = 0;
  
  float burst_x1, burst_x2;
  
  unsigned int T_in;
  char mode = 0;

  
  // Serial connection for debugging
  Serial.begin(9600);
  
  // ICP (Pin 8) with 16Bit-Timer1
  pinMode(8, INPUT);
  
  // PWM Outputs (Pin A0-A3, 10-13)
  DDRC = 0x00;
  PORTC = 0;
  pinMode(10, INPUT);
  pinMode(11, INPUT);
  pinMode(12, INPUT);
  pinMode(13, INPUT);
  PORTB = 0;
  
  // Multiplexer
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  digitalWrite(2, 0);
  digitalWrite(3, 0);
  digitalWrite(4, 1);
  
  // Debugging timer
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  
  // Read calibrations
  for (int i=0; i<2; i++) {
    b_x1 += EEPROM.read (i) << (i*8);
    b_x2 += EEPROM.read (2+i) << (i*8);
    b_y1 += EEPROM.read (4+i) << (i*8);
    b_y2 += EEPROM.read (6+i) << (i*8);
    p_x1 += EEPROM.read (8+i) << (i*8);
    p_x2 += EEPROM.read (10+i) << (i*8);
    p_y1 += EEPROM.read (12+i) << (i*8);
    p_y2 += EEPROM.read (14+i) << (i*8);
  }
  
  while (true) {
    
    // Receive commands
    if (Serial.available () > 0)
      mode = Serial.read ();
    
    // Branch according to the current mode
    // 0, '0', 'o': do nothing
    // 'c': calibrate (next to Bytes are Temperature, unsigned int, LSB first)
    // 'b': measure wind (burst mode), return over serial port, [4B 4B 4B 4B] all float [(speed of sound) (speed of wind) (angle of wind) (temperature)]
    // 'p': measure wind (phase mode), return over serial port, [4B 4B 4B 4B] all float [(speed of sound) (speed of wind) (angle of wind) (temperature)]
    // 'v': measure wind (burst mode) verbose
    // 'q': measure wind (phase mode) verbose
    // 's': measure wind, safe mode; does calibrate automatically
    // 'd': debug mode
    switch (mode) {
      
      // 0, '0', 'o': do nothing
      case 0:
      case '0':
      case 'o':
      
      break;
      
      // 'c': calibrate (next to Bytes are Temperature, unsigned int, LSB first)
      case 'c':
        
        T_in = Serial.read ();
        T_in += Serial.read () << 8;
        
        calibrate (297);
        
        mode = 0;
        
      break;
     
      // 'b': measure wind (burst mode), return over serial port, [4B 4B 4B 4B] all float [(speed of sound) (speed of wind) (angle of wind) (temperature)]
      case 'b':
        
        // Measure delay times in x direction
        t_x2 = measureBurst (0, 1);                                                
        t_x1 = measureBurst (1, 0);
        t_x2 = measureBurst (0, 1);
        
        c = d/2.0f * (1000.0f/t_x1+1000.0f/t_x2);
        v_x = d/2.0f * (1000.0f/t_x2-1000.0f/t_x1);
        
        // Measure delay times in y direction
        t_y1 = measureBurst (3, 2);
        t_y2 = measureBurst (2, 3);
        
        v_y = d/2.0f * (1000.0f/(float)t_y2-1000.0f/(float)t_y1);
        
        // calculate v and angle
        v = sqrt (v_x*v_x+v_y*v_y);
        a = atan2 ( v_y, v_x ) * 180/PI;
        T = c*c / (20.063f*20.063f);
        
        // Serial answer
        Serial.write ( (uint8_t*)&c, 4 );
        Serial.write ( (uint8_t*)&v, 4 );
        Serial.write ( (uint8_t*)&a, 4 );
        Serial.write ( (uint8_t*)&T, 4 );
        
      break;
      
      // 'p': measure wind (phase mode), return over serial port, [4B 4B 4B 4B] all float [(speed of sound) (speed of wind) (angle of wind) (temperature)]
      case 'p':
      
        // Do Phase measures and try to get values betweeen -120 and 280 which is according to a time between 717.5µs and 742.5 µs
        startPhaseDifference (1, 0);
        _delay (8000);
        p_m = (stopPhaseDifference () + p_x1 + 400)%400;
        if (p_m>280) {p_m-=400;}
        t_x1 = 725 + p_m/16.0f;
        _delay (8000);
        
        startPhaseDifference (0, 1);
        _delay (3000);
        p_m = (stopPhaseDifference () + p_x2 + 400)%400;
        if (p_m>280) {p_m-=400;}
        t_x2 = 725 + p_m/16.0f;
        _delay (8000);
        
        // dummy measure, needed so that the measurement works correctly
        startPhaseDifference (2, 3);
        _delay (8000);
        p_m = (stopPhaseDifference () + p_y2 + 400)%400;
        if (p_m>280) {p_m-=400;}
        t_y1 = 725 + p_m/16.0f;
        _delay (8000);
        
        startPhaseDifference (3, 2);
        _delay (8000);
        p_m = (stopPhaseDifference () + p_y1 + 400)%400;
        if (p_m>280) {p_m-=400;}
        t_y1 = 725 + p_m/16.0f;
        _delay (8000);
        
        startPhaseDifference (2, 3);
        _delay (3000);
        p_m = (stopPhaseDifference () + p_y2 + 400)%400;
        if (p_m>280) {p_m-=400;}
        t_y2 = 725 + p_m/16.0f;
        _delay (8000);
        
        // Calculate speed of sound and wind in x- and y- direction
        c = d/2.0f * (1000.0f/t_x1+1000.0f/t_x2);
        v_x = d/2.0f * (1000.0f/t_x2-1000.0f/t_x1);
        v_y = d/2.0f * (1000.0f/(float)t_y2-1000.0f/(float)t_y1);
        
        // calculate v and angle
        v = sqrt (v_x*v_x+v_y*v_y);
        a = atan2 ( v_y, v_x ) * 180/PI;
        T = c*c / (20.063f*20.063f);
        
        // Serial answer
        Serial.write ( (uint8_t*)&c, 4 );
        Serial.write ( (uint8_t*)&v, 4 );
        Serial.write ( (uint8_t*)&a, 4 );
        Serial.write ( (uint8_t*)&T, 4 );
      
      break;
      
      // 'v': measure wind (burst mode) verbose
      case 'v':
        
        // Measure delay times in x direction
        t_x2 = measureBurst (0, 1);
        t_x1 = measureBurst (1, 0);
        t_x2 = measureBurst (0, 1);
        
        c = d/2.0f * (1000.0f/t_x1+1000.0f/t_x2);
        v_x = d/2.0f * (1000.0f/t_x2-1000.0f/t_x1);
        
        // Measure delay times in y direction
        t_y2 = measureBurst (2, 3);
        t_y1 = measureBurst (3, 2);
        t_y2 = measureBurst (2, 3);
        
        v_y = d/2.0f * (1000.0f/(float)t_y2-1000.0f/(float)t_y1);
        
        // calculate v and angle
        v = sqrt (v_x*v_x+v_y*v_y);
        a = atan2 ( v_y, v_x ) * 180/PI;
        T = c*c / (20.063f*20.063f);
          
        Serial.print ("c = ");
        Serial.print (c);
        Serial.print (" m/s, v = ");
        Serial.print (v);
        Serial.print (" m/s, a = ");
        Serial.print (a);
        Serial.print (", T = ");
        Serial.print (T);
        Serial.print (" K\n");
        
      break;
     
      // measure wind (phase mode) verbose
      case 'q':
      
        // Do Phase measures and try to get values betweeen -120 and 280 which is according to a time between 717.5µs and 742.5 µs
        startPhaseDifference (1, 0);
        _delay (8000);
        p_m = (stopPhaseDifference () + p_x1 + 400)%400;
        if (p_m>280) {p_m-=400;}
        t_x1 = 725 + p_m/16.0f;
        _delay (8000);
        
        startPhaseDifference (0, 1);
        _delay (3000);
        p_m = (stopPhaseDifference () + p_x2 + 400)%400;
        if (p_m>280) {p_m-=400;}
        t_x2 = 725 + p_m/16.0f;
        _delay (8000);
        
        // dummy measure
        startPhaseDifference (2, 3);
        _delay (8000);
        p_m = (stopPhaseDifference () + p_y2 + 400)%400;
        if (p_m>280) {p_m-=400;}
        t_y1 = 725 + p_m/16.0f;
        _delay (8000);
        
        startPhaseDifference (3, 2);
        _delay (8000);
        p_m = (stopPhaseDifference () + p_y1 + 400)%400;
        if (p_m>280) {p_m-=400;}
        t_y1 = 725 + p_m/16.0f;
        _delay (8000);
        
        startPhaseDifference (2, 3);
        _delay (3000);
        p_m = (stopPhaseDifference () + p_y2 + 400)%400;
        if (p_m>280) {p_m-=400;}
        t_y2 = 725 + p_m/16.0f;
        _delay (8000);
        
        // Calculate speed of sound and wind in x- and y- direction
        c = d/2.0f * (1000.0f/t_x1+1000.0f/t_x2);
        v_x = d/2.0f * (1000.0f/t_x2-1000.0f/t_x1);
        v_y = d/2.0f * (1000.0f/(float)t_y2-1000.0f/(float)t_y1);
        
        // calculate v and angle
        v = sqrt (v_x*v_x+v_y*v_y);
        a = atan2 ( v_y, v_x ) * 180/PI;
        T = c*c / (20.063f*20.063f);
        
        Serial.print ("c = ");
        Serial.print (c);
        Serial.print (" m/s, v = ");
        Serial.print (v);
        Serial.print (" m/s, a = ");
        Serial.print (a);
        Serial.print (", T = ");
        Serial.print (T);
        Serial.print (" K\n");
      
      break;
      
    }

  
  }
  

}



void loop() {
}



// Function declarations
//
//
//


// Calibrate the system and writes calibrations into EEPROM; ATTENTION: Calibration must be executed in still air!
//
// T: Temperatur [K]
//
void calibrate (unsigned int T) {
 
  float c = 20.063 * sqrt (T);                                    // Calculate speed of sound
  float t = d / c * 1000.0f;                                      // Calculate the desired delay time
  float bd_x1 = 0 ,bd_x2 = 0, bd_y1 = 0, bd_y2 = 0;
  float dummy;
  
  // reset older calibrations
  b_x1 = b_x2 = b_y1 = b_y2 = 0;
  p_x1 = p_x2 = p_y1 = p_y2 = 0; 
  
  
  // Measure some burst delays
  for (int i=0; i<NUM_CALIB; i++) {
    
    dummy = measureBurst (0, 1);
    bd_x1 += measureBurst (1, 0);
    bd_x2 += measureBurst (0, 1);
    
    
  }
  bd_x1 /= NUM_CALIB;
  bd_x2 /= NUM_CALIB;
  _delay(1000);
  
  for (int i=0; i<NUM_CALIB; i++) {
    
    dummy = measureBurst (2, 3);
    bd_y1 += measureBurst (3, 2);
    bd_y2 += measureBurst (2, 3);
    
  }
  
  bd_y1 /= NUM_CALIB;
  bd_y2 /= NUM_CALIB;
  _delay(1000);
  
  // Calculate measure error
  b_x1 = bd_x1 - t;
  b_x2 = bd_x2 - t;
  b_y1 = bd_y1 - t;
  b_y2 = bd_y2 - t;
  
  // Measure phase with decent waiting times
  startPhaseDifference (1, 0);
  _delay (6000);
  for (int i=0; i<NUM_CALIB; i++) {
    p_x1 += ICR1;
    _delay(100);
  }
  stopPhaseDifference ();
  p_x1 /= NUM_CALIB;
  _delay(10000);
  
  startPhaseDifference (0, 1);
  _delay (6000);
  for (int i=0; i<NUM_CALIB; i++) {
    p_x2 += ICR1;
    _delay(100);
  }
  stopPhaseDifference ();
  p_x2 /= NUM_CALIB;
  _delay(10000);
  
  startPhaseDifference (3, 2);
  _delay (6000);
  for (int i=0; i<NUM_CALIB; i++) {
    p_y1 += ICR1;
    _delay(100);
  }
  stopPhaseDifference ();
  p_y1 /= NUM_CALIB;
  _delay(10000);
  
  startPhaseDifference (2, 3);
  _delay (6000);
  for (int i=0; i<NUM_CALIB; i++) {
    p_y2 += ICR1;
    _delay(100);
  }
  stopPhaseDifference ();
  p_y2 /= NUM_CALIB;
  
  // Calculate phase errors: (t mod 25)*16 - p_x1: number of cycles between the burst phase and the measured phase
  // has to be added on the later phase measure
  p_x1 = (t - ((int)(t/25))*25)*16 - p_x1;
  p_x2 = (t - ((int)(t/25))*25)*16 - p_x2;
  p_y1 = (t - ((int)(t/25))*25)*16 - p_y1;
  p_y2 = (t - ((int)(t/25))*25)*16 - p_y2;
  
  // Write delays into EEPROM
  for (int i=0; i<2; i++) {
    EEPROM.write (i, (b_x1 >> (8*i)) & 0xFF);
    EEPROM.write (2+i, (b_x2 >> (8*i)) & 0xFF);
    EEPROM.write (4+i, (b_y1 >> (8*i)) & 0xFF);
    EEPROM.write (6+i, (b_y2 >> (8*i)) & 0xFF);
    EEPROM.write (8+i, (p_x1 >> (8*i)) & 0xFF);
    EEPROM.write (10+i, (p_x2 >> (8*i)) & 0xFF);
    EEPROM.write (12+i, (p_y1 >> (8*i)) & 0xFF);
    EEPROM.write (14+i, (p_y2 >> (8*i)) & 0xFF);
  }
  
  return;
  
}


// Starts measuring phase difference. The phase difference can be obtained from the ICR1-Register
//
// t: Multiplexindex of the transmitter
// r: Multiplexindex of the receiver
//
void startPhaseDifference (char t, char r) {
  
  // PWM Settings
  interrupt_mode = 0;
  TIMSK1 = 0;
  TCCR0A = 1 << COM0A1 | 1 << COM0B0 | 1 << COM0B1;                // OCA0 = 0, OCB0 = 1
  TCCR0B = 1 << FOC0A | 1 << FOC0B;
  
  TCCR0A = 1 << COM0A0 | 1 << COM0B0 | 1 << WGM01;                 // Configure Timer0 as 40kHz impulse machine for the transmitter
  TCCR0B = 1 << CS00;
  TIMSK0 = 1 << OCIE0B;
  OCR0A = 199;
  OCR0B = 199;
  
  // Timer1 is needed to detect the impulse edges
  TCCR1A = 1 << COM1A0;                                            // CTC
  TCCR1B = 1 << WGM12 | 1 << CS10 | 1 << ICES1;                    // Prescale 1 (16Mhz/400 = 40kHz), Input Capture rising edge
  OCR1A = 399;
  
  TCNT0 = 0;                                                       // Synchronize timers
  TCNT1 = cycleDiff;
  
  
  // Transmitter starts with high value
  tMaskB = 1 << (2 + t);
  tMaskC = 1 << t;
  DDRB |= 1 << (2 + t);
  DDRC = 1 << t;
  transmitter = t;
  
  // Switch receiver
  digitalWrite (2, r%2);
  digitalWrite (3, r/2);
  digitalWrite (4, 0);
  
}


// Stops measuring phase difference
//
int stopPhaseDifference (void) {
  
  int Phase = ICR1;
  
  // Reset timers
  TCCR0A = 0;
  TCCR0B = 0;
  TIMSK0 = 0;
  TCCR1A = 0;
  TCCR1B = 0;
  
  // Turn off receiver
  digitalWrite (4, 1);
  PORTB = 0;
  PORTC = 0;
  DDRB &= ~(1 << (2 + transmitter));
  DDRC = 0;
  burstCount = 0;
  
  
  return Phase;
  
}


// Measure burst-time between Transmitter and receiver
//
// t: Multiplexindex of the transmitter
// r: Multiplexindex of the receiver
//
float measureBurst (char t, char r) {

  // Check, whether transmitter and receiver indices are in range
  if (r >= 0 && r <= 3 && t >= 0 && t <= 3) {
    
    interrupt_mode = 1;
    
    // Transmitter starts with high value
    tMaskB = 1 << (2 + t);
    tMaskC = 1 << t;
    DDRB |= 1 << (2 + t);
    DDRC = 1 << t;
    transmitter = t;
    digitalWrite(4,0);
    
    
    // Set Registers to prevent failures  
    burstCount = 0;
    TIMSK1 = 1 << ICIE1;
    TIFR1 = 0;
    
    // Transmitter settings
    TCCR0A = 1 << COM0A1 | 1 << COM0B1;                              // OCA0 = 0, OCB0 = 0
    TCCR0B = 1 << FOC0A | 1 << FOC0B;
    TIMSK0 = 1 << OCIE0B;
    OCR0A = 199;                                                     // Max values
    OCR0B = 199;
    
    // Use Timer1 to measure time
    TCCR1A = 0;                                                      // Start Timer
    TCCR1B = 1 << CS10 | 1 << ICES1;                                 // Prescale 1, Interrupt Capture rising edge
    TIMSK1 = 1 << ICIE1;
    OCR1A = 0xFFFF;
    
    
    // !!! Start timecritical part !!!
    
    
    // Start first impulse
    TCCR0A = 1 << COM0A1 | 1<< COM0B0 | 1 << COM0B1;                 // OCA0 = 0, OCB0 = 1
    TCCR0B = 1 << FOC0A | 1 << FOC0B;
    
    TCCR0A = 1 << COM0A0 | 1 << COM0B0 | 1 << WGM01;                 // Configure Timer0 as 40kHz impulse machine (CTC mode)
    TCCR0B = 1 << CS00;
    
    // Synchronize timers
    TCNT0 = cycleOffset;
    TCNT1 = cycleOffset + cycleDiff;
    
    // Force constant period time
    
    asm ("nop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\n");
    
    // Switch transmitter
    PORTB = tMaskB;
    PORTC = 0;
  
    // !!! End timecritical part !!!
   
    
    // Switch receiver
    digitalWrite (2, r%2);
    digitalWrite (3, r/2);
    
  
    _delay (40000);
  
    
    // Turn off receiver
    digitalWrite (4, 1);
    DDRB &= ~(1 << (2 + transmitter));
    DDRC = 0;
    burstCount = 0;
    TIMSK1 = 0;
    if (r == 0)
      return burstTime/16.0f-b_x1;
    if (r == 1)
      return burstTime/16.0f-b_x2;
    if (r == 2)
      return burstTime/16.0f-b_y1;
    if (r == 3)
      return burstTime/16.0f-b_y2;

    
  }
  
  else {
    
    return -1;
    
  }
  
}


// Interrupt routine: Stops after the 8 impulse burst
ISR (TIMER0_COMPB_vect) {
  
  if (burstCount++%2 == 0) {
    PORTB = 0;
    PORTC = tMaskC;
  }
  else {
    PORTB = tMaskB;
    PORTC = 0;
  }
  
  if (burstCount == 16 && interrupt_mode == 1) {
    
    PORTB = 0;
    PORTC = 0;
    
    TIMSK0 &= ~(1 << OCIE0B);
    
    TCCR0A = 1 << COM0A1 | 1 << COM0B1;                            // OCA0 = 0, OCB0 = 0
    TCCR0B = 1 << FOC0A | 1 << FOC0B;
    
    TCCR0A = 0;
    TCCR0B = 0;
    
  }
  
}

// Interrupt routine: Measures the delay of the Input edge
ISR (TIMER1_CAPT_vect) {
  
  TIMSK1 = 0;
  TIFR1 = 0;
  
  burstTime = ICR1;

  TCCR1A = 0;
  TCCR1B = 0;
  
}


// Delays a specified amount of time
//
// del: number of loops to delay 50ms ^= 110000
//
void _delay (unsigned long del) {
  while (--del) { asm ("nop"); }
}

 

Quellcode mit den SRF02 (läuft auf keinem Controller)

// I2C - Interface
#include <Wire.h>


// Change the ID-number of the specified SRF02-module
void changeAddress (byte oldAddress, byte newAddress);

// Launch 8-impulse burst at the specified SRF02-module
void launchBurst (byte address);

// Launch receive of 8-impulse burst at the specified SRF02-module
void receiveBurst (byte address);

// Measure time between launch and receive of the burst at the specified SRF02-module
long measureTime (byte address);


// Main Program
//
//
//
void setup() {
  
  // Address of the SRF02
  const byte address[2] = {0xE4, 0xE6};
  const float d = 1.96;                  // distance of the two SRF02
  long t1, t2;
  float c, v, T;
  
  // I2C Setup
  Wire.begin();
  
  // Serial connection for debugging
  Serial.begin(9600);
  
  while (true) {

    delay (500);
    
    
    c = 0;
    v = 0;
    
    for (int i=0; i<5; i++) {
    
      // Launch one burst and receive it
      launchBurst (address[0]);
      receiveBurst (address[1]);
      t1 = measureTime (address[1])-12;
      
      // Launch another burst into the other direction
      delay(200);
      launchBurst (address[1]);
      receiveBurst (address[0]);
      t2 = measureTime (address[0])+12;
      
	  // Calculate air speed and sonic speed
      c = (c*i + (d/2.0f * (1000000.0f/(float)t1+1000000.0f/(float)t2)))/((float)i+1);
      v = (v*i + (d/2.0f * (1000000.0f/(float)t2-1000000.0f/(float)t1)))/((float)i+1);
        
      delay (100);
    
    }
    
    Serial.print ("c = ");
    Serial.print (c);
    Serial.print ("m/s, v = ");
    Serial.print (v);
    Serial.print ("m/s, T = ");
    Serial.print (c*c/(20.063f*20.063f)-273.15f);
    Serial.print ("C\n");
    
  }
  
}



void loop() {
}



// Function declarations
//
//
//

// Change the ID-number of the specified SRF02-module
//
// oldAddress: Address of the module to change
// newAddress: New address of the module
//
void changeAddress (byte oldAddress, byte newAddress) {
  
  oldAddress = oldAddress >> 1;
  
  Wire.beginTransmission (oldAddress);
  Wire.write (0x00);
  Wire.write (0xA0);
  Wire.endTransmission ();

  Wire.beginTransmission (oldAddress);
  Wire.write (0x00);
  Wire.write (0xAA);
  Wire.endTransmission ();

  Wire.beginTransmission (oldAddress);
  Wire.write (0x00);
  Wire.write (0xA5);
  Wire.endTransmission ();

  Wire.beginTransmission (oldAddress);
  Wire.write (0x00);
  Wire.write (newAddress);
  Wire.endTransmission ();
}

// Launch 8-impulse burst
//
// address: Address of the SRF02-module to burst
//
void launchBurst (byte address) {
  
  Wire.beginTransmission (address>>1);
  Wire.write (0x00);
  Wire.write (0x5C);
  Wire.endTransmission ();
  
}

// Launch receive of 8-impulse burst at the specified SRF02-module
//
// address: Address of the SRF02-module to receive
//
void receiveBurst(byte address) {
 
  Wire.beginTransmission (address>>1);
  Wire.write (0x00);
  Wire.write (0x58);
  Wire.endTransmission ();
  
}

// Measure time between launch and receive of the burst at the specified SRF02-module
//
// address: Address of the SRF02-module to receive
//
long measureTime (byte address) {
  
  long time = -1;
  
  Wire.beginTransmission (address>>1);        // set the register that shall be read
  Wire.write (0x02);
  Wire.endTransmission ();
  
  //delay (80);
  
  Wire.requestFrom (address>>1, 2);           // request 2 bytes
  
  if (Wire.available()>=2) {                  // wait for 2 bytes to receive
  
    time = Wire.read();
    time = time << 8;
    time += Wire.read() + 329;                // 320

  }
  
  return time;
  
}