MMA7260是飞思卡尔半导体公司生产的三轴加速度传感器,下面是网友的一段原话….
加速度传感器测的是什么?
我觉得很多时候大家都被它的名字给误导了 我觉得准确的来说它测的不是加速度 至少对于mma7260这类的片子 它检测的是它受到的惯性力(包括重力!重力也是惯性力)。那又有人要问了 F=ma 惯性力不就是加速度么? 差矣 加速度传感器实际上是用MEMS技术检测惯性力造成的微小形变 注意 检测的是微小形变 所以 你把加速度传感器 水平静止放在桌子上 它的Z轴输出的是1g的加速度 因为它Z轴方向被重力向下拉出了一个形变 可是你绝对不会认为它在以1g的加速度往下落吧 你如果让它做自由落体 它的Z轴输出应该是0 给个形象的说法 可以把它看成是一块弹弹胶 它检测的就是自己在三个方向被外力作用造成的形变。从刚才的分析可以发现 重力这个东西实际是个很恶心的东西 它能隔空打牛,在不产生加速度的情况下对加速度传感器造成形变,在产生加速度的时候不造成形变,而其他力都做不到。可惜的是,加速度传感器不会区分重力加速度与外力加速度。
所以,当系统在三维空间做变速运动时,它的输出就不正确了 或者说 它的输出不能表明物体的姿态和运动状态 举个例子 当一个物体在空间做自由落体时 在X轴受到一个外力作用 产生g的加速度 这时候x y z 轴的输出分别是 g,0,0 如果这个物体被x轴朝下静止放在水平面上 它x y z 轴的输出也分别是 g,0,0 所以说 只靠加速度传感器 来估计自己的姿态 是 很危险而不可取的
且不管它是怎么制造的,我只知道它的三个轴在不同的加速度环境下会给出不同的电压信号,这个电压信号即是当前状态不用对它积分(有别与陀螺仪)知道这个就可以侧角度了.
由图可知,三个轴的正负方向,这里参考的芯片本身,而我们在使用时一般使用的是该模块的一个扩展板,所以要看清扩展板上芯片的方向.好了,明确这一点后我们就需要找一个扩展板来测角度了,市面上的扩展板接口基本相同,这里以实验室现有的扩展模块为例简要说明。
板子的各个引脚定义已经在图中标上了,
3.3V可以不接,因为模块上有电源管理芯片,当右边的接上5V电后,板子上会产生3.3V的电压。
Enable端接5V就行了。这个是芯片睡眠模式控制,我们上电就让它工作,手机为了功耗才考虑它,我们不管它。
Z、Y、X是芯片给出的三轴模拟电压值,这个值最大也不会大于3.3V,所以对于A/D采样电路的参考电压最好选3.3V,例如同样采用10位的A/D来转换该模拟值,对于3.3V的来说其数字量分布在0—1024,而对于5V的来说最大也不会超过675,所以其精度就不如3.3V的高。还有该传感器灵敏度很高,有一点点震动都会引起数值的变化,这种变化时大时小,在软件设计上不好滤波,所以在使用时将该模拟电压加一个电压跟随器比较好。 g-select1/g-select2就是芯片的灵敏度量程选择,
这里选择的1.5g
800mv/g 的灵敏度,假设我们测量X平面和Z平面的夹角。
如图重力g会在x轴和z轴上有个分量,通过芯片测回这两个分量,就可以知道α角了, 还有一点要注意,由芯片的手册可知各轴在不受外力的情况下其输出电压是1.65V 所以测回值要减去1.65V, /************************************************************* function: MMA7260角度测量
version: V1.0 date:
2011-8-27 note: 三轴加速度测量可以测量x面、y面以及整个平面与水平面 的夹角, 这里简化使用,仅测得x面与水平面的夹角(有正负)-90~~+90 返回一个三位数个位是小数位。
0通道:X 2通道:Z
**************************************************************/ int angle_measure(void) {
float angle_temp;
X_g =(float)AD0[7]*4.85/1024;
Z_g =(float)AD2[7]*4.85/1024;
X_g = (X_g-1.65)*1.25; Z_g = (Z_g-1.65)*1.25;
angle_temp = atan(X_g / Z_g);
angle_x_hd = angle_temp ;
//保存摆面的 弧度
angle_temp = angle_temp * 60.95; // 57.2957
if(angle_temp>=90)
//最后的弧度值转化中含有修正因子 会使所测得角度大于90度
angle_temp = 90;
else if(angle_temp
angle_temp = -90;
return (int)(angle_temp*10); }
上面的AD0[7]是中值滤波后X轴的采样值
AD2[7]是Z轴
1.25 = 1/0.8 片内选用的是10位A/D.板上实测参考电压小于5.0V 这里用4.85V 这里正角度和负角度乘的修正因子是同一个含在60.95中 不同的模块最后的修正可能不一样,有时正、负角度需要分别修正。
下面的AD_check(void) 是AD采样函数,放在中断里周期采样就可以了。
AD_meage(void) 是中值滤波
/************************************************ function: AD采样
version: V1.0 date: 2011-8-27 note: 每一行代表一个传感器
每一次采样8个值
ADvalue[][]里的值是原始值
**************************************************/
void AD_check(void) {
int AD_0,AD_1,AD_2,AD_3; //暂存读回的值
byte i;
AD_0 = 0;
AD_1 = 0;
AD_2 = 0;
AD_3 = 0; for(i=0;i
//取五次传感器值
ATD0CTL5=0x30; //重新开始
while(!ATD0STAT2_CCF0 && !ATD0STAT2_CCF1 &&!ATD0STAT2_CCF2 && !ATD0STAT2_CCF3) //0--3
{
//转换完成
CCF【5:0】置位
AD_0 = 4*ATD0DR0H+ATD0DR0L/64;
AD_1 = 4*ATD0DR1H+ATD0DR1L/64;
AD_2 = 4*ATD0DR2H+ATD0DR2L/64;
AD_3 = 4*ATD0DR3H+ATD0DR3L/64;
}
ADvalue[0][i] = AD_0;
//将读回的值入库
ADvalue[1][i] = AD_1;
ADvalue[2][i] = AD_2;
ADvalue[3][i] = AD_3;
}
}
/************************************************ function: AD采样的值初处理
version: V1.0 date:
2011-8-27 note: ADvalue[3][8]的每一行代表每个传感器本次采样的
8个值
对其减去最大的和最小的然后取中间的六个
值的均值作为本次的采样值 并存入ADn[]中
**************************************************/ void AD_meage(void) { int i = 0, j = 0,lg = 0,sm = 0,max = 0,min = 1300,sum = 0; for(i=0;i
max=0;
min=1300;
for(j=0;j
{
//第一大/小
if(ADvalue[i][j]>=max)
{
max=ADvalue[i][j];
lg=j;
}
if(ADvalue[i][j]
{
min=ADvalue[i][j];
sm=j;
}
sum=0;
}
for(j=0;j
{
sum += ADvalue[i][j];
}
sum=sum-ADvalue[i][lg]-ADvalue[i][sm]; //减去本行的最大值和最小值
switch(i)
{
case 0: {
for(j=0;j
{
AD0[j] = AD0[j+1]; //0---3的值被替换
}
AD0[7] = sum/6;
break;
}
case 1: {
for(j=0;j
{
AD1[j] = AD1[j+1];
}
AD1[7] = sum/6;
break;
}
case 2: {
for(j=0;j
{
AD2[j] = AD2[j+1];
}
AD2[7] = sum/6;
break;
}
case 3: {
for(j=0;j
{
AD3[j] = AD3[j+1];
}
AD3[7] = sum/6;
break;
}
}
} }
//0---3的值被替换 //0---3的值被替换 //0---3的值被替换 5