打印
[单片机芯片]

基于CH32V208的无刷有感电机驱动

[复制链接]
11599|17
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 袁胜富 于 2023-2-6 16:24 编辑

#技术资源# #申请原创# 1.项目简介:
       基于CH32V208WBU6芯片,预驱芯片用的是EG2133,最大支持输入电压75V,功率1000W,支持USB下载程序,板载一路485,引出USART1接口,板载蓝牙天线,板载旋转电位器。实现了电机的按键启停,按键切换旋转方向,速度环PID,测量母线电压,电机运行电流以及基于硬石上位机协议的PID调参。

2.硬件说明:1.电源电路
    电源电路使用XDS(芯鼎盛)的TX4139,宽电压输入4.5V-75V,TX4139将输入电压降压至12V,LM317AG-TN3-R将12V降压至5V,AMS1117-3.3将5V降压至3.3V供给CH32V208WBU6,12V电压供给预取芯片EG2133.
2.霍尔电路

3.预驱电路

4.三相桥电路

5.电流采集电路

6.RS485电路

7.按键电路

8.USB下载电路

9.最小系统电路

3.软件说明:


1.开发平台使用MounRiver Studio,使用六路互补PWM配置,PWM方波频率为4KHZ,使用外部高速晶振(HSE).PLL系统时钟频率为96MHZ。
2.系统软件框架图
3.电机状态机代码
    if(!GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_4))
    {
        delay_ms(1);
        if(!GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_4))
        {
            if(BLDC1.Motor_Status == M_IDLE)
            {
                BLDC1.Motor_Status = M_Start;
                if(Get_Motor_Dir() == 1)
                {
                    BLDC1.Motor_Dir = M_CCW;
                }
                else {
                    BLDC1.Motor_Dir = M_CW;
              }
            }
        }
        while(!GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_4));
    }
    if(!GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_5))
    {
        delay_ms(1);
        if(!GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_5))
        {
            if(BLDC1.Motor_Status == M_Running)//只有电机运行状态下才能停止电机
            {
                BLDC1.Motor_Status = M_Stop;
            }
        }
        while(!GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_5));
    }
    if(BLDC1.Motor_Status == M_Start)
    {
        BLDC_Motor_Start();
        BLDC1.MotorStopFalg = 0;
        BLDC1.Motor_Status = M_Accelerate;
    }
    if(BLDC1.Motor_Status == M_Accelerate)
    {
    if(BLDC1.Motor_Dir == M_CCW)
    {
        if((Result<50) && (Result>0))
        {
            Motor_AccleleRate(8000);
        }
        else {
            Motor_AccleleRate(6000);
        }
    }
    else {
        if((Result<50) && (Result>0))
        {
            Motor_AccleleRate(10000);
        }
        else {
            Motor_AccleleRate(6000);
        }
    }
        //delay_ms(5);
        BLDC1.Motor_Status = M_Running;
    }
    if((BLDC1.Motor_Status == M_Stop) && (BLDC1.MotorStopFalg == 0))
    {
        BLDC1.MotorStopFalg = 1;
        BLDC_Stop_Motor();
        BLDC1.Motor_Status = M_IDLE;
    }
    if(BLDC1.Motor_Status == M_IDLE)
    {
        BLDC_Motor_Brake();
        BLDCStopCounter++;
        if(BLDCStopCounter == 1500)
        {
            TIM_ITConfig(TIM2, TIM_IT_Trigger, DISABLE);
            TIM_ClearITPendingBit(TIM2, TIM_IT_Trigger);
            BLDC1.Motor_Speed = 0;
            PID_Result = 0;
            BLDCStopCounter = 0;
        }
    }
    if(BLDC1.Motor_Status == M_Running)
    {
        //Monitor_Speed();//监控电机速度状态
        NoDelaySystickTaskStart(&BLDC1.PIDTimeFlag, PIDTask);//每隔30ms执行一次PID
    }
    if(RData.RXfinished == 1)
    {
        if(CommandCheck(RData.RXBuffer) == 1)
        {
        }
        RData.RXfinished = 0;
        memset((char*)RData.RXBuffer, 0,RXMaxSize);
    }
