【GD32F427开发板试用】基于蓝牙的远程步进电机控制

本篇文章来自极术社区与兆易创新组织的GD32F427开发板评测活动,更多开发板试用活动请关注极术社区网站。作者:寒冰1988

一、前言

接上篇文章【GD32F427开发板试用】基于蓝牙模块的远程点灯演示,本篇是第二篇,基于调通的蓝牙模块添加对步进电机的控制。实现步进电机的控制以后就可以进一步延申实现车辆的前进、后退、转向和简单的机械臂控制等功能。

二、硬件环境

2.1 步进电机简介

本次实验采用的步进电机型号为28BYJ-48,为外径28毫米四相八拍式永磁减速型步进电机,该款型号步进电机支持如下三种驱动方式:

本文的实现中选用八拍模式,各组管脚的控制逻辑如下图所示:

2.2 ULN2003驱动板

由于单片机本身的驱动能力不足,因此通常会使用ULN2003来驱动电机。

2.3 设备连接

采用PC7-PC10四根管脚来控制电机的相位,采用移动电源给电机驱动板提供5V的输入,蓝牙模块的链接参见上篇文章。

三、软件实现

3.1 相位控制逻辑

按照2.1章节中介绍,以此拉高PC7-PC10,实现相位的控制,代码如下

#define A_ON                             gpio_bit_set(GPIOC, GPIO_PIN_7)
#define A_OFF                            gpio_bit_reset(GPIOC, GPIO_PIN_7)
#define B_ON                             gpio_bit_set(GPIOC, GPIO_PIN_8)
#define B_OFF                            gpio_bit_reset(GPIOC, GPIO_PIN_8)
#define C_ON                             gpio_bit_set(GPIOC, GPIO_PIN_9)
#define C_OFF                            gpio_bit_reset(GPIOC, GPIO_PIN_9)
#define D_ON                             gpio_bit_set(GPIOC, GPIO_PIN_10)
#define D_OFF                            gpio_bit_reset(GPIOC, GPIO_PIN_10)

3.2 配置GPIO的模式

参照PC6的配置,将PC7-PC10配置为GPIO-OUTPUT模式,代码如下

gpio_mode_set(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_6);
gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_6);
gpio_mode_set(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_7);
gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_7);  
gpio_mode_set(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_8);
gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_8);  
gpio_mode_set(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_9);
gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9);  
gpio_mode_set(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_10);
gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_10);

组要注意是如果管脚反转过快过着过慢会出现电机振动但是不转的现象,通过多次实验,将每循环的的延时定位2ms,参见完整代码_motor_forward()_和_motor_backoff_两个函数。

3.3 蓝牙的控制

根据之前的定义,发送“0”字符(对应ASII码0x30)关闭LED灯,发送“1”字符(对应ASII码0x31)开启LED灯,继续增加“2”字符代表电机停止,“3”代表正转,“4”代表反转;

3.4 完整代码

#include "gd32f4xx.h"
#include "gd32f427v_start.h"
#include "systick.h"
#include <stdio.h>
 
#define A_ON                             gpio_bit_set(GPIOC, GPIO_PIN_7)
#define A_OFF                            gpio_bit_reset(GPIOC, GPIO_PIN_7)
#define B_ON                             gpio_bit_set(GPIOC, GPIO_PIN_8)
#define B_OFF                            gpio_bit_reset(GPIOC, GPIO_PIN_8)
#define C_ON                             gpio_bit_set(GPIOC, GPIO_PIN_9)
#define C_OFF                            gpio_bit_reset(GPIOC, GPIO_PIN_9)
#define D_ON                             gpio_bit_set(GPIOC, GPIO_PIN_10)
#define D_OFF                            gpio_bit_reset(GPIOC, GPIO_PIN_10)
 

void UART0_Transmit(unsigned char *Data,unsigned int Lenth)
{
    int i=0;
    for(i=0;i<Lenth;i++)
    {
        usart_data_transmit(USART0,Data[i]);
        while(RESET == usart_flag_get(USART0, USART_FLAG_TC));
    }
}

void motor_stop(void)
{
    gpio_bit_reset(GPIOC, GPIO_PIN_7);
    gpio_bit_reset(GPIOC, GPIO_PIN_8);
    gpio_bit_reset(GPIOC, GPIO_PIN_9);
    gpio_bit_reset(GPIOC, GPIO_PIN_10);
    
    return;
}

