2011年5月4日 星期三

BeagleBoard i2c SRF08 example code

According to http://www.robot-electronics.co.uk/htm/srf08tech.shtml


i2c_srf08.h



/*
 * i2c_srf08.h : SRF08 ultra sonic range finder
 *
 *  (C) 2011 by Steve Chang
 *  stevegigijoe@yahoo.com.tw
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#ifndef _I2C_SRF08_H
#define _I2C_SRF08_H

#include "bool.h"

typedef struct I2cSrf08 I2cSrf08;

I2cSrf08 *I2cSrf08_DefaultInstance(char *device);
int I2cSrf08_Open(I2cSrf08 *is);
void I2cSrf08_Close(I2cSrf08 *is);
void I2cSrf08_SetMaxRange(I2cSrf08 *is, unsigned char range);
void I2cSrf08_SetMaxGain(I2cSrf08 *is, unsigned char gain);
int I2cSrf08_BlockRangeInCentimeters(I2cSrf08 *is);
int I2cSrf08_RangingInCentimeters(I2cSrf08 *is);
int I2cSrf08_GetRange(I2cSrf08 *is);

#endif


i2c_srf08.c


/*
 * i2c_srf08.c : SRF08 ultra sonic range finder
 *
 *  (C) 2011 by Steve Chang
 *  stevegigijoe@yahoo.com.tw
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
#include
#include
#include
#include
#include
#include
#include

#include "i2c_srf08.h"

struct I2cSrf08  {
  int fd;
  char *device;
  unsigned char range;
  unsigned char gain;
  bool ranging;
};

I2cSrf08 *I2cSrf08_DefaultInstance(char *device)
{
  static I2cSrf08 i2csrf08;
 
  if(!device)
    return 0;

  memset(&i2csrf08, 0, sizeof(I2cSrf08));
 
  i2csrf08.device = strdup(device);
#if 0 
  i2csrf08.range = 0xff; /*  11 m : default */
  i2csrf08.range = 0x8c; /*  6 m */
  i2csrf08.range = 0x18; /*  1 m */
  i2csrf08.range = 0x1;  /*  86 mm */
  i2csrf08.range = 0x0;  /*  43 mm */
#endif
  i2csrf08.range = 0xff; /*  11 m : default */

#if 0
  i2csrf08.gain = 0x0; /*  min 94 */
  i2csrf08.gain = 0x1f; /* default & max 1025 */
#endif
  i2csrf08.gain = 0x1f;
 
  return &i2csrf08;
}

#define SRF08_I2C_ADDR  0x70

int I2cSrf08_Open(I2cSrf08 *is)
{
  is->fd = open(is->device, O_RDWR);
  if(is->fd == -1)
    return -1;
 
  if(ioctl(is->fd, I2C_SLAVE, SRF08_I2C_ADDR) < 0)  {
    printf("[SRF08] None exist device address 0x%x\n", SRF08_I2C_ADDR);
    close(is->fd);
    is->fd = 0;
    return -1;
  }
 
  unsigned char buf[2];
 
  buf[0] = 0x1; /*  Register 1  */
  buf[1] = is->gain;  /*  Gain */
  if(write(is->fd, buf, 2) != 2)
    return -1;

  buf[0] = 0x2; /*  Register 2  */
  buf[1] = is->range;  /*  Range */
  if(write(is->fd, buf, 2) != 2)
    return -1;
 
  return is->fd;
}

void I2cSrf08_Close(I2cSrf08 *is)
{
  if(is->fd)
    close(is->fd);
  is->fd = 0;
}

void I2cSrf08_SetMaxRange(I2cSrf08 *is, unsigned char range)
{
  is->range = range;
 
  unsigned char buf[2];
 
  buf[0] = 0x2; /*  Register 2  */
  buf[1] = is->range;  /*  Range */
  if(write(is->fd, buf, 2) != 2)
    printf("[SRF08] Fail to write !!!\n");
 
  return;
}

void I2cSrf08_SetMaxGain(I2cSrf08 *is, unsigned char gain)
{
  if(gain > 0x1f)
    gain = 0x1f;
 
  is->gain = gain;
 
  unsigned char buf[2];
 
  buf[0] = 0x1; /*  Register 1  */
  buf[1] = is->gain;  /*  Gain */
  if(write(is->fd, buf, 2) != 2)
    printf("[SRF08] Fail to write !!!\n");
 
  return;
}

