混控
这是本人第一次写技术博客,还望多多包涵。愿与大家共享知识,相互学习。
项目由来
我是一个航模爱好者,手头有一台天地飞07的遥控器。但同时,我也十分喜欢造小车。那如果我想用航模遥控器来控制一台两轮的小车,究竟应该怎么做呢?
在遥控器中立位置时,小车会静止。
当遥控器摇杆向前后左右四个方向拨动时,小车也会分别作出前进、后退、原地左转、原地右转的动作,而且随着摇杆朝四个方向拨动的程度增大,小车运动的速度也会增大。
那当遥控器摇杆处在其他任意位置时呢?小车可能在前后运动的基础上,又叠加了左右运动。这便要求在写程序时考虑混控,即混合控制,在前进后退方向和左右方向上的混合控制。
摇杆的角度确定两轮转动的方向和转速比例,而摇杆拨动的程度决定两轮的速度,基于这个思路,我尝试完成这个混控程序。
我用Arduino解决这个问题。
以游戏摇杆为例
Step1 用Arduino完成基础步骤
可以按下摇杆作为数字输出,这里姑且不管。游戏摇杆在两个方向上都是模拟输出,两个方向设置为x方向和y方向。两个方向构成了一个正方形的可操纵区域。
使用Arduino UNO,将x轴、y轴的信号端输入到A0、A1引脚。确保x轴从左往右输出增大,y轴从下往上输出增大。
因为用Arduino,所以采集到的x、y轴模拟量数据都处于0~1023之间。
这是摇杆最初的状态
将坐标完成最基础的转换:将0~1023映射到-1~1
x=x/1023-1;
y=y/1023-1;
Step2 压缩坐标
摇杆是正方形,然而映射到小车运动,应该是一个圆形。现在我们把现有坐标压缩成圆形。
因为是线性压缩,所以考虑几个特殊点,方便计算。
在阴影部分内:
b=1/长边,即直角三角形的底边/长边,即:
b=abs(cosθ);
同理易得,在阴影部分外的范围内,
b=abs(sinθ);
那么,
x=x*b;
y=y*b;
得到了一个圆坐标。
Step3 映射到轮子的运动上
规定:left和right来表示两个轮子的转速,+为正转,-为反转。
那么最基本的,y轴控制小车向前进和向后退。
若只有y方向的操作,
left=y;right=y;
同理,x轴控制小车原地左转和右转。
若只有x方向的操作,
left=x;right=-x;
角度决定了这两个方向上操作的“权重”:x方向的权重为cosθ的平方,y方向的权重为sinθ的平方。
则:
left=x*cosθ*cosθ+y*sinθ*sinθ;
right=-x*cosθ*cosθ+y*sinθ*sinθ;
现在,left和right被映射进了-1~1的区间。
Step4 化简和整理
long Cos=x/sqrt(x*x+y*y);
long Sin=y/sqrt(x*x+y*y);
if((x>0 && y<=x && y>-x) || (x<0 && y<-x && y>=x))
{
left =( x*Cos*Cos+y*Sin*Sin)*Cos;
right = (-x *Cos*Cos+y*Sin*Sin)*Cos;
}
if((y>0 && y>x && y>=-x) || (y<0 && y`<`x && y<=-x))
{
left =( x*Cos*Cos+y*Sin*Sin)*Sin;
right = (-x *Cos*Cos+y*Sin*Sin)*Sin;
}
Step5 考虑实际情况
- 考虑到摇杆中立位置不稳定,可以在整个摇杆区间中挖出一块,作为中立区间。
- 考虑到不同的电机驱动板的需求不同,有些还需要映射到1000到2000的脉冲宽度,有些还需要映射到analogWrite(0~255)……所以后续部分不再写了。可以根据需要再映射一下。