4.电压电流采集代码
        if(ADC_EOF)
        {
            int sum = 0;
            ADC_AMPBuffer[ADC_AMPCounter++] = ADC_Value[3];
            if(ADC_AMPCounter == 512)
            {
                ADC_AMPCounter = 0;
                for(int i =0;i<512;i++)
                {
                    sum += ADC_AMPBuffer;
                }
                sum = sum/512;
                //Rs485_Printf("SUM=%d\r\n",sum);
                BLDC1.Motor_Current = (((float)sum)*3.3f)/4096;
                BLDC1.Motor_Current = BLDC1.Motor_Current/34.0f;
                BLDC1.Motor_Current = (BLDC1.Motor_Current/0.002)/2.0;
                //Rs485_Printf("Motor_Current=%.3f\r\n",BLDC1.Motor_Current);
                sum = 0;
            }
            counter ++;
            VBUS = 20.61 * 3.3 *((float)Get_ConversionVal(ADC_Value[0]));
            VBUS = (VBUS /4096.00f);
            BLDC1.Vbus_Voltage = VBUS;
            //Rs485_Printf("VBUS=%.3f\r\n",VBUS);
            BFB = (float)Get_ConversionVal(ADC_Value[1])/4096.00;
            Result = ceil(BFB * 100.0);
            if(!(temp == Result))
            {
                //PWM_Value_Set(BFB*15800);
                if(BLDC1.Motor_Status == M_Stop)
                {
                    //PwmDutyUpdate(pwm_value);
                }
            }
            temp = Result;
            if(counter == 10)
            {
                counter = 0;
                //Rs485_Printf("%.0f%s\r\n",Result,"%");
            }
            ADC_EOF = 0;
        }
4.霍尔信号换相和转速测量代码
void TIM2_IRQHandler(void)
{
    uint8_t Hall_status;
    if(TIM_GetITStatus(TIM2, TIM_IT_Trigger) != RESET)
    {
        /** Clear interrupt flag */
        TIM_ClearITPendingBit(TIM2, TIM_IT_Trigger);
        Hall_status = Get_Hall_Value();
        //printf("Hall_status=%d\r\n",Hall_status);
        BLDC_Phase_Change(Hall_status);//换相操作
        /* 每换向360°读取TIM3,从而得到360°的换向周期 */
        if(Hall_status == 2)
        {
            /* 计算2次换向周期的平均值 */
            CommutateTime = (CommutateTime + TIM4->CNT) >> 1;
            TIM4->CNT = 0;
            /* 计算电机转速 */
            Get_MotorSpeed();
        }
    }

}
5.main函数代码
int main(void)
{
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
//    Delay_Init();
    Systick_Init();
    DMA_Channel1_Init();
    DMA_Channel2_Init(u8UartTx3Buffer);
    DMA_Channel3_Init(u8UartRx3Buffer);
    DMA_Channel4_Init(u8UartTxBuffer);
    DMA_Channel5_Init(u8UartRxBuffer);
    Bsp_Gpio_Init();
    OPA2_Init();
    Drv_Uart_Init(115200);
    Drv_Rs485_Init(115200);
    Drv_Hall_Init();
    Drv_Adc_Init();
    Drv_Tim4_Init();
    Drv_Pwm_Init();
    Speed_PIDInit();
    SystickStart(1000, BLDC_ParInit);
    BLDC_ParInit();//电机参数初始化
    IWDG_Feed_Init(IWDG_Prescaler_32,3200);   // 3.2s IWDG reset
    while(1)
    {
        IWDG_ReloadCounter();   //Feed dog
        if(ADC_EOF)
        {
            int sum = 0;
            ADC_AMPBuffer[ADC_AMPCounter++] = ADC_Value[3];
            if(ADC_AMPCounter == 512)
            {
                ADC_AMPCounter = 0;
                for(int i =0;i<512;i++)
                {
                    sum += ADC_AMPBuffer;
                }
                sum = sum/512;
//                printf("SUM=%d\r\n",sum);
                BLDC1.Motor_Current = (((float)sum)*3.3f)/4096;
                BLDC1.Motor_Current = BLDC1.Motor_Current/34.0f;
                BLDC1.Motor_Current = (BLDC1.Motor_Current/0.002)*1.223f;
                //printf("Motor_Current=%.3f\r\n",BLDC1.Motor_Current);
                sum = 0;
            }
            counter ++;
            VBUS = 20.61 * 3.3 *((float)Get_ConversionVal(ADC_Value[0]));
            VBUS = (VBUS /4096.00f);
            BLDC1.Vbus_Voltage = VBUS;
            //printf("VBUS=%.3f\r\n",VBUS);
            BFB = (float)Get_ConversionVal(ADC_Value[1])/4096.00;
            Result = ceil(BFB * 100.0);
            if(!(temp == Result))
            {
                PWM_Value_Set(BFB*15800);
                if(BLDC1.Motor_Status == M_Stop)
                {
                    PwmDutyUpdate(pwm_value);
                }
            }
            temp = Result;
            if(counter == 10)
            {
                counter = 0;
                //printf("%.0f%s\r\n",Result,"%");
            }
            ADC_EOF = 0;
        }
        NoDelaySystickTaskStart(&BLDC1.MotorTaskSchFlag, MotorTask);//每隔1ms调度一次电机任务
        NoDelaySystickTaskStart(&BLDC1.LEDToggleTimeFlag, Led1_Toggle);//每隔500MSLED翻转一次
        NoDelaySystickTaskStart(&BLDC1.CommunicationFlag, CommunicationTask);//每隔500MSLED翻转一次
        if((BLDC1.Motor_Status == M_Running) || (BLDC1.Motor_Status == M_Accelerate))
        {
            NoDelaySystickTaskStart(&BLDC1.Motor_StalledFlag, BLDC_Motor_Stalled);//检测电机是否堵转
        }
    }
}

