基于CW32的CW-W88水泵通用控制板设计方案

描述

一、前言

无刷水泵被广泛应用于许多领域,如工业生产、农业灌溉以及家庭应用。它具有高效、可靠和节能的特点,因此备受青睐。但是无刷水泵的供电是一个问题。怎么能随时随地的使用无刷水泵呢?总不能拿一个水泵,还要配一台发电机吧。所以本次我们使用电动车供电,可以满足用户骑车到哪,水泵都可以使用的特点。

在户外的各种场景下,肯定要选择一颗稳定的抗干扰的芯片才行。强烈推荐CW32系列芯片。抗干扰能力值得您的信赖!

CW32F030C8T6支持工作温度: -40℃ 至 105℃

工作电压:1.65V 至 5.5V

存储容量:  64K 字节FLASH,数据保持25年@85℃ 8K 字节RAM,支持奇偶校验,128字节OTP存储器

使用一颗好芯片,为您照亮开发之路!

二、CW-W88水泵通用控制板-方案介绍

简介

CW-W88水泵通用控制板适用于水泵电机抽水控制应用。配合水泵电机,可使用48V或60V电池组(电动车电池组)抽水使用。使用前请将电池充满(电池至少在一半电量以上使用)。控制板具有欠压保护、过压保护、过流保护、无水停止保护、堵转保护,速度异常等功能。可广泛应用于各类水泵抽水控制。

系统功能

电源接线:红色,黑色接电源,不分正负,建议按使用习惯接:红色接正、黑色接负。

相线接线:UVW随机接入电机的相线,试看电机运行方向。如需要反转,随意调换两根相线,重新上电即可。

电源电压接入不能超过70V。上电2S后,电机启动开始抽水运行(可根据需求缩短上电稳定时间)。速度增到最大功率以后,按设定的最大功率值控制运行。如果用户电机功率达不到设定的功率,控制板则按电机的最大输出能力输出运行。

电机在无水检测或其它任何故障时,会自动停止运行,且以指闪灯的闪烁频率指示故障状态。

工作参数

型号:CW-W88

使用环境:48V或60V电池组

工作电压:40V~60V

工作电流:48V电池组13A、60V电池组10A

最大功率:600W

控制方式:电流闭环

尺寸:板子为圆形,直径8CM,高度3CM。建议至少加3MM厚的散热器

项目组成部分:

CW32主控芯片

这是整个项目的关键组成部分,它负责控制无刷水泵电机的运行和参数调节。CW32主控芯片具有高性能和低功耗的特点,可以满足无刷水泵电机控制器项目的需求。

无刷水泵电机:

无刷水泵电机是项目的核心部分,它可以通过电磁感应实现转子转动的无刷电机效果。无刷水泵电机具有较高的效率和可靠性,适用于各种应用场景。

硬件电路:

包含驱动电路,电流采集电路,母线电压采集电路,反电动势采集电路,电源电路。

软件编写:

包含电机驱动代码,高压,低压保护及自恢复。电流保护,速度异常保护,空载保护,启动堵转保护。

三、项目设计说明

硬件设计及PCB制板

此线控器是基于武汉芯源半导体推出的CW32F030C8T6产品设计研发而成的,其主要包括MCU、电源部分、电流采样、电压采样、EG3014驱动、反电动势采集等部分,设计系统原理框图如图1所示:

芯片

该控制器功能包含:

上电自启动,缓慢加速。

启动堵转保护

速度异常保护

过欠压自恢复保护

电流保护

空载保护

2.设计原理图及PCB板实物图

芯片

芯片

芯片

芯片

芯片

3.软件部分

软件部分主要分为以下几部分内容,软件构成如图7所示:

芯片

状态机代码

 

