在这里,和大家分享一下我用单片机做的一个直流电机控制系统。这是我在计算机学院的一个实训中做出来的,当时我是机械学院的,对嵌入式很感兴趣,就跨专业选了这个实训(教务网允许)。初衷嘛,我是想实现一个四旋翼飞行器,若能很好的控制4个高速电机的转速,就可以使飞行器飘起来。为此,我使用3D打印技术,制作了一个四旋翼的机架,将四个电机分别安装到4个翅膀上。下面就开始实施我的计划了!!(下面有成果图)
实现的效果是:电机的转速分为7个等级,对于4个电机,可以使用旋钮使整体调速,也可以用遥杆单独调速(在旋钮整体调速的基础上),并在显示屏上显示转速等级。
目录
1.课题简介 1
2.风扇控制系统的总体设计 1
3.电路设计 1
3.1 LED1602液晶显示屏电路图 1
3.2 旋钮的控制电路 2
3.3摇杆的控制电路 2
3.4显示模块:LCD1602液晶显示屏 2
4.程序设计 4
4.1单片机1主函数的流程图 4
4.2单片机1子函数1流程图 5
4.3单片机1子函数2流程图 6
4.4单片机2主函数设计 6
4.5单片机2 pwm中断程序设计 7
5 系统测试 8
5.1测试的原理 8
5.2测试的过程 8
6.附录 10
附录A:实物照片 10
附录B:源代码 10
7.总结 22
8.感谢 22
9. 参考文献 22
1.课题简介
随着时代的发展,科技的进步,微电子技术也在不断的发展。单片机的应用也越来越贴近生活,用单片机来实现一些电子设计也变得很容易。直流电机的控制在生产生活中很常见,本次设计是用单片机来控制简单的直流电机系统,通过控制模块来调节单片机的转速。
2.风扇控制系统的总体设计
3.电路设计
3.1 LED1602液晶显示屏电路图
(此处略,网上有各种资料)
3.2 旋钮的控制电路
介绍:旋钮模块一共有五个引脚,其中两根为电源和接地引脚。SW引脚的作用是旋钮按下去时,给单片机低电平的信号。另外两个引脚CLK与DT相互作用,来表示旋钮的正反转,当两个引脚的信号变化为11——01——00——10时,表示顺时针旋转。当两个引脚的信号变化为11—–10—–00—–01时,表示逆时针旋转。单片机检测整个模块传来的电信号,进行数据处理。
3.3摇杆的控制电路
摇杆模块一共有五个引脚,其中两根为电源和接地,SW引脚判断摇杆是否按下,VRx与VRy引脚是用来表示x方向与y方向的位移大小。在单片机系统设计中,其实是用数模转换模块PCF8591,通过I2C总线传输的方式进行数据传输,并在串口调试助手中一直检测x方向和y方向的电阻值变化
4.程序设计(这里本来有许多图,还不会用这个博客,图片弄不上去。。。。)
5 系统测试
5.1测试的原理
整个系统一共有两个控制模块,旋钮和摇杆,当旋钮顺时针旋转时,电机的转速逐渐升高,在LCD显示屏中显示电机的转速级别,逆时针旋转时,电机转速逐渐降低,直至为0.当按下旋钮时,电机的转速直接跳转为0。摇杆的作用是分别控制四个电机的转速,摇杆的方向分别为上,下,左,右时,对应的控制电机序号分别为一,二,三,四。按下旋钮,各个电机的转速增量变为0。同时,摇杆和旋钮可以共同作用,一起控制电动机的转速。
5.2测试的过程
(1)旋钮和摇杆的控制
6.附录
附录A:实物照片
附录B:源代码
单片机1源代码
#include
#include "lcd.h"
#define uchar unsigned char
#define PCF8591 0x90
unsigned char AD_CHANNEL;
unsigned long xdata LedOut[8];
unsigned char D[32];
sbit aPin=P1^0;
sbit bPin=P1^1;
sbit press=P1^2;
sbit P2_0 = P2^0;
sbit P2_1 = P2^1;
sbit p22 = P2^2;//
sbit p23 = P2^3;//
sbit p24 = P2^4;//
sbit p12 = P1^2;
sbit p13 = P1^3;//
sbit p14 = P1^4;//
sbit p15 = P1^5;//
sbit p16 = P1^6;
sbit p17 = P1^7;
unsigned char peng[]="0123456789";
unsigned char date;
unsigned int num;
unsigned int suv;
int a;
unsigned char count;
//unsigned char jd=8;
//sbit pwm0=P2^2;
//sbit pwm1=P2^3;
//sbit pwm2=P2^4;
//sbit pwm3=P2^3;
sbit jia=P3^2;
sbit jian=P3^3;
unsigned char jd;
//
int scan();
void display(int m);
void delay(int i);
bit DACconversion(unsigned char sla,unsigned char c, unsigned char Val);
bit ISendByte(unsigned char sla,unsigned char c);
unsigned char IRcvByte(unsigned char sla);
void Initial_com(void);
void xuanniu_process();
void yaogan_process();
void xuanniu_process()//
{
a=a+scan();
if(a<0) a=0;
if(a>7) a=7;
display(a);
jd=a;
if(p12==0) a=0;
switch (jd)
{
case 0:p24=0;p23=0;p22=0;break;
case 1:p24=0;p23=0;p22=1;break;
case 2:p24=0;p23=1;p22=0;break;
case 3:p24=0;p23=1;p22=1;break;
case 4:p24=1;p23=0;p22=0;break;
case 5:p24=1;p23=0;p22=1;break;
case 6:p24=1;p23=1;p22=0;break;
case 7:p24=1;p23=1;p22=1;break;
}
}
void yaogan_process()//
{
switch(AD_CHANNEL)
{
case 0: ISendByte(PCF8591,0x41);
D[0]=IRcvByte(PCF8591); //
break;
case 1: ISendByte(PCF8591,0x42);
D[1]=IRcvByte(PCF8591); //
break;
case 2: ISendByte(PCF8591,0x43);
D[2]=IRcvByte(PCF8591); //
break;
case 3: ISendByte(PCF8591,0x40);
D[3]=IRcvByte(PCF8591); //ADC3
break;
case 4: DACconversion(PCF8591,0x40, D[4]); //
break;
}
D[4]=D[3]; //
if(++AD_CHANNEL>4) AD_CHANNEL=0;
delay(200);
delay(200);
SBUF=D[0];
delay(200);
SBUF=D[3];
delay(200);
if (D[0]<=130) num=0;//80
else if (D[0]>130&&D[0]<136) num=1;
else if (D[0]>=136) num=2;
if (D[3]<=110) suv=0;//80
else if (D[3]>110&&D[0]<=134) suv=1;
else if (D[3]>134) suv=2; //i have try a lot,but it seems that
if(num==0&&suv==1) {p15=0;p14=0;p13=0;} //right
if(num==2&&suv==1) {p15=0;p14=1;p13=0;}//left
if(num==1&&suv==0) {p15=0;p14=1;p13=1;}//up
if(num==1&&suv==2) {p15=1;p14=0;p13=1;}//down
if(num==1&&suv==1) {p15=0;p14=0;p13=1;}//center
if(RI)
{
date=SBUF; //
SBUF=date; //
RI=0;
}
}
int scan()
{
static int oldA=0;
static int oldB=0;
int result =0;
int newA =aPin,newB=bPin;
if(oldA!=newA||oldB!=newB)//something has changed
{
/*if (oldA==0&&oldB==0)
{
if (newA==1) result=1;
else result =-1;
}
else if (oldA==1&&oldB==1)
{
if (newA==1) result=-1;
else result =1;
if (oldA==0&&newA==1)
result = -(oldB * 2 - 1);
//else result=0;
}
oldA=newA;
oldB=newB;
return result;
}
void display(int m)
{
LcdWriteCom(0x80);
LcdWriteData(peng[m]);
}
main()
{
a=0;
count=0;
//Time0_Init();
LcdInit();
Initial_com();
while(1)
{
xuanniu_process();//
yaogan_process();//
//unsigned int num1;
}
}
void delay(int i)
{
uchar j,k;
for(j=i;j>0;j--)
for(k=125;k>0;k--);
}
bit DACconversion(unsigned char sla,unsigned char c, unsigned char Val)
{
Start_I2c(); //Æô¶¯×ÜÏß
SendByte(sla); //•¢ËÍÆ÷¼þµØÖ•
if(ack==0)return(0);
SendByte(c); //•¢ËÍ¿ØÖÆ×Ö½Ú
if(ack==0)return(0);
SendByte(Val); //•¢ËÍDACµÄÊýÖµ
if(ack==0)return(0);
Stop_I2c(); //½áÊø×ÜÏß
return(1);
}
bit ISendByte(unsigned char sla,unsigned char c)
{
Start_I2c(); //
SendByte(sla); //
if(ack==0)return(0); //
SendByte(c); //
if(ack==0)return(0);
Stop_I2c(); //
return(1);
}
unsigned char IRcvByte(unsigned char sla)
{ unsigned char c;
Start_I2c(); //
SendByte(sla+1); //
if(ack==0)return(0);//
c=RcvByte(); //
Ack_I2c(1); //
Stop_I2c(); //
return(c);
}
void Initial_com(void)
{
EA|=1; //
ES|=1; //
ET1|=1; //
TMOD|=0x20; //
PCON|=0x00; //SMOD=0
SCON|=0x50; //
TH1=0xfd; //
TL1=0xfd;
TR1=1; //
}
单片机2代码
#include
unsigned char count;
sbit pwm0=P0^0;
sbit pwm1=P0^1;
sbit pwm2=P0^2;
sbit pwm3=P0^3;//ÓÃÀ´¿ØÖƵç»úµÄËĸöÒý½Å
sbit p07=P0^7;
sbit p25=P2^5;
sbit p26=P2^6;
sbit p27=P2^7;
sbit jia=P3^2;
sbit jian=P3^3;
sbit p10=P1^0;
sbit p22 = P2^2;
sbit p23 = P2^3;
sbit p24 = P2^4;
sbit p13 = P0^4;
sbit p14 = P0^5;
sbit p15 = P0^6;
sbit p16 = P1^6;
sbit p17 = P1^7;
sbit p30=P3^0;
sbit p31=P3^1;
unsigned char wu[]=" I Love You! ";
unsigned char peng[]="000045090135180";
unsigned char jd;
unsigned char jd0;
unsigned char jd1;
unsigned char jd2;
unsigned char jd3;
int DisplayData[4]={0,1,2,3};
void Time0_Init()
{
TMOD=0x01;
IE=0x82;//
TH0=0xfe;
TL0=0x33;
TR0=1;
}
void Time0_Int()interrupt 1
{
TH0=0xfe;
TL0=0x33;
if(count1;
else
pwm0=0;
if(count1;
else
pwm1=0;
if(count1;
else
pwm2=0;
if(count1;
else
pwm3=0;
count=(count+1);
count=count%7;
}
/keyscan//
void bottomscan()
{
if(p10==0)
{
jd0=0;jd1=0;jd2=0;jd3=0;
}
}
void keyscan()
{
int a,b,c;
a=p22;b=p23;c=p24;
jd=(a*1+b*2+c*4);
}
/handle/
void handlescan()
{ int m=0;
static int old0=0,old1=0,old2=0;
int new0,new1,new2;
int jd00=0,jd11=0,jd22=0,jd33=0;//everytime it become zero
new0=p13;new1=p14;new2=p15;
//jd0=jd;jd1=jd;jd2=jd;jd3=jd;
if(old0!=new0||old1!=new1||old2!=new2)//something has changed
{
if(p15==0&&p14==0&&p13==0) m=0;
if(p15==0&&p14==0&&p13==1) m=1;
if(p15==0&&p14==1&&p13==0) m=2;
if(p15==0&&p14==1&&p13==1) m=3;
if(p15==1&&p14==0&&p13==0) m=4;
if(p15==1&&p14==0&&p13==1) m=5;
if(p15==1&&p14==1&&p13==0) m=6;
if(p15==1&&p14==1&&p13==1) m=7;
switch (m)
{
case 0:{jd00=1;break;}
case 1:break;
case 2:{jd22=1;break;}
case 3:{jd11=1;break;}
case 4:break;
case 5:{jd33=1;break;}
}
}
old0=new0;old1=new1;old2=new2;
jd0+=jd00;jd1+=jd11;jd2+=jd22;jd3+=jd33;
}
void main()
{
jd=0;
count=0;
Time0_Init();
p16=0;p17=0;p30=0;p31=0;
while(1)
{bottomscan();
handlescan();
keyscan();
}
}
`
7.总结
本次风扇系统的设计实现了对电机单独控制和集体控制的效果。实际上在工程中或车间里,经常会应用到各式各样的电机,为了满足生产生活的要求,需要对电机进行实时的控制,而我正是模拟了这样的控制。
由于风扇的扇叶是使用的飞行器的机翼,在转速较高的情况下,可产生较高的升力。原本希望在旋翼在转动时可以带动机体,可是由于自身重力等原因,飞不起来,可是任然能产生较大的升力。
在实时操控的模块中,摇杆的信号是通过串口的数据检测并判断的,所以有较小的延时,不能达到真正的实时控制。如果做进一步的改进的话,用中断的控制方法更为快速。