玩了一陣子LI-BCM3M1 camera board發現不管什麼解析度都只能達到5~8fps.數據相當的難看,主要原因是driver限制住了.
到chip vendor Aptina網站找mt9t112 datasheet 竟然還要簽 NDA,發信去也不鳥我...Shit.
因此轉而試試五百萬畫素的LI-5M03, Aptina 有提供datasheet
http://www.aptina.com/products/image_sensors/mt9p031i12stc/
此外更提供給BeagleBoard XM driver source code放在github,我clone了一份.
https://github.com/gigijoe/BeagleBoard-xM
mt9p031 driver我有做一些修改
其中值得一提的是Camera輸出的影像非常暗,所以我把analog gain調高
@@ -538,12 +538,19 @@
mdelay(200);
ret |= mt9p031_set_params(priv->client, pix->width, pix->height);
-
+#if 0
ret |= mt9p031_reg_write(client, REG_MT9P031_GREEN_1_GAIN, 0x0051); //Green1_gain_reg
ret |= mt9p031_reg_write(client, REG_MT9P031_BLUE_GAIN, 0x0051); //Blue_gain_reg
ret |= mt9p031_reg_write(client, REG_MT9P031_RED_GAIN, 0x0051); //Red_gain_reg
ret |= mt9p031_reg_write(client, REG_MT9P031_GREEN_2_GAIN, 0x0051); //Green2_gain_reg
ret |= mt9p031_reg_write(client, REG_MT9P031_GLOBAL_GAIN, 0x0008); //Analog Gain
+#endif
+ ret |= mt9p031_reg_write(client, REG_MT9P031_GREEN_1_GAIN, 0x0079); //Green1_gain_reg
+ ret |= mt9p031_reg_write(client, REG_MT9P031_BLUE_GAIN, 0x0079); //Blue_gain_reg
+ ret |= mt9p031_reg_write(client, REG_MT9P031_RED_GAIN, 0x0079); //Red_gain_reg
+ ret |= mt9p031_reg_write(client, REG_MT9P031_GREEN_2_GAIN, 0x0079); //Green2_gain_reg
+ ret |= mt9p031_reg_write(client, REG_MT9P031_GLOBAL_GAIN, 0x0026); //Analog Gain
+
這份driver source code 要自行擺放檔案到正確的位置,以及部份檔案需要手動剪貼.
基本上不困難,我就不在此詳述.更動檔案如下
arch/arm/mach-omap2/board-omap3beagle.c
arch/arm/mach-omap2/board-omap3beagle-camera.c
drivers/media/video/mt9p031.c
drivers/media/video/mt9p031.h
drivers/media/video/Makefile
drivers/media/video/Kconfig
設定mt9p031 kernel config 為
接著重新compile kernel及module並安裝至root file system.
如果driver 順利掛上,在kernel log會看到
mt9p031 2-0048: mt9p031 chip ID 1801
根據driver source 中 README提到可以透過sysfs更改camera 參數.我實際測試卻出現錯誤@@
# cd /sys/devices/platform/i2c_omap.2/i2c-2/2-0048/
# cat gain_val 24
# echo "40" > gain_val
[ 2209.002258] mt9p031 2-0048: Error setting gain.-121
[ 2209.006988] mt9p031: Global gain write failed
Camera 測試的可用gstreamer.
不過實際測試frame rate還是無法到達30fps應該是gstreamer效率的關係,
因此我修改TI提供的demo程式來讀取camera確實就能達到30fps.
接著再把以前曾經實做過的以TI DSP encode H.264加上去,最後再輸出打包為H264RTP封包.
source code放在github
https://github.com/gigijoe/BeagleBoard-xM-video_encode_v4l2_rtp
將project抓下來後請搬到
$DVSDK/dmai_2_20_00_14/packages/ti/sdo/dmai/apps/
cd $DVSDK
make dmai
執行檔位在
dmai_2_20_00_14/packages/ti/sdo/dmai/apps/video_encode_v4l2_rtp/linux/video_encode_v4l2_rtp_dm3730.x470MV
將它複製到root filesystem中 /usr/share/ti/ti-dmai-apps/
萬事具備,執行吧
BeagleBoard xM
cd /usr/share/ti/ti-dmai-apps/
./video_encode_v4l2_rtp_dm3730.x470MV -b 2000000 -c h264enc -i /dev/video0 -o 192.168.168.93 -p 1234 -r 640x480 --benchmark
PC : IP 192.168.168.93
gst-launch udpsrc port=1234 caps="application/x-rtp,media=(string)video,clock-rate=(int)90000,encoding-name=(string)H264" ! rtph264depay ! ffdec_h264 ! xvimagesink
最後在透過usb ethernet 傳送影像會hang住,網路上有人發生過但還沒有答案.
http://groups.google.com/group/beagleboard/browse_thread/thread/375026c833e1308b/528751f3690c7d5b?lnk=raot
[ 103.995117] ------------[ cut here ]------------
[ 103.999908] WARNING: at net/sched/sch_generic.c:255 dev_watchdog+0x17c/0x280()
[ 104.007202] NETDEV WATCHDOG: usb0 (smsc95xx): transmit queue 0 timed out
[ 104.014099] Modules linked in: sdmak lpm_omap3530 dsplinkk cmemk bufferclass_ti omaplfb pvrsrvkm ipv6 rtc_twl rtc_core mt9p031
[ 104.025756] [ ] (unwind_backtrace+0x0/0xdc) from [ ] (warn_slowpath_common+0x48/0x60)
[ 104.035247] [ ] (warn_slowpath_common+0x48/0x60) from [ ] (warn_slowpath_fmt+0x24/0x30)
[ 104.044921] [ ] (warn_slowpath_fmt+0x24/0x30) from [ ] (dev_watchdog+0x17c/0x280)
[ 104.054199] [ ] (dev_watchdog+0x17c/0x280) from [ ] (run_timer_softirq+0x268/0x378)
[ 104.063568] [ ] (run_timer_softirq+0x268/0x378) from [ ] (__do_softirq+0xf0/0x1ec)
[ 104.072784] [ ] (__do_softirq+0xf0/0x1ec) from [ ] (irq_exit+0x48/0x9c)
[ 104.081024] [ ] (irq_exit+0x48/0x9c) from [ ] (asm_do_IRQ+0x74/0x90)
[ 104.089019] [ ] (asm_do_IRQ+0x74/0x90) from [ ] (__irq_svc+0x44/0xa8)
[ 104.097076] Exception stack(0xc0603f88 to 0xc0603fd0)
[ 104.102172] 3f80: 00000000 80000013 00f9982c 00000000 c0602000 c064db9c
[ 104.110412] 3fa0: c002f014 c0605e68 8002cc0c 413fc082 0000001f 00000000 c06085b8 c0603fd0
[ 104.118774] 3fc0: c0045450 c0036f1c 60000013 ffffffff
[ 104.123962] [ ] (__irq_svc+0x44/0xa8) from [ ] (cpu_idle+0x78/0xbc)
[ 104.131866] [ ] (cpu_idle+0x78/0xbc) from [ ] (start_kernel+0x260/0x2c0)
[ 104.140197] [ ] (start_kernel+0x260/0x2c0) from [<80008034>] (0x80008034)
[ 104.147827] ---[ end trace 640b83e4eff706c8 ]---
我猜應該是hardware的問題,因為我用USB Wifi也會當.
目前的解法是從USB otg port接USB hub再接USB wifi.
這樣,網路就不會斷了...
Reference :
http://maxgalemin.blogspot.com/2011/04/li-5m03-camera-on-beagleboard-xm.html
http://gitorious.org/rowboat/hardware-ti-omap3/blobs/e82865bd56a086480972fecdecc6f38308c05c35/liboverlay/v4l2_utils.c
http://blogold.chinaunix.net/u/19273/showart_2254379.html
http://e2e.ti.com/support/dsp/davinci_digital_media_processors/f/100/t/7826.aspx
http://e2e.ti.com/support/dsp/omap_applications_processors/f/447/p/87922/303994.aspx
2011年5月13日 星期五
2011年5月5日 星期四
BeagleBoard Uart Level Shift
There are three Uart port can be use on BeagleBoard, while Uart 3 as default console port, Uart 1 & 2 are free to use. There are many devices can be connect to Uart, such as GPS module, blue tooth module and PWM controller.
But, there's a serious problem. The BeagleBoard I/O works at 1.8v and for most of devices 1.8v is not "High" enough. So, I'm trying to higher the 1.8v signal to 5v signal.
Google this issue, I found the procdure is called "Level Shift" and can be done with two n-channel FET. The actual electronic circuit as below.
http://www-g.eng.cam.ac.uk/mmg/teaching/linearcircuits/mosfet.html
The n-channel FET is 2N7000
http://www.fairchildsemi.com/ds/2N/2N7000.pdf
According to BeagleBoard SRM (System Reference Manual), Uart 2 pins can be found on the expansion header.
PIN 6 - UART2_TX
Make sure the pin mux is correct configured. It should be work.
But, there's a serious problem. The BeagleBoard I/O works at 1.8v and for most of devices 1.8v is not "High" enough. So, I'm trying to higher the 1.8v signal to 5v signal.
Google this issue, I found the procdure is called "Level Shift" and can be done with two n-channel FET. The actual electronic circuit as below.
http://www-g.eng.cam.ac.uk/mmg/teaching/linearcircuits/mosfet.html
The n-channel FET is 2N7000
http://www.fairchildsemi.com/ds/2N/2N7000.pdf
According to BeagleBoard SRM (System Reference Manual), Uart 2 pins can be found on the expansion header.
PIN 6 - UART2_TX
Make sure the pin mux is correct configured. It should be work.
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
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
訂閱:
文章 (Atom)