MPU60X0是invenSence公司的一款全球首例9軸運動處理傳感器。它內部集成了3軸MEMS陀螺儀和3軸MEMS加速度計,同時可以通過I2C接口(注意這個接口是XDA、XCL,而開發板與MPU6050通信的接口是SDA、SCL)連接一個第三方的數據傳感器,比如說磁力計,擴展成9軸數據輸出。MPU6050內置1024字節的fifo緩沖區,可編程的加速度范圍和陀螺儀范圍,可編程的中斷,使用400khz快速模式的i2c通信。對於MPU6050這款傳感器的介紹,更詳細的可參考手冊和度娘,這款傳感器很經典,網上的資料特別多。
MPU6050這款傳感器應用場合非常多,如果你仔細觀察,你會發現我們身邊也有許多它的影子。如下
無人機
看完上邊花里胡哨的圖片后,想必您對這款傳感器不陌生了,現在我開始說如何在ROC-RK3308-CC開發板上輕松簡單的實現設備的驅動,MPU6050作為一款經典而且性能非常強大的傳感器,在RK3308的SDK中可以用多種方式去驅動,我在這簡單總結一下,如下
如何使用invensense自身的驅動
ROC-RK3308的SDK中已經集成了invenSense廠商的驅動代碼,因此我們無需再去寫驅動代碼,只需要完成設備樹的適配就可以驅動相應的設備,invenSense的驅動框架源碼目錄如下
linux/kernel/drivers/staging/iio/imu/inv_mpu
其實這個invenSense的驅動框架是與安卓的Hal層配合使用的,那么既然Hal層能獲取數據,那么我們Linux的用戶層也一樣能拿到數據。
下面我們一步一步來實現適配。
1.設備數的適配
既然驅動代碼都已經有了,那么我們就可以按照官方的驅動代碼去填寫我們的設備樹,設備樹進行如下配置:
&i2c1 {
clock-frequency = <400000>;
status = "okay";
mpu6050: mpu@68 {
compatible = "invensense,mpu6050";
reg = <0x68>;
mpu-int_config = <0>;
mpu-level_shifter = <0>;
mpu-orientation = <1 0 0 0 1 0 0 0 1>;
orientation-x= <1>;
orientation-y= <0>;
orientation-z= <0>;
irq-gpio = <&gpio0 RK_PB7 IRQ_TYPE_LEVEL_LOW>;
mpu-debug = <1>;
status = "okay";
};
};
參數含義(很重要!!)
compatible必須是"invensense,mpu6050"
reg = <0x68>;這個是i2c從設備地址,這個地址取值mpu6050的ADO腳,它接地就是0x68,它拉高就是0x69
irq-gpio = <&gpio0 RK_PB7 IRQ_TYPE_LEVEL_LOW>;這個就是mpu6050的int腳接的中斷口,必須要接中斷才能獲取設備數據。
mpu-int_config = <0>;是中斷使能配置寄存器的值(如果擴展成9軸,那么這個參數還會作用於中斷引腳配置寄存器),填0即可,因為內部驅動代碼會幫你開相應中斷。
這里額外要注意,比如如果要填0x10的話,那么這樣填寫mpu-int_config = <0x10000000>或者mpu-int_config = /bits/ 8 <0x10>; 。
mpu-orientation=<1 0 0 0 1 0 0 0 1>;是設備的3*3的方向矩陣
orientation-x= <1>;//代表取反
orientation-y= <0>;
orientation-z= <0>;
根據你實際的layout進行配置方向矩陣,這部分的信息可通過sysfs文件系統的接口獲取,進而實現你的設備layout
到這里也許你會問,我就想獲取一些數據而已,怎么搞那么多的參數,我不配置那么多行不行?
答案是不行的,要么就自己去改源碼咯。因為在probe函數里遍歷設備樹的驅動代碼如果沒有匹配到這些選項就會立即報錯退出。
2.make menuconfig的選配
打開驅動目錄下的Kconfig
linux/kernel/drivers/staging/iio/imu/inv_mpu/Kconfig
從文件中可以看出,要想用invenSense的驅動框架,必須將相應的依賴項選配上。
config INV_MPU_IIO
tristate "Invensense MPU devices"
depends on I2C && SYSFS && IIO && IIO_KFIFO_BUF && IIO_TRIGGER && !INV_MPU
default n
help
This driver supports the Invensense MPU devices.
This includes MPU6050/MPU3050/MPU9150/ITG3500/MPU6500/MPU9250.
This driver can be built as a module. The module will be called
inv-mpu-iio.
將編譯好的新內核燒錄進開發板中,將會出現三個文件
/dev/iio:device0 /sys/bus/iio/devices/iio:device0 /sys/bus/iio/devices/trigger0
3.配置sysfs和獲取傳感器數據
如果上述操作成功,那么在/sys/bus/iio/devices/iio\:device0/目錄下將會生成這些文件
這些文件就是啟動參數的配置文件,這些文件的含義具體是什么屬性,我就不逐一介紹了,更詳細的參考附件的文檔,在用戶層我們進行以下配置就可以獲取加速度和角速度的數據,代碼如下
//配置sysfs文件系統的啟動參數
system("echo 1 > /sys/bus/iio/devices/iio:device0/accl_enable ");
system("echo 1 > /sys/bus/iio/devices/iio:device0/gyro_enable ");
system("echo 1 > /sys/bus/iio/devices/iio:device0/scan_elements/in_accel_x_en ");
system("echo 1 > /sys/bus/iio/devices/iio:device0/scan_elements/in_accel_y_en ");
system("echo 1 > /sys/bus/iio/devices/iio:device0/scan_elements/in_accel_z_en");
system("echo 1 > /sys/bus/iio/devices/iio:device0/scan_elements/in_anglvel_x_en ");
system("echo 1 > /sys/bus/iio/devices/iio:device0/scan_elements/in_anglvel_y_en");
system("echo 1 > /sys/bus/iio/devices/iio:device0/scan_elements/in_anglvel_z_en");
system("echo 0 > /sys/bus/iio/devices/iio:device0/scan_elements/in_timestamp_en");
system("echo 12 > /sys/bus/iio/devices/iio:device0/buffer/length");
system("echo 1 > /sys/bus/iio/devices/iio:device0/buffer/enable");
啟動參數配置好,我們就可以read讀取傳感器的數據了
ret=poll(&fp,1,-1);
if(ret==-1)
{
printf("poll failed\n");
exit(-1);
}
ret=read(fp.fd,buff,512);
根據獲取的數據buff進行解析成相應的加速度和角速度
以x軸加速度為例,其他軸的詳細的源碼參考附件。
//accel x
x=buff[1]*256+buff[0];
if(x>32767)
{
ax=(65535-x)/16384.0;
ax=-ax;
}else
{
ax=x/16384.0;
}
printf("ax:%.2lfg\n",ax);
4.demo測試
經過上面的步驟后,我們就可以在用戶層獲取源源不斷的設備數據了。數據效果如下:
