说说我折腾DFR0182无线手柄遥控乐高ev3的过程
2016-12-082.3万
精华项目
AI 快速预览详细
本文介绍了使用DFR0182无线手柄通过蓝牙功能遥控乐高EV3的过程。文中提到,乐高EV3通常使用红外遥控器,但红外遥控器的按键操控性不如手柄方便。DFR0182手柄支持蓝牙2.0版本,可以替代红外遥控器。文章还提到了一些安装和调试过程中遇到的问题,如USB转换板插上去松动、按键容易脱落等,并提供了解决方案。通过这种方式,用户可以更方便地遥控乐高EV3,实现更多创意项目。
|
乐高EV3的遥控一般采用红外遥控器和传感器,合计400多毛大大。EV3本身带有蓝牙(2.1版本)功能,如果使用蓝牙,就不需要安装红外传感器了。同时红外遥控器的按键操控性不如手柄方便,所以我打算找一款带蓝牙功能的可编程手柄。问度娘古哥和某宝,目前看来,dfrobot是唯一选择。等拿到dfr0182手柄,感觉比预想的大,做工相当好,不过请允许我先吐几个槽点: 1、贵!手柄加蓝牙模块508毛大大,蓝牙2.0居然卖到140毛大大,比BLE4.0的蓝牙贵了近一倍!和EV3红外比,没有优势了(当然蓝牙模块可以买第三方的,便宜一些)。另外还从dfrobot的另一家店铺买了DFR0008手柄,其实是一款带摇杆和按键的Arduino扩展板,以后再介绍。两个店铺看起来是同一个发货地址,收到两个包裹,运费免了一份;2、上传程序的usb转换板插上去很松,容易脱落,不知道是否由于我曾拆开手柄装蓝牙模块,导致哪里没有卡到位?原包装不带mini usb线,买手柄的亲们要自己准备一根mini usb线;3、拆开手柄安装蓝牙后,发现手柄左上和右上四个按键容易脱落,而且按键内侧的小塑料圈也容易掉落,导致按键不起作用,琢磨了一会,发现窍门是,要从里往外按,才能卡住按键,然后再合上手柄外壳; 4、手柄内部的两根黑红电池线容易断,不方便调试,后来我干脆把线拔了,等电脑上程序调试通过,再找人焊线。 未完待续 |

1、贵!手柄加蓝牙模块508毛大大,蓝牙2.0居然卖到140毛大大,比BLE4.0的蓝牙贵了近一倍!和EV3红外比,没有优势了(当然蓝牙模块可以买第三方的,便宜一些)。另外还从dfrobot的另一家店铺买了DFR0008手柄,其实是一款带摇杆和按键的