switch(USER_sSysStateErr.sSystemState)//状态机{
case STATE_IDLE_A: MDS_v_charge();break;//充电
case STATE_INIT_B: MDS_v_Init();break;//初始化
case STATE_START_C: MDS_v_Start_the_judgment(); break;//等待启动信号
case STATE_ALIGNMENT_D: MDS_v_The_motor_starts();break;//启动
case STATE_ADCLOOP_E:MDS_v_OPEN_starts();break; // 开环模式
case STATE_BRAKE_F:MDS_v_brake();break; // 刹车
case STATE_FAULT_G:MDS_v_Misjudgment();break; // 错误判断
case STATE_WAIT_L:
MDS_v_Error_recovery(USER_sSysStateErr.sSysTime.u32ReStartTime);
break; // 错误恢复判断
case STATE_STOP_M:Stop_Motor();break; // 停止
default:break;}

 

电流电压采集计算代码

 

void V_A_calculation(void)
{
USER_sVoltageAll.s16Udc=(float)(SampleData[2]*UPDS_resistance_compute);
        keep_adcvlaue+=SampleData[4];
        keep_adcvnum++;
        if(keep_adcvnum>2)
        {
                keep_adcvnum=0;
        keep_adcvlaue=keep_adcvlaue/2;
        USER_sCurrentAll.s32IdcUse=(SampleData[4]*UPDS_Current_compute)/10;//100mA
        USER_sCurrentAll.IdcValue=(float)USER_sCurrentAll.s32IdcUse/100.0;
        }
}

 

电机启动代码,判断启动是否失败

 

//(3):电机启动代码,判断启动是否失败。
void Sensorless_MOTOR_START(void)
{
        unsigned char coun = 0;
        USER_BLDC.HALLcountS = 0;
        USER_BLDC.QDPwm = 20; // 启动占空比
        do
        {
                if (Sensorless_START() == 0)
                {
                        coun++;
                        USER_BLDC.QDPwm += 5;
                }
                else
                        break;
        } while (coun < 5 && ErrorCode == 0);
        if (coun >= 5 && ErrorCode == 0)
        {
                ErrorCode = 3;
        } // 启动失败
}

 

电机运行代码

 

//(4):电机运行代码
void ADCS_chuli(void)
{
        static unsigned char cou = 0;
        unsigned char hx = 0;
        unsigned int thre = 0;
        if (USER_BLDC.Sta != 2)
                return;
        BEMFConvertedValue = SampleData[TAB_BEMFChannel[Forward_rotation][bHallStartStep1]];
        RisingFalling = TAB_RFling[Forward_rotation][bHallStartStep1];


        if (USER_BLDC.Tonoroff == 0)
                thre = 50; // 30;//248;  //OFF时刻采集。0.2V阀值248
        else
                thre = SampleData[2] / 2;
        if (RisingFalling == FALLING) // 下降沿
        {
                if (BEMFConvertedValue < thre)
                {
                        cou++;
                        if (cou >= 2)
                        {
                                cou = 0;
                                USER_BLDC.Sta = 3;
                        USER_BLDC.StCountComm++; // 正确检测到第三相反电动势
                                FFlag = 1;
                                hx = 1;
                        }
                }
                else
                {
                        cou = 0;
                }
        }
        else if (RisingFalling == RISING)
        {
                if (BEMFConvertedValue > thre)
                {
                        cou++;
                        if (cou >= 2)
                        {
                                cou = 0;
                                USER_BLDC.Sta = 3;
                        USER_BLDC.StCountComm++; // 正确检测到第三相反电动势
                                FFlag = 1;
                                hx = 1;
                        }
                }
                else
                {
                        cou = 0;
                }
        }
        if (USER_BLDC.StCountComm >= STCount && USER_BLDC.StOk == 0) // 连续检测到固定数量的过零时,认为启动成功
        {
                USER_BLDC.StOk = 1;
        }
        if (USER_BLDC.StOk == 1 && hx == 1)
        {
                hx = 0;
                BTIM_SetAutoreload(CW_BTIM3, USER_BLDC.StepTime / 5);
                BTIM_SetCounter(CW_BTIM3, 0);
                BTIM_Cmd(CW_BTIM3, ENABLE);
        }
}

 

电机报警代码及其自恢复功能

 

//(5):电机报警代码及其自恢复功能


void US_vSysErrorCheck(void)
{
        US_vSysCurrentCheck();                  // 电流报警
        US_vSysVoltageCheck();                  // 电压报警
        US_vSysStuck_in();                          // 启动堵转保护
        US_vSysSPEED_ERRORCheck();          // 速度异常保护
        US_vSyscarrying_idlerCheck(); // 空载保护
}


void MDS_v_Error_recovery(uint32_t WaitTime) // 错误恢复
{
        static uint32_t lg_u32WaitCount = 0;
        if (lg_u32WaitCount >= WaitTime)
        {
                USER_sSysStateErr.sSystemStatePre = USER_sSysStateErr.sSystemState;
                USER_sSysStateErr.sSystemState = STATE_INIT_B;
                USER_sSysStateErr.uSystemError.OverGUdcFlag = false;
                USER_sSysStateErr.uSystemError.OverLUdcFlag = false;
                USER_sSysStateErr.uSystemError.overStuck_in = false;
                USER_sSysStateErr.uSystemError.GlobalErrorFlag = false;
                ErrorCode = 0;
                lg_u32WaitCount = 0;
        }
else if (((USER_sVoltageAll.s16Udc < UPDS_UDC_PROTECT_MAX_V_recover) && (USER_sSysStateErr.uSystemError.OverGUdcFlag == true)) || ((USER_sVoltageAll.s16Udc > UPDS_UDC_PROTECT_MIN_V_recover) && (USER_sSysStateErr.uSystemError.OverLUdcFlag == true))  || (USER_sSysStateErr.uSystemError.overStuck_in == true))
        {
                lg_u32WaitCount++;
        }
        else
                lg_u32WaitCount = 0;
}

 

电机反电动势及运行代码

反电动势过零检测法基本原理:

忽略电动机电枢反应,无刷直流电动机在稳态运行过程中,通过检测关断相的反电动势过零点获得转子的位置信号,进行对逆变器开关导通顺序切换,控制电机运动。

较为典型的 BLDCM 的无位置传感器控制方法有基于反电势的检测法、磁链估计法、电感检测法等,在该系统中采用反电势过零检测法。

反电动势过零检测法是以直流无刷电机中性点电压为基准进行反电动势过零检测的,属于间接反电动势检测方法。该方法将端电压作分压滤 波处理得到直流无刷电机的位置信号,由于有滤波电路存在,获得的位置信号比真实的反电动势过零点延时了一定的角度。

在理想情况下,电机三相绕组反电势 Ea 、Eb、Ec 的波形为梯形波。无刷电机采用 120°导通方式,在任何时刻只有两相导通,这两相电流的大小 相等、方向相反,另一相电流为零,故三相电流的 总和为零。

芯片

反电动势零点 变化趋势
C- C相反电动势由正到负
B+ B相反电动势由负到正
A- A相反电动势由正到负
C+ C相反电动势由负到正
B- B相反电动势由正到负
A+ A相反电动势由负到正

表: 正向反电动势过零点变化

反电动势部分代码

 