int I2cSrf08_BlockRangeInCentimeters(I2cSrf08 *is)
{
  unsigned char buf[2];
 
  buf[0] = 0x0; /*  Register 0  */
  buf[1] = 81;  /*  Range in centimeters */
  if(write(is->fd, buf, 2) != 2)
    return -1;
 
  while(1)  {
    usleep(65000);

    buf[0] = 0x0; /*  Register 0 : software reversion */
    if(write(is->fd, buf, 1) != 1)  {
      usleep(100);
      continue;
    }
   
    if(read(is->fd, buf, 1) != 1)  {
      usleep(100);
      continue;
    }
   
    if(buf[0] != 0xff)  /*  While ranging it returns 0xff */
      break;  /*  Range data ready now  */
  }
 
  int i;
  char hb, lb;
  unsigned short r = 0;
  for(i=0;i<17;i++) { /*  There are 17 echo buffers */
    buf[0] = 2 + (i << 1); /*  Register 2, 4, 6 ...  */
    if(write(is->fd, buf, 1) != 1)
      return -1;
    if(read(is->fd, buf, 1) != 1)
      return -1;
    hb = buf[0];

   
    buf[0] = 3 + (i << 1); /*  Register 3, 5, 7 ...  */
    if(write(is->fd, buf, 1) != 1)
      return -1;
    if(read(is->fd, buf, 1) != 1)
      return -1;
    lb = buf[0];

    if(hb == 0 && lb == 0)
      break;
/*   
    printf("High byte : %d\n", hb);
    printf("Low byte : %d\n", lb);
*/
    r = (hb << 8) + lb;
    printf("[SRF08] %dst echo range = %u\n", i, r);
  }
 
  return 0;
}

int I2cSrf08_RangingInCentimeters(I2cSrf08 *is)
{
  if(is->ranging == true)
    return 0;

  unsigned char buf[2];

  buf[0] = 0x0; /*  Register 0  */
  buf[1] = 81;  /*  Range in centimeters */
  if(write(is->fd, buf, 2) != 2)
    return -1;
 
  is->ranging = true;
 
  return 0;
}

int I2cSrf08_GetRange(I2cSrf08 *is)
{
  if(is->ranging == false)
    return 0;

  unsigned char buf[1];

  char hb, lb;

  buf[0] = 0x0; /*  Register 0 : software reversion */
  if(write(is->fd, buf, 1) != 1)
    return -1;
  if(read(is->fd, buf, 1) != 1) {
    printf("[SRF08] Fail to read !!!\n");
    return -1;
  }

  if(buf[0] == 0xff)  {
    printf("[SRF08] Range data not ready !!!\n");
    return -1;
  }

  buf[0] = 2; /*  Register 2, 4, 6 ...  */
  if(write(is->fd, buf, 1) != 1)
    return -1;

  if(read(is->fd, buf, 1) != 1)
    return -1;

  hb = buf[0];

  buf[0] = 3; /*  Register 3, 5, 7 ...  */
  if(write(is->fd, buf, 1) != 1)
    return -1;

  if(read(is->fd, buf, 1) != 1)
    return -1;

  lb = buf[0];

  is->ranging = false;
 
  if(hb == 0 && lb == 0)  {
    printf("[SRF08] Fail to get range !!!\n");
    return -1;
  }

  unsigned short r = (hb << 8) + lb;
 
  return (int)r;
}


ultra_sonic.c


/*
 * ultra_sonic.c : SRF08 ultra sonic range finder sample program
 *
 *  (C) 2011 by Steve Chang
 *  stevegigijoe@yahoo.com.tw
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
#include

#include "i2c_srf08.h"

#define I2C_SRF08_DEVICE  "/dev/i2c-2"

int main(int argc, char **argv)
{
  I2cSrf08 *is = I2cSrf08_DefaultInstance(I2C_SRF08_DEVICE);
 
  int r = I2cSrf08_Open(is);
  if(r == -1) {
    printf("Fail to open %s\n", I2C_SRF08_DEVICE);
    goto leave;
  }

  while(1)
    I2cSrf08_BlockRangeInCentimeters(is);

leave:
  I2cSrf08_Close(is);

  return r;
}


The result as below

# ./ultra_sonic
[  851.740844] i2c_omap i2c_omap.2: Transmit error
[SRF08] 0st echo range = 32
[SRF08] 1st echo range = 86
[SRF08] 2st echo range = 150
[SRF08] 3st echo range = 216
[SRF08] 4st echo range = 280
[SRF08] 5st echo range = 344
[SRF08] 6st echo range = 410
[SRF08] 7st echo range = 474
[SRF08] 8st echo range = 560
[SRF08] 9st echo range = 795
[SRF08] 10st echo range = 926
[SRF08] 11st echo range = 1050
[SRF08] 0st echo range = 33
[SRF08] 1st echo range = 87
[SRF08] 2st echo range = 151
[SRF08] 3st echo range = 217
[SRF08] 4st echo range = 281
[SRF08] 5st echo range = 346
[SRF08] 6st echo range = 410
[SRF08] 7st echo range = 474
[SRF08] 8st echo range = 563
[SRF08] 9st echo range = 630
[SRF08] 10st echo range = 795





沒有留言:

張貼留言