前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >动手智能小车记(5)-坦克底盘硬件模块大杂烩

动手智能小车记(5)-坦克底盘硬件模块大杂烩

作者头像
杨源鑫
发布2020-07-01 15:34:09
5160
发布2020-07-01 15:34:09
举报
文章被收录于专栏:嵌入式开发圈嵌入式开发圈

关于小车,之前也写了好几期了,先给大家放一段视频,后面打算将机械臂集成到坦克上,目前还在调试中,夹具已经能够控制夹紧和松开了:

http://mpvideo.qpic.cn/0bf2vyaaeaaajqaep4pxgrpfblwdakxaaaqa.f10002.mp4?dis_k=0c73278a604b7e7d88192d644375be4f&dis_t=1593588816

上次那辆小车的底盘实在是脆弱,一不小心就撞碎了,后面直接上了个坦克底盘,在基于坦克底盘的小车上,控制坦克行走和之前小车的方法一致,采用的是PWM直驱,通过改变占空比的形式让坦克前进、后退、左右转。此次加上各种模块,分别如下:

  • 激光瞄准头
  • 蜂鸣器报警(因为还没买电磁炮,所以暂时用来代替发射)
  • 步进电机(用来调节发射瞄准角度)
  • MG996R舵机(打算做成360°旋转避障,据说会影响精度,还没试)
  • 超声波模块SR04
  • 游戏摇杆模块控制

一、激光瞄准头

这个没什么好说的,就跟点灯一样,高电平打开激光射线,低电平关闭激光射线,但我总觉得这个太暗了,改天一定要买一个亮度更大,效果看起来更明显的。

二、蜂鸣器

这里选用的是有源蜂鸣器,也是跟点灯一样,高低电平控制,当小车收到SHOT指令时,发射炮弹,用蜂鸣器高电平的响声暂时代替,后续替换成电磁炮。

三、步进电机的控制

电机控制是一门非常高深的学问,如果想去走工控行业需要玩到电机方面的,那么步进电机一定少不了,不管怎么说,我们还是可以把它驱动起来的,以下是我买的一个步进电机驱动模块:

步进电机选用的型号是:28BYJ48-H12

这里在软件编程上有一个比较重要参数需要了解一下,就是步距角。

那么什么是步距角呢?度娘给你答案,可以详细看看。

https://baike.baidu.com/item/%E6%AD%A5%E8%B7%9D%E8%A7%92/5946465?fr=aladdin

来看看下面这个换算公式,或许你就明白了,如上图所示,步距角=5.625°/64,意思就是每64个脉冲步进电机就会转5.625度,因此我们很容易得出以下计算公式:电机转一圈有360°,那么转一圈的脉冲数 = 360 / 5.625 * 64 = 4096 个脉冲。进而很容易得到以下角度与脉冲的简单算法:

代码语言:javascript
复制
/*
 Rotation_Angle:旋转角度
 返回:Motor_Pulse 根据公式计算得出的脉冲个数
*/
int Motor_Angle_Cal(int Rotation_Angle)
{
    if(Rotation_Angle < 0 || Rotation_Angle > 360)
      return -1 ;
    Motor_Pulse = (int)((double)(Rotation_Angle / 5.625) * 64) ;
    return Motor_Pulse ;
}

关于详细配置和程序编写,之前在CSDN博客上也已经做过类似的笔记,这里就不重复写了:

https://yangyuanxin.blog.csdn.net/article/details/100901635

四、MG996R舵机控制

关于舵机控制,我想世伟之前写的文章介绍就已经非常详细了,链接如下:

STM32Cube-21(补充) | 使用通用定时器产生PWM驱动舵机

这里的舵机我让它以固定频率进行360旋转,这个效果感觉像激光雷达哈哈哈,有时间一定买个来玩玩。

五、超声波模块SR04

主要用来实现测距避障用,引用之前学习32时听了温老师的课,这是他的课堂笔记,我觉得下面这个图理解起来超级通俗易懂了,文末回复关键字获取。

六、游戏摇杆模块控制

根据模块提供的手册,下面来了解下工作原理以及如何来应用

看到这里我们就明白了,x,y是模拟量,而z是一个二值数据,在这里,可以利用STM32的ADC控制器来读取X,Y的输出,Z轴就很简单了,把它当作普通按键就可以了,关于ADC介绍,温老师的笔记值得收藏,通俗易懂。

关于游戏摇杆模块控制小车,其实只要把摇杆方向的AD值测出来,然后写个简单的函数进行区分就可以了,以下是我实测的控制数据,可能并不是特别精准,但个人觉得够用了,后期也可以进行优化:

代码语言:javascript
复制
//通过DMA通道转换得到的值
uint32_t JOY_VALUE[2];
//保存转换计算后的电压值
__IO float ADC_VOL_VALUE[2];

#define UP         0
#define DOWN       1
#define LEFT       2
#define RIGHT      3
#define LEFT_UP    4
#define LEFT_DOWN  5
#define RIGHT_UP   6
#define RIGHT_DONW 7
#define ENTER      8
#define UNKNOW_KEY 99

//获取摇杆键值
uint8_t GET_KEY_VALUE(int x, int y, int z)
{
    if((0 == x) && (y > 50 && y < 255))
        return UP;
    else if((255 == x) && (y > 0 && y < 255))
        return DOWN ;
    else if((x > 0 && x < 255) && (255 == y))
        return LEFT ;
    else if((x > 0 && x < 255) && (0 == y))
        return RIGHT ;
    else if((0 == x) && (255 == y))
        return LEFT_UP ;
    else if((255 == x) && (255 == y))
        return LEFT_DOWN ;
    else if((0 == x) && (0 == y))
        return RIGHT_UP ;
    else if((255 == x) && (0 == y))
        return RIGHT_DONW ;
    else if(x > 0 && y > 0 && 0 == z)
        return ENTER ;

    return UNKNOW_KEY ;
}

