OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 1072|回复: 2

STM32F429 BLDC无刷电机驱动

[复制链接]

13

主题

49

帖子

0

精华

高级会员

Rank: 4

积分
542
金钱
542
注册时间
2017-10-17
在线时间
118 小时
发表于 2024-1-19 11:15:51 | 显示全部楼层 |阅读模式
本帖最后由 冯必兴 于 2024-1-19 15:16 编辑

本驱动是基于源自个的基于407上作出修改的,原子哥使用的是HAL库,但是对于使用标准库的人是种罪过,由此就修改了一下,最后不得不说原子哥做的确实稳,后期出FOC
玩BLDC必须要了解一下几个内容
1.硬件,是使用DRV8313等之类的驱动芯片还是 分立元器件搭建的
2.BLDC换相原理 ,换相需要的霍尔信号是怎样的?
3.为什么速度跟PWM占空比有关 ,速度最快占空比为多少
4.速度计算原理
重点:最好看一下原子哥的视频:https://www.bilibili.com/video/B ... Fvp&up_id=394620890



主函数内容:

#include "stm32f4xx.h"

#include "usart.h"
//#include "bldc_tim.h"



//#include "bldc.h"
#include "pid.h"
#include "debug.h"
#include "delay.h"
#include "bldc.h"
#include "bldc_tim.h"
//#include "mcu_time4.h"

//RCC_ClocksTypeDef get_RCC_Clocks;
/*********************************************************************
* 函   数  名: main
* 函数入参: void
* 函数出参: 无
* 返   回  值: void
* 功能描述:  主函数
**********************************************************************/
RCC_ClocksTypeDef     RCC_Clocks;
extern float* user_setpoint;
extern float debug_data_temp;
extern int32_t motor_pwm_s;
//extern int32_t temp_pwm1;
//extern int16_t adc_amp_un[3];
//extern float  adc_amp_bus;
//extern uint16_t g_adc_value[ADC_CH_NUM * ADC_COLL];
extern uint8_t clc;

uint32_t times = 0;
int main(void)
{

    uint8_t debug_cmd = 0;                   /* 存放上位机指令 */
    float current_lpf[4] = {0.0f};           /* 存放三相电流以及母线电流 */
    uint8_t key, t;
    char buf[32];
    float current[3] = {0.0f};
    int16_t speed_diplay = 0;
    float user_setpoint_temp  = 0.0;


    //延时函数初始化
    delay_init();
    usart_init(115200);
                LED_Init();
               
    bldc_init(180000 / 18 - 1, 0);
    bldc_ctrl(MOTOR_1, CCW, 0);              /* 初始无刷电机接口1速度 */
    pid_init();

    debug_init();                           /* PID调试初始化 */
    debug_send_motorcode(BLDC_MOTOR);      /* 直流电机 */
    debug_send_motorstate(IDLE_STATE);      /* 电机空闲 */
    /* 初始化同步数据(选择第x组PIDX,目标速度地址,P,I,D参数)到上位机 */
    debug_send_initdata(TYPE_PID1, (float*)(&g_speed_pid.SetPoint), C_KP, C_KI, C_KD); /* 电流环PID参数(PID1)*/
    debug_send_initdata(TYPE_PID2, (float*)(&g_speed_pid.SetPoint), S_KP, S_KI, S_KD); /* 速度环PID参数(PID2)*/

    RCC_GetClocksFreq(&RCC_Clocks);
                //            g_bldc_motor1.pwm_duty = 15000;                                                                                                       /* 加速启动速度 */
     //       start_motor1();
        //        TIM_SetCompare1(TIM1, 500);
    while(1)
    {
        t++;

        if(t % 20 == 0)
        {

            user_setpoint_temp = (*user_setpoint);
            speed_diplay = g_bldc_motor1.speed;


//            LED0_TOGGLE();                                                                              /* LED0(红灯) 翻转 */
            /* 三相电流计算 */
//            current[0] = adc_amp_un[0] * ADC2CURT; /*U*/
//            current[1] = adc_amp_un[1] * ADC2CURT; /*V*/
//            current[2] = adc_amp_un[2] * ADC2CURT; /*W*/

            /*一阶数字滤波 滤波系数0.1 用于显示*/
            FirstOrderRC_LPF(current_lpf[0], current[0], 0.1f);
            FirstOrderRC_LPF(current_lpf[1], current[1], 0.1f);
            FirstOrderRC_LPF(current_lpf[2], current[2], 0.1f);
//            FirstOrderRC_LPF(current_lpf[3], adc_amp_bus, 0.1f);
            if(g_bldc_motor1.run_flag == STOP)                  /* 停机的电流显示 */
            {
                current_lpf[0] = 0;
                current_lpf[1] = 0;
                current_lpf[2] = 0;
                current_lpf[3] = 0;
            }



        }
//#if DEBUG_ENABLE
//        /* Debug发送部分 */
//        /* 主要显示参数 */
//        debug_send_valtage(g_adc_value[0] * ADC2VBUS);                  /* 发送电压*/
        debug_send_speed(g_bldc_motor1.speed);                          /* 发送速度*/
//        debug_send_temp(50, get_temp(g_adc_value[1]));                  /* 发送电机温度、驱动板温度*/
        debug_send_current((float)(current_lpf[0] / 1000), (float)(current_lpf[0] / 1000), (float)(current_lpf[0] / 1000)); /*发送电流*/
        /* 电流波形和速度波形 */
        debug_send_wave_data(1, (int16_t)g_bldc_motor1.speed);          /* 选择通道1 发送实际速度 */
        debug_send_wave_data(2, (int16_t)*user_setpoint);               /* 选择通道2 发送目标速度 */
        debug_send_wave_data(3, current_lpf[0]);                        /* 选择通道3 发送实际电流U */
        debug_send_wave_data(4, current_lpf[1]);                        /* 选择通道4 发送实际电流V */
        debug_send_wave_data(5, current_lpf[2]);                        /* 选择通道5 发送实际电流W */
        debug_send_wave_data(7, current_lpf[3]);                        /* 选择通道7 发送实际电流 */
        debug_send_wave_data(8, g_current_pid.SetPoint);                /* 选择通道8 发送目标电流 */
        /* Debug接收部分 */
        debug_receive_pid(TYPE_PID1, (float*)&g_current_pid.Proportion, /* 查询接收PID助手的PID1参数*/
                          (float*)&g_current_pid.Integral, (float*)&g_current_pid.Derivative);
        debug_receive_pid(TYPE_PID2, (float*)&g_speed_pid.Proportion,   /* 查询接收PID助手的PID2参数*/
                          (float*)&g_speed_pid.Integral, (float*)&g_speed_pid.Derivative);
        debug_cmd = debug_receive_ctrl_code();                          /* 读取命令 */
        if(debug_cmd == HALT_CODE)                                      /* 停机 */
        {
            pid_init();
            g_bldc_motor1.run_flag = STOP;  /* 标记停机 */
            stop_motor1();                  /* 停机 */
            g_bldc_motor1.speed = 0;
            motor_pwm_s = 0;
            g_bldc_motor1.pwm_duty = 0;
        }
        else if(debug_cmd == RUN_CODE)                                  /* 运行 */
        {
            g_bldc_motor1.run_flag = RUN;                               /* 运行标记 */
            *user_setpoint = 7200;                                    /* 自动设置目标 */
//            g_bldc_motor1.pwm_duty = 15000;                                                                                                       /* 加速启动速度 */
            debug_data_temp = *user_setpoint;
            start_motor1();                                             /* 启动电机 */
            debug_send_motorstate(RUN_STATE);                           /* 电机运行 */
        }
        else if(debug_cmd == BREAKED)                                   /* 刹车(电机停止 点击电机运行才可解除) */
        {
            *user_setpoint = 0;                                         /* 减速直至0 */
            debug_send_motorstate(BREAKED_STATE);                       /* 电机刹车 */
        }
//#endif

        delay_ms(20);
    }
}