//反电动势部分代码
void ADCS_chuli(void)
{
        static unsigned char cou = 0;
        unsigned char hx = 0;
        unsigned int thre = 0;


        if (USER_BLDC.Sta != 2)
                return;


        BEMFConvertedValue = SampleData[TAB_BEMFChannel[Forward_rotation][bHallStartStep1]];
        RisingFalling = TAB_RFling[Forward_rotation][bHallStartStep1];


        if (USER_BLDC.Tonoroff == 0)
                thre = 50; // 30;//248;  //OFF时刻采集。0.2V阀值248
        else
                thre = SampleData[2] / 2;


        if (RisingFalling == FALLING) // 下降沿
        {
                if (BEMFConvertedValue < thre)
                {
                        cou++;
                        if (cou >= 2)
                        {
                                cou = 0;
                                USER_BLDC.Sta = 3;


                                USER_BLDC.StCountComm++; // 正确检测到第三相反电动势
                                FFlag = 1;
                                hx = 1;
                        }
                }
                else
                {
                        cou = 0;
                }
        }
        else if (RisingFalling == RISING)
        {
                if (BEMFConvertedValue > thre)
                {
                        cou++;
                        if (cou >= 2)
                        {
                                cou = 0;
                                USER_BLDC.Sta = 3;


                                USER_BLDC.StCountComm++; // 正确检测到第三相反电动势
                                FFlag = 1;
                                hx = 1;
                        }
                }
                else
                {
                        cou = 0;
                }
        }


        if (USER_BLDC.StCountComm >= STCount && USER_BLDC.StOk == 0) // 连续检测到固定数量的过零时,认为启动成功
        {
                USER_BLDC.StOk = 1;
        }


        if (USER_BLDC.StOk == 1 && hx == 1)
        {
                hx = 0;
                BTIM_SetAutoreload(CW_BTIM3, USER_BLDC.StepTime / 5);
                BTIM_SetCounter(CW_BTIM3, 0);
                BTIM_Cmd(CW_BTIM3, ENABLE);
        }
}
 

 

母线电压监测-分压电路原理及代码

可以看原理图中的分压电路是两个电阻

软件保护

 

void US_vSysErrorCheck(void)
{
        US_vSysCurrentCheck();                  // 电流报警
        US_vSysVoltageCheck();                  // 电压报警
        US_vSysStuck_in();                          // 启动堵转保护
        US_vSysSPEED_ERRORCheck();          // 速度异常保护
        US_vSyscarrying_idlerCheck(); // 空载保护
}

 

1):电流保护

在无刷电机运行中,有时候堵转很容易烧mos管,所以电流保护就尤为的重要。

在程序中配置了电流触发保护值,是15A,因为我们额定功率是500W。还有电流采集电路没有加入运放,采集不精确,所以需要把电流值设置大一点。之后也要根据实际的调试而改变。

 

//电流保护
void US_vSysCurrentCheck(void) // 电流保护
{
#if (UPDS_ISUM_DETECTION == 1)
        if ((USER_sCurrentAll.IdcValue) >= UPDS_OVERISUM_limit_MAX) // 一级电流保护
        {
                USER_sSysStateErr.sSysTime.s32OverIdcFirstlevelCount++;
                if (USER_sSysStateErr.sSysTime.s32OverIdcFirstlevelCount >= UPDS_OVERISUM_limit_MS)
                {
                        USER_sSysStateErr.sSysTime.s32OverIdcFirstlevelCount = UPDS_OVERISUM_limit_MS;
                        USER_sSysStateErr.uSystemError.OverIdcFirstlevelFlag = true;
                        USER_sSysStateErr.sSystemStatePre = USER_sSysStateErr.sSystemState;
                        USER_sSysStateErr.sSystemState = STATE_FAULT_G;
                }
        }
        else
        {
                USER_sSysStateErr.sSysTime.s32OverIdcFirstlevelCount--;
                if (USER_sSysStateErr.sSysTime.s32OverIdcFirstlevelCount <= 0)
                {
                        USER_sSysStateErr.sSysTime.s32OverIdcFirstlevelCount = 0;
                        USER_sSysStateErr.uSystemError.OverIdcFirstlevelFlag = false;
                }
        }


#endif
}




/********************限流保护值***********************/ 
#define UPDS_OVERISUM_limit_MAX         (15) //unit: A 限流保护值 
#define UPDS_OVERISUM_limit_MS           (500)//unit: ms  触发保护时间


/**********************报警设置********************/
#define  UPDS_ISUM_DETECTION                         (1)                //电流保护使能

 

2):电压保护

