51单片机STC15W408AS做的无刷电调
http://player.youku.com/player.php/sid/XODE5NDUxOTI0/v.swf看到很多人在用C8051做无感无刷电机的驱动,论坛里也好久没有做电调的动静了。今天我给大家来个国产51单片机STC15W408AS驱动无刷电机的驱动资料吧!
1.硬件设计
主控单片机使用STC15W408AS,这是STC在2014年新出的片子,2元一片,主频35M,无需外部晶振和复位电路,接好VCC和GND就可以工作。单片机自带硬件PWM模块、ADC模块和比较器模块,所以非常适合做无刷电机的驱动,半桥电路使用PMOS+NMOS的组合,PMOS为IRF9540,NMOS为IRF540.驱动芯片用TC4427A。
先在洞洞板上做实验吧。原理图如下所示,懒得用软件画了,还是手画来得快些。下面的图中,只画出了A相的桥,B相和C相的桥与A相一样。
按照原理图,焊接好元器件
连接好电机
2.软件设计
2.1PWM模块
void PWM_Init(void)
{
PWM0_L=0;
PWM1_L=0;
PWM2_L=0;
AUXR |= 0X80; //定时器0工作在1T模式
TMOD=0X02; // 定时器0工作于8位自动重载模式
TH0=0xfa; // 产生23K的频率
TL0=0xfa;
TR0=1; // 打开定时器0
CMOD=0x04; //PCA的时钟选择“T0的溢出”
CL=0; // 计数器清0
CH=0;
CCAP0H=0; //PWM1占空比为0
CCAP0L=0;
CCAPM0=0x42;//开启PWM模式
CCAP1H=0; //PWM2占空比为0
CCAP1L=0;
CCAPM1=0x42; // 开启PWM模式
CCAP2H=0; // PWM3占空比为0
CCAP2L=0;
CCAPM2=0x42;//开启PWM模式
CR = 1;// 打开PCA
}
2.2ADC模块和比较器模块
比较器用来做反电动势的过零检测,选择P5.4引脚为比较器的负输入端,选择ADC通道为比较器的正输入端。
void CMP_Init(void) // 比较器初始化函数
{
CMPCR1=0X8C; // 打开比较器,把P5.4引脚设置为负输入端,ADC通道为正输入端
CMPCR2=50;// 延时消抖时间设置
}
void ADC_Init(void) // ADC模块初始化
{
P1ASF = 0X38; //开通P1.3 P1.4 P1.5端口的模拟输入端
}
2.3六步时序换相
BLDC的六步时序为AB AC BC BA CA CB,下面程序中,分别用0~5表示每一步。
void StepXL(void) // 换相序列函数
{
switch(Step)
{
case 0: // AB
CCAP0H=PWM_Value;CCAP1H=0;CCAP2H=0; // 打开A相的高端
PWM0_L=0;PWM2_L=0;PWM1_L=1; // 打开B相的低端
ADC_CONTR = 0XED; // 选择P1.5作为ADC输入 即c相电压
CMPCR1 |= 0x10; // 使能下降沿中断
break;
case 1: // AC
CCAP0H=PWM_Value;CCAP1H=0;CCAP2H=0; // 打开A相的高端
PWM0_L=0;PWM1_L=0;PWM2_L=1; // 打开C相的低端
ADC_CONTR = 0XEC; // 选择P1.4作为ADC输入 即B相电压
CMPCR1 |= 0x20; // 使能上升沿中断
break;
case 2: // BC
CCAP0H=0;CCAP2H=0;CCAP1H=PWM_Value; // 打开B相的高端
PWM0_L=0;PWM1_L=0;PWM2_L=1; // 打开C相的低端
ADC_CONTR = 0XEB; // 选择P1.3作为ADC输入 即a相电压
CMPCR1 |= 0x10; // 使能下降沿中断
break;
case 3: // BA
CCAP0H=0;CCAP2H=0;CCAP1H=PWM_Value; // 打开B相的高端
PWM1_L=0;PWM2_L=0;PWM0_L=1; // 打开A相的低端
ADC_CONTR = 0XED; // 选择P1.5作为ADC输入 即c相电压
CMPCR1 |= 0x20; // 使能上升沿中断
break;
case 4: // CA
CCAP0H=0;CCAP1H=0;CCAP2H=PWM_Value; // 打开C相的高端
PWM1_L=0;PWM2_L=0;PWM0_L=1; // 打开A相的低端
ADC_CONTR = 0XEC; // 选择P1.4作为ADC输入 即B相电压
CMPCR1 |= 0x10; // 使能下降沿中断
break;
case 5: // CB
CCAP0H=0;CCAP1H=0;CCAP2H=PWM_Value;// 打开C相的高端
PWM0_L=0;PWM2_L=0;PWM1_L=1; // 打开B相的低端
ADC_CONTR = 0XEB; // 选择P1.3作为ADC输入 即a相电压
CMPCR1 |= 0x20; // 使能上升沿中断
break;
default:break;
}
}
2.4电机启动函数
char QiDong(void)
{
unsigned int timer = 300,i;
DISABLE_CMP_INT;
PWM_Value = 26; // 占空比=26/256=10%
Step=0;
StepXL();
delay_ms(100);
while(1)
{
for(i=0;i<timer; i++)
{
delay_us(100); //
}
timer-= timer/15+1;
if(timer < 25) return(1);
if(Step<5)Step++;
else Step=0;
StepXL();
}
}
2.5闭环控制
电机启动以后,需要闭环控制电机的通电时序和速度。这个在比较器的中断函数里面实现。
void CMP_INT(void) interrupt 21 // 比较器中断函数
{
CMPCR1 &=~0X40; // 需软件清除中断标志位
if(Step<5)Step++;
else Step=0;
StepXL();
}
2.6通信控制接口
用电脑上的串口调试助手给单片机串口发送“启动”“加速”“减速”“停止”命令。这个功能放到主函数while循环中。
串口初始化函数:
void serial_open(void)
{
SCON = 0X50;//工作在串口模式
AUXR |= 0X04;//
TL2 = 0X71;// 9600 @35MHz
TH2 = 0Xfc;
AUXR|=0X10;
}
主函数:
void main(void)
{
uchar rec=0; // 定义串口接收数据变量
PWM_Init(); // 初始化PWM
ADC_Init(); // 初始化ADC
CMP_Init(); // 初始化比较器
serial_open(); // 打开串口
while (1)
{
if(RI) // 如果串口收到数据
{
rec=SBUF; // 把收到的数据给了rec
RI=0; // 串口接收标志清0
if(rec==0x22)// 加速命令
{
if(PWM_Value<250)
{
PWM_Value++; // 增加占空比
}
}
else if(rec==0x33)// 减速命令
{
if(PWM_Value>10)
{
PWM_Value--; // 减小占空比
}
}
else if(rec==0x11) // 启动命令
{
QiDong(); // 启动
ENABLE_CMP_INT; // 允许比较器中断
EA=1; // 打开全局中断
}
else if(rec==0x44) // 停止命令
{
CCAP0H=0;CCAP1H=0;CCAP2H=0;// 占空比都置0
EA=0; // 关闭全局中断
DISABLE_CMP_INT; // 关闭比较器中断
}
}
}
}
3.总结
上面的软件和硬件,只是实现了简单的控制转动。
缺点:1.没有任何的保护程序,比如电流检测、堵转保护等。我在做实验的过程中,烧了2个PMOS、1个NMOS、3个TC4427A.
2.比较器过0直接换相,有些提前。电机转动噪音比较大。期待日后改进吧!或者哪位大侠伸手改进改进。
源程序工程文件:
楼主威武,可以加个过温(但楼主这板子貌似不用)和过流保护 收下回去看下 51也可以搞BLDC啊?不错不错 学习了 不错学习了!!{:lol:} 支持楼主{:lol:}话说楼主在设计软件之前是否参考了什么资料 kingway00 发表于 2014-11-5 22:08
支持楼主话说楼主在设计软件之前是否参考了什么资料
参考了很多驱动无刷电机的资料!
支持楼主,学习了,顶一个{:lol:} 支持BLDC,谢谢! 支持楼主,建议还可以参考BLHELI开源程序。 支持楼主! 能否加入闭环控制 强大,支持楼主。 mark{:smile:} 留个脚印,,回家慢慢看 挺好,谢谢。 本帖最后由 瑞生 于 2014-11-8 11:05 编辑
发现了一个程序的大BUG,在换相函数里面,上升沿和下降沿的切换上,程序中只用了“或”,没有用“与”把之前的清掉,实际上变成双边沿中断了。为了运行速度,下面的程序直接赋值,不用“与”“或”赋值了。改了之后,电机的噪音小多了,尤其是在高速运转的时候。希望大师们继续改进!
void StepXL(void) // 换相序列函数
{
switch(Step)
{
case 0:// AB
CCAP0H=PWM_Value;CCAP1H=0;CCAP2H=0; // 打开A相的高端
PWM0_L=0;PWM2_L=0;PWM1_L=1; // 打开B相的低端
ADC_CONTR = 0XED; // 选择P1.5作为ADC输入 即c相电压
CMPCR1=0x9c; // 使能下降沿中断
break;
case 1:// AC
CCAP0H=PWM_Value;CCAP1H=0;CCAP2H=0; // 打开A相的高端
PWM0_L=0;PWM1_L=0;PWM2_L=1; // 打开C相的低端
ADC_CONTR = 0XEC; // 选择P1.4作为ADC输入 即B相电压
CMPCR1=0xac; // 使能上升沿中断
break;
case 2:// BC
CCAP0H=0;CCAP2H=0;CCAP1H=PWM_Value; // 打开B相的高端
PWM0_L=0;PWM1_L=0;PWM2_L=1; // 打开C相的低端
ADC_CONTR = 0XEB; // 选择P1.3作为ADC输入 即a相电压
CMPCR1=0x9c; // 使能下降沿中断
break;
case 3:// BA
CCAP0H=0;CCAP2H=0;CCAP1H=PWM_Value; // 打开B相的高端
PWM1_L=0;PWM2_L=0;PWM0_L=1; // 打开A相的低端
ADC_CONTR = 0XED; // 选择P1.5作为ADC输入 即c相电压
CMPCR1=0xac; // 使能上升沿中断
break;
case 4: // CA
CCAP0H=0;CCAP1H=0;CCAP2H=PWM_Value; // 打开C相的高端
PWM1_L=0;PWM2_L=0;PWM0_L=1; // 打开A相的低端
ADC_CONTR = 0XEC; // 选择P1.4作为ADC输入 即B相电压
CMPCR1=0xac; // 使能下降沿中断
break;
case 5: // CB
CCAP0H=0;CCAP1H=0;CCAP2H=PWM_Value;// 打开C相的高端
PWM0_L=0;PWM2_L=0;PWM1_L=1; // 打开B相的低端
ADC_CONTR = 0XEB; // 选择P1.3作为ADC输入 即a相电压
CMPCR1=0xac; // 使能上升沿中断
break;
default:break;
}
}
http://player.youku.com/player.php/sid/XODIxOTgyMjM2/v.swf
新的源代码工程:
程序加入堵转保护了!实现方法,设置定时器T0产生50ms中断,在电机启动之后打开定时器T0,在换相中断比较器中,加入给T0初值的代码。这样,只要不堵转,就不会进去定时器T0中断函数;只要堵转,就会进入T0中断函数,关闭所有功率管,保护器件和电机不会烧坏!
上面的程序中,PWM的产生是用T0的溢出作为时钟源的,为了解放T0,我们设置PWM的时钟源为系统时钟,频率还设置为22K。
PWM初始化代码:
void PWM_Init(void)
{
PWM0_L=0;
PWM1_L=0;
PWM2_L=0;
CMOD=0X0C; //选择系统时钟/6为时钟源,即频率=35M/6/256=22.8K
CL=0; // PCA计数器清零
CH=0;
PCA_PWM0 = 0X00;
CCAP0H=0; // 初始化占空比为0% H的值装载到L中
CCAP0L=0;
CCAPM0=0x42; // 设置为PWM模式
PCA_PWM1 = 0X00;
CCAP1H=0; // 初始化占空比为0%
CCAP1L=0;
CCAPM1=0x42; // 设置为PWM模式
PCA_PWM2 = 0X00;
CCAP2H=0; // 初始化占空比为0%
CCAP2L=0;
CCAPM2=0x42; // 设置为PWM模式
CR = 1;
}
T0初始化函数:
void T0_Iint(void)
{
TMOD=0X01; // T0工作于16位计数模式
TH0=0x00; //
TL0=0X00;
ET0=1;// 允许ET0中断
}
T0中断函数:
void T0_Int(void) interrupt 1
{
CCAP0H=0;CCAP1H=0;CCAP2H=0;// 占空比为0
PWM0_L=0;PWM1_L=0;PWM2_L=0;
TR0=0;
EA=0;
DISABLE_CMP_INT;
TH0=0x3C; // 计时10ms
TL0=0XAF;
QiDong(); // 再次启动
ENABLE_CMP_INT; // 打开比较器中断
EA=1; // 打开总中断
TR0=1; // 打开定时器0
}
其它地方没有变
新的源代码工程:
标记一下,回来电脑上仔细阅读 这个标记一下,谢谢分享。 赞一个!值得鼓励,希望您做的更好,加油! 瑞生 发表于 2014-11-9 09:42
程序加入堵转保护了!实现方法,设置定时器T0产生50ms中断,在电机启动之后打开定时器T0,在换相中断比较器 ...
楼主,你还在更新吗,能不能问你几个问题 redworlf007 发表于 2014-11-24 15:17
楼主,你还在更新吗,能不能问你几个问题
问吧!不一定会{:sweat:} 感谢分享,最近在驱动硬盘的主轴电机玩,
新出的15系列有这么便宜?15系列现在功能也算不错了 正好自己想学……赞一个! 楼主威武 15的要6块的吧 谢谢楼主,下载了 强,学习了 学习了,希望出过完整的图纸分享。 学习了,希望出过完整的图纸分享。 应广大网友要求,用PROTEL99SE画了个板子,已经交给嘉立创打样了,过几天回来给大家发板子!
做实验嘛,没有用小的封装,板子做的比较大!
pdf原理图:
完整的PROTEL99SE工程文件:
这个不错,正需要。 向楼主学习 楼主你这个为什么咯噔咯噔地响,像是柴油机?{:shocked:} 51现在的片上外设其实也挺强大的。。。 能否做出高压的,比如直接220整流输出的310V驱动的
话说有没有这么样子的电机? 楼主威武 启动有点卡。整体还行吧 感谢lz,从lz的程序学到不少 楼主威武,超赞哦 学习 下 {:handshake:} {:tongue:} 感谢lz,从lz的程序学到不少 本帖最后由 CK345 于 2014-12-26 08:04 编辑
楼主有pcb空板吗 搭车同学习{:smile:} 不错啊,值得学习 本帖最后由 瑞生 于 2014-12-27 13:40 编辑
今天好不容易有空,试了一下板子,噪音是由于换相不正时引起的,待后续大家共同改进,下面发出电路板的源程序KEIL工程文件。
视频:http://player.youku.com/player.php/sid/XODU3OTE0MDQ0/v.swf
51也能做到这样的无刷,牛人, 感谢楼主!
早前拿到楼主代码,不错,可以启动,但是噪声大,后来我看了,是切换比较器的中断部分有点小问题,改了就比较好了。
比较器输入端我用了0.1uf电容,就更顺了,很稳定。
由于程序没有处理30度延时,所以0.1uf电容组成的RC刚好可以大约弥补高速时的30度延时。
控制改为了PPM脉冲,从P3.2输入,1.100ms~1.610ms为0~100%PWM。 另外,MOSFET建议换用SOP8封装的、低内阻的型号,否则大电流时,发热很大。
是呀
{:funk:} 换向有问题,速度上不去,电机没力。 把复杂的设计简单化就是高手。 这个相当不错啊 楼主是没有考虑PWM对比较器的影响吧……加0.1uf是可以滤除影响,但是对相位会有延时,且转速越高影响越大。到现在我还没找到去掉电容的方法,有些资料上说择多检测方式可行,也许可以试一下。有些大神早就把电容去掉了,就是不愿告知方法……{:mad:} 本帖最后由 瑞生 于 2015-1-13 10:49 编辑
Leon_yang 发表于 2015-1-12 15:00
楼主是没有考虑PWM对比较器的影响吧……加0.1uf是可以滤除影响,但是对相位会有延时,且转速越高影响越大。 ...
我买了个好盈无刷电调,电路和我的一样简单,没有用电容,一样运行非常好,一点噪音也没有。
我通过示波器观察,它也是输出3路PWM,另3路控制通断,并不是人们说的6路PWM比较好。 今天有空,又修改了两个程序的BUG,噪音没有了(看下面的视频),但是还是没有加30度换相的代码,以后有空再加
BUG1:STC15W408AS的ADC转换完毕,要重新开启转换才可以
BUG2:STC15W408AS的比较器滤波时钟最大是0x3f,以前没有注意
视频地址:http://v.youku.com/v_show/id_XODg0MDUwNzk2.html
最新的KEIL源代码:
本帖最后由 118139 于 2015-2-1 13:01 编辑
手头上也有几块用STC12C5204AD 外加比较器做的无刷电机驱动板,商品化的产品,
直流300V,电机可以大负载下频繁启停和运行,运行一般还可以。
背面用了集成了MOS管的,外加功率模块..
型号是
FSBB30CH60f
很不错,楼主高手!学习中。。。{:loveliness:} 请教下楼主,你做实验时,TC4427A烧毁的原因是什么?我现在也烧了好几个了,找不到原因 shishine 发表于 2015-2-4 21:20
请教下楼主,你做实验时,TC4427A烧毁的原因是什么?我现在也烧了好几个了,找不到原因 ...
这个片子很容易烧,我也烧了好几个,不过现在不烧了
以前都是程序不完善,造成P管和N管都导通,造成电流过大的时候烧的。 瑞生 发表于 2015-2-4 21:29
这个片子很容易烧,我也烧了好几个,不过现在不烧了
以前都是程序不完善,造成P管和N管都导通,造成电流 ...
我的程序应该说不可能使上下臂同时导通的,但这片子还是很容易烧。有点摸不着北了。。对了,楼主你的电调发热严重吗?我的电调高速运转时3对MOS有一对很烫,而其他两对没什么温度。。这是MOS问题还是程序问题啊? shishine 发表于 2015-2-4 21:34
我的程序应该说不可能使上下臂同时导通的,但这片子还是很容易烧。有点摸不着北了。。对了,楼主你的电调 ...
我也遇到过这个有一对烫的问题,后来发现是TC4427的问题,你把TC4427两个互换,就能看出来 这个都可以,牛人呀!学习一下 瑞生 发表于 2015-2-4 22:52
我也遇到过这个有一对烫的问题,后来发现是TC4427的问题,你把TC4427两个互换,就能看出来 ...
嗯 好的 谢了 搭车问一下,单管驱动的直流电机,没有传感器能否探测到电机转速? LS,比较困难。 您好,在论坛上看到你 《51单片机STC15W408AS做的无刷电调的这个帖子》,非常感兴趣;由于自己也正在学习这个,非常渴望能够自己测试下,所以想问下你的电路板还有么,能否送我几片做测试学习,卖给我也可以。期待你的回复。 学习学习! 这个片子 有几个定时器? MARK huangqi412 发表于 2015-3-1 20:26
这个片子 有几个定时器?
两个定时器,3路PCA用做 PWM,还有ADC 天使之翼 发表于 2015-3-1 19:55
您好,在论坛上看到你 《51单片机STC15W408AS做的无刷电调的这个帖子》,非常感兴趣;由于自己也正在学习 ...
不好意思,现在没有了{:handshake:} 这个不错,可以有{:lol:} 小李非刀 发表于 2015-3-2 09:11
两个定时器,3路PCA用做 PWM,还有ADC
还有定时器就能做延时三十度吧。 收藏学习,楼主碉堡了 mark,努力学习
{:lol:}楼主能否留个邮箱交流学习学习 上次看了吗没有学会,又来了 学习了,不错! 不错,做个记号 楼主你的程序怎么没有对续流状态过零点误检测的判断?以及PWM开关干扰下也会造成过零点误检测,这些你都没有遇到过吗? 记号,学习了 不错,先收下了。回再看。 学习了,正好需要这个东西
赞一个!值得鼓励,希望您做的更好,加油! 学习下{:lol:} 瑞生 发表于 2014-12-4 12:46
应广大网友要求,用PROTEL99SE画了个板子,已经交给嘉立创打样了,过几天回来给大家发板子!
做实验嘛,没 ...
楼主请问一下,这个检测换向的问题,因为PWM是由硬件产生的,那么是不是每当这个PWM从高到低或者从低到高的时候,都是需要换向一次呢?那如果这个PWM的频率达到100K了,占空比为50%时,那是不是相当于约5us就要进行换向一次呢?
谢谢指导一下 本帖最后由 知识阅览者 于 2015-11-22 11:46 编辑
哦,这个文件好像早就看到过了!而且在STC官网也有内容的!!!
更改一下,我确实也是在瑞生电子论坛看到的!!!没有看到楼主就是瑞生!!!! 知识阅览者 发表于 2015-11-21 12:38
哦,这个文件好像早就看到过了!而且在STC官网也有内容的!!!
请问一下,我在上一楼说的对吗? jaky80000 发表于 2015-11-22 11:21
请问一下,我在上一楼说的对吗?
不好意思,我只是看到这个知识点,没有去做实验!!! 谢谢 我也准备做一个 牛人啊, 新人慢慢学~ 楼主威武。 楼主,你连消磁事件都没有进行滤波还能转起来让我很诧异,而且你没有加rc滤波,噪声应该很多的,还能正常换相,是因为stc15的比较器输入内部带rc滤波吗? 我看了一下st15资料,原来内部有比较延时时钟设置,楼主你的效率怎么样,我的无负载还行,有负载就挂了 不是STC15W404AS吗? 楼主毕设中参考了你的无刷电机拓补电路,谢谢楼主 那个stc四轴的前端 原型机 研发么?{:lol:}{:victory:}
页:
[1]
2