LSM303DLHC

2023-05-16

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

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

ST官网的开发套件

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

STEVAL-MKI108V2

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

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_BufferReadI2C_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=%5d yM=%5d zM=%5d   ", dataM.AXIS_X, dataM.AXIS_Y, dataM.AXIS_Z);
            BSP_LCD_DisplayStringAtLine(13, (uint8_t *) B);
        }
    }
    return ret;
}

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

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

时间xMyMzM
17:378-3-4
17:408-3-4
17:438-3-4
17:478-3-4
17:578-3-4
18: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 这个软件应该可以做个漂亮一点的界面,有兴趣的童鞋可以去看看这个软件。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

LSM303DLHC 的相关文章

随机推荐

  • CAN总线综述-转发一篇关于CAN总线的详细介绍文章

    CAN总线 一 原文出处 xff1a http www cnblogs com jacklu p 4729638 html 嵌入式的工程师一般都知道CAN总线广泛应用到汽车中 xff0c 其实船舰电子设备通信也广泛使用CAN xff0c 随
  • Python 安装 MaxMind GeoLite City

    1 先安装 geoip c library geoip c library gt 61 1 4 6 installed on your machine gt 61 1 4 6 installed on your machine wget h
  • 华为MA5626-8密码恢复

    设备型号 xff1a 华为MA5626 8 display version VERSION MA5626V800R308C00 PATCH SPC500 SPH505 HP5105 PRODUCT MA5626 准备工作 xff1a 超级终
  • SNMP 获取交换机端口相关信息

    我们想用snmpwalk查看网络设备的端口 xff0c MIB库中相关定义的信息如下 xff1a root 64 redcock lifeng snmpwalk v 2c c lifeng 192 168 100 100 注意后面的点 xf
  • phpMyAdmim和Yii 连接Mysql报错。

    故障 xff1a 之前phpMyAdmim和Yii连接Mysql都好着的 xff0c 某天 xff0c 同时出现如下报错 xff1a 1 linux下phpMyAdmin 出现 缺少 mysqli 扩展 xff0c 请检查 PHP 配置 2
  • linux shell 执行多个命令的方法

    xff08 1 xff09 在每个命令之间用 xff1b xff08 分号 xff09 隔开 xff08 2 xff09 在每个命令之间用 amp amp 隔开 amp amp 表示 xff1a 若前一个命令执行成功 xff0c 才会执行下
  • ARP 属于哪层协议

    教材上把ARP 协议划到网络层 xff0c 是因为 ARP 协议属于 TCP IP 协议簇 在TCP IP 模型中 xff0c 它所有定义的协议是在网际层上的 再看按照OSI 的标准 xff0c 数据在传递时每层会加上自己的信息 当网络层的
  • 什么叫一层交换机,二层交换机,三层交换机?

    转自 xff1a http blog csdn net happypolo article details 5934429 简单地说 xff1a 一层交换机 只支持物理层协议 电话程控交换机可以算一个 二层交换机 支持物理层和数据链路层协议
  • Linux Shell 脚本中字符串的连接方法

    Linux Shell 脚本中字符串的连接方法 如果想要在变量后面添加一个字符 xff0c 可以用一下方法 xff1a value1 61 home value2 61 value1 34 61 34 echo value2 把要添加的字符
  • linux 如何将路径加入环境变量

    PATH 61 PATH 后面加路径 PATH是环境变量 要大写那几个目录是你放置linux命令的目录 输入命令后系统会去PATH中寻找是否存在该命令 查看当前环境变量 echo PATH也可以用set命令看一下设置 export PATH
  • expect spawn、linux expect 用法

    使用expect实现自动登录的脚本 xff0c 网上有很多 xff0c 可是都没有一个明白的说明 xff0c 初学者一般都是照抄 收藏 可是为什么要这么写却不知其然 本文用一个最短的例子说明脚本的原理 脚本代码如下 xff1a usr bi
  • python 调用 shell python shell 间变量传递

    python gt shell xff1a 1 环境变量 python view plain copy print import os var 61 123 或var 61 123 os environ var 61 str var env
  • vSphere,ESXi和vCenter 的区别

    最近在看 VMware 一直没有搞清楚这几个产品之间的区别和联系 正好在网上搜索到一个好文 xff0c 翻译下来 本文翻译自 xff1a http www mustbegeek com difference between vsphere
  • equals和hashCode详解

    在学习的过程中 xff0c 特别是学习集合的时候 xff0c equals和hashCode一直是经常出现的方法 xff0c 而且在面试题中 xff0c 也经常出现equals和 61 61 的区别等问题 xff0c 现在我们就从底层详细的
  • NuttX的应用记录 4 (小记录)

    好久没看过NuttX了 xff0c 做个移植试一试 板子是STM32F407ZE xff0c 有两块屏幕 xff0c 蜂鸣器 xff0c FLASH xff0c E2PROM xff0c LED 先找个类似的 xff0c 复制一个副本 st
  • PetaLinux学习笔记 3

    过年回家没带开发板 终于可以搞一搞了 更新petaLinux到2019 2 重建项目 xff0c flash调整一下 启动过程中提示 xff1a m25p80 spi0 0 found w25q256 expected n25q512a m
  • 高云GW1N-9的SerDes笔记

    GW1NR 9的片子 xff1a 看起来还是很强的 xff0c 但是在工程中使用后会这样提示 xff1a 看起来有点虚标啊 那就按1G来先 xff0c 做个后仿 直接用OSER来输出数据 看起来还可以 输出可以 在做一个输入 xff0c 根
  • NuttX的学习笔记 1

    学习这个系统 xff0c 开始是在PIX的飞控上了解到的 xff0c 感觉这个系统很有兴趣 xff0c 当然 xff0c 这是我第一次接触RTOS xff0c 有不正确的地方 xff0c 请予以指正 注意 过程是我边操作边写的 xff0c
  • NuttX的学习笔记 2

    README文档目录的第二部分 Configuring NuttX Instantiating Canned ConfigurationsRefreshing ConfigurationsNuttX Configuration ToolFi
  • LSM303DLHC

    xff08 PS xff1a 最近在帮人做一个电子罗盘 xff0c 刚好STM32F429i DISCO上有个MEMS xff0c 但是我自己没有看到底是个什么传感器 xff0c 搞搞搞了半天 xff0c 读出来三个数据 xff0c 但我移