[align=left]Y轴(上下):25~131~228[/align]
[align=left][font="]X轴(左右):[/font]34~128~232[/align][align=left]
[/align][align=left]鸡腿还有一个三轴加速传感器,任意摇动鸡腿时(不是摇杆),XYZ三个坐标值会变,不过这种方式操控ev3有点别扭。[/align]
开头提到还入手了一块便宜DFR0008手柄,带四个按建和一个摇杆,足够用了,arduino程序相对简单,我就不重复了,只贴一张靓照。
手柄插上蓝牙模块,再插在arduino上,arduino固定在乐高搭成的支架里,下面绑一块电池供电,非常牢固。
如果能找一个便宜的xbee 2.0蓝牙模块,全部加起来不超过200元,便宜实惠。:lol
等有时间再上传操控乐高EV3小车的视频。
接下来准备加一个红外模块,用手柄遥控乐高PF马达 :lol
[code]unsigned char hexLJoystickX[15] = {0x0d,0x00,0x00,0x00,0x81,0x9e,0x02,0x78,0x00,0x40,0x00,0x00,0x00,0x00,0x00};
unsigned char hexLJoystickY[15] = {0x0d,0x00,0x00,0x00,0x81,0x9e,0x02,0x79,0x00,0x40,0x00,0x00,0x00,0x00,0x00};
unsigned char hexRJoystickX[15] = {0x0d,0x00,0x00,0x00,0x81,0x9e,0x02,0x76,0x00,0x40,0x00,0x00,0x00,0x00,0x00};
unsigned char hexRJoystickY[15] = {0x0d,0x00,0x00,0x00,0x81,0x9e,0x02,0x77,0x00,0x40,0x00,0x00,0x00,0x00,0x00};
int RJoystickY = joystick[2];
int RJoystickX = joystick[3];
int LJoystickY = AnalogButton[0];
int LJoystickX = AnalogButton[1];
union data
{
unsigned char c[4];
float f;
};
union data x;
x.f = RJoystickY;
hexRJoystickY[11] = x.c[0];
hexRJoystickY[12] = x.c[1];
hexRJoystickY[13] = x.c[2];
hexRJoystickY[14] = x.c[3];
Serial1.write(hexRJoystickY,15);
x.f = RJoystickX;
hexRJoystickX[11] = x.c[0];
hexRJoystickX[12] = x.c[1];
hexRJoystickX[13] = x.c[2];
hexRJoystickX[14] = x.c[3];
Serial1.write(hexRJoystickX,15);
x.f = LJoystickY;
hexLJoystickY[11] = x.c[0];
hexLJoystickY[12] = x.c[1];
hexLJoystickY[13] = x.c[2];
hexLJoystickY[14] = x.c[3];
Serial1.write(hexLJoystickY,15);
x.f = LJoystickX;
hexLJoystickX[11] = x.c[0];
hexLJoystickX[12] = x.c[1];
hexLJoystickX[13] = x.c[2];
hexLJoystickX[14] = x.c[3];
Serial1.write(hexLJoystickX,15);[/code]
然后在EV3上测试是否能收到摇杆值:
运行后,在EV3液晶屏上显示左右摇杆数据:
LX:484
LY:505
RX:498
RY:497
拨动摇杆,显示随之变化。
未完待续。。。。。。。
同样,坐标X值代表转向,0-1023对应乐高转向功率-100到+100,偏离0功率越大,转向越急:
由于XY是动态值,无法按前面17个按键那样分配固定的值,需要在arduino里用union类型,把XY值转换成32位浮点数:
[code]union data
{ int i;
unsigned char c[4];
float f;
};
union data x;
union data y;[/code]
把XY坐标值赋给x.f、y.f,这样就可以得到坐标值的XY值对应的32位浮点数x.c、y.c,再按二楼的方式拼装一个16进制字符数组,将[font=微软雅黑, Tahoma, Helvetica, SimSun, sans-serif]16进制字符数组发送到EV3上不同名称的mailbox程序块,比如将X坐标的[/font][font=微软雅黑, Tahoma, Helvetica, SimSun, sans-serif]16进制字符数组,发送到EV3中名称为x的[/font][font=微软雅黑, Tahoma, Helvetica, SimSun, sans-serif]mailbox[/font][font=微软雅黑, Tahoma, Helvetica, SimSun, sans-serif],[/font][font=微软雅黑, Tahoma, Helvetica, SimSun, sans-serif]将Y坐标的[/font][font=微软雅黑, Tahoma, Helvetica, SimSun, sans-serif]16进制字符数组,发送到[/font][font=微软雅黑, Tahoma, Helvetica, SimSun, sans-serif]EV3中名称为y的mailbox。蓝牙数据包中,以x078、0x79代替上面的0x61。EV3收到XY坐标后,分别转换成转向功率和速度功率。[/font][font=微软雅黑, Tahoma, Helvetica, SimSun, sans-serif]
[/font]注意由于摇杆XY值分布不均匀,中间值并非1023/2,需要在EV3程序里分两段进行raw值到功率的转换。
未完待续。。。。。。
由于乐高EV3使用特有的蓝牙数据包格式,为方便在蓝牙主从两端的程序中处理,我将17个按键按1-17编号,发送给EV3,EV3解包后,根据收到的数字,在EV3程序中做相应的处理,如前进后退转向加减速等等。数据包格式如下图:
在arduino里,如何发送蓝牙数据包给EV3呢?请看下面程序片断,修改了DFR的按键检测程序:
[code]unsigned char hexS2[15] = {0x0d,0x00,0x00,0x00,0x81,0x9e,0x02,0x61,0x00,0x40,0x00,0x00,0x00,0x60,0x41};
unsigned char hexS1[15] = {0x0d,0x00,0x00,0x00,0x81,0x9e,0x02,0x61,0x00,0x40,0x00,0x00,0x00,0x50,0x41};
unsigned char hexUP[15] = {0x0d,0x00,0x00,0x00,0x81,0x9e,0x02,0x61,0x00,0x40,0x00,0x00,0x00,0xa0,0x40};
unsigned char hexLEFT[15] = {0x0d,0x00,0x00,0x00,0x81,0x9e,0x02,0x61,0x00,0x40,0x00,0x00,0x00,0xe0,0x40};
unsigned char hexDOWN[15] = {0x0d,0x00,0x00,0x00,0x81,0x9e,0x02,0x61,0x00,0x40,0x00,0x00,0x00,0xc0,0x40};
unsigned char hexRIGHT[15] = {0x0d,0x00,0x00,0x00,0x81,0x9e,0x02,0x61,0x00,0x40,0x00,0x00,0x00,0x00,0x41};
unsigned char hex1[15] = {0x0d,0x00,0x00,0x00,0x81,0x9e,0x02,0x61,0x00,0x40,0x00,0x00,0x00,0x80,0x3f};
unsigned char hex4[15] = {0x0d,0x00,0x00,0x00,0x81,0x9e,0x02,0x61,0x00,0x40,0x00,0x00,0x00,0x80,0x40};
unsigned char hex2[15] = {0x0d,0x00,0x00,0x00,0x81,0x9e,0x02,0x61,0x00,0x40,0x00,0x00,0x00,0x00,0x40};
unsigned char hex3[15] = {0x0d,0x00,0x00,0x00,0x81,0x9e,0x02,0x61,0x00,0x40,0x00,0x00,0x00,0x40,0x40};
unsigned char hexRZ1[15] = {0x0d,0x00,0x00,0x00,0x81,0x9e,0x02,0x61,0x00,0x40,0x00,0x00,0x00,0x30,0x41};
unsigned char hexRZ2[15] = {0x0d,0x00,0x00,0x00,0x81,0x9e,0x02,0x61,0x00,0x40,0x00,0x00,0x00,0x40,0x41};
unsigned char hexLZ1[15] = {0x0d,0x00,0x00,0x00,0x81,0x9e,0x02,0x61,0x00,0x40,0x00,0x00,0x00,0x10,0x41};
unsigned char hexLZ2[15] = {0x0d,0x00,0x00,0x00,0x81,0x9e,0x02,0x61,0x00,0x40,0x00,0x00,0x00,0x20,0x41};
unsigned char hexJ1[15] = {0x0d,0x00,0x00,0x00,0x81,0x9e,0x02,0x61,0x00,0x40,0x00,0x00,0x00,0x70,0x41};
unsigned char hexJ2[15] = {0x0d,0x00,0x00,0x00,0x81,0x9e,0x02,0x61,0x00,0x40,0x00,0x00,0x00,0x80,0x41};
void printData(){
for(int i = 0; i < 17; i++) Serial.print(buttonState),Serial.print(" ");
for(int i = 0; i < 4; i++) Serial.print(joystick),Serial.print(" ");
for(int i = 0; i < 2; i++) Serial.print(AnalogButton),Serial.print(" ");
Serial.println("");
Serial.print("Button Pressed:");
for(int i = 0; i < 2; i++)
{
if(buttonState < 100)
{
Serial.print(Buttons),Serial.print(",");
if ( i == 0 )
Serial1.write(hexJ2,15);
else
Serial1.write(hexJ1,15);
}
}
for(int i = 3; i < 17; i++)
if(buttonState == 0)
{
Serial.print(Buttons);
Serial.print(",");
switch (i)
{
case 3:
Serial1.write(hexS2,15);
break;
case 4:
Serial1.write(hexS1,15);
break;
case 5:
Serial1.write(hexUP,15);
break;
case 6:
Serial1.write(hexLEFT,15);
break;
case 7:
Serial1.write(hexDOWN,15);
break;
case 8:
Serial1.write(hexRIGHT,15);
break;
case 9:
Serial1.write(hex1,15);
break;
case 10:
Serial1.write(hex4,15);
break;
case 11:
Serial1.write(hex2,15);
break;
case 12:
Serial1.write(hex3,15);
break;
case 13:
Serial1.write(hexRZ1,15);
break;
case 14:
Serial1.write(hexRZ2,15);
break;
case 15:
Serial1.write(hexLZ1,15);
break;
case 16:
Serial1.write(hexLZ2,15);
}
}
Serial.println("");
Serial.print("Analog Sticks:");
for(int i = 0; i < 4; i++) Serial.print(joystick),Serial.print(",");
Serial.println("---");
for(int i = 0; i < 2; i++) Serial.print(AnalogButton),Serial.print(",");
Serial.println("");
Serial.println("");
}[/code]
[i][i][i][i][i][i][i][i]
EV3程序里,用一个循环加一个名称为a,读取数字的mailbox块,就可以得到arduino发来的蓝牙按键对应的数字了。当然,事先要在EV3液晶屏里进行蓝牙配对,或程序里配对,应该能看到一个名为“bluetooth_xbee“的设备,就是手柄里的蓝牙模块了。[/i][/i][/i][/i][/i][/i][/i][/i][i][i][i][/i][/i][/i]
[i][i][i][i][i][i][i][i]未完待续。。。。。。
[/i][/i][/i][/i][/i][/i][/i][/i]