void motor_forward(void)
{
    int i = 8, rotation = 0;

        for(rotation=0; rotation<1000; rotation++)
        {
        switch(i)
        {
            case 0:
                A_ON;  B_OFF; C_OFF; D_OFF;
            break;
            case 1:
                A_ON;  B_ON;  C_OFF; D_OFF;
            break;
            case 2:
                A_OFF; B_ON;  C_OFF; D_OFF;
            break;
            case 3:
                A_OFF; B_ON;  C_ON;  D_OFF;
            break;
            case 4:
                A_OFF; B_OFF; C_ON;  D_OFF;
            break;
            case 5:
                A_OFF; B_OFF; C_ON;  D_ON;
            break;
            case 6:
                A_OFF; B_OFF; C_OFF; D_ON;
            break;
            case 7:
                A_ON;  B_OFF; C_OFF; D_ON;
            break;
        }
        i--; 
        if(i==0) i=8; 
        delay_1ms(2);
        }
    
    return;
}
    
void motor_backoff(void)
{
    int i = 0, rotation = 0;

        for(rotation=0; rotation<1000; rotation++)
        {
        switch(i)
        {
            case 0:
                A_ON;  B_OFF; C_OFF; D_OFF;
            break;
            case 1:
                A_ON;  B_ON;  C_OFF; D_OFF;
            break;
            case 2:
                A_OFF; B_ON;  C_OFF; D_OFF;
            break;
            case 3:
                A_OFF; B_ON;  C_ON;  D_OFF;
            break;
            case 4:
                A_OFF; B_OFF; C_ON;  D_OFF;
            break;
            case 5:
                A_OFF; B_OFF; C_ON;  D_ON;
            break;
            case 6:
                A_OFF; B_OFF; C_OFF; D_ON;
            break;
            case 7:
                A_ON;  B_OFF; C_OFF; D_ON;
            break;
        }
        i++; 
        if(i==8) i=0; 
        delay_1ms(2);
        }
    
    return;
}

/*!
    \brief      main function
    \param[in]  none
    \param[out] none
    \retval     none
*/
int main(void)
{
    unsigned char Data[]={"this is a UART0 Test Demo\r\n" };
    unsigned char rxbuf[16] = {0}, ch = 0;
    int i = 0, ret=0, j=0;

    /* configure systick */
    systick_config();

    /* enable clock */
    rcu_periph_clock_enable(RCU_GPIOC);
    rcu_periph_clock_enable(RCU_GPIOB);
    rcu_periph_clock_enable(RCU_USART0);

    /* configure GPIO port */
    gpio_mode_set(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_6);
    gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_6);
    gpio_mode_set(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_7);
    gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_7);  
    gpio_mode_set(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_8);
    gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_8);  
    gpio_mode_set(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_9);
    gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9);  
    gpio_mode_set(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_10);
    gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_10);   

    /* reset GPIO pin */
    gpio_bit_reset(GPIOC, GPIO_PIN_6);
    gpio_bit_reset(GPIOC, GPIO_PIN_7);
    gpio_bit_reset(GPIOC, GPIO_PIN_8);
    gpio_bit_reset(GPIOC, GPIO_PIN_9);
    gpio_bit_reset(GPIOC, GPIO_PIN_10);


    /* configure the USART0 TX pin and USART0 RX pin */
    gpio_af_set(GPIOB, GPIO_AF_7, GPIO_PIN_6);
    gpio_af_set(GPIOB, GPIO_AF_7, GPIO_PIN_7);

    /* configure USART0 TX as alternate function push-pull */
    gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_6);
    gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_6);

    /* configure USART0 RX as alternate function push-pull */
    gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_7);
    gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_7);

    /* USART configure */
    usart_deinit(USART0);
    usart_baudrate_set(USART0, 9600U);
    usart_receive_config(USART0, USART_RECEIVE_ENABLE);
    usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);
    usart_enable(USART0);

    //ch = 0x30;
    while(1) {
        while (RESET == usart_flag_get(USART0, USART_FLAG_RBNE));
        ch = usart_data_receive(USART0);
        if (ch == 0x30) {
            /* turn off LED2 */
            gpio_bit_reset(GPIOC, GPIO_PIN_6);
            ch = 0;
        }
        if (ch == 0x31) {
            /* turn on LED2 */
            gpio_bit_set(GPIOC, GPIO_PIN_6);
            ch = 0;
        }
        if (ch == 0x32) {
            /* motor stop */
            motor_stop();
            ch = 0;
        }
        if (ch == 0x33) {
            /* motor forward */
            motor_forward();
            ch = 0;
        }
        if (ch == 0x34) {
            /* motor backoff */
            motor_backoff();
            ch = 0;
        }
        //ch ++;
        //if(ch == 0x35) ch = 0x30;
        //delay_1ms(1000);
    }

    return 0;
}