在高压和低压保护中,我们在程序中加入了自恢复功能,如果电压高于58v就会触发高压保护,电机停止,等待电压下降到55v以下,就会触发自恢复功能,等待自恢复时间结束,电机重新启动。低压也是同理。

 

//电压保护
void US_vSysVoltageCheck(void) // 电压保护
{
#if (UPDS_UDC_DETECTION == 1)
        if (USER_sVoltageAll.s16Udc > UPDS_UDC_PROTECT_MAX_V)
        {
                USER_sSysStateErr.sSysTime.s32OverGUdcCount++;
                if (USER_sSysStateErr.sSysTime.s32OverGUdcCount >= UPDS_OVERVOLTAGE_VOLTAGE_MS)
                {
                        USER_sSysStateErr.sSysTime.s32OverGUdcCount = UPDS_OVERVOLTAGE_VOLTAGE_MS;
                        USER_sSysStateErr.uSystemError.OverGUdcFlag = true;
                        USER_sSysStateErr.sSystemStatePre = USER_sSysStateErr.sSystemState;
                        USER_sSysStateErr.sSystemState = STATE_FAULT_G; // 高压保护
                }
        }
        if (USER_sVoltageAll.s16Udc < UPDS_UDC_PROTECT_MIN_V && USER_sVoltageAll.s16Udc > 5)
        {
                USER_sSysStateErr.sSysTime.s32OverLUdcCount++;
                if (USER_sSysStateErr.sSysTime.s32OverLUdcCount >= UPDS_UNDERVOLTAGE_VOLTAGE_MS)
                {
                        USER_sSysStateErr.sSysTime.s32OverLUdcCount = UPDS_UNDERVOLTAGE_VOLTAGE_MS;
                        USER_sSysStateErr.uSystemError.OverLUdcFlag = true;
                        USER_sSysStateErr.sSystemStatePre = USER_sSysStateErr.sSystemState;
                        USER_sSysStateErr.sSystemState = STATE_FAULT_G; // 低压保护
                }
        }
#endif
}


/**********************报警设置********************/
#define  UPDS_UDC_DETECTION                           (1)                //电压保护使能


/********************电压保护值***********************/
#define UPDS_UDC_REAL                                         (48.0f) //unit: V;电压源电压
#define UPDS_UDC_PROTECT_MAX_V                        (58.0f)        //unit: V;过压值
#define UPDS_UDC_PROTECT_MAX_V_recover        (54.0f) //unit: V;过压恢复值
#define UPDS_OVERVOLTAGE_VOLTAGE_MS         (10.0)  //Unit: ms 过电压持续时间1ms基准
#define UPDS_UDC_PROTECT_MIN_V                        (30.0f)        //unit: V;欠压值
#define UPDS_UDC_PROTECT_MIN_V_recover        (32.0f)        //unit: V;欠压恢复值
#define UPDS_UNDERVOLTAGE_VOLTAGE_MS         (14.0)  //Unit: ms 欠电压持续时间1ms基准

 

3):启动堵转保护

在堵转保护之中,我们同样设置了自恢复启动,但是自恢复启动有次数,只有五次。如果5次都没有启动成功,电机将停止转动。不会启动。

 

/启动堵转保护
void US_vSysStuck_in(void) // 堵转保护启动5次
{
        if ((USER_stuck_in.locked_rotor_flag == 1) || (ErrorCode == 3)) // 检测如果触发了一次堵转保护之后 电流大于额定值都没有启动
        {
                USER_stuck_in.locked_rotor_flag = 0;
                USER_sSysStateErr.uSystemError.overStuck_in = true;           // 启动堵转标志
                USER_sSysStateErr.uSystemError.GlobalErrorFlag = true; // 全局错误标志位
                USER_sSysStateErr.sSystemStatePre = USER_sSysStateErr.sSystemState;
                USER_sSysStateErr.sSystemState = STATE_FAULT_G; // 跳入错误判断
                USER_sADSampleAll.s16VSPLPF = 0;                                   // 清空一下电位器
                USER_stuck_in.Phase_Stuck_num++;                                   // 启动堵转报警加1
        }
}

 