/*********************************************END OF FILE**********************/
纠正一下:/*******************************************************************************************
函数名:MotorSpeed_Get
输入:GetCount 计数次数 ,hall_single_sta 霍尔信号时长 ,dir 电机方向,speed_coeff 计算速度
输出:无
返回值:temp_speed_output 计算输出结果
描述:通过霍尔的极性计算速度
第一步:t = C/Ft(其中Ft是计数频率,C为计数次数)
第二步:旋转一圈需要时间 T= 2*C/Ft
第三步:rmp = Ft/(2*C)*60
*********************************************************************************************/
int32_t MotorSpeed_Get(uint32_t *GetCount, uint32_t hall_single_sta, uint8_t dir, uint32_t speed_coeff,int32_t *speed)
{
    static uint32_t no_single = 0;
    static int16_t temp_speed = 0;
                //const int32_t temp_speed_output = 0;
    uint8_t hall_sta_edge = uemf_edge(hall_single_sta);
    if(hall_sta_edge == 0)    /* 统计单个霍尔信号的高电平时间 */
    {
        /* 计算速度 */
        if(dir == CW)
            temp_speed = (speed_coeff / *GetCount);
        else
            temp_speed = -(speed_coeff / *GetCount);
        FirstOrderRC_LPF(*speed, temp_speed, 0.2379);  //滤波
        no_single = 0;
        *GetCount = 0;
    }else if(hall_sta_edge == 1)
    {
        no_single = 0;
        *GetCount = 0;
    }else  if(hall_sta_edge == 2)            /* 霍尔值一直不变代表未换向 */
    {
        no_single++;                  /* 不换相时间累计 超时则判定速度为0 */
        if(no_single > 15000)
        {
            no_single = 0;
            *speed  = 0;                /* 超时换向 判定为停止 速度为0 */
        }
    }
                return 0;//g_bldc_motor1.speed;
}
有个函数需要修改以上这样


文件[/hide]




所需文件.rar

17.25 KB, 下载次数: 18

文件

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

7

主题

88

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
273
金钱
273
注册时间
2015-1-10
在线时间
69 小时
发表于 2024-2-8 18:53:42 | 显示全部楼层
楼主请问下,有没有在stm32f103上移植过?我移植了之后发下pid部分出问题了,电机一下子就以最高速度转起来了,然后电机驱动板就亮红灯了
回复 支持 反对

使用道具 举报

13

主题

49

帖子

0

精华

高级会员

Rank: 4

积分
542
金钱
542
注册时间
2017-10-17
在线时间
118 小时
 楼主| 发表于 2024-3-11 10:04:49 | 显示全部楼层
colinh 发表于 2024-2-8 18:53
楼主请问下,有没有在stm32f103上移植过?我移植了之后发下pid部分出问题了,电机一下子就以最高速度转起来 ...

那你得看一下这个定时器是不是有编码器模式,然后还要看看编码器反馈回来准不准
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-22 16:30

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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