目录
Gsensor driver. 1
一、Gsensor文件建立与编译... 1
二、Gsensor的原理图... 2
三、Gsensor的相关配置... 2
四、Gsensor I2C 读写... 3
五、X、Y、Z轴数据的获取... 4
六、Gsensor加速度算法... 8
七、驻车监控功能:... 9
八、Xxx 调试总结:... 11
G-sensor中文是重力传感器的意思(英文全称是Gravity-sensor),它能够感知到加速力的变化,加速力就是当物体在加速过程中作用在物体上的力,比如晃动、跌落、上升、下降等各种移动变化都能被G-sensor转化为电信号,然后通过微处理器的计算分析后,就能够完成程序设计好的功能,比如汽车在行驶过程中突然加速前进或静止或剧烈震动,从而触发紧急录影,以及驻车监控功能。
驱动文件路径:peripheral\g_sensor
建立A_GSensor_MEMS_XXX.c、A_GSensor_MEMS_XXX.h
添加kconfig 选项
config G_SENSOR_MEMS_XXX
bool"G_SENSOR_MEMS_XXX"
default n
Gsensor编译:
ifdef CONFIG_G_SENSOR_MEMS_XXX
libperipheral-objs += $(GSENSORPATH)/A_GSensor_MEMS_XXX.o
endif
GsensorXXX的原理图与LIS3DE pin to pin,(XXX 无INT2.) XXX的引脚4和6分别是SCL和SDA并与A__I2C_CHANNEL2相连接,9脚为INT2脚,连接DSP PWC_wkup1,用于驻车监控唤醒。INT1 为硬件gpio 中断,并未使用。
寄存器地址的配置
/* Reg address defination */
#define GSENSOR_MEMS_XXX_I2C_ADDR 0x30
//Digital Gyro Register Define
#define REG_WHO_AM_I 0x04 /*xx change*/
#define REG_POWER_DOWN_CTRL 0X01 /*xx add*/
#define REG_ACTION 0X02 /*xx add*/
#define REG_MOTION_THRESHOLD 0X03 /*xx add*/
#define REG_START_DATA_READ 0X04 /*xx add*/
#define REG_STATUS 0X05 /*xx add*/
//06h~0Dh: Data registers
#define REG_X_L 0x06
#define REG_X_H 0x07
#define REG_Y_L 0x08
#define REG_Y_H 0x09
#define REG_Z_L 0x0A
#define REG_Z_H 0x0B
#define REG_INT_CFG 0X15 /*xx add*/
#define REG_CTRL1 0x16
#define REG_CTRL2 0x17
#define REG_CTRL3 0x18
#define REG_OVERSAMPLING 0x38
#define MAX_REG (REG_OVERSAMPLING)
Gsensor初始化的设置
int GSENSOR_MEMS_XXX_Init(void)
{
UINT16 Data;
UINT8 temp[10] = {0};
if((GSENSOR_MEMS_XXX_Read( REG_WHO_AM_I, &Data) != OK) || (Data !=WHO_AM_I_ID)){
GSENSOR_DBG("[%s]: Addr: 0x%02x, Data: 0x%02x", __func__,REG_WHO_AM_I, (UINT8)Data);
return NG;
}else{
MY_MSG("REG_WHO_AM_I:0x%X",Data);
}
GSENSOR_MEMS_XXX_Write( REG_POWER_DOWN_CTRL, 0x02); // Powerdown reset
A_KAL_TaskSleep(3);
GSENSOR_MEMS_XXX_Write(0x03,0x1F);//
GSENSOR_MEMS_XXX_Write(0x38,0x9F);//
GSENSOR_MEMS_XXX_Write(0x15,0x00);//0x00 low active 0x08 high active(INT PIN)
GSENSOR_MEMS_XXX_Write(0x16,0x00);//
GSENSOR_MEMS_XXX_Write(0x02,0x02);//
GSENSOR_MEMS_XXX_Write(0x02,0x00);//
GSENSOR_MEMS_XXX_Write(0x02,0x04);//
GSENSOR_MEMS_XXX_Write(0x02,0x00);//
return OK;
}
一次读取多个字节:
VoidGSENSOR_MEMS_XXX_ReadData(UINT16addr,intRxDataSize,UINT8*RxDataBuf)
{
UINT16WorkUINT16[3];
WorkUINT16[0]= A__I2C_RESTART_FLAG | XXX_Info.I2CAddr; /* Slave Address + r/w (0) */
WorkUINT16[1]= addr; /* Sub Address */
WorkUINT16[2]= A__I2C_RESTART_FLAG | XXX_Info.I2CAddr | 0x01;
if(A_I2C_ReadAfterWrite(XXX_Info.I2CCHN, A__I2C_SPEED_FAST, 3, WorkUINT16, RxDataSize, RxDataBuf, 5000)!= OK) {
GSENSOR_DBG("[%s]fail", __func__);
return;
}
}
GSENSOR_MEMS_XXX_ReadData(0x00, 1, temp1);
GSENSOR_MEMS_XXX_ReadData(0x04, 3, temp);
GSENSOR_MEMS_XXX_ReadData(0x06, 6, temp);
int AppGSensor_XXX_DetectHandle(void)
{
UINT16 data;
INT16 xdata,ydata,zdata;
INT32 xTemp = 0, yTemp = 0, zTemp = 0;
float gx, gy, gz,g_value_sqrt;
UINT8 temp[10] = {0};
UINT8 temp1[2] = {0};
GSENSOR_MEMS_XXX_ReadData(0x00, 1,temp1);
GSENSOR_MEMS_XXX_ReadData(0x04, 3,temp);
GSENSOR_MEMS_XXX_ReadData(0x06, 6,temp);
A_Prinxxolor(GREEN,"[8bit]%x,%x,%x,%x,%x,%x",temp[0],temp[1],temp[2],temp[3],temp[4],temp[5]);
data = temp[0];
data |= (temp[1] << 8);
xdata = data;
//xdata = xdata/256;//256/g
data = temp[2];
data |= (temp[3] << 8);
ydata = data;
//ydata = ydata/256;//256/g
data = temp[4];
data |= (temp[5] << 8);
zdata = data;
//zdata=zdata/256;//256/g
A_Prinxxolor(GREEN, "[16bit/havechange to complement ]xdata:%d, ydata:%d, zdata:%d",xdata,ydata,zdata);
#if 0
/*if ((xdata & 0x8000) == 0x8000)
{
//最高位是符号位,补码转换
xTemp = -((0xffff)- xdata));
}
if ((ydata & 0x8000) == 0x8000)
{
//最高位是符号位,补码转换
yTemp = -((0xffff)- ydata));
}
if ((zdata & 0x8000) == 0x8000)
{
//最高位是符号位,补码转换
zTemp = -((0xffff)- zdata));
}*/
if ((xdata >> (13)) == 0x0007)
{
//最高位是符号位,补码转换
xTemp = -((0xffff - xdata)+1);
//xTemp = -((7 << 13) -1 - xdata);
}
else
{
xTemp = xdata;
}
if ((ydata >> (13)) == 0x0007)
{
//最高位是符号位,补码转换
yTemp = -((0xffff -ydata)+1);
//yTemp = -((7 << 13) -1 - ydata);
}
else
{
yTemp = ydata;
}
if ((zdata >> (13)) == 0x0007)
{
//最高位是符号位,补码转换
zTemp = -((0xffff -zdata)+1);
//zTemp = -((7 << 13) -1 - zdata);
}
else
{
zTemp = zdata;
}
#endif
#if 0
xTemp = xTemp/2;
yTemp = yTemp/2;
zTemp = zTemp/2;
//A_Prinxxolor(RED,"x:%d,y:%d,z:%d", xTemp, yTemp, zTemp);
//------------------Add moving avg forZ---------------------
#endif
if((temp1[0]==0xA2) || (temp1[0]==0xA3)|| (temp1[0]==0xA5))
{
#if 1
#define moving_step 5 //Setup the times of moving average.
static int pointer = -1;
static shortbufferave[1][moving_step]; //buffer of Z, data
short sum[3]; // sum of moving_step
int k,j;
if ( pointer == -1 )
{
for(k = 0; k < moving_step; ++k)
{
bufferave[0][k]= zdata;
}
}
pointer++;
pointer %= moving_step;
bufferave[0][pointer] =zdata;
sum[0] = 0;
for(j = 0; j
{
sum[0] +=bufferave[0][j];
}
sum[0] = sum[0] /moving_step;
zTemp = sum[0];
xTemp = xdata/2;
yTemp = ydata/2;
zTemp = zTemp;
#if 0
if((moving_step==1)&&(zTemp<(256*0.2)))
{
zTemp=0;
}
elseif((moving_step>1)&&(zTemp<(256*0.2)))
{
zTemp=zTemp;
}
//-----------------------------------------------
#endif
#endif
//xdata = xdata/2;//256/g
//ydata = ydata/2;//256/g
//zdata = zdata ;//256/g
}
else
{
xTemp = xdata/2;//256/g
yTemp = ydata/2;//256/g
zTemp = zdata/2;//256/g
}
calc_gvalue_xxx(xTemp, &gx);
calc_gvalue_xxx(yTemp, &gy);
calc_gvalue_xxx(zTemp, &gz);
gx_cur = gx;
gy_cur = gy;
gz_cur = gz;
g_value_sqrt=sqrt(pow(gx,2)+pow(gy,2)+pow(gz,2));
A_Prinxxolor(RED,"g_value_sqrt:%3.3f",g_value_sqrt);
Check_even_xxx(gx, gy, gz);
return OK;
}
检测算法:将13位数据(3位为符号位)转换g 值后,判断实时g值与平均g值的大小来检测是否触发紧急录影。
void Check_even_xxx(float x, float y, floatz)
{
static float g_data[5][3] = {0.0};
static int gc =0;
int i = 0, j = 0;
static float avg[3] = {0.0};
static float dtmax, dtx, dty, dtz;
if (gc<5){
g_data[gc][0] = x;
g_data[gc][1] = y;
g_data[gc][2] = z;
gc++;
avg[0] = (g_data[0][0] + g_data[1][0] + g_data[2][0] + g_data[3][0] +g_data[4][0])/gc;
avg[1] = (g_data[0][1] + g_data[1][1] + g_data[2][1] + g_data[3][1] +g_data[4][1])/gc;
avg[2] = (g_data[0][2] + g_data[1][2] + g_data[2][2] + g_data[3][2] +g_data[4][2])/gc;
return;
}else{
Gfabs_xxx(&dtx, (x-avg[0]));
Gfabs_xxx(&dty, (y-avg[1]));
Gfabs_xxx(&dtz, (z-avg[2]));
Max3_xxx(&dtmax, dtx, dty, dtz);
A_Print("dtmax = %.2f,g_target: %.2f", dtmax,g_target);
if (dtmax > g_target){
A_Prinxxolor(BLUE,"urgent event:sendmsg:AMSG_CMD_GSENSOR_EVEN");
SendMsg(EVENT_RECORD, 1, 0);
gc = 0;
return;
}
for(i=0; i<4; i++){
for(j=0; j<3; j++){
g_data[i][j] = g_data[i+1][j];
}
}
g_data[4][0] = x;
g_data[4][1] = y;
g_data[4][2] = z;
avg[0] = (g_data[0][0] + g_data[1][0] + g_data[2][0] + g_data[3][0] +g_data[4][0])/5.0;
avg[1] = (g_data[0][1] + g_data[1][1] + g_data[2][1] + g_data[3][1] +g_data[4][1])/5.0;
avg[2] = (g_data[0][2] + g_data[1][2] + g_data[2][2] + g_data[3][2] +g_data[4][2])/5.0;
}
}
碰撞触发紧急录影灵敏度设置:
int AppGSensor_XXX_set_event_sensitivity(UINT16sens)
{
if(sens== 1)/*height*/
g_target= 1.0;
elseif(sens == 2)/*middle*/
g_target= 1.5;
elseif(sens == 3)/*low*/
g_target= 2.0;
else
g_target= 0;
return 0;
}
在DVR关机时,设置REG_MOTION_THRESHOLD等寄存器来打开或关闭驻车监控功能。REG_MOTION_THRESHOLD设置碰撞灵敏度
static int GSENSOR_MEMS_XXX_enable_interrupt(intsensitivity){
UINT16 Data;
MY_MSG("[GSENSOR_MEMS_XXX_enable_interrupt]sensitivity:%d",sensitivity);
Data = 0x1B;
GSENSOR_MEMS_XXX_Write( REG_CTRL1, Data);
swixxh(sensitivity){
case 0:
Data = 0;
GSENSOR_MEMS_XXX_Write( REG_CTRL1, Data);
Data = 0;
GSENSOR_MEMS_XXX_Write( REG_INT_CFG, Data);
break;
case 1:
Data = 0x04;/*xx modify as 1g*/
GSENSOR_MEMS_XXX_Write( REG_MOTION_THRESHOLD, Data);//0x01 ~ 0x1F . 0x01= 0.25G. 0x04:1G 0x1F:7.75G
break;
case 2:
Data = 0x14;
GSENSOR_MEMS_XXX_Write( REG_MOTION_THRESHOLD, Data);
break;
case 3:
Data = 0x1F;
GSENSOR_MEMS_XXX_Write( REG_MOTION_THRESHOLD, Data);
break;
default:
break;
}
GSENSOR_MEMS_XXX_Read(0x04, &Data);
GSENSOR_MEMS_XXX_Read(0x05, &Data);
GSENSOR_MEMS_XXX_Read(0x06, &Data);
GSENSOR_MEMS_XXX_Read(0x07, &Data);
GSENSOR_MEMS_XXX_Read(0x08, &Data);
GSENSOR_MEMS_XXX_Read(0x09, &Data);
GSENSOR_MEMS_XXX_Read(0x0A, &Data);
GSENSOR_MEMS_XXX_Read(0x0B, &Data);
Data =0x4C;
GSENSOR_MEMS_XXX_Write( REG_INT_CFG, Data);
/*啟動中斷 有上拉電組--高電平輸出0x5D,低電平0x55
沒上拉電組--高電平輸出0x4C,低電平0x44*/
return OK;
}
1.调试I2C 通讯:注意排除i2c 总线上的其它设备干扰、确认i2c地址是否正确、硬件上i2c 是否需滤波和上拉。
2.GSENSOR GMA305 I2C 调通之后,获取gsensor GMA305 三轴数据不准确。原因是初始化之后,打开驻车监控功能(读写寄存器)导致gsensor模式错乱造成读取数据不正确。猜想是本身IC问题。ST的 LIS3DE 无此问题。
3. 数据读取正常后,数据漂移大。
数据conclusion:
平放(Orientation 6):
[00279860][CA9] [16bit/have change tocomplement ]xdata:37, ydata:86, zdata:-32
[00279860][CA9] xTemp: 18, yTemp: 43,zTemp: -16,gx: 0.070,gy: 0.168,gz: -0.059
垂直(Orientation 1):
[00152277][CA9] [16bit/have change tocomplement ]xdata:614, ydata:128, zdata:438
[00152277][CA9] xTemp: 307, yTemp: 64,zTemp: 219,gx: 1.199,gy: 0.250,gz: 0.855
垂直(Orientation 2):
[00226348][CA9] [16bit/have change tocomplement ]xdata:71, ydata:619, zdata:492
[00226348][CA9] xTemp: 35, yTemp: 309,zTemp: 246,gx: 0.137,gy: 1.207,gz: 0.961
垂直(Orientation 3):
[00114901][CA9] [16bit/have change tocomplement ]xdata:-495, ydata:59, zdata:460
[00114901][CA9] xTemp: -247, yTemp: 29,zTemp: 230,gx: -0.961,gy: 0.113,gz: 0.898
垂直(Orientation 4):
[00302658][CA9] [16bit/have change tocomplement ]xdata:8, ydata:-452, zdata:387
[00302658][CA9] xTemp: 4, yTemp: -226,zTemp: 193,gx: 0.016,gy: -0.879,gz: 0.754
平放(Orientation 5):
[00037125][CA9] [16bit/have change tocomplement ]xdata:85, ydata:27, zdata:911
[00037125][CA9] xTemp: 42, yTemp: 13,zTemp: 455,gx: 0.164,gy: 0.051,gz: 1.777