TA的每日心情 | 奋斗 2013-7-4 23:49 |
---|
签到天数: 21 天 连续签到: 1 天 [LV.4]偶尔看看III
|
一:小四轴通讯协议。小四轴和上位机采用下面的协议方式进行通讯:数据头+数据+校验码+数据尾。所有数据采用ASC码的方式进行通信。
数据头: 0x3A(对应字符:)
数据:0x30-0x39,0x41-0x46 (分别对应0-9,A-F的ASC码)
检验码:采用相加和为00的方式
数据尾:0x2F (对应字符/)
一个通讯格式的例子(字符串显示方式)为:B644FF431C0D1B80/
其中数据段为:B6,44,FF,43,1C,0D,1B
其中校验码为:80
我们把各个数据依次相加: B6+44+FF+43+1C+0D+1B+80=300
取低8位,结果为00,表明数据校验通过。
把上述例子转化到ASC码,可以得到(以十六进制表示):
3A,42,36,34,34,46,46,34,33,31,43,30,44,31,42,38,30,2F
二:发送小四轴姿态数据给上位机。首先我们结合一个小四轴发送到上位机的欧拉角数据进行逆向分析,然后再给出一个正向分析的例子。
假定小四轴发送到上位机的欧拉角数据为 :B73C66410C4460B6/
去除数据头,数据尾,和校验码,我们得到数据(以十六进制表示):
B7,3C66,410C,4460
转为到十进制,可以得到:0x3C66=15462,0x410C=16652,0x4460=17504
第一个数字B7的B是数据类型标识,该标识告诉上位机所发送的数据是欧拉角数据。
第一个数字B7的7是数据偏移标识,该标识告诉上位机所发送的数据有没有作18000的数据偏移。
我们把第一个数字B7的7以二进制的方式来表示,得到0111, 其中第一个必须为0,第2个为1表示15462这个数据已经做了18000的偏移,依次类推,第3个为1表示16652这个数据已经做了18000的偏移,第4个为1表示17504这个数据已经做了18000的偏移。如果为0,则表示没有做数据偏移。
把上述的十进制数根据第一个数字B7中的7的标识,去除数据偏移价值,可以得到:
0x3C66=15462,减去18000=2538
0x410C=16652,减去18000=1348
0x4460=17504,减去18000=96
把数据除以100,可以得到:
Pitch=2538/100=25.38度
Roll=1348/100=13.48度
Yaw=96/100=0.96度
通过上面的逆向数据分析,我们基本可以了解了小四轴的欧拉角数据传播格式。下面我们来做一个正向推导。
假定我们要传一个下面的角度给上位机软件:
俯仰角(pitch)=0.02;横滚角(roll)=-0.11;偏航角(yaw)=-0.07
第一步,我们把角度放大100倍,依次得到0002,-0011,-0007。
第二步,我们把负数做一个18000的数据偏移,依次得到:
0001,17989,17993,
转换到16进制为: 0001,4645,4649
由于第2和第3个数据做了18000的数据偏移,所以我们数据偏移标识数据是0011(二进制表示),添加上数据类型标识B, 我们得到第一个数据是: B3
因而我们得到的数据流是:B3,00,01,46,45,46,49
把上述7个数据相加,可以得到低两位的结果是CE。
用0x100-0xCE,得到校验和:32
把数据加上数据头和数据尾,则可得到:
:B300014645464932/
转化到ASC码,可以得到(以十六进制表示):
3A,42,33,30,30,30,31,34,36,34,35,34,36,34,39,33,32,2F
依次把上述数据通过串口发送到上位机(先发3A,后发2F),上位机即可以把该欧拉角显示出来。
下面列出更多数据供大家参考:
:B300DD45704394E4/ :B300DD45714394E3/ :B300DD45714394E3/
下面为参考代码:
Int Pitch=pitch*100;int Roll=roll*100;int Yaw=yaw*100; unsigned char euler_data_sign=0; if(Pitch<0) {euler_data_sign|=4;pitch+=18000;} if(Roll<0) {euler_data_sign|=2; roll+=18000;} if(Yaw<0) {euler_data_sign|=1;yaw+=18000;}
mpu6050_euler_data[0]= Pitch; mpu6050_euler_data[1]= Roll; mpu6050_euler_data[2]= Yaw; for(i=0;i<3;i++){ mpu6050_euler_data_buf[i*2]=(mpu6050_euler_data>>8)&0xff; mpu6050_euler_data_buf[i*2+1]=mpu6050_euler_data&0xff;} data_type=0xB0| mpu6050_euler_data_sign; checksum=data_type; for(i=0;i<6;i++) checksum+=anbt_mpu6050_euler_data_buffer; checksum&=0xff; checksum=~checksum; checksum++; AnBT_Uart1_Send_Char(':');Uart1_Send_Num(data_type); for(i=0;i<6;i++)Uart1_Send_Num(mpu6050_euler_data_buf); Uart1_Send_Num(checksum); Uart1_Send_Char('/');
void Uart1_Send_Num(unsigned char number){
unsigned char num_low,num_high;
num_low=number&0x0f;num_high=(number&0xf0)>>4; if(num_high<10)USART_SendData(USART1,num_high+48);
else USART_SendData(USART1,num_high+55) while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET){};
if(num_low<10)USART_SendData(USART1,num_low+48);
else USART_SendData(USART1,num_low+55);
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET){}}
|
|