一沙一世界 一树一菩提
分类: LINUX
2016-02-16 16:43:40
这几天看pixhawk代码中关于传感器的代码,下面是一些记录。
先说下,大家看pixhawk的代码可能不知道从哪开始,我个人是从启动应用的脚本看起的:rcS。这个脚本是操作系统启动以后,具体启动应用的先后顺序,按照这个顺序研究或者修改代码也可以让你理解运行pixhawk代码的飞控的工作流程,比较符合认识事物的过程。
rcS会按照一定顺序调用其它脚本,如下面关于传感器的部分,rcS调用rc.sensors脚本。
另外,脚本里启动某个程序,如mpu6000 start,在代码中要对应关系也比较容易,每个应用程序或者驱动启动都是start启动的,对应的mpu6000的代码的命令行参数会解析“start”,然后启动具体的操作。如果你用source insight看代码,那么找到mpu6000.cpp,然后搜索start,就可以定位程序的开始了。不至于太无目的。
还有一点,根据rcS找到对应的代码,还可以让你很快找到哪些源文件没有用到,这样就可以快速定位到你要修改的文件啦。
下面正文:
下面内容是传感器有关的信息,供大家参考,可能有理解不正确的地方,大家发现哪里有不合理的地方,可以补充。互相共勉。
看sensors.cpp这个文件。从task_main看起。大体结构是:
Init(accel, gyro,mag,baro,adc)?setup fds?while(poll?pulish)
很简洁。这种编程风格值得推荐。函数最好都写成这样。唯一感觉不太理想的地方就是函数太长。这点是不是很重要?
在init阶段,一共初始化的传感器有:accel,gyro,mag,baro,adc
其中accel和gyro是使用高精度定时器来保证周期的准确度。
Accel:默认使用的是mpu6000。
通过ioctl设置采样速度,这个接口实际操作的是底层的实际硬件,如果系统连接mpu6000,那就是操作mpu6000,如果没有连接mpu6000,那就是操作LSM303D。
如果使用的是mpu6000,则设置采样周期800us。获得数据后有一个二阶低通滤波,然后publish给sensors.
如果没有mpu6000,那就设置LSM303D,设置采样周期是1050us,然后也是通过一个二阶低通滤波,然后publish给sensors。
Mpu6000的accel范围是-8g---+8g.
Gyro范围是2000度,弧度数自己算。
Gyro: 默认使用的是mpu6000.
也是通过ioctl设置,如果系统连接mpu6000,那就是操作mpu6000,如果没有连接mpu6000,那就是操作L3GD20.
如果使用的是mpu6000,则和使用mpu6000 accel的设置一样,周期也是800us。
如果使用的是L3GD20(L3G4200D),采集周期是716us,如果是L3G4200D,则周期是650us。
以上的不管是使用mpu6000,还是L3GD20还是L3G4200D,采集的数据都通过低通滤波,然后publish到sensors.
MAG:默认使用的是hmc5883
LSM303D,mag采集频率是100Hz,没有滤波。直接publish。LSM303D的采集频率较低,但是还是放在了高精度定时器的操作里,有点不太明白,既然频率要求不要,为何要放在定时器的控制下呢?窃以为可能是下面原因:
A LSM303D同时也是accel传感器,为了统一合适和使用
B LSM303D是第二选择,第一选择是HMC5883.
2 Hmc5883,采集频率是150Hz,也没有滤波,但是xyz轴有相互转换的过程,然后publish。
其中scale的范围如下:
#define FLT_EPSILON 1.1920929e-07F
(-FLT_EPSILON + 1.0f < _scale.x_scale && _scale.x_scale < FLT_EPSILON + 1.0f)
每次从硬件读取的数据有效范围(xyz相同):
(abs(report.x) < 2048)
Hmc5883的操作分成两部分,首先发送采集命令,然后延时,接下来读取数据。循环操作不是放在定时器里的,而是在每次读到数据以后,再次发送采集命令,然后安装回调函数,在延时一定时间后再次执行,这里用的是系统提供的任务队列,高优先级任务队列。
work_queue(HPWORK,
&_work,
(worker_t)&HMC5883::cycle_trampoline,
this,
USEC2TICK(HMC5883_CONVERSION_INTERVAL));
BARO:默认使用的是ms5611
气压采集周期是100Hz,详细而言应该是温度25Hz,气压75Hz,即每采集一次温度值,计算用于温度补偿的三个值:_TEMP、_OFF、_SENS。
然后采集三次气压值。根据上面的三个值进行计算,求出气压值,在根据气压值计算出海拔高度,然后把气压,高度值publish到sensors。
气压具体的采集周期是这样的(假设当前时间是10ms):
10ms(采集温度)?20ms(采集气压,publish)?30ms(采集气压,pulish)?40ms(采集气压,publish)?50ms(采集温度)。。。。。。。
可见,采集温度的周期实际是40ms,而气压采集是每40ms三次。
另外,ms5611的调用方式也不是使用定时器,和hmc5883相同,使用高优先级任务队列:
work_queue(HPWORK,
&_work,
(worker_t)&MS5611::cycle_trampoline,
this,
USEC2TICK(MS5611_CONVERSION_INTERVAL));