|
本帖最后由 tim4146 于 2016-3-25 17:54 编辑
为了检测地面移动设备的移动速度,我尝试使用了光流传感器,下面把我使用过程中的一些过程分享出来,如果可以的话麻烦给条裤子。
随便说几句
传感器是X宝买的,目测卖家只是个卖硬件的,固件部分卖家应该有过优化。图片是下面的,网址就不给了,以免说我做广告
传感器官方是有个配套地面站软件的,叫做QGroundControl 下载地址是:http://www.mavlink.org/downloads
这个传感器不能再64位的WIN7使用,我试了好几台都不行,试了第一台win7 32位就脸上了
传感器和QGroundControl的连接主要是验证传感器性能正常,并且通过图像来调节摄像头的焦距(如果需要的话)
关于通讯
PX4FLOW有三种对外通讯方式,上面说的和QGroundControl 的通讯是通过USB口,还有就是串口和I2C ,这个在官方是有介绍的
STM32读取数据有两种办法:1、串口 2、I2C 下面我一个个说
stm32串口读取数据
难点主要在于Marvlink协议的问题,这个我没太折腾直接在本论坛找到了一个程序,感谢原作者
最核心的代码如下
- void FLOW_MAVLINK(unsigned char data)
- {
-
- switch(s_flow)//这里是读出串口输出的连续26个字节数据
- {
- case 0: if(data==0xFE)
- s_flow=1;
- break;
- case 1: if(data==0x1A)
- { s_flow=2;}
- else
- s_flow=0;
- break;
- case 2:
- if(data_cnt<4)
- {s_flow=2; FLOW_STATE[data_cnt++]=data;}
- else
- {data_cnt=0;s_flow=3;flow_buf[data_cnt++]=data;}
- break;
- case 3:
- if(FLOW_STATE[3]==100)
- {
- if(data_cnt<26)
- {
- s_flow=3;
- flow_buf[data_cnt++]=data;
- }
-
- else
- {
- data_cnt=0;
- s_flow=4;
- }
- }
- else
- {
- data_cnt=0;
- s_flow=0;
- }
- break;
- case 4:get_one_fame=1;s_flow=0;data_cnt=0;break;
- default:s_flow=0;data_cnt=0;break;
- }//--end of s_uart
-
- if(get_one_fame)
- {
- get_one_fame=0;
- //实测flow_buf[0]是最低位 flow_buf[7]是最高位
- //实际使用[0]-[3]就足以完成实验
- flow.time_sec=(flow_buf[3]<<24)|(flow_buf[2]<<16)|(flow_buf[1]<<8)|(flow_buf[0]);
- floattobyte[0]=flow_buf[8];
- floattobyte[1]=flow_buf[9];
- floattobyte[2]=flow_buf[10];
- floattobyte[3]=flow_buf[11];
- flow.flow_comp_x =ByteToFloat(floattobyte);
-
- floattobyte[0]=flow_buf[12];
- floattobyte[1]=flow_buf[13];
- floattobyte[2]=flow_buf[14];
- floattobyte[3]=flow_buf[15];
- flow.flow_comp_y =ByteToFloat(floattobyte);
-
- floattobyte[0]=flow_buf[16];
- floattobyte[1]=flow_buf[17];
- floattobyte[2]=flow_buf[18];
- floattobyte[3]=flow_buf[19];
- flow.hight=ByteToFloat(floattobyte);//ground_distance float Ground distance in m. Positive value: distance known. Negative value: Unknown distance
-
- flow.flow_x=(int16_t)((flow_buf[20])|(flow_buf[21]<<8));
- flow.flow_y=(int16_t)((flow_buf[22])|(flow_buf[23]<<8));
-
-
- flow.id=flow_buf[24];
- flow.quality=flow_buf[25]; //Optical flow quality / confidence. 0: bad, 255: maximum quality
-
- }
- }
复制代码
为了得到是实时的速度,我只需要时间 x速度 y速度,因此最后用串口1输出的时候是这样的:
- printf("t:%u",flow.time_sec/1000);//输出时间 单位是ms
- printf(" ");
- printf("x:%f",flow.flow_comp_x*1000);//输出x方向速度 单位mm/s
- printf(" ");
- printf("y:%f\r\n",flow.flow_comp_y*1000);//输出y方向速度 单位mm/s
复制代码
这里要注意,固件里面时间用了一个u64数据类型,实测flow_buf[0]是最低位 flow_buf[7]是最高位,实际使用[0]-[3]就足以完成实验,毕竟做个实验几十秒就差不多了,最后根据需要的精度我,flow.time_sec/1000得到毫秒为单位的时间
经过小修改的工程代码在这里:
stm32的I2C读取数据
关于I2C的数据,我只关心速度部分,官方描述是这样的
那么对应的x方向速度就是地址0x06 0x07 Y方向速度地址就是 0x08 0x09低位在前 高位在后
关于I2C的设备地址是最容易出错的,官方这样说的
那么默认的地址就是0x42,发现不是,因为i2c是七位地址,所以需要左移一位才行,反映在代码就是下面这样:0x42左移一位就是0x84
- //在光流指定地址读出一个数据
- //ReadAddr:开始读数的地址
- //返回值 :读到的数据
- u8 PX4FLOW_ReadOneByte(u16 ReadAddr)
- {
- u8 temp=0;
- IIC_Start();
- IIC_Send_Byte(0X84); //发送器件地址0X42,写数据
- IIC_Wait_Ack();
- IIC_Send_Byte(ReadAddr); //发送低地址
- IIC_Wait_Ack();
- IIC_Start();
- IIC_Send_Byte(0X85); //进入接收模式
- IIC_Wait_Ack();
- temp=IIC_Read_Byte(0);
- IIC_Stop();//产生一个停止条件
- return temp;
- }
复制代码
同理,我还是只需要时间、x速度、y速度,所以最好输出是这样:
- PX4FLOW_Read(0,datatemp,22);//连续读出22字节
- temp=datatemp[6]+datatemp[7]*256;
- printf("flow_comp_m_x=%d",temp);//输出X速度
- printf(" ");
- temp=datatemp[8]+datatemp[9]*256;
- printf("flow_comp_m_y=%d",temp);//输出Y速度
- printf(" ");
- printf("t=%d\r\n",datatemp[19]);//输出时间
复制代码
但是发现输出的时间貌似不是时间,官方的描述是“uint8_t sonar_timestamp;// time since last sonar update [milliseconds]”,单位是milliseconds 毫秒,但是类型是u8,想想应该也是不够时间记录的...
工程文件这样的:
实验数据简单介绍
因为I2C我暂时没法得到实时的系统时间,串口那边倒是可以,所以暂且用串口来测速的
光流传感器被我安装在一个四轮小车前端,地面是大理石,实验过程固定了LED灯照明,车体本身存在振动,最后的速度曲线是这样的
曲线可以看出速度有明显波动,其实小车没这么大波动,原因在于:
1、传感器本身存在测量误差,但是误差没这么大
2、振动导致数据波动。这个绝对是最大的因素,光流传感器及时在四轴使用也是很注意抗震的,在我的小车(Mecanum轮)上,车体本身的振动比四轴大很多,及时传感器内部集成加速度陀螺仪数据的补偿,还是会产生不小的影响吧。
转载请注明转自阿莫论坛
编辑原因:错别字改动 |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?注册
x
阿莫论坛20周年了!感谢大家的支持与爱护!!
知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)
|