设为首页收藏本站

说说我折腾DFR0182无线手柄遥控乐高ev3的过程

taelons 发表于 2016-12-8 12:15:25 | 显示全部楼层 [复制链接]
13 838
本帖最后由 taelons 于 2016-12-8 17:07 编辑

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

未完待续


发表于 2016-12-8 13:47:49 | 显示全部楼层
本帖最后由 taelons 于 2016-12-8 13:48 编辑

接下来上传DFR提供的手柄按键检测程序,arduino ide里执行无误,串口监视界面里能显示按下了哪个键。14个键连接到arduino的数字口,低电平0表示按下,从串口监视器和代码里很容易看出。接下来要确定摇杆不同位置的键值分布(姑且称之为raw值),我不懂电路,摇杆是电位器,其raw值应该是模拟的电压值转换成数字值。为方便辨识,将程序中的延迟加大,经多次运行代码,记录如下摇杆raw值分布:


摇杆值.jpg




由于乐高EV3使用特有的蓝牙数据包格式,为方便在蓝牙主从两端的程序中处理,我将17个按键按1-17编号,发送给EV3,EV3解包后,根据收到的数字,在EV3程序中做相应的处理,如前进后退转向加减速等等。数据包格式如下图:
s数据包格式.jpg


在arduino里,如何发送蓝牙数据包给EV3呢?请看下面程序片断,修改了DFR的按键检测程序:

[C] 纯文本查看 复制代码
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[i]),Serial.print(" ");
  for(int i = 0; i < 4; i++)  Serial.print(joystick[i]),Serial.print(" ");
  for(int i = 0; i < 2; i++)  Serial.print(AnalogButton[i]),Serial.print(" ");
  Serial.println("");
  Serial.print("Button Pressed:");
  for(int i = 0; i < 2; i++)  
  {
      if(buttonState[i] < 100) 
      {
        Serial.print(Buttons[i]),Serial.print(",");
        if ( i == 0 )
          Serial1.write(hexJ2,15);
        else
          Serial1.write(hexJ1,15);
      }
  }
      
  for(int i = 3; i < 17; i++)  
  if(buttonState[i] == 0)
  {
    Serial.print(Buttons[i]);
    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[i]),Serial.print(",");
  Serial.println("---");
  for(int i = 0; i < 2; i++)  Serial.print(AnalogButton[i]),Serial.print(",");
  Serial.println("");
  Serial.println("");
}



EV3程序里,用一个循环加一个名称为a,读取数字的mailbox块,就可以得到arduino发来的蓝牙按键对应的数字了。当然,事先要在EV3液晶屏里进行蓝牙配对,或程序里配对,应该能看到一个名为“bluetooth_xbee“的设备,就是手柄里的蓝牙模块了。
未完待续。。。。。。



回复 支持 反对

使用道具 举报

发表于 2016-12-8 16:35:24 | 显示全部楼层
楼主加油更新啊
回复 支持 反对

使用道具 举报

发表于 2016-12-9 12:20:22 | 显示全部楼层
上面的程序是单个键的蓝牙数据发送,这里不需要考虑组合按键,因为手柄的17个键足够分配不同功能了,四个按键就可以完成前进后退左右转向,要玩些花哨功能,如原地打转或漂移等,手柄左上右上四个按键很适合,组合按键徒增操控和编码的复杂度。接下来是摇杆功能的设计,一个摇杆就能完成所有常用功能。此时要向EV3发送坐标值XY。按上面的raw值分布表,Y值代表速度,介意0-1023之间,0代表后退最高速度,在EV3里对应马达功率-100,1023是前进最高速度,在EV3里对应+100。很简单,EV3只需将收到的raw值转换成-100到+100就可以了。
同样,坐标X值代表转向,0-1023对应乐高转向功率-100到+100,偏离0功率越大,转向越急:
转向.jpg

由于XY是动态值,无法按前面17个按键那样分配固定的值,需要在arduino里用union类型,把XY值转换成32位浮点数:
[AppleScript] 纯文本查看 复制代码
union data 
{    int i;
     unsigned char c[4];
     float f;  
};  
union data x;
union data y;