4):速度异常保护

检测目标速度和实际速度之比,如果较小或者较大就是速度异常

 

//速度异常保护
float value;
void US_vSysSPEED_ERRORCheck(void) // 速度异常保护
{


        if (USER_sADSampleAll.s16VSPLPF > 2500) // 启动之后
        {
                value = (float)USER_sADSampleAll.s16VSPLPF / (float)USER_sADSampleAll.s32SpdUse;
                if ((value > 1.5) || (value < 0.5))
                {
                        USER_sSysStateErr.sSysTime.s32OverIdcFirstlevelCount++;
                        if (USER_sSysStateErr.sSysTime.s32OverIdcFirstlevelCount >= UPDS_SPEED_IDLER_MS)
                        {
                                USER_sSysStateErr.sSysTime.s32OverIdcFirstlevelCount = UPDS_CARRYING_IDLER_MS;
                                USER_sSysStateErr.uSystemError.over_speed_error = true;
                                USER_sSysStateErr.sSystemStatePre = USER_sSysStateErr.sSystemState;
                                USER_sSysStateErr.sSystemState = STATE_FAULT_G;
                        }
                }
                else
                {
                        USER_sSysStateErr.sSysTime.s32OverIdcFirstlevelCount--;
                        if (USER_sSysStateErr.sSysTime.s32OverIdcFirstlevelCount <= 0)
                        {
                                USER_sSysStateErr.sSysTime.s32OverIdcFirstlevelCount = 0;
                                USER_sSysStateErr.uSystemError.over_speed_error = false;
                        }
                }
        }
}

 

5):空载保护

空载保护是不让水泵电机空转,检测方法是检测电流大小,如果在水里,电流会比较大,只需要在速度达到某一点时,检测电流的大小就可以实现。

 

//空载保护
void US_vSyscarrying_idlerCheck(void) // 空载保护
{
        if (USER_sADSampleAll.s32SpdCommand > 3000) // 启动之后
        {
                if ((USER_sCurrentAll.IdcValue) < UPDS_CARRYING_IDLER_MAX)
                {
                        USER_sSysStateErr.sSysTime.s32OverIdcFirstlevelCount++;
                        if (USER_sSysStateErr.sSysTime.s32OverIdcFirstlevelCount >= UPDS_CARRYING_IDLER_MS)
                        {
                                USER_sSysStateErr.sSysTime.s32OverIdcFirstlevelCount = UPDS_CARRYING_IDLER_MS;
                                USER_sSysStateErr.uSystemError.overload_protection = true;
                                USER_sSysStateErr.sSystemStatePre = USER_sSysStateErr.sSystemState;
                                USER_sSysStateErr.sSystemState = STATE_FAULT_G;
                        }
                }
                else
                {
                        USER_sSysStateErr.sSysTime.s32OverIdcFirstlevelCount--;
                        if (USER_sSysStateErr.sSysTime.s32OverIdcFirstlevelCount <= 0)
                        {
                                USER_sSysStateErr.sSysTime.s32OverIdcFirstlevelCount = 0;
                                USER_sSysStateErr.uSystemError.overload_protection = false;
                        }
                }
        }



 

调试部分

下载程序即可上电调试;

接上电机的UVW三相,记得在代码中设置一下分压电阻,电流采样的电阻(如果没有更改就不需要更换)。四线插入正确,按下烧录键即可烧录成功。烧录后电机就3s缓启动正常运行起来了。需要检测电机的UVW三相,如果是如图9这样呈现梯形就可以。

芯片

芯片

4. 小结

以上即为本次无刷电机驱动板设计的全部基本内容。芯源推出的CW32F030系列产品,已全面实现-40℃ 至 105℃超宽温度范围和 1.65V~5.5V 超宽工作电压,面向最广泛的各种基础应用。用户可以根据自己的需求自行更改代码功能。

  审核编辑:汤梓红

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分