写在前面
使用过Odive Foc驱动器的小伙伴们应该都知道,驱动器的数据反馈是通过串口或者CAN总线实现的,我们这里只分享串口数据反馈的解算方法,仅仅作为参考。
在这里我要首先声明一下,我所用的方法是最为笨拙的解算方法,也就是一个字符一个字符地读取。因此,这里我不建议大家学习使用我这种方法,仅仅作为分享和交流的材料。
数据格式
这里ODRIVE官网的源码里面给了数据反馈的格式,当然也可以在官方文档里面找到
根据这个格式,我们就需要自己来写解析
我一直没想明白,为什么odrive官方既然都用ASCII发送数据,为什么不用十六进制的格式发送呢?弄一个字符串,我们使用者写起解算来还挺麻烦的(也可能是我孤陋寡闻,没有找到更好的算法),大家如果有什么好方法也希望能够提出来,避免更多的小伙伴踩坑
代码
代码如下:
// 由于我读了ODRIVE两路的数据反馈,因此变量的命名后面都加了一个1
if(RX_BUF1) // RX_BUF1 是串口接收到的字符,这里我是一个一个接收的
{
// 判断第一个字符是否是数字
if(RX_BUF1 > '9' && RX_BUF1 < '0' && RX_BUF1 != '\n' && RX_BUF1 != '.' && RX_BUF1 != 32 && RX_BUF1 != '-')
{
//
pos1 = 0;
vel1 = 0;
rx_flag1 = 0;
}
else
{
if(rx_flag1 == 0)
{
// 第一步 判断换行
if(RX_BUF1 == '\n')
{
rx_flag1 = 1;
}
}
else if(rx_flag1 == 1)
{
// 判断是不是负数
if(RX_BUF1 == '-')
{
rx_flag1 = 1;
naflag1 = 1; // 如果是负数,则需要标记,最后要把读出来的浮点数×-1
}
else
{
// 下面就是一个数一个数的读了,每读一次更新一下变量pos1
if(RX_BUF1 != '.') // 判断小数点
{
pos1 *= 10;
pos1 += (RX_BUF1 - '0');
rx_cnt1 ++;
}
else
{
rx_cnt1 = 0;
rx_flag1 = 2;
}
if(rx_cnt1 > 3)
{
rx_flag1 = 0;
rx_cnt = 0;
pos1 = 0;
vel1 = 0;
}
}
}
else if(rx_flag1 == 2)
{
if(RX_BUF1 == 32) // 32 是空格的ascii, 也可以直接打' '
{
// 遇到空格之后,如果之前有读到负号,就要把数据置为负值
if(naflag1 == 1)
{
naflag1 = 0;
pos1 *= -1;
}
rx_cnt1 = 0;
rx_flag1 = 3;
}
else
{
// 过了小数点,并且还没遇到空格的时候,一位一位读即可,我这里只读了三位
rx_cnt1++;
if(rx_cnt1 == 1) pos1 += (RX_BUF1 - '0') * 0.1;
else if(rx_cnt1 == 2) pos1 += (RX_BUF1 - '0') * 0.01;
else if(rx_cnt1 == 3) pos1 += (RX_BUF1 - '0') * 0.001;
}
}
// 后面是速度的解析,和上面是一样的,就不再赘述了
else if(rx_flag1 == 3)
{
if(RX_BUF1 == '-')
{
naflag1 = 1;
}
else
{
if(RX_BUF1 != '.')
{
vel1 *= 10;
vel1 += (RX_BUF1 - '0');
rx_cnt1 ++;
}
else
{
rx_cnt1 = 0;
rx_flag1 = 4;
}
if(rx_cnt1 > 3)
{
rx_flag1 = 0;
rx_cnt1 = 0;
pos1 = 0;
vel1 = 0;
}
}
}
else if(rx_flag1 == 4)
{
if(rx_cnt1 == 4)
{
if(naflag1 == 1)
{
naflag1 = 0;
vel1 *= -1;
}
rx_cnt1 = 0;
rx_flag1 = 5;
}
else
{
rx_cnt1++;
if(rx_cnt1 == 1) vel1 += (RX_BUF1 - '0') * 0.1;
else if(rx_cnt1 == 2) vel1 += (RX_BUF1 - '0') * 0.01;
else if(rx_cnt1 == 3) vel1 += (RX_BUF1 - '0') * 0.001;
}
}
else
{
// 最后把读到的值赋值出去,然后变量清理,以便下一次读取
rx_flag1 = 0;
final_pos1 = pos1;
final_vel1 = vel1;
pos1 = 0;
vel1 = 0;
}
}
}
我的代码总体思路就是一个字符一个字符判断,然后判断符合要求就用一个变量记录下来,然后继续往下读字符,直到读出两个数据为止
这种办法虽然笨拙,但是亲测有效
期待评论区能够有更优秀的方法出现