8.WaRP7开发板上传感器模块FXOS8700CQ和MPL3115A2简单使用。
时间:10-02
整理:3721RD
点击:
FXOS8700CQ模块是一款体积小,功耗低的6轴加速度和重力传感器。有i2c和spi接口,14位加速度数据输出,16位重力数据输出。 我总结对类似I2c接口的传感器可以从以下几个方面入手研究:
1.明确传感器在SOC上的接线情况,确认接到i2c1上还是i2c2上,我们这里接到i2c3上,但是我没有找到接线原理图,只是从参考代码确定;
2.从dts文件冲判断模块的一些参数设置,
3.找到相应的驱动程序(也许没有驱动程序)
将近1000行的代码,这里就不在贴出,有兴趣去看看源代码,这里只列出关键点:
3.1驱动入口函数:
3.4重力实现与加速度实现类似,只是传感器寄存器不同0x33,0x34,0x35,0x36,0x37,0x38,见下图:
4.应用程序获取传感器输出结果
4.1应用程序源代码如下:
4.3测试结果每次都一样,但是前面测试的时候输出结果并不是每次都一样,还有其具体含义需要与业务联系。
MPL3115A2使用一MEMS压力传感器, 带有I2C接口, 可提供精准的电压/高度和温度数据. 这一传感器为数字化输出, 使用一个高分辨率的24位模数转换器. 内部处理省去了主控MCU系统的补偿任务. 另有多个可用户编程, 电源节约, 中断和自治数据采集模式, 包括已编程的采集周期计时器和只轮询模式. 典型电源电流为40μA每测量-秒, 用于稳定的10cm输出分辨率。
从读取传感器输出结果的角度来说,MPL3115A2和FXOS8700CQ是一样的,因为他们都使用IIC接口,只是传感器寄存器不同而已,但是因为MPL3115A2驱动没有FXOS8700CQ驱动那么强大,所以我们可以换一个方法来读取传感器输出结果。
应用程序代码如下:
输出结果分析:
1.虽然目前家里的温度大约是29左右,但是开发板的温度还是比较高,所以39度算是一个比较合理的数值,曾经对比电风扇吹一会的实验,电风扇开启前后温度输出有比较明显的变化,从44度可以下降到36度左右,我认为温度输出结果符合实际,当然真的做产品则需要更加准确和测试;
2.关于高度的输出结果,目前的几个是80m,考虑北京的平均海拔40-50m,而我家是11楼,大概高度也有35-44m左右,这个高度输出也在合理的范围内,但是刚开始读取数值大约是136m左右,后面又测试是110m左右。这里可以认为是传感器测试需要一定时间来达到一个稳定数值。
本来以为开发板没有集成陀螺仪传感器,后来才知道FXAS21002CQR1就是,不过这个传感器与前面的FXOS8700CQ模块很类似,驱动也基本一样,所以这里就不在研究,如果后面有时间则把这个三部分数据集成起来实现功能:“使能“多重感知”设备磁力-加速计,气压计,陀螺仪。并将数据简单处理然后通过wifi发送给固定PC。”。
下面会看看电池和电源管理的功能实现。
1.明确传感器在SOC上的接线情况,确认接到i2c1上还是i2c2上,我们这里接到i2c3上,但是我没有找到接线原理图,只是从参考代码确定;
2.从dts文件冲判断模块的一些参数设置,
- &i2c4 {
- clock-frequency = <100000>;
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_i2c4>;
- status = "okay";
- fxas2100x@20 {
- compatible = "fsl,fxas2100x";
- reg = <0x20>;
- };
- fxos8700@1e {
- compatible = "fsl,fxos8700";
- reg = <0x1e>;
- };
- mpl3115@60 {
- compatible = "fsl,mpl3115";
- reg = <0x60>;
- };
- codec: sgtl5000@0a {
- #sound-dai-cells = <0>;
- reg = <0x0a>;
- compatible = "fsl,sgtl5000";
- clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_CLK>;
- VDDA-supply = <&vgen4_reg>;
- VDDIO-supply = <&vgen4_reg>;
- };
- };
3.找到相应的驱动程序(也许没有驱动程序)
将近1000行的代码,这里就不在贴出,有兴趣去看看源代码,这里只列出关键点:
3.1驱动入口函数:
- static const struct i2c_device_id fxos8700_id[] = {
- {"fxos8700", 0},
- { /* sentinel */ }
- };
- MODULE_DEVICE_TABLE(i2c, fxos8700_id);
- static SIMPLE_DEV_PM_OPS(fxos8700_pm_ops, fxos8700_suspend, fxos8700_resume);
- static struct i2c_driver fxos8700_driver = {
- .driver = {
- .name = FXOS8700_DRIVER,
- .owner = THIS_MODULE,
- .pm = &fxos8700_pm_ops,
- },
- .probe = fxos8700_probe,
- .remove = fxos8700_remove,
- .id_table = fxos8700_id,
- };
- module_i2c_driver(fxos8700_driver);
- result = misc_register(&fxos8700_acc_device);
- if (result != 0) {
- printk(KERN_ERR "register acc miscdevice error");
- goto err_regsiter_acc_misc;
- }
- pdata->acc_miscdev = &fxos8700_acc_device;
- result = misc_register(&fxos8700_mag_device);
- if (result != 0) {
- printk(KERN_ERR "register acc miscdevice error");
- goto err_regsiter_mag_misc;
- }
- case SENSOR_GET_RAW_DATA:
- position = atomic_read(&pdata->position);
- ret = fxos8700_read_data(pdata->client, &data, FXOS8700_TYPE_ACC);
- if (!ret) {
- fxos8700_data_convert(&data, position);
- sdata[0] = data.x;
- sdata[1] = data.y;
- sdata[2] = data.z;
- if (copy_to_user(argp, sdata, sizeof(sdata))) {
- printk(KERN_ERR "SENSOR_GET_RAW_DATA copy_to_user failed.");
- ret = -EFAULT;
- }
- }
- break;
3.4重力实现与加速度实现类似,只是传感器寄存器不同0x33,0x34,0x35,0x36,0x37,0x38,见下图:
4.应用程序获取传感器输出结果
4.1应用程序源代码如下:
- /* *************************************************************
- * File name:
- * Function:
- * Description:
- *
- * *************************************************************/
- #include "i2c_io.h"
- static int fd;
- char I2C_DevName_String[] = "/dev/i2c-3";
- char *I2C_DevName = I2C_DevName_String;
- unsigned int I2C_SLAVE_Address = 0x1E;
- #define SENSOR_IOCTL_BASE 'S'
- #define SENSOR_GET_MODEL_NAME _IOR(SENSOR_IOCTL_BASE, 0, char *)
- #define SENSOR_GET_POWER_STATUS _IOR(SENSOR_IOCTL_BASE, 2, int)
- #define SENSOR_SET_POWER_STATUS _IOR(SENSOR_IOCTL_BASE, 3, int)
- #define SENSOR_GET_DELAY_TIME _IOR(SENSOR_IOCTL_BASE, 4, int)
- #define SENSOR_SET_DELAY_TIME _IOR(SENSOR_IOCTL_BASE, 5, int)
- #define SENSOR_GET_RAW_DATA _IOR(SENSOR_IOCTL_BASE, 6, short[3])
- #define FXOS8700CQ_SLAVE_ADRESS 0xC7
- #define FXOS8700CQ_OUT_X_MSB 0x1
- #define FXOS8700CQ_OUT_X_LSB 0x2
- #define FXOS8700CQ_OUT_Y_MSB 0x3
- #define FXOS8700CQ_OUT_Y_LSB 0x4
- #define FXOS8700CQ_OUT_Z_MSB 0x5
- #define FXOS8700CQ_OUT_Z_LSB 0x6
- #define FXOS8700CQ_WHO_AM_I 0x0D
- typedef struct _SRAWDATA {
- int16_t x;
- int16_t y;
- int16_t z;
- } SRAWDATA;
- /*********************************************
- *fxos8700cq chip id
- *fxos8700cq_chipid
- *
- *
- * erro -> -1 sucess -> 0
- **********************************************/
- int fxos8700cq_read_chip_id(int fd,int* fxos8700cq_chipid)
- {
- char buf;
- int ret;
-
- ret= iic_read(fd,&buf,FXOS8700CQ_WHO_AM_I,1);
- if(ret < 0){
- printf(" <erro> fxos8700cq_chip_id failed \n");
- return ret;
- }
-
- if(buf != FXOS8700CQ_SLAVE_ADRESS){
- *fxos8700cq_chipid = 0;
- return -1;
- }
-
- //return fxos8700cq_chipid value
- *fxos8700cq_chipid = buf;
- printf(" fxos8700cq_chip_id:0x%x\n", *fxos8700cq_chipid);
- return 0;
- }
- static int read_register(int file, unsigned char address, unsigned char reg, unsigned char *data)
- {
- unsigned char input_buffer, output_buffer;
- struct i2c_rdwr_ioctl_data packets;
- struct i2c_msg messages[2];
- output_buffer = reg;
- messages[0].addr= address;
- messages[0].flags = 0;
- messages[0].len = sizeof(output_buffer);
- messages[0].buf = &output_buffer;
- messages[1].addr= address;
- messages[1].flags = I2C_M_RD;
- messages[1].len = sizeof(input_buffer);
- messages[1].buf = &input_buffer;
- packets.msgs= messages;
- packets.nmsgs = 2;
- if(ioctl(file, I2C_RDWR, &packets) < 0) {
- perror("Error sending data");
- return 1;
- }
- *data = input_buffer;
-
- return 0;
- }
- int main(int argc, char* argv[])
- {
- int i = 0;
- int ret = 0;
- int fd = 0;
- int fd_mag = 0;
- int file = 0;
- unsigned char fxos8700cq_chipid;
- char buf[8] = "";
- int tmp_msb = 0;
- int tmp_lsb = 1;
- int* nStatus = &tmp_lsb;
- fxos8700_data_axis mfxos8700_data_axis;
- fxos8700_data_axis* pfxos8700_acc_axis;
- pfxos8700_acc_axis = &mfxos8700_data_axis;
-
- // printf("Test for FXOS8700CQ (3-axis linear accelerometer)\n");
- printf("Please check the device ID (Should be 0xC7)\n");
- if ((file = open("/dev/i2c-3", O_RDWR)) < 0)
- {
- perror("Error openning file!");
- exit(1);
- }
- if(read_register(file, I2C_SLAVE_Address, FXOS8700CQ_WHO_AM_I, &fxos8700cq_chipid))
- exit(1);
- else
- {
- {
- printf("GET:Register[0x%02X]: whoami-deviceID=0x%02X\n" , 0x1e , fxos8700cq_chipid);
- }
- }
- close(file);
-
- if ((fd = open("/dev/FreescaleAccelerometer", O_RDWR)) < 0)
- {
- perror("Error openning /dev/FreescaleAccelerometer!");
- exit(1);
- }
- pfxos8700_acc_axis->x = 0;
- pfxos8700_acc_axis->y = 0;
- pfxos8700_acc_axis->z = 0;
- printf("=1= pfxos8700_acc_axis->x=%d, pfxos8700_acc_axis->y=%d, pfxos8700_acc_axis->z=%d\n", pfxos8700_acc_axis->x, pfxos8700_acc_axis->y, pfxos8700_acc_axis->z);
- for(i = 0; i < 5; i++)
- {
- ret = ioctl(fd,SENSOR_GET_RAW_DATA,pfxos8700_acc_axis); //I2C
- printf("=2= pfxos8700_acc_axis->x=%d, pfxos8700_acc_axis->y=%d, pfxos8700_acc_axis->z=%d\n", pfxos8700_acc_axis->x, pfxos8700_acc_axis->y, pfxos8700_acc_axis->z);
- }
- close(fd);
- if ((fd_mag = open("/dev/FreescaleMagnetometer", O_RDWR)) < 0)
- {
- perror("Error openning /dev/FreescaleMagnetometer!");
- exit(1);
- }
- pfxos8700_acc_axis->x = 0;
- pfxos8700_acc_axis->y = 0;
- pfxos8700_acc_axis->z = 0;
- printf("=1= pfxos8700_mag_axis->x=%d, pfxos8700_mag_axis->y=%d, pfxos8700_mag_axis->z=%d\n", pfxos8700_acc_axis->x, pfxos8700_acc_axis->y, pfxos8700_acc_axis->z);
- for(i = 0; i < 5; i++)
- {
- ret = ioctl(fd_mag,SENSOR_GET_RAW_DATA,pfxos8700_acc_axis); //I2C
- printf("=2= pfxos8700_mag_axis->x=%d, pfxos8700_mag_axis->y=%d, pfxos8700_mag_axis->z=%d\n", pfxos8700_acc_axis->x, pfxos8700_acc_axis->y, pfxos8700_acc_axis->z);
- }
- close(fd_mag);
-
- return 0;
- }
4.3测试结果每次都一样,但是前面测试的时候输出结果并不是每次都一样,还有其具体含义需要与业务联系。
MPL3115A2使用一MEMS压力传感器, 带有I2C接口, 可提供精准的电压/高度和温度数据. 这一传感器为数字化输出, 使用一个高分辨率的24位模数转换器. 内部处理省去了主控MCU系统的补偿任务. 另有多个可用户编程, 电源节约, 中断和自治数据采集模式, 包括已编程的采集周期计时器和只轮询模式. 典型电源电流为40μA每测量-秒, 用于稳定的10cm输出分辨率。
从读取传感器输出结果的角度来说,MPL3115A2和FXOS8700CQ是一样的,因为他们都使用IIC接口,只是传感器寄存器不同而已,但是因为MPL3115A2驱动没有FXOS8700CQ驱动那么强大,所以我们可以换一个方法来读取传感器输出结果。
应用程序代码如下:
- #include <stdio.h>
- #include <stdint.h>
- #include <linux/i2c.h>
- #include <linux/i2c-dev.h>
- #include <fcntl.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <sys/ioctl.h>
- #include <string.h>
- //#define FLAG_DBG_ENABLE 1
- static int write_register(int file,unsigned char address,unsigned char reg,unsigned char data)
- {
- unsigned char output_buffer[2];
- struct i2c_rdwr_ioctl_data packets;
- struct i2c_msg messages[1];
-
- messages[0].addr= address;
- messages[0].flags = 0;
- messages[0].len = sizeof(output_buffer);
- messages[0].buf = output_buffer;
-
- output_buffer[0] = reg;
- output_buffer[1] = data;
-
- packets.msgs= messages;
- packets.nmsgs = 1;
-
- if(ioctl(file, I2C_RDWR, &packets) < 0) {
- perror("Error sending data");
- return 1;
- }
- return 0;
- }
- static int read_register(int file, unsigned char address, unsigned char reg, unsigned char *data)
- {
- unsigned char input_buffer, output_buffer;
- struct i2c_rdwr_ioctl_data packets;
- struct i2c_msg messages[2];
- output_buffer = reg;
- messages[0].addr= address;
- messages[0].flags = 0;
- messages[0].len = sizeof(output_buffer);
- messages[0].buf = &output_buffer;
- messages[1].addr= address;
- messages[1].flags = I2C_M_RD;
- messages[1].len = sizeof(input_buffer);
- messages[1].buf = &input_buffer;
- packets.msgs= messages;
- packets.nmsgs = 2;
- if(ioctl(file, I2C_RDWR, &packets) < 0) {
- perror("Error sending data");
- return 1;
- }
- *data = input_buffer;
-
- return 0;
- }
- int main() {
- int file, i;
- unsigned char data;
- int val1;
- int val2;
- float t_m;
- int choice;
- int DBG_ENABLE = 1;
- char string[200];
- #ifdef FLAG_DBG_ENABLE
- printf("Enable Debugging [1-Enable/0-Disable] :");
- scanf("%d",&choice);
-
-
- if (choice == 1)
- DBG_ENABLE = 1;
- else if (choice == 0)
- DBG_ENABLE = 0;
- else
- {
- printf("Unknown choice \n Exiting... \n");
- exit(1);
- }
- #endif
-
- if ((file = open("/dev/i2c-3", O_RDWR)) < 0)
- {
- perror("Error openning file!");
- exit(1);
- }
- #ifdef FLAG_DBG_ENABLE
- if(DBG_ENABLE == 0)
- printf("Debugging Disabled \n");
- else if(DBG_ENABLE == 1)
- printf("Debugging Enabled \n");
- else
- printf("No idea");
- #endif
- //0x0C whoami verify
- if(read_register(file, 0x60, 0x0C, &data))
- exit(1);
- else
- {
- if(DBG_ENABLE == 1)
- {
- printf("GET:Register[0x%02X]: whoami-deviceID=0x%02X\n" , 12 , data);
- }
- }
- //0x26 ctrlreg1 get/set ACTIVE
- if(read_register(file, 0x60, 0x26, &data))
- exit(1);
- else
- {
- if(DBG_ENABLE == 1)
- {
- printf("GET:Register[0x%02X]: CTRL_REG1=0x%02X\n" , 38 , data);
- }
- }
- if(write_register(file, 0x60, 0x26, 0x03 | 0x80))
- exit(1);
- else
- {
- if(read_register(file, 0x60, 0x26, &data))
- exit(1);
- else
- {
- if(DBG_ENABLE == 1)
- {
- printf("SET/GET:Register[0x%02X]: CTRL_REG1=0x%02X\n" , 38 , data);
- }
- }
- }
- int counter=0;
- while(counter<5)
- {
- //read temperature MSB/LSB
- if(read_register(file, 0x60, 0x04, &data))
- exit(1);
- /* else*/
- /*{ if(DBG_ENABLE == 1)*/
- /*{ printf("Register[0x%02X]: 0x%02X\n" , 4 , data);*/
- /*}*/
- /*}*/
-
- val2 = (int)data;
- if(DBG_ENABLE == 1) printf("val2: initial :%d:\n",val2);
- val2 <<=4;
- //if(DBG_ENABLE == 1) printf("val2: shift :%d:\n",val2);
- if(read_register(file, 0x60, 0x05, &data))
- exit(1);
- else
- {
- if(DBG_ENABLE == 1)
- printf("Register[0x%02X]: 0x%02X\n" , 5 , data);
- }
- // val2 = val2+ (int)data;
-
- t_m = (float)data;
- // printf("=1=t_m :%f:\n",t_m);
- t_m = t_m / 1000;
- printf("=2=t_m :%f:\n",t_m);
- if(DBG_ENABLE == 1)
- { //printf("val2 :%d:\n",val2);
- }
- t_m = t_m + (val2 >> 4);// & 0xff;
- printf("temperature :%.3f: \n",t_m);
- //printf("temperature string:%d: \n",string);
- if(read_register(file, 0x60, 0x01, &data))
- exit(1);
- /* else*/
- /*{ if(DBG_ENABLE == 1)*/
- /*{ printf("Register[0x%02X]: 0x%02X\n" , 4 , data);*/
- /*}*/
- /*}*/
-
- val2 = (int)data;
- if(DBG_ENABLE == 1) printf("val2: initial :%d:\n",val2);
- val2 <<=8;
- if(read_register(file, 0x60, 0x02, &data))
- exit(1);
- /* else*/
- /*{ if(DBG_ENABLE == 1)*/
- /*{ printf("Register[0x%02X]: 0x%02X\n" , 4 , data);*/
- /*}*/
- /*}*/
-
- val1 = (int)data;
- if(DBG_ENABLE == 1) printf("val1: initial :%d:\n",val1);
- val2 = val1 + val2;
- printf("altitude :%d: m\n", val2);
- //system(string);
- sleep(1);
- counter++;
- }
- close(file);
- return 0;
- }
输出结果分析:
1.虽然目前家里的温度大约是29左右,但是开发板的温度还是比较高,所以39度算是一个比较合理的数值,曾经对比电风扇吹一会的实验,电风扇开启前后温度输出有比较明显的变化,从44度可以下降到36度左右,我认为温度输出结果符合实际,当然真的做产品则需要更加准确和测试;
2.关于高度的输出结果,目前的几个是80m,考虑北京的平均海拔40-50m,而我家是11楼,大概高度也有35-44m左右,这个高度输出也在合理的范围内,但是刚开始读取数值大约是136m左右,后面又测试是110m左右。这里可以认为是传感器测试需要一定时间来达到一个稳定数值。
本来以为开发板没有集成陀螺仪传感器,后来才知道FXAS21002CQR1就是,不过这个传感器与前面的FXOS8700CQ模块很类似,驱动也基本一样,所以这里就不在研究,如果后面有时间则把这个三部分数据集成起来实现功能:“使能“多重感知”设备磁力-加速计,气压计,陀螺仪。并将数据简单处理然后通过wifi发送给固定PC。”。
下面会看看电池和电源管理的功能实现。