LSM303DLHC

xiaoxiao2021-02-28  73

(PS:最近在帮人做一个电子罗盘,刚好STM32F429i_DISCO上有个MEMS,但是我自己没有看到底是个什么传感器,搞搞搞了半天,读出来三个数据,但我移动板子时发现数据不对劲,仔细看了看原理图,居然是L3GD20,这是个陀螺仪,顿时感到一阵无语,我记得不错的话,PX4的板子上是有过一个冗余的陀螺仪的,貌似就是这个。相应的PX4原理图上还有一个LSM303D的加速度计+磁传感器,发现这两个都是ST公司的产品,由于最近比较用CUBEMX用的比较爽,对ST公司影响很好,所以果断就是它了。)

首先,果断考虑ST官网的开发套件。

这个 STEVAL-MKI108V2 看起来就很不错,居然同时装备两个传感器。

但是往下一看就傻眼了,居然要30刀,我确定我没看错。

ST公司在和我开玩笑,上某宝搜一下,L3GD20和LSM303D怎么也凑不够30刀。。算了,我还是放弃官方套件吧。

在某报上随便买了一个LSM303D的板子。货到感觉还不错。

开始下载资料。

找到这个像是驱动文件的文件,居然有写驱动,ST公司还是很厚道的嘛。 http://www.st.com/content/st_com/en/products/embedded-software/mems-and-sensors-software/drivers-for-mems/stsw-mems009.html 但是,接下来的事情就很匪夷所思了,一个0kb的文档+一个不知道从什么地方随便拿出来的驱动文件。如下: http://download.csdn.net/detail/yt454287063/9835449 有总比没有好吧。随便编译一下,出现了连个错误,I2C_BufferRead和I2C_ByteWrite 丢失,这好办我就把原来的BSP代码封装一下就行了,但是这个命名规则怎么看都是两个人写的。而且没有一个标准约束。

uint8_t I2C_BufferRead(uint8_t* Data, uint8_t deviceAddress, uint8_t Reg, uint16_t Length) { return I2Cx_ReadBuffer(deviceAddress, Reg, Data, Length); } void I2C_ByteWrite(uint8_t *Data, uint8_t deviceAddress, uint8_t WriteAddr) { I2Cx_WriteData((uint16_t) deviceAddress, WriteAddr, *Data); }

总之这个驱动文件已经接入进来了。 参照main函数中的配置方法,照着现有的BSP文件随便写了个初始化函数:

uint8_t BSP_LSM303D_Init(void) { uint8_t ret = LSM303D_OK; I2Cx_Init(); BSP_LCD_SelectLayer(LTDC_LAYER_1); BSP_LCD_SetFont(&Font12); BSP_LCD_SetTextColor(LCD_COLOR_WHITE); BSP_LCD_SetBackColor(LCD_COLOR_BLACK); if (BSP_ACC_ReadID() == I_AM_LMS303DLHC) { uint8_t response; char LCD_Line_Text[34]; char ACC_Str[3] = "ACC"; char MAG_Str[3] = "MAG"; char *Set_ACC_Object[4] = { "SetODR", "SetMode", "SetFullScale", "SetAxis" }; char *Set_MAG_Object[4] = { "SetODR_M", "SetModeMag", "SetGainMag", "SetTemperature" }; char *Get_MAG_Object[1] = { "GetTemperature" }; char *Set_Ret_State[2] = { "NO", "OK" }; uint8_t Line_Num = 4; uint8_t Obje_Num = 0; //Set ACC //set ODR_ACCELEROMETER (turn ON device) sprintf(LCD_Line_Text, "%s %-14s ...[..]", ACC_Str, Set_ACC_Object[Obje_Num++]); BSP_LCD_SetTextColor(LCD_COLOR_WHITE); BSP_LCD_DisplayStringAtLine(Line_Num, (uint8_t *) LCD_Line_Text); response = SetODR(ODR_25Hz); if (response == MEMS_ERROR) ret = LSM303D_ERROR; BSP_LCD_SetTextColor(response ? LCD_COLOR_GREEN : LCD_COLOR_RED); BSP_LCD_DisplayStringAt(31 * 7, LINE(Line_Num++), (uint8_t *) (Set_Ret_State[response]), LEFT_MODE); //set PowerMode sprintf(LCD_Line_Text, "%s %-14s ...[..]", ACC_Str, Set_ACC_Object[Obje_Num++]); BSP_LCD_SetTextColor(LCD_COLOR_WHITE); BSP_LCD_DisplayStringAtLine(Line_Num, (uint8_t *) LCD_Line_Text); response = SetMode(NORMAL); if (response == MEMS_ERROR) ret = LSM303D_ERROR; BSP_LCD_SetTextColor(response ? LCD_COLOR_GREEN : LCD_COLOR_RED); BSP_LCD_DisplayStringAt(31 * 7, LINE(Line_Num++), (uint8_t *) (Set_Ret_State[response]), LEFT_MODE); //set Fullscale sprintf(LCD_Line_Text, "%s %-14s ...[..]", ACC_Str, Set_ACC_Object[Obje_Num++]); BSP_LCD_SetTextColor(LCD_COLOR_WHITE); BSP_LCD_DisplayStringAtLine(Line_Num, (uint8_t *) LCD_Line_Text); response = SetFullScale(FULLSCALE_2); if (response == MEMS_ERROR) ret = LSM303D_ERROR; BSP_LCD_SetTextColor(response ? LCD_COLOR_GREEN : LCD_COLOR_RED); BSP_LCD_DisplayStringAt(31 * 7, LINE(Line_Num++), (uint8_t *) (Set_Ret_State[response]), LEFT_MODE); //set axis Enable sprintf(LCD_Line_Text, "%s %-14s ...[..]", ACC_Str, Set_ACC_Object[Obje_Num++]); BSP_LCD_SetTextColor(LCD_COLOR_WHITE); BSP_LCD_DisplayStringAtLine(Line_Num, (uint8_t *) LCD_Line_Text); response = SetAxis(X_ENABLE | Y_ENABLE | Z_ENABLE); if (response == MEMS_ERROR) ret = LSM303D_ERROR; BSP_LCD_SetTextColor(response ? LCD_COLOR_GREEN : LCD_COLOR_RED); BSP_LCD_DisplayStringAt(31 * 7, LINE(Line_Num++), (uint8_t *) (Set_Ret_State[response]), LEFT_MODE); //Set MAG Obje_Num = 0; //set ODR_MAGNETOMETER (turn ON device) sprintf(LCD_Line_Text, "%s %-14s ...[..]", MAG_Str, Set_MAG_Object[Obje_Num++]); BSP_LCD_SetTextColor(LCD_COLOR_WHITE); BSP_LCD_DisplayStringAtLine(Line_Num, (uint8_t *) LCD_Line_Text); response = SetODR_M(ODR_220Hz_M); if (response == MEMS_ERROR) ret = LSM303D_ERROR; BSP_LCD_SetTextColor(response ? LCD_COLOR_GREEN : LCD_COLOR_RED); BSP_LCD_DisplayStringAt(31 * 7, LINE(Line_Num++), (uint8_t *) (Set_Ret_State[response]), LEFT_MODE); //set Magnetometer Mode sprintf(LCD_Line_Text, "%s %-14s ...[..]", MAG_Str, Set_MAG_Object[Obje_Num++]); BSP_LCD_SetTextColor(LCD_COLOR_WHITE); BSP_LCD_DisplayStringAtLine(Line_Num, (uint8_t *) LCD_Line_Text); response = SetModeMag(CONTINUOUS_MODE); if (response == MEMS_ERROR) ret = LSM303D_ERROR; BSP_LCD_SetTextColor(response ? LCD_COLOR_GREEN : LCD_COLOR_RED); BSP_LCD_DisplayStringAt(31 * 7, LINE(Line_Num++), (uint8_t *) (Set_Ret_State[response]), LEFT_MODE); //set Magnetometer Gain sprintf(LCD_Line_Text, "%s %-14s ...[..]", MAG_Str, Set_MAG_Object[Obje_Num++]); BSP_LCD_SetTextColor(LCD_COLOR_WHITE); BSP_LCD_DisplayStringAtLine(Line_Num, (uint8_t *) LCD_Line_Text); response = SetGainMag(GAIN_450_M); if (response == MEMS_ERROR) ret = LSM303D_ERROR; BSP_LCD_SetTextColor(response ? LCD_COLOR_GREEN : LCD_COLOR_RED); BSP_LCD_DisplayStringAt(31 * 7, LINE(Line_Num++), (uint8_t *) (Set_Ret_State[response]), LEFT_MODE); //set temperature Enable sprintf(LCD_Line_Text, "%s %-14s ...[..]", MAG_Str, Set_MAG_Object[Obje_Num++]); BSP_LCD_SetTextColor(LCD_COLOR_WHITE); BSP_LCD_DisplayStringAtLine(Line_Num, (uint8_t *) LCD_Line_Text); response = SetTemperature(MEMS_ENABLE); if (response == MEMS_ERROR) ret = LSM303D_ERROR; BSP_LCD_SetTextColor(response ? LCD_COLOR_GREEN : LCD_COLOR_RED); BSP_LCD_DisplayStringAt(31 * 7, LINE(Line_Num++), (uint8_t *) (Set_Ret_State[response]), LEFT_MODE); //get temperature data value (DegC) i16_t temperature = 0; sprintf(LCD_Line_Text, "%s %-14s ...[..]", MAG_Str, Get_MAG_Object[0]); BSP_LCD_SetTextColor(LCD_COLOR_WHITE); BSP_LCD_DisplayStringAtLine(Line_Num, (uint8_t *) LCD_Line_Text); response = GetTempRaw(&temperature); if (response == MEMS_ERROR) ret = LSM303D_ERROR; BSP_LCD_SetTextColor(response ? LCD_COLOR_GREEN : LCD_COLOR_RED); BSP_LCD_DisplayStringAt(31 * 7, LINE(Line_Num++), (uint8_t *) (Set_Ret_State[response]), LEFT_MODE); sprintf(LCD_Line_Text, " Temperature: %d *C", temperature); BSP_LCD_DisplayStringAtLine(13, (uint8_t *) LCD_Line_Text); //get Magnetometer data MagAxesRaw_t dataM; response = GetMagAxesRaw(&dataM); if (response == MEMS_ERROR) { BSP_LCD_DisplayStringAtLine(13, "MAG [NODATA] ...[ERROR]"); ret = LSM303D_ERROR; } else { char B[34]; sprintf(B, "Mag: xM=] yM=] zM=] ", dataM.AXIS_X, dataM.AXIS_Y, dataM.AXIS_Z); BSP_LCD_DisplayStringAtLine(13, (uint8_t *) B); } } return ret; }

改的像Linux那样启动的过程。看起来很爽。效果也不错。

不得不说,这个磁传感器用起来很方便。暂时放一会也看不到它漂移的。很稳定。

时间xMyMzM17:378-3-417:408-3-417:438-3-417:478-3-417:578-3-418:158-3-4

.

按照它的XYZ大概一个坐标就能出来。 这里抛开Z轴,按照数值,可以大概列出一个XYZ转换为角度的关系,指向北方的时候,

方位xMyM北8+0南-60西0-8东07

果断选用arctan

Angel = atan2(dataM.AXIS_Y, dataM.AXIS_X);

把它打印在屏幕上,通过旋转并观察屏幕上的角度值,要在屏幕上画一条线用来指示方向的话,就有:

Point_XY.X = (uint16_t)((LCD_XSize / 2) - (LCD_XSize / 2 - 10) * arm_sin_f32(Angel)); Point_XY.Y = (uint16_t)((LCD_YSize - LCD_XSize / 2) - (LCD_XSize / 2 - 10) * arm_cos_f32(Angel));

完成后看起来很不错:

指向的方向基本是在北面,加还是减去一个小角度就可以消除这个误差。 最后这个罗盘界面看起来比较简单(丑)。不过Embedded Wizard Studio 这个软件应该可以做个漂亮一点的界面,有兴趣的童鞋可以去看看这个软件。

转载请注明原文地址: https://www.6miu.com/read-66024.html

最新回复(0)