要控制小车,那么就要把WIFI和摇杆模块的控制绑定起来,首先肯定是要让WIFI进入透传模式,然后通过WIFI发送控制指令给小车,核心代码如下:

代码语言:javascript
复制
int main(void)
{
    /* USER CODE BEGIN 1 */
    int JOY_X, JOY_Y, JOY_Z ;
    uint8_t key_value ;
    /* USER CODE END 1 */

    /* MCU Configuration--------------------------------------------------------*/

    /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
    HAL_Init();

    /* USER CODE BEGIN Init */

    /* USER CODE END Init */

    /* Configure the system clock */
    SystemClock_Config();

    /* USER CODE BEGIN SysInit */

    /* USER CODE END SysInit */

    /* Initialize all configured peripherals */
    MX_GPIO_Init();
    MX_DMA_Init();
    MX_USART1_UART_Init();
    MX_USART3_UART_Init();
    MX_ADC1_Init();
    /* USER CODE BEGIN 2 */
    ESP8266_Init();
    printf("正在配置 ESP8266 ......\n" );

    if(ESP8266_AT_Test())
    {
        printf("AT test OK\n");
    }

    printf("\n< 1 >\n");

    if(ESP8266_Net_Mode_Choose(STA))
    {
        printf("ESP8266_Net_Mode_Choose OK\n");
    }

    printf("\n< 2 >\n");

    while(!ESP8266_JoinAP(User_ESP8266_ApSsid, User_ESP8266_ApPwd));

    printf("\n< 3 >\n");
    ESP8266_Enable_MultipleId(DISABLE);

    while(!ESP8266_Link_Server(enumTCP, User_ESP8266_TcpServer_IP, User_ESP8266_TcpServer_Port, Single_ID_0));

    printf("\n< 4 >\n");

    while(!ESP8266_UnvarnishSend());

    printf("配置 ESP8266 完毕\n");
    HAL_ADC_Start_DMA(&hadc1, JOY_VALUE, 2);
    /* USER CODE END 2 */

    /* Infinite loop */
    /* USER CODE BEGIN WHILE */
    while (1)
    {
        /* USER CODE END WHILE */

        /* USER CODE BEGIN 3 */
        //3.3V为AD转换的参考电压值,STM32的AD转换为12bit,所以2^12=4096
        //故当输入参考电压为3.3V时,AD转换的结果为4096
        //取12bit数值
        //ADC_VOL_VALUE[0] = (float)(JOY_VALUE[0] & 0xFFF) * 3.3 / 4096 ;
        //ADC_VOL_VALUE[1] = (float)(JOY_VALUE[1] & 0xFFF) * 3.3 / 4096 ;
        //printf("x:%.2fv   y:%.2fv\n", ADC_VOL_VALUE[0], ADC_VOL_VALUE[1]);
        //只取8位有效数据
        JOY_X = JOY_VALUE[0] & 0xFF;
        JOY_Y = JOY_VALUE[1] & 0xFF;
        JOY_Z = HAL_GPIO_ReadPin(JOY_Z_GPIO_Port, JOY_Z_Pin);
        key_value = GET_KEY_VALUE(JOY_X, JOY_Y, JOY_Z);
        //printf("x:%d   y:%d  z:%d\n", JOY_X, JOY_Y, JOY_Z);

        switch(key_value)
        {
            //小车前进
            case UP :
                printf("上\n");
                ESP8266_SendString(ENABLE,"GO",strlen("GO"),0);
                break ;

            //小车后退
            case DOWN :
                printf("下\n");
                ESP8266_SendString(ENABLE,"BACK",strlen("BACK"),0);
                break ;

            //小车左转
            case LEFT :
                printf("左\n");
                ESP8266_SendString(ENABLE,"LEFT",strlen("LEFT"),0);
                break ;

              //小车右转
            case RIGHT  :
                printf("右\n");
                ESP8266_SendString(ENABLE,"RIGHT",strlen("RIGHT"),0);
                break ;

              //控制步进电机向右旋转45°
            case LEFT_UP:
                printf("左上\n");
                ESP8266_SendString(ENABLE,"MOTOR_RADJ",strlen("MOTOR_RADJ"),0);
                break ;

            case LEFT_DOWN:
                printf("左下\n");
                break ;

            //控制步进电机向左旋转45°
            case RIGHT_UP:
                printf("右上\n");
                ESP8266_SendString(ENABLE,"MOTOR_LADJ",strlen("MOTOR_LADJ"),0);
                break ;

            case RIGHT_DONW :
                printf("右下\n");
                break ;

           //控制发射炮弹
            case ENTER :
                printf("确认\n");
                ESP8266_SendString(ENABLE,"SHOT",strlen("SHOT"),0);
                break ;

            //控制小车停止
            default:
                ESP8266_SendString(ENABLE,"STOP",strlen("STOP"),0);
                break ;
        }

        HAL_Delay(200);
    }

    /* USER CODE END 3 */
}
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-06-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 嵌入式云IOT技术圈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、激光瞄准头
  • 二、蜂鸣器
  • 三、步进电机的控制
  • 四、MG996R舵机控制
  • 五、超声波模块SR04
  • 六、游戏摇杆模块控制
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档