【翻译】利用加速度求解位置的算法——三轴传感器
2015-03-30 19:21
901 查看
摘要
此文档描述并使用MMA7260QT三轴加速计和低功耗的9S08QG8八位单片机实现求解位置的算法 。
在今天先进的电子市场,有不少增加了许多特性和智能的多功能的产品。定位和游戏只是得益于获取到的位置信息的一部分市场。一个获取这种信息的可选方案是通过使用惯性传感器。从这些传感器中取得的信号需要进行一些处理,因为在加速度和位置之间没有一种直接转换。
为了获得位置,需要对加速度进行二次积分。本文介绍一种简单的算法实现加速度的二重积分。为了获取加速度的二重积分,一个简单的积分要进行两次,因为这样也可以顺便获取速度。
接下来要展示的算法,能够应该于任何传感轴,所以一维、二维、三维的位置都可以被计算出。当在获取三维位置信息时,要特别地除去重力加速度的影响。下面的算法实现还包括了一个二维系统的例子(比如鼠标)。
应用潜力
这种算法的应用潜力在于个人导航、汽车导航和(back-up)GPS、防盗设备、地图追踪、3D游戏、计算机鼠标等等。这类产品都需要用到求解位置信息的算法。
本文所介绍的算法在位移精度要求不是很严格的情况下很有用。其他的情况和影响特别是应用,当采用本文算法时,需要考虑一下。对最终程序进行微小的修改和调整,这种算法能够达到更高的精度。
理论知识和算法
理解本文算法的最好方法是回顾一下数学上的积分知识。
加速度是一个对象速度的变化速率。同时,速度是同样一个对象位置的变化速率。换句话说,速度是位置的导数,加速度是速度的导数,因此如下公式:
View Code
原理图
总结
本文档为利用加速度计实现定位算法提供了一些基本的概念。
这种特定的算法在对位移精度要求不是很严格中非常有用。其他注意事项和具体的应用程序的影响应该在实现这个示例时被考虑。
这种积分算法适合于低端嵌入式应用,因为它的简单性和少量的指令。它也没有涉及任何浮点运算。
原文链接:http://cache.freescale.com/files/sensors/doc/app_note/AN3397.pdf?fsrch=1&sr=2
本文链接:/article/7044966.html
此文档描述并使用MMA7260QT三轴加速计和低功耗的9S08QG8八位单片机实现求解位置的算法 。
在今天先进的电子市场,有不少增加了许多特性和智能的多功能的产品。定位和游戏只是得益于获取到的位置信息的一部分市场。一个获取这种信息的可选方案是通过使用惯性传感器。从这些传感器中取得的信号需要进行一些处理,因为在加速度和位置之间没有一种直接转换。
为了获得位置,需要对加速度进行二次积分。本文介绍一种简单的算法实现加速度的二重积分。为了获取加速度的二重积分,一个简单的积分要进行两次,因为这样也可以顺便获取速度。
接下来要展示的算法,能够应该于任何传感轴,所以一维、二维、三维的位置都可以被计算出。当在获取三维位置信息时,要特别地除去重力加速度的影响。下面的算法实现还包括了一个二维系统的例子(比如鼠标)。
应用潜力
这种算法的应用潜力在于个人导航、汽车导航和(back-up)GPS、防盗设备、地图追踪、3D游戏、计算机鼠标等等。这类产品都需要用到求解位置信息的算法。
本文所介绍的算法在位移精度要求不是很严格的情况下很有用。其他的情况和影响特别是应用,当采用本文算法时,需要考虑一下。对最终程序进行微小的修改和调整,这种算法能够达到更高的精度。
理论知识和算法
理解本文算法的最好方法是回顾一下数学上的积分知识。
加速度是一个对象速度的变化速率。同时,速度是同样一个对象位置的变化速率。换句话说,速度是位置的导数,加速度是速度的导数,因此如下公式:
#include <hidef.h> #include "derivative.h" #include "adc.h" #include "buzzer.h" #include "SCItx.h" #pragma DATA_SEG MY_ZEROPAGE unsigned char near Sample_X; unsigned char near Sample_Y; unsigned char near Sample_Z; unsigned char near Sensor_Data[8]; unsigned char near countx,county ; signed int near accelerationx[2], accelerationy[2]; signed long near velocityx[2], velocityy[2]; signed long near positionX[2]; signed long near positionY[2]; signed long near positionZ[2]; unsigned char near direction; unsigned long near sstatex,sstatey; #pragma DATA_SEG DEFAULT void init(void); void Calibrate(void); void data_transfer(void); void concatenate_data(void); void movement_end_check(void); void position(void); void main (void) { init(); get_threshold(); do { position(); }while(1); } /******************************************************************************* The purpose of the calibration routine is to obtain the value of the reference threshold. It consists on a 1024 samples average in no-movement condition. ********************************************************************************/ void Calibrate(void) { unsigned int count1; count1 = 0; do{ ADC_GetAllAxis(); sstatex = sstatex + Sample_X; // Accumulate Samples sstatey = sstatey + Sample_Y; count1++; }while(count1!=0x0400); // 1024 times sstatex=sstatex>>10; // division between 1024 sstatey=sstatey>>10; } /*****************************************************************************************/ /****************************************************************************************** This function obtains magnitude and direction In this particular protocol direction and magnitude are sent in separate variables. Management can be done in many other different ways. *****************************************************************************************/ void data_transfer(void) { signed long positionXbkp; signed long positionYbkp; unsigned int delay; unsigned char posx_seg[4], posy_seg[4]; if (positionX[1]>=0) { //This line compares the sign of the X direction data direction= (direction | 0x10); //if its positive the most significant byte posx_seg[0]= positionX[1] & 0x000000FF; // is set to 1 else it is set to 8 posx_seg[1]= (positionX[1]>>8) & 0x000000FF; // the data is also managed in the // subsequent lines in order to posx_seg[2]= (positionX[1]>>16) & 0x000000FF; // be sent. The 32 bit variable must be posx_seg[3]= (positionX[1]>>24) & 0x000000FF; // split into 4 different 8 bit // variables in order to be sent via // the 8 bit SCI frame } else {direction=(direction | 0x80); positionXbkp=positionX[1]-1; positionXbkp=positionXbkp^0xFFFFFFFF; posx_seg[0]= positionXbkp & 0x000000FF; posx_seg[1]= (positionXbkp>>8) & 0x000000FF; posx_seg[2]= (positionXbkp>>16) & 0x000000FF; posx_seg[3]= (positionXbkp>>24) & 0x000000FF; } if (positionY[1]>=0) { // Same management than in the previous case direction= (direction | 0x08); // but with the Y data. posy_seg[0]= positionY[1] & 0x000000FF; posy_seg[1]= (positionY[1]>>8) & 0x000000FF; posy_seg[2]= (positionY[1]>>16) & 0x000000FF; posy_seg[3]= (positionY[1]>>24) & 0x000000FF; } else {direction= (direction | 0x01); positionYbkp=positionY[1]-1; positionYbkp=positionYbkp^0xFFFFFFFF; posy_seg[0]= positionYbkp & 0x000000FF; posy_seg[1]= (positionYbkp>>8) & 0x000000FF; posy_seg[2]= (positionYbkp>>16) & 0x000000FF; posy_seg[3]= (positionYbkp>>24) & 0x000000FF; } delay = 0x0100; Sensor_Data[0] = 0x03; Sensor_Data[1] = direction; Sensor_Data[2] = posx_seg[3]; Sensor_Data[3] = posy_seg[3]; Sensor_Data[4] = 0x01; Sensor_Data[5] = 0x01; Sensor_Data[6] = END_OF_FRAME; while (--delay); SCITxMsg(Sensor_Data); // Data transferring function while (SCIC2 & 0x08); } /*****************************************************************************************/ /****************************************************************************************** This function returns data format to its original state. When obtaining the magnitude and direction of the position, an inverse two's complement is made. This function makes the two's complement in order to return the data to it original state. It is important to notice that the sensibility adjustment is greatly impacted here, the amount of "ones" inserted in the mask must be equivalent to the "ones" lost in the shifting made in the previous function upon the sensibility modification. ******************************************************************************************/ void data_reintegration(void) { if (direction >=10) {positionX[1]= positionX[1]|0xFFFFC000;} // 18 "ones" inserted. Same size as the //amount of shifts direction = direction & 0x01; if (direction ==1) {positionY[1]= positionY[1]|0xFFFFC000;} } /****************************************************************************************** This function allows movement end detection. If a certain number of acceleration samples are equal to zero we can assume movement has stopped. Accumulated Error generated in the velocity calculations is eliminated by resetting the velocity variables. This stops position increment and greatly eliminates position error. ******************************************************************************************/ void movement_end_check(void) { if (accelerationx[1]==0) //we count the number of acceleration samples that equals cero { countx++;} else { countx =0;} if (countx>=25) //if this number exceeds 25, we can assume that velocity is cero { velocityx[1]=0; velocityx[0]=0; } if (accelerationy[1]==0) //we do the same for the Y axis { county++;} else { county =0;} if (county>=25) { velocityy[1]=0; velocityy[0]=0; } } /*****************************************************************************************/ /****************************************************************************************** This function transforms acceleration to a proportional position by integrating the acceleration data twice. It also adjusts sensibility by multiplying the "positionX" and "positionY" variables. This integration algorithm carries error, which is compensated in the "movenemt_end_check" subroutine. Faster sampling frequency implies less error but requires more memory. Keep in mind that the same process is applied to the X and Y axis. *****************************************************************************************/ void position(void) { unsigned char count2 ; count2=0; do{ ADC_GetAllAxis(); accelerationx[1]=accelerationx[1] + Sample_X; //filtering routine for noise attenuation accelerationy[1]=accelerationy[1] + Sample_Y; //64 samples are averaged. The resulting //average represents the acceleration of //an instant count2++; }while (count2!=0x40); // 64 sums of the acceleration sample accelerationx[1]= accelerationx[1]>>6; // division by 64 accelerationy[1]= accelerationy[1]>>6; accelerationx[1] = accelerationx[1] - (int)sstatex; //eliminating zero reference //offset of the acceleration data accelerationy[1] = accelerationy[1] - (int)sstatey; // to obtain positive and negative //acceleration if ((accelerationx[1] <=3)&&(accelerationx[1] >= -3)) //Discrimination window applied {accelerationx[1] = 0;} // to the X axis acceleration //variable if ((accelerationy[1] <=3)&&(accelerationy[1] >= -3)) {accelerationy[1] = 0;} //first X integration: velocityx[1]= velocityx[0]+ accelerationx[0]+ ((accelerationx[1] -accelerationx[0])>>1); //second X integration: positionX[1]= positionX[0] + velocityx[0] + ((velocityx[1] - velocityx[0])>>1); //first Y integration: velocityy[1] = velocityy[0] + accelerationy[0] + ((accelerationy[1] -accelerationy[0])>>1); //second Y integration: positionY[1] = positionY[0] + velocityy[0] + ((velocityy[1] - velocityy[0])>>1); accelerationx[0] = accelerationx[1]; //The current acceleration value must be sent //to the previous acceleration accelerationy[0] = accelerationy[1]; //variable in order to introduce the new //acceleration value. velocityx[0] = velocityx[1]; //Same done for the velocity variable velocityy[0] = velocityy[1]; positionX[1] = positionX[1]<<18; //The idea behind this shifting (multiplication) //is a sensibility adjustment. positionY[1] = positionY[1]<<18; //Some applications require adjustments to a //particular situation //i.e. mouse application data_transfer(); positionX[1] = positionX[1]>>18; //once the variables are sent them must return to positionY[1] = positionY[1]>>18; //their original state movement_end_check(); positionX[0] = positionX[1]; //actual position data must be sent to the positionY[0] = positionY[1]; //previous position direction = 0; // data variable to direction variable reset } /*****************************************************************************************/
View Code
原理图
总结
本文档为利用加速度计实现定位算法提供了一些基本的概念。
这种特定的算法在对位移精度要求不是很严格中非常有用。其他注意事项和具体的应用程序的影响应该在实现这个示例时被考虑。
这种积分算法适合于低端嵌入式应用,因为它的简单性和少量的指令。它也没有涉及任何浮点运算。
原文链接:http://cache.freescale.com/files/sensors/doc/app_note/AN3397.pdf?fsrch=1&sr=2
本文链接:/article/7044966.html
相关文章推荐
- 【翻译】利用加速度求解位置的算法——三轴传感器
- 【翻译】利用加速度求解位置的算法——三轴传感器
- 利用加速度求解位置的算法——三轴传感器
- 利用加速度求解位置的算法——三轴传感器
- 利用加速度求解位置的算法——三轴传感器
- 一个数组算法题,利用递归-回溯求解
- 三轴正交型传感器的正交性修正算法
- 栈的应用:利用顺序栈求解迷宫问题(改编自严蔚敏算法)
- 利用惯性和加速度进行网游位置同步
- 利用分治思想,写一个求解从n个元素里选取m个有多少种组合方案的(非递归)高性能算法
- 三分算法及利用三分算法求解二次函数问题
- 利用信赖域算法求解无约束的非线性最小二乘问题~
- 华为oj素数伴侣,利用匈牙利算法求解
- 三轴正交型传感器的正交性修正算法
- GY-273 HMC5883L电子指南针罗盘模块 三轴磁场传感器 avr 获取 三维位置
- 静态条件下三轴加速度求角度的算法
- 利用标准库算法求解排列组合
- 利用惯性和加速度进行网游位置同步
- 利用中国剩余定理加速解密算法求解
- 第十二周 项目4-利用遍历算法求解图问题(6,7)