把XY坐标值赋给x.f、y.f,这样就可以得到坐标值的XY值对应的32位浮点数x.c、y.c,再按二楼的方式拼装一个16进制字符数组,将16进制字符数组发送到EV3上不同名称的mailbox程序块,比如将X坐标的16进制字符数组,发送到EV3中名称为x的mailbox将Y坐标的16进制字符数组,发送到EV3中名称为y的mailbox。蓝牙数据包中,以x078、0x79代替上面的0x61。EV3收到XY坐标后,分别转换成转向功率和速度功率。
注意由于摇杆XY值分布不均匀,中间值并非1023/2,需要在EV3程序里分两段进行raw值到功率的转换。
未完待续。。。。。。

回复 支持 反对

使用道具 举报

发表于 2016-12-9 14:17:28 | 显示全部楼层
大写的赞~
回复 支持 反对

使用道具 举报

发表于 2016-12-9 17:31:51 | 显示全部楼层
坐等楼主更新
回复 支持 反对

使用道具 举报

发表于 2016-12-10 22:22:13 | 显示全部楼层
666
回复 支持 反对

使用道具 举报

发表于 2016-12-11 08:51:06 | 显示全部楼层
我的EV3 usb口貌似有故障,暂时不能调试程序,摇杆的程序先贴出来。

[AppleScript] 纯文本查看 复制代码
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);



然后在EV3上测试是否能收到摇杆值:
bt.jpg


运行后,在EV3液晶屏上显示左右摇杆数据:

LX:484
LY:505
RX:498
RY:497

拨动摇杆,显示随之变化。

未完待续。。。。。。。
回复 支持 反对

使用道具 举报

发表于 2016-12-11 21:23:15 | 显示全部楼层
经过以上几步,EV3已能通过蓝牙接收手柄按键和摇杆数据,剩下的事情就简单了,在LEGO MINDSTORMS EV3 Home Edition中用程序块拖放编程,这里就不打算说了。

开头提到还入手了一块便宜DFR0008手柄,带四个按建和一个摇杆,足够用了,arduino程序相对简单,我就不重复了,只贴一张靓照。

IMG_20161211_205750.jpg


手柄插上蓝牙模块,再插在arduino上,arduino固定在乐高搭成的支架里,下面绑一块电池供电,非常牢固。
如果能找一个便宜的xbee 2.0蓝牙模块,全部加起来不超过200元,便宜实惠。

等有时间再上传操控乐高EV3小车的视频。

接下来准备加一个红外模块,用手柄遥控乐高PF马达
回复 支持 反对

使用道具 举报

发表于 2016-12-12 11:05:02 | 显示全部楼层
arduino的便利性就在这里,如果玩的溜,乐高都是给arduino打工的……
回复 支持 反对

使用道具 举报

发表于 2016-12-14 11:35:47 | 显示全部楼层
这个帖子要赞一下。  把乐高并入到Arduino的世界。
回复 支持 反对

使用道具 举报

发表于 2016-12-15 11:36:50 | 显示全部楼层
同样的方法可以实现用任天堂wii chuck手柄(俗称鸡腿)配合arduino操控,前天拿到dfrobot的wii 转接板,记录下鸡腿的摇杆XY轴坐标值:

Y轴(上下):25~131~228

X轴(左右):34~128~232

鸡腿还有一个三轴加速传感器,任意摇动鸡腿时(不是摇杆),XYZ三个坐标值会变,不过这种方式操控ev3有点别扭。

回复 支持 反对

使用道具 举报

发表于 2016-12-21 07:49:17 | 显示全部楼层
真心不错呀
回复 支持 反对

使用道具 举报

发表于 2017-1-6 21:17:00 | 显示全部楼层
叼                       牛                       资料不错
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册  

本版积分规则 允许回帖同步到新浪微博  

  • 中级技师
  • 519
  • 3
  • 萌萌哒新人

    萌萌哒新人

推荐阅读

精华导读




公司简介| 联系我们| 加入我们| 微博| 优酷| 英文网站| DF创客社区 ( 沪ICP备09038501号-4  
友情链接| 硬创邦| 花生壳社区| 模友之吧| 云汉电子社区| 创客星球| 电子发烧友社区| 电子工程网| 与非网|

上海智位机器人有限公司  沪ICP备09038501号-4   

Powered by Discuz! X3.1

Licensed Comsenz Inc.

返回顶部 返回列表