本帖最后由 袁胜富 于 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
|