5iMX宗旨:分享遥控模型兴趣爱好

5iMX.com 我爱模型 玩家论坛 ——专业遥控模型和无人机玩家论坛(玩模型就上我爱模型,创始于2003年)
查看: 1796|回复: 6
打印 上一主题 下一主题

枪控单手模式的实现

[复制链接]
跳转到指定楼层
楼主
发表于 2019-12-3 16:22 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 wienne 于 2019-12-4 10:35 编辑

枪控单手模式
一、       目标
枪式遥控器需要一手控制油门,另一手控制手轮实现车辆的转向。单手模式是指仅用单手控制油门的同时利用手腕的转动实现转向的控制。
相比单手用姆指控手轮,天生的不同可能根本无法实现。即使可行也只能实现部分的手轮控量。或者使用衣夹成为手轮的延伸,类比延长姆指。几无成本,只是控制量比姆指式还要低。




二、       原理
枪式遥控器配置的手轮,本质为带回中功能的高精度90度电位器。通过旋转电位器达到不同的角度以产生不同的电压值,遥控器将此转化对舵机转向量。
接管手轮的电位器输出,增加第二种控制量,在一系列处理后,将控制量再以模拟量的方式传递给遥控器的中心处理单元,最终实现对车辆转向的第二种控制。
本实现属于增加功能,并不影响原有手轮的使用。只是使用手轮前需要特定动作。
原理图:



三、       方法
电子陀螺仪有三个轴向的转动量。X轴可以理解为固定翼飞机的副翼控制,Y轴理解为俯仰控制,Z轴理解为方向控制。


本实现利用X轴的转动代替手轮的旋转实现对车辆的转向控制。
Z轴的转动与现实中方向的转向相同,但会受到如身体和手臂的转动而产生转向量的叠加,导致转向控制过于敏感。故而使用与真车方向盘的转向相同的X轴转动,即手腕的转动作为控制量。

四、       MCU
它实时读取陀螺仪的转动角度值,以及和手轮电位器的电压值。根据特定条件选择输出陀螺仪的转动角度或是手轮的转动角度。


五、       DAC
鉴于Arduino Pro Micro自带的数模DAC是10位1024的输出,无法满足FUTABA 7PX中心处理器的要求。故而增加1块12位的DAC输出模块MCP4725,很好的满足了使用需求。它是本实现的关键指标之一,如与中心处理单元不匹配时,会产生抖舵。


六、       实现
本实现并不局限于Futaba 7PX这一款遥控器,理论上讲任一款枪式遥控器都可实现本功能。
主要受限于新增加的电子原件的安装空间,及是否考虑美观度。



七、       接线图



八、       流程图


九、       实物图1.
手轮Futaba 7PX


       Futaba为了方便更换手轮方向,将手轮设计为便于拔插,同时又将电位器的连接如此直观的展现出来,简直就是为了改造而设计。

2. 手轮下拉器
       手轮下拉器提供了陀螺仪等模块的安装空间。如果不使用下拉器,在液晶屏的下方,有一定的空间可以安装模块,但很空间很紧凑。




3. 陀螺仪JY901
本实现中,陀螺仪的性能是关键点之一。根据尺寸和成本,必须选择陀螺仪在静止不动,角度的变化不应大于0.05度,否则将会出现抖舵。

鉴于淘宝几块钱的三轴陀螺仪误差实在是太大,在一分钱一分货的教训下选择了价值一百元的九轴加速器 JY901,效果很好。


因为在下拉器里是垂直安装陀螺仪,所以在陀螺仪的设置程序里修改安装方向为‘垂直’。



4. DAC MCP4725
       MCP 4725芯片需要将上图中黄框中的ADDR与VCC焊接到一起,以启用I2C的地址0x61。其他地址请参考芯片手册。



5. Arduino Pro Micro
在尺寸和供电的限制下,选择了ArduinoPro Micro。国内兼容厂商实际使用了的是LEONARDO,在芯片选择上注意Arduino的型号。

其实有更小的ATTINY85,但模块需要5V供电,而遥控器只能3.3供电。使用升压模块又会多一样东西。这块板也放得下,就用它了。



6. 最终设备组装图



十、       物品清单

  
名称
  
型号
数量
单位
价格
  
手轮下拉器
  
FUTABA 7PX适用
1
88
  
陀螺仪
  
JY901
1
98
  
DAC
  
MCP 4725
1
4.3
  
MCU
  
Arduino Pro Micro
1
26
  
合计
  
216.3



十一、         缺憾
由于Futaba 7PX遥控器头重脚轻,液晶屏及主要电路板及手轮加起来比电池仓重,实际使用陀螺仪控制时,并不像想的那么顺手。当然如果在下部增加点配重手感会好很多,只是手就有点累了。
由于连接手轮电位器的是Arduino Pro Micro的10位ADC,精度方面差一个档次。在舵机的监视里仔细观察会发现不如原始般的顺滑,但考虑到此次主要是实现用陀螺仪控制转身,此步暂因实现困难而先放一边。
由于没有现成的模块,只有贴片式的芯片,想按厂家的设计电路实现,在不想打电路板的情况下,纯用手工焊接,对我来说真是个不可能完成的任务。










发贴不易,望多顶帖


------------------------------------
  1. /*
  2. 名称:枪控的单手控制转向和油门
  3. 功能:利用陀螺仪的X轴偏转代替枪式遥控器手轮的旋转,满足单手控制油门和方向的需求
  4. 硬件:                Arduino Pro Micro,30元
  5. 陀螺仪:        JY901,100元
  6. DAC:                MCP4725,10元
  7. 附件:                FUTABA 方向盘下拉器,100元。FUTABA 7PX 需要此附件内安装以上3个模块
  8. 作者:                武汉关山-小孙
  9. QQ:                271198361
  10. 日期:                2019/12/2
  11. 版本:                1.0

  12. 陀螺仪与Arduino的接线
  13. JY901    Arduino
  14. SDA <---> SDA
  15. SCL <---> SCL

  16. MCP4725通过JY901串接至Arduino, 连线方便
  17. MCP4725  JY901        
  18. SDA <---> SDA
  19. SCL <---> SCL
  20. */

  21. //#define HARD_DEBUG                                                        //如此行未被注释,开启USB串口的调试输出
  22. //#define SOFT_DEBUG                                                        //如此行未被注释,开启软串口的调试输出

  23. #ifdef SOFT_DEBUG                                                                //使用软件模拟的串口查看调试信息,使用如“USR-TCP232”工具软件查看
  24.         #include <SoftwareSerial.h>                                        //软串口库文件
  25.         SoftwareSerial mySerial(14, 15);                         //RX接收, TX发送
  26. #endif

  27. #include <EEPROM.h>                                                                //基础库文件,保存变量
  28. #include <Wire.h>                                                                //基础库文件
  29. #include <JY901.h>                                                                //陀螺仪库文件
  30. #include <Adafruit_MCP4725.h>                                        //MCP4725库文件

  31. Adafruit_MCP4725 dac_x;                                                 //创建MCP4725的类型变量
  32. #define MCP4725_MIN                                                0                //12位精度时最小值
  33. #define MCP4725_MAX                                                4095        //12位精度时最大值
  34. #define MCP4725_HALF                MCP4725_MAX / 2                //12位精度的一半


  35. #define SURFACE_PIN                                                A7                //手轮,手轮电位器输出线连接到Arduino的端口号,接模拟输入
  36. #define SURFACE_X_CENTER                                522                //522,为开发期间调试时检测到FUTABA 7PX手轮的中立点
  37. #define SURFACE_X_DIEZONE                                5                /*手轮,死区。即会忽略的轻微的动作量范围。
  38.                                                                                                         最小0,最大不宜超过20。
  39.                                                                                                         过大,手轮反应会感觉迟钝。
  40.                                                                                                         过小,当手轮的电位器中立点跳动较大时,易导致认为手轮有动作而忽略陀螺仪传递的变化值*/
  41. #define SURFACE_IDLE_TIME                                2500        //手轮空闲时间,在此时间内手轮无动作后,切换至陀螺仪控制,单位:毫秒
  42. #define GYRO_INITIALIZE_TIME                        1500        //等待陀螺仪启动和初始化,如无此等待程序将出现异常,单位:毫秒
  43. #define STATISTICS_COUNT                                500                //统计取样数,用统计方法计算中立点

  44. #define GYRO_X_MIN                                                -4500        /*陀螺仪x轴,最大允许‘逆时针’时旋转的度数(数值除100,为实际度数)
  45.                                                                                                         角度过大,手腕旋转不过来,且控制速度过慢,太伤手腕
  46.                                                                                                         角度过小,手腕旋转速度快,但控制精度降低
  47.                                                                                                         可根据实际情况调整
  48.                                                                                                         最大,9000,即90度
  49.                                                                                                         最小,0。即禁用陀螺仪控制。*/
  50. #define GYRO_X_MAX                                                4500         //陀螺仪x轴,最大允许‘顺时针’时旋转的度数。其他同上变量说明。

  51. #define GYRO_Y_MAX                                                3500        //陀螺仪y轴,当枪控被‘举起’的角度,正数
  52. #define GYRO_Y_MIN                                                -7500         //陀螺仪y轴,当枪控被‘放下’的角度,负数
  53.                                                                                                 //符合此值说明的条件:左手控制油门,右手控制手轮。
  54.                                                                                                 //如果手轮的安装与此相反,上述两值取反。

  55. int surface_x        =                                                0        ;        //手轮,读取到手轮的电压值

  56. int surface_x_max =                                         0        ;        //手轮,电压值最大值
  57. int surface_x_min =                                         0        ;        //手轮,电压值最小值
  58. int surface_x_center =                                        0        ;        //手轮,中立点
  59. unsigned long surface_x_sum =                        0        ;        //手轮,中立点的平均值汇总
  60. unsigned int surface_x_c_left =                 0        ;        //手轮,轻微动作,小于中立点
  61. unsigned int surface_x_c_right=                 0        ;        //手轮,轻微动作,大于中立点
  62. unsigned long surface_action_time =         0         ;         //手轮,有动作的开始时间

  63. bool gyro_lead =                                         true        ;        //陀螺仪,优先状态。默认优先陀螺仪控制转向。
  64. float         gyro_x =                                                 0        ;        //陀螺仪x轴,有符号数值
  65. float         gyro_y =                                                 0        ;        //陀螺仪y轴,有符号数值
  66. float         gyro_x_min =                                        0        ;        //陀螺仪x轴,实际参与计算的变量
  67. float         gyro_x_max =                                        0        ;        //陀螺仪x轴,实际参与计算的变量
  68. float         gyro_y_min =                                        0        ;        //陀螺仪y轴,实际参与计算的变量
  69. float         gyro_y_max =                                        0        ;        //陀螺仪y轴,实际参与计算的变量
  70. long        gyro_x_sum =                                          0         ;        //陀螺仪x轴,缺省为0度
  71. long        gyro_y_sum =                                          0         ;        //陀螺仪y轴,缺省为0度
  72. int                gyro_x_center =                                        0         ;        //陀螺仪x轴,经计算后的中立点
  73. int                gyro_y_center =                                        0         ;        //陀螺仪y轴,经计算后的中立点
  74. int         final_x        =                                                0        ;        /*最终输出的x值
  75.                                                                                                 使用MCP 4275,输出精度为12位,最大值4096。
  76.                                                                                                 如使用Arduino自带的PWM模拟输出,会看到遥控器的舵量条有严重抖动*/
  77.                                                                                                 
  78. union save_data{               
  79.   int val;
  80.   byte v[2];
  81. };

  82. save_data surface_x_save        ;


  83. //性能统计
  84. //unsigned long process_count = 0 ;        //测试程序性能计数器
  85. //unsigned long system_begin_time = 0 ;

  86. void setup() {

  87.         //如果更换了ADC模块,导致手轮的最大值和最小值,从大值变为了小值,需要将EEPROM清零
  88.         //此功能代码还需要另写
  89.         
  90.         //从EEPROM读取保存过的手轮的最大值和最小值
  91.         for(int n=0;n<2;n++)        surface_x_save.v[n]=EEPROM.read(n);
  92.         surface_x_save.v[0]=EEPROM.read(0);
  93.         surface_x_save.v[1]=EEPROM.read(1);
  94.         surface_x_max = surface_x_save.val;        //手轮,记录到的旋转最大值

  95.         surface_x_save.v[0]=EEPROM.read(2);
  96.         surface_x_save.v[1]=EEPROM.read(3);
  97.         surface_x_min = surface_x_save.val;        //手轮,记录到的旋转最小值
  98.         if(surface_x_min == 0) surface_x_min=10000        ;
  99.         
  100.         JY901.StartIIC();        //陀螺仪初始化
  101.         dac_x.begin(0x61);        //输出X轴的DAC初始化

  102.         #ifdef HARD_DEBUG
  103.                 Serial.begin(9600);
  104.         #endif

  105.         #ifdef SOFT_DEBUG
  106.                 mySerial.begin(9600);
  107.         #endif

  108.         delay(GYRO_INITIALIZE_TIME);                         //必要等待,让陀螺仪启动和初始化,否则后续程序可能不会执行

  109.         //计算中立点
  110.         calc_center();
  111.         
  112.         //X及Y轴的中立点,不能偏移超过设定的限定值
  113.         while( gyro_x_center < GYRO_X_MIN ){        
  114.                 show(MCP4725_MIN, 1000 );                        //最大左转
  115.                 delay(1500);
  116.                 calc_center();
  117.         }
  118.         while( gyro_x_center > GYRO_X_MAX ){
  119.                 show(MCP4725_MAX, 1000 );                        //最大右转
  120.                 delay(1500);
  121.                 calc_center();
  122.         }

  123.         while( gyro_y_center < GYRO_Y_MIN ){
  124.                 show(MCP4725_MAX/4, 1000 );                        //中度左转
  125.                 delay(1500);
  126.                 calc_center();
  127.         }
  128.         while( gyro_y_center > GYRO_Y_MAX ){
  129.                 show(MCP4725_MAX/4*3, 1000 );                //中度右转
  130.                 delay(1500);
  131.                 calc_center();
  132.         }


  133.         //中立点计算结束,展示两个转向端点
  134.         show(MCP4725_MIN, 100 );//最大左转
  135.         show(MCP4725_MAX, 100 );//最大右转

  136.         #ifdef HARD_DEBUG
  137.                 Serial.println(); Serial.println();
  138.                 Serial.print("Center:");
  139.                 Serial.print(surface_x_center);Serial.print(",");
  140.                 Serial.print(gyro_x_center);Serial.print(",");
  141.                 Serial.print(gyro_y_center);Serial.print(",");
  142.                 Serial.println();
  143.                 Serial.print("S_x_sum:");Serial.print(surface_x_sum);Serial.print(",");
  144.                 Serial.print("G_x_sum:");Serial.print(gyro_x_sum);Serial.print(",");
  145.                 Serial.print("F_y_sum:");Serial.print(gyro_y_sum);Serial.print(",");
  146.                 Serial.print("COUNT:");Serial.print(STATISTICS_COUNT);
  147.                 Serial.println(); Serial.println();
  148.                 Serial.println("Begin:");
  149.         #endif


  150.         //性能统计
  151.         //system_begin_time = millis();
  152. }

  153. void loop() {

  154.         if( gyro_lead ){        //默认由陀螺仪进行控制
  155.         
  156.                 //2019/11/13        从陀螺仪取值,最多每 0.0716 秒输出一次控制量
  157.                 //2019/11/21        10/8347= 0.001198s/次        //将同时读取手轮电压值分离
  158.                 //2019/12/2                10/8364= 0.001195s/次        //可能电压变化,可视无差别
  159.                
  160.                 //手轮无动作时间后才取陀螺仪的各值,减少有手轮控制时又去取陀螺仪各值的无用cpu消耗
  161.                 JY901.GetAngle();                                                                           //取陀螺仪的角度值
  162.                 gyro_x = (float)JY901.stcAngle.Angle[0]/32768*18000 ;        //陀螺仪,X轴绝对值。度数放大100倍,用于提高用角度进行map转换的精度
  163.                 gyro_y = (float)JY901.stcAngle.Angle[1]/32768*18000 ;        //陀螺仪,Y轴绝对值。度数放大100倍
  164.                 //gyro_z = (float)JY901.stcAngle.Angle[2]/32768*180 ;         //陀螺仪,Z轴绝对值。原始度数
  165.                                 
  166.                 if(gyro_x < gyro_x_min )  gyro_x = gyro_x_min ;                        //限定逆时针时的旋转最大度角
  167.                 if(gyro_x > gyro_x_max )  gyro_x = gyro_x_max ;                        //限定顺时针时的旋转最大度角

  168.                 /*当枪控被举起(Y轴为正数)或放下(Y轴为负数)的角度大于设定值时
  169.                         1,将X轴的输出值置回中立点,让转向快速回到中立点,是否能引出特殊控制方式,效果待测
  170.                         2,只有此时,手轮才‘将’可控。
  171.                                 鉴于arduino的analogRead函数工作原理。理论每秒最多取值一万次,实际最多约接近九千次/秒。
  172.                                 如果每个循环周期不论如何都读取一次手轮的电压值,实际却是在用陀螺仪做控制,这将导致无意义的大量cpu被消耗。
  173.                                 将实时读取手轮的电压值,改为枪控被举起或放下后的一段时间内转向才受手轮的控制。
  174.                                 整体性能提升约40%,得到控制量更细腻,舵量条变量更顺滑。
  175.                         3,能让手臂休息一下,避免产生误操作。
  176.                 */
  177.                 if(gyro_y < gyro_y_min or gyro_y > gyro_y_max ){                //当枪控被举起或放下
  178.                         gyro_x = gyro_x_center;                                                                //转向回到中立点
  179.                         gyro_lead = false ;                                                                        //优先手轮
  180.                         surface_action_time = millis() ;                                        //确定手轮将可以动作的起始时间
  181.                 }
  182.                
  183.                 //使用陀螺仪的角度值
  184.                 final_x = map(gyro_x, gyro_x_min, gyro_x_max, MCP4725_MIN, MCP4725_MAX);        
  185.                
  186.         }else{
  187.         
  188.                 //2019/11/13        从手轮取值,最多每 0.0167 秒输出一次控制量
  189.                 //2019/11/21        10/37845= 0.000264s/次        //大幅调整读取逻辑
  190.                 //2019/12/2                10/37709= 0.000265s/次        //增加最大及最小值保存至EEPROM
  191.                
  192.                 surface_x = analogRead(SURFACE_PIN) ;        //读取手轮的电压值
  193.                 if(surface_x > surface_x_max ){                        //取手轮电压值的最大值
  194.                         surface_x_max = surface_x ;
  195.                         surface_x_save.val = surface_x ;        //保存手轮的电压值最大值
  196.                         EEPROM.write(0, surface_x_save.v[0]);
  197.                         EEPROM.write(1, surface_x_save.v[1]);
  198.                 }                        
  199.                 if(surface_x < surface_x_min ){                        //取手轮电压值的最小值
  200.                         surface_x_min = surface_x ;                        
  201.                         surface_x_save.val = surface_x ;        //保存手轮的电压值最小值
  202.                         EEPROM.write(2, surface_x_save.v[0]);
  203.                         EEPROM.write(3, surface_x_save.v[1]);
  204.                 }
  205.                
  206.                 if(surface_x < surface_x_c_left or surface_x > surface_x_c_right ){//手轮有动作
  207.                         //更新手轮动作时的发生时间,能持续一段时间让手轮控制转向
  208.                         surface_action_time = millis();
  209.                         
  210.                         //使用手轮的电压值
  211.                         final_x = map(surface_x, surface_x_min, surface_x_max, MCP4725_MIN, MCP4725_MAX);        
  212.                 }else{
  213.                         //手轮没有动作时,即认为在中立点。使用DAC最大值的一半作为输出值               
  214.                         final_x = MCP4725_HALF ;
  215.                         
  216.                         //重新让陀螺仪优先控制
  217.                         if( millis() - surface_action_time > SURFACE_IDLE_TIME ) gyro_lead = true ;
  218.                 }
  219.                
  220.                
  221.         }

  222. #ifdef HARD_DEBUG
  223.         Serial.print("G_x:");Serial.print(gyro_x);Serial.print(",");
  224.         Serial.print("G_x_min:");Serial.print(gyro_x_min);Serial.print(",");
  225.         Serial.print("G_x_max:");Serial.print(gyro_x_max);Serial.print(",");
  226.         Serial.print("G_x_c:");Serial.print(gyro_x_center);Serial.print(",");
  227.         
  228.         Serial.print("G_y:");Serial.print(gyro_y);Serial.print(",");
  229.         Serial.print("G_y_min:");Serial.print(gyro_y_min);Serial.print(",");
  230.         Serial.print("G_y_max:");Serial.print(gyro_y_max);Serial.print(",");
  231.         Serial.print("G_y_c:");Serial.print(gyro_y_center);Serial.print(",");
  232.         
  233.         Serial.print("S_x:");Serial.print(surface_x);Serial.print(",");
  234.         Serial.print("S_max:");Serial.print(surface_x_max);Serial.print(",");
  235.         Serial.print("S_min:");Serial.print(surface_x_min);Serial.print(",");
  236.         Serial.print("S_c:");Serial.print(surface_x_center);Serial.print(",");
  237.         Serial.print("S_L:");Serial.print(surface_x_c_left);Serial.print(",");
  238.         Serial.print("S_R:");Serial.print(surface_x_c_right);Serial.print(",");

  239.         Serial.print("x:");        Serial.println(final_x);

  240.         delay(100);
  241. #endif

  242. #ifdef SOFT_DEBUG
  243.         mySerial.print("G_x:");mySerial.print(gyro_x);mySerial.print(",");
  244.         mySerial.print("G_x_min:");mySerial.print(gyro_x_min);mySerial.print(",");
  245.         mySerial.print("G_x_max:");mySerial.print(gyro_x_max);mySerial.print(",");
  246.         mySerial.print("G_x_c:");mySerial.print(gyro_x_center);mySerial.print(",");
  247.         
  248.         mySerial.print("G_y:");mySerial.print(gyro_y);mySerial.print(",");
  249.         mySerial.print("G_y_min:");mySerial.print(gyro_y_min);mySerial.print(",");
  250.         mySerial.print("G_y_max:");mySerial.print(gyro_y_max);mySerial.print(",");
  251.         mySerial.print("G_y_c:");mySerial.print(gyro_y_center);mySerial.print(",");
  252.         
  253.         mySerial.print("S_x:");mySerial.print(surface_x);mySerial.print(",");
  254.         mySerial.print("S_max:");mySerial.print(surface_x_max);mySerial.print(",");
  255.         mySerial.print("S_min:");mySerial.print(surface_x_min);mySerial.print(",");
  256.         mySerial.print("S_c:");mySerial.print(surface_x_center);mySerial.print(",");

  257.         mySerial.print("X:");mySerial.print(final_x, DEC);
  258.         mySerial.println();
  259.         delay(100);
  260. #endif


  261.         dac_x.setVoltage(final_x, false); //输出转向


  262. //性能统计
  263. /*         process_count++ ;        
  264.         if(millis() - system_begin_time > 10000){
  265.                 Serial.print(process_count);
  266.                 while(1);
  267.         } */
  268. }

  269. void calc_center() {

  270.         /*        计算中立点
  271.                 初始化完成后,计算手轮和陀螺仪X、Y轴的中立点
  272.                 即:在打开枪控电源后,保持遥控器处于水平位置不动,并且不要旋转手轮。
  273.                 直待转向轮左右摇摆一次并回中后,中立点计算完成。
  274.                
  275.                 主要目的:
  276.                 陀螺仪芯片在枪控里安装的位置狭小,难以保证绝对的水平和垂直。
  277.                 为了实现即使有点歪斜也不影响使用,让系统自动计算中立点。
  278.                 但为了使用感受,最好还是让遥控器在水平的位置计算各轴的相对中立点。*/
  279.         
  280.         surface_x_sum = 0        ;
  281.         gyro_x_sum =         0        ;
  282.         gyro_y_sum =         0        ;
  283.         
  284.         for(int i = 0 ; i < STATISTICS_COUNT ; i++){
  285.                 JY901.GetAngle();                                                                           //取陀螺仪生产的各值
  286.                 gyro_x = (float)JY901.stcAngle.Angle[0]/32768*18000 ;        //陀螺仪,读X轴。度数放大100倍,用于提高用角度进行map转换的精度
  287.                 gyro_y = (float)JY901.stcAngle.Angle[1]/32768*18000 ;        //陀螺仪,读Y轴。度数放大100倍
  288.                 //gyro_z = (float)JY901.stcAngle.Angle[2]/32768*180 ;         //陀螺仪,读Z轴。原始度数
  289.                 surface_x_sum         += analogRead(SURFACE_PIN) ;        //累加手轮的中立点值
  290.                 gyro_x_sum                 += gyro_x ;                                                //累加陀螺仪X轴的中立点值
  291.                 gyro_y_sum                 += gyro_y ;                                                //累加陀螺仪Y轴的中立点值

  292.                 #ifdef HARD_DEBUG
  293.                         Serial.print("surface_x_sum:");Serial.print(surface_x_sum);Serial.print("\t");
  294.                         Serial.print("gyro_x_sum:");Serial.print(gyro_x_sum);Serial.print("\t");
  295.                         Serial.print("gyro_y_sum:");Serial.println(gyro_y_sum);
  296.                 #endif        
  297.         }
  298.         
  299.         //计算手轮的中立点
  300.         if(surface_x_sum == 0 ) surface_x_center = SURFACE_X_CENTER ; else         surface_x_center = surface_x_sum / STATISTICS_COUNT        ;
  301.         //计算陀螺仪X轴的中立点
  302.         if(gyro_x_sum == 0 ) gyro_x_center = 0 ; else gyro_x_center = gyro_x_sum / STATISTICS_COUNT ;
  303.         //计算陀螺仪Y轴的中立点
  304.         if(gyro_y_sum == 0 ) gyro_y_center = 0 ; else gyro_y_center = gyro_y_sum / STATISTICS_COUNT ;
  305.         
  306.         surface_x_c_left = surface_x_center - SURFACE_X_DIEZONE ;
  307.         surface_x_c_right = surface_x_center + SURFACE_X_DIEZONE ;

  308.         gyro_x_min = GYRO_X_MIN + gyro_x_center;
  309.         gyro_x_max = GYRO_X_MAX + gyro_x_center;

  310.         gyro_y_min = GYRO_Y_MIN + gyro_y_center;
  311.         gyro_y_max = GYRO_Y_MAX + gyro_y_center;
  312.         
  313. }

  314. void show(int v , int t ) {
  315.         dac_x.setVoltage(v, false);
  316.         delay(t);
  317.         dac_x.setVoltage(MCP4725_MAX/2, false);
  318.         delay(t);
  319. }

复制代码



发贴不易,望多顶帖



欢迎继续阅读楼主其他信息

沙发
发表于 2019-12-3 18:01 | 只看该作者
高手
3
发表于 2019-12-3 19:01 | 只看该作者
有想法,有技术,有能力,牛人啊。
4
发表于 2019-12-3 23:32 | 只看该作者
楼主的想法很好,但恕在下直言,楼主练习使用陀螺仪转向的想法比在下练习使用手机屏幕摇杆玩飞机的想法更加困难。


来自安卓客户端来自安卓客户端
5
发表于 2019-12-4 05:57 | 只看该作者
直接来个手势遥控
来自苹果客户端来自苹果客户端
6
 楼主| 发表于 2019-12-4 10:06 | 只看该作者

枪控单手模式的实现

t20109020 发表于 2019-12-3 23:32
楼主的想法很好,但恕在下直言,楼主练习使用陀螺仪转向的想法比在下练习使用手机屏幕摇杆玩飞机的想法更加 ...

谢谢您的直言。这个想法耗时近三个月已实现。

用陀螺仪比用手机控制困难?这倒不一定哟。

只是我绝对敢用陀螺仪方式控制车模,你绝不敢用手机虚拟摇杆控制真直机。(开个玩笑哈)

陀螺仪方式控制感觉确实比手轮控制要更难,但多出一只手,想撸啥撸啥
7
发表于 2019-12-4 11:18 | 只看该作者
wienne 发表于 2019-12-4 10:06
谢谢您的直言。这个想法耗时近三个月已实现。

用陀螺仪比用手机控制困难?这倒不一定哟。

哈哈,其实在下之前也用过重力感应方式在模拟器玩飞机,那酸爽!在下已经放弃。但我相信楼主只要有毅力练习,假以时日无论以何种操纵方式玩何种模型都是可以得心应手的。
来自安卓客户端来自安卓客户端
您需要登录后才可以回帖 登录 | 我要加入

本版积分规则

关闭

【站内推荐】上一条 /1 下一条

快速回复 返回顶部 返回列表