4.演示效果:

关于例程代码和设计文件(生产文件已经打包至附件),本例程只能作为学习使用,严禁商用。
1.演示照片

2.演示视频

https://b23.tv/fhW6Zkp


(硬件)V2.0.zip

912.46 KB

SDK.zip

181.72 KB

使用特权

评论回复
沙发
LOVEEVER| | 2023-2-8 09:29 | 只看该作者
CH32V208有双USB 支持

使用特权

评论回复
板凳
klbyf| | 2023-2-9 08:56 | 只看该作者

使用特权

评论回复
地板
leeyouhon| | 2023-2-9 09:25 | 只看该作者
感谢楼主大大的无私分享

使用特权

评论回复
5
yuchl| | 2023-2-9 14:52 | 只看该作者
感谢分享

使用特权

评论回复
6
huazi2008| | 2023-2-15 11:57 | 只看该作者

使用特权

评论回复
7
WoodData| | 2023-2-20 17:55 | 只看该作者
感谢分享

使用特权

评论回复
8
Innercourage| | 2023-2-27 09:02 | 只看该作者
不错不错,学到了

使用特权

评论回复
9
qbwww| | 2023-2-28 12:41 | 只看该作者
基于CH32V208WBU6芯片,预驱芯片用的是EG2133,最大支持输入电压75V,功率1000W,支持USB下载程序,板载一路485,引出USART1接口,板载蓝牙天线,板载旋转电位器。实现了电机的按键启停,按键切换旋转方向,速度环PID,测量母线电压,电机运行电流以及基于硬石上位机协议的PID调参。

使用特权

评论回复
10
CH32V208 支持2个USB 接口,可以独立工作,其中一个可以作为Host和Device(USB2),另外一个只能作为Device 使用(USB1)。

使用特权

评论回复
11
LOVEEVER| | 2023-3-2 16:53 | 只看该作者
CH32V208系列是基于32位RISC-V设计的无线型微控制器,配备了硬件堆栈区、快速中断入口,在标准RISC-V基础上大大提高了中断响应速度

使用特权

评论回复
12
tpgf| | 2023-3-6 16:19 | 只看该作者
请问楼主什么叫做无刷有感电机呀

使用特权

评论回复
13
木木guainv| | 2023-3-6 16:58 | 只看该作者
有感无刷电机中的感是指“霍尔传感器”。

使用特权

评论回复
14
磨砂| | 2023-3-6 17:07 | 只看该作者
无刷电机的转速是靠交流电频率决定的,那么电调要想方设法弄明白目前电机的转速以及当前电机的状态

使用特权

评论回复
15
晓伍| | 2023-3-6 17:19 | 只看该作者
无感无刷电机会在低速时线性不好甚至可能会颤抖,而起步的扭力也难以强过同等级有刷电机

使用特权

评论回复
16
八层楼| | 2023-3-7 08:08 | 只看该作者
在运行的过程中 电容有没有稍微发热的现象啊

使用特权

评论回复
17
观海| | 2023-3-7 08:55 | 只看该作者
LOVEEVER 发表于 2023-2-8 09:29
CH32V208有双USB 支持

请问它带的双USB都可以工作在什么usb模式下啊

使用特权

评论回复
18
WoodData| | 2023-3-20 09:22 | 只看该作者
看一看

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

27

主题

140

帖子

2

粉丝