四、效果展示

参考如下视频,通过手机依次发送“0”、“1”、“2”、“3”、“4”等控制指令,从而实现LED灯的亮灭、步进电机的停止、正转、反转灯功能。

https://www.bilibili.com/video/BV1bW4y1K7rA​www.bilibili.com/video/BV1bW4y1K7rA

五、后记

基于蓝牙控制步进电机的开发工作上周完成,因为一些时间,本篇文章耽搁了一些。两篇试用涉及的内容本身难度不大,都是基于手中有的模块完成,是嵌入式开发的一些基本功,希望能给初学者一些启发。通过这些开发工作对GD32本身的开发流程也做了一个初步的学习,接下来会根据时间,上RTOS,进而开发一些更有意思的应用。

六、参考资料

  1. GD32F427V-START-V1.0.pdf
  2. GD32F4xx_gujiankushiyongzhinan_V1.0.pdf
  3. GD32F4xx_User_Manual_Rev2.7_CN.pdf
  4. GD32F427xx_Datasheet_Rev1.2.pdf
  5. GD32427V_START_Demo_Suites\Projects\01_GPIO_Running_LED
  6. DX-BT04-E 蓝牙模块技术手册2022.01.07.pdf
  7. 28BYJ-48单极性步进电机
  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
功能及说明 一、基本功能 1、两路直流电机驱动,可调速和正反转控制。 2、两路正交编码器接口,可用于电机速度反馈。 3、1路USB转串口,用于电路的参数设定。 4、6轴运动处理器件MPU6050,可用于平衡小车的开发。 5、蓝牙4.0接口模块,可通过手机上的app(TTC-BLE)对电机进行加速、减速、正反转控制。 6、DC12V供电。 7、1个USB指示灯、1个蓝牙模块指示灯、2个用户指示灯(用户程序控制)。 8、1个轻触开关,供用户程序使用。 二、各部分电路说明 1、供电接口: 本模块采用DC12V供电,供电接口有2针2.54端子,并配有船型手动电源开关。 2、USB接口: USB接口为USB转串口,选择的芯片为CH340E,串口连接到单片机的USART0口,供用户程序使用,并带有LED指示灯。 3、单片机调试口和boot设定: GD32F330CBT6单片机采用的SWD调试口,开发环境MDK或IAR,开发工具为ST-LINK V2,资料中的程序两种开发环境都支持。电路中将BOOT0脚引出,可通过跳线开关去选择单片机的启动程序地址,可通过跳线选择BOOT0脚后,用USART0对用户程序进行升级,具体操作参见单片机的数据手册。 4、电机驱动电路 本电路中具有2路电机驱动接口,同时可以接2路正交编码器,可对电机转速和方向实时反馈;驱动芯片采用RZ7889,一款 DC 双向马达驱动电路,它适用于玩具等类的电机驱动、自动阀门电机驱动、电磁门锁驱动等。它有两个逻辑输入端子用来控制电机前进、后退及制动。该电路具有良好的抗干扰性,微小的待机电流、低的输出内阻,同时,他还具有内置二极管能释放感性负载的反向冲击电流。工作电压3-15V。电机驱动用到单片机的TIMER15和TIMER16,编码器检测用到单片机的TIMER1和TIMER2,具体操作参见程序。 5、6轴运动传感器电路 MPU-6050是世界上第一款集成 6 轴MotionTracking设备。它集成了3轴MEMS陀螺仪,3轴MEMS加速度计。 MPU-6050也可以通过其I2C接口连接非惯性的数字传感器,比如压力传感器。MPU-6050对陀螺仪和加速度计分别用了三个16位的ADC,将其测量的模拟量转化为可输出的数字量。为了精确跟踪快速和慢速的运动,传感器的测量范围都是用户可控的,陀螺仪可测范围为±250, ±500, ±1000, ±2000°/秒( dps),加速度计可测范围为±2, ±4,±8, ±16g。 可以采用本电路中的6轴运动传感器和2路直流电机控制做两轮平衡小车的开发。 6、蓝牙接口 蓝牙接口采用的是深圳市昇润科技有限公司的HY-254101 V1蓝牙4.0模块。使用简单,无需任何蓝牙协议栈应用经验。支持蓝牙主机、蓝牙从机、蓝牙主从一体,共 3 种版本。用户接口使用通用串口设计,全双工双向通讯,最低波特率支持 9600bps。通过AT命令对模块进行控制,再配上手机端的TCC-BLE软件可以和模块进行实时通信控制。模块的详细资料参照附件中资料。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值