单片机交流
直播中

他在笑

9年用户 723经验值
擅长:可编程逻辑 电源/新能源 制造/封装
私信 关注
[问答]

关于实现AR rc漂移车操作有么有什么建议?

前几天偶然看到了《马里奥赛车 Live:家庭巡回赛》这款运行在switch上的AR游戏,这款游戏由玩家通过switch设备操控现实中的带有摄像头的实体赛车在家中客厅布置赛道,可以通过switch看到赛车的视角,布置完成后通过AR技术在switch设备上操控遥控车并在现实中进行马里奥赛车比赛。 然而十分令人遗憾的是该游戏并没有实现《马里奥赛车》中最经典的漂移操作。基于此,我决定利用单片机和rc漂移车模型来实现一键漂移这一功能与AR结合并搭建服务器使其能够进行远程操作实现一些下楼取快递之类的附加功能,

回帖(3)

王凯

2021-10-13 11:38:23
一、物料准备



  • 车架:樱花D5S 后驱漂移车架
  • 舵机:JX Servo/PDI-4409/10KG大扭力矩金属齿轮数字数码标准短身舵机(90度 25T)
  • 电调:好盈1060防水有刷电调 60A有刷ESC电调 RTR版本(或1080)
  • 马达:雪豹540有刷电机(21T)
  • 电池:ACE格氏 2S 7.4V 3000mAh毫安 50C 青训版 LIPO 短电 锂电池
  • BB响
  • 陀螺仪、接收机、摄像头(准备直接用手机代替)
  • b6充电器
  • 遥控器:不需要,后期用蓝牙或者网络进行信号传输
  • 单片机STM32F103开发板学习板 指南者(后期功能确定下来重画板子)
  • 电压表、示波器、杜邦线等常用工具

  提示:以上材料基于成本考量仅供参考
二、车辆安装

安装视频教程
我也是看得b站上这老哥的教程,简直是手把手教,非常细致,不多赘述。
三、舵机调试

注意:由于我们不用接收机,不用遥控器,所以我们没法像普通rc漂移车那样利用接收机给舵机供电并输出信号,无法直接用遥控器进行调试,此处我们直接用单片机进行舵机调试。
1.舵机控制原理

该舵机通过PWM信号进行控制,但值得注意的是,并非是不同的占空比对应于不同的角度,而是舵机的角度取决于高电平的持续时间,也就是说对于这款舵机不论PWM信号的频率是多少,驱动舵机转动的PWM信号高电平持续时间只能在1~2ms之间(可能有误,但大致范围就是这样找到归中的位置慢慢尝试) ,这就需要我们手动设置给出合适的占空比了。
2.舵机供电及连线

此处我们用电调给舵机供电,将电调上引出的原本要插在接收机上的三根细线中的供电的线通过杜邦线与舵机对应的正负极插好,电调和舵机的信号线都暂时不插。此处非常值得注意的是,给电调供电的电池必须要与单片机共地否则后续用单片机输出PWM信号无法控制舵机,共地的方法就是把电池上原本要接bb响的信号线中的负极与单片机上的地相接(插单片机铜柱上就行),此时就完成了给舵机供电的工作。
3.PWM控制舵机

这里关于如何设置PWM信号我直接参考了野火STM32F103“输出四路PWM”的例程。具体原理不展开,此处只讲如何设置我们想要的占空比。
假设我要PWM的TIM3以50HZ的频率运行(系统时钟 = 72MHZ)
且此时我们令arr = 9999,
又TIM3的计数时钟/(arr+1) = 50HZ
求得 TIM3的计数时钟=500KHZ
所以(psc+1)=系统时钟(72M)/TIM3的计数时钟 = 144
求得psc=143
而占空比P=CCR/(ARR+1)
于是我们就求得了设置一个频率为50HZ的PWM信号的全部参数,只需改变CCR的值即可改变占空比。
bsp_GeneralTim.h
#define         
   GENERAL_TIM_Period   
        9999  //(ARR)#define   
        GENERAL_TIM_Prescaler  
       143  //PSC bsp_GeneralTim.c
uint16_t CCR1_Val= 665; 最后只需要把输出PWM信号的引脚与之前舵机上没有连接的信号线接口连接,然后不断的改变AAR的值,目测前轮方向,找到归中和左右极限位置所对应的AAR即可(最后的调整仍需等车动起来再调)。
举报

张丽雯

2021-10-13 11:40:32
电机调试

注意:请将车辆架起悬空再进行调试小心受伤;将电机安装到车辆上后再调试电机,否则没有齿轮组和减速器可能会烧坏电机。调试方法仍然是使用单片机。
1.电机控制原理

该项目的使用的电机由好盈1060电调控制,所谓的电调的就是电子调速器,它根据输入的控制信号来调节电机转速。所以我们只需要用单片机输出合适的PWM信号给电调即可(与舵机原理类似,高电平持续时间在1~2ms之间)。按照网上查阅的说明来看,首次使用电调需要进行解锁,具体操作为单片机给电调一个代表着“高油门”的PWM信号(2ms),待电机发出“哔-哔-”两声后,再输出一个代表着“低油门”的信号,此时电机会发出“哔-”的一声(在此期间电机不动),之后输出PWM信号即可实现控制。









  以上是使用遥控器解锁并控制的方法,可更形象的理解,但在本人实际使用过程中并非完全一样,后面会给出我的方法及代码。
2.电机供电及连线

给电机供电的连线与普通的遥控rc漂移车没有区别,将电调和电机上的两根粗线正负相接即可(红正黑负/黄正蓝负)。除此之外,我们还需要把原来电调连接舵机的信号线中的负极与单片机的地相连接(插铜柱)。
3.PWM控制电机

在这里我们要使用延时函数,但野火的库里并没有找到,所以上网找了现成的轮子进行毫秒级延迟(最多只能延迟1800ms,因为除了调试也不太会用到,想多延时几秒就多复制几遍吧)。我们只需要再写俩“.c”和“.h”文件放在项目的USER文件夹中,并在keil左侧边栏的USER中右键“ADD”这两个文件到项目中即可。
代码如下(delay.h):
#ifndef DELAY_H#define DELAY_H#include "stm32f10x.h"void delay_init(void);void Delay_Us(u32 nus);void Delay_Ms(u16 nms);#endif 代码如下(delay.c):
#include "delay.h" static u8  fac_us=0;//us延时倍乘数           
                static u16 fac_ms=0;//ms延时倍乘数,在ucos下,代表每个节拍的ms数void delay_init(){         SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);   
    //选择外部时钟  HCLK/8  
      fac_us=SystemCoreClock/8000000;               
                //为系统时钟的1/8      
    fac_ms=(u16)fac_us*1000;         


                               //非OS下,代表每个ms需要的systick时钟数    }         
                                                          //延时nus//nus为要延时的us数.                                                                                
       void Delay_Us(u32 nus){        
                u32 temp;               
             SysTick->LOAD=nus*fac_us;  
                                       //时间加载         
                          SysTick->VAL=0x00;      
                                          //清空计数器   
    SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;     
   //开始倒数         
        do   
    {         
       temp=SysTick->CTRL;   
    }while((temp&0x01)&&!(temp&(1<<16)));      
          //等待时间到达     
      SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;   
    //关闭计数器        SysTick->VAL =0X00;      
                                        //清空计数器   
     }//延时nms//注意nms的范围//SysTick->LOAD为24位寄存器,所以,最大延时为://nms<=0xffffff*8*1000/SYSCLK//SYSCLK单位为Hz,nms单位为ms//对72M条件下,nms<=1864 void Delay_Ms(u16 nms){         
                                    u32 temp;           
                SysTick->LOAD=(u32)nms*fac_ms;               
                //时间加载(SysTick->LOAD为24bit)     
   SysTick->VAL =0x00;                    
                                    //清空计数器   
     SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;      
  //开始倒数   
      do        {            
    temp=SysTick->CTRL;     
   }while((temp&0x01)&&!(temp&(1<<16)));              
  //等待时间到达     
      SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;   
     //关闭计数器      
  SysTick->VAL =0X00;   
                                           //清空计数器            
         之前我们调试舵机使用的是输出比较通道1,这次我们选择输出比较通道2(其他参数没变,就是加了个通道),并定义
uint16_t CCR2_Val = 1000;//      油门高位 这样我们就保证了在定时器初始化时信号处于油门高位。
解锁并启动的代码如下:
#include "stm32f10x.h"#include "bsp_GeneralTim.h"  #include "delay.h" #include "bsp_led.h"  #include "bsp_key.h" int main(void){  delay_init();/* 延时初始化 */            
    Delay_Ms(1000);     
   Delay_Ms(1000);   
     Delay_Ms(1000);      
  GENERAL_TIM_Init();/* 定时器初始化 */      
  TIM_SetCompare1(TIM3,665);//通道1为舵机
   TIM_SetCompare2(TIM3,600);//通道2为马达 油门最低点 最高点初始化时候就给了  
      Delay_Ms(1000);//只能延时1800ms以内 迷惑 但够用了 后面也不需要延时     
   Delay_Ms(1000);      
  TIM_SetCompare2(TIM3,800);//驱动马达的最低占空比为6.22% 最高为10.8% 对应1244um~2160um
       Delay_Ms(1000);  
  TIM_SetCompare2(TIM3,600);}
具体操作和表现为:首先给单片机烧录程序,然后手动复位,此时打开电调开关,会听到“哔-哔-”两声,几秒钟后发出“哔-”一声,然后几秒钟后车轮驱动1秒钟并刹车。这里我尝试了很多次,解锁低油门PWM占空比至少为6%,而能驱动马达转动的占空比则为6.22% ~10.8%,对应持续时间为1244um到2160um,可能有设备差异,而且每次上电都会重新解锁,无法直接正常启动(但能反正能正常使用)
下面是实际操作视频
link
举报

王霞

2021-10-13 11:40:36
也使用了网上给出的一些其他方法,我尝试后并未成功,下面给出主要代码(仅供参考)



  • 方法一是为了模拟手推摇杆的过程,然而我尝试并未成功。

for(int ccr2=1000;ccr2>500;ccr2=ccr2-50){TIM_SetCompare2(TIM3,ccr2);//通道2为马达 油门最高点Delay_Ms(100);}Delay_Ms(1000);Delay_Ms(1000);


  • 方法二是用按键中断代替延时和复位/* LED端口初始化 */LED_GPIO_Config();LED1_ON;/* 按键端口初始化 */Key_GPIO_Config();/* 轮询按键状态,若按键按下则反转LED */TIM_SetCompare2(TIM3,1000);//通道2为马达 油门最高点while(1)   
  •                        {           
  • if( Key_Scan(KEY1_GPIO_PORT,KEY1_GPIO_PIN) == KEY_ON  )  {     
  •     /*LED1反转*/         
  • LED1_TOGGLE;      
  •   TIM_SetCompare2(TIM3,500);     
  •     break;  }
  • if( Key_Scan(KEY2_GPIO_PORT,KEY2_GPIO_PIN) == KEY_ON  )  {   
  •       /*LED2反转*/      
  •    LED2_TOGGLE;  }                }Delay_Ms(1000);Delay_Ms(1000);TIM_SetCompare2(TIM3,850);Delay_Ms(1000);TIM_SetCompare2(TIM3,1000);Delay_Ms(1000);TIM_SetCompare2(TIM3,500);

举报

更多回帖

发帖
×
20
完善资料,
赚取积分