找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3231|回复: 1
打印 上一主题 下一主题
收起左侧

单片机PID控制步进电机转动

[复制链接]
跳转到指定楼层
楼主
ID:385032 发表于 2018-8-10 16:16 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
1.  #include<reg52.h>
2.  #include"lcd1602.h"
3.   
4.  sfr T2MOD =0x0c9;
5.  #defineuchar unsigned char
6.  #define uintunsigned int
7.   
8.  sbit Q0 =P2^4;
9.  sbit Q1 =P2^5;
10. sbit Q2 =P2^6;
11. sbit Q3 =P2^7;
12.  
13. sbitGORB        = P1^6; //换相
14. sbit PWM =P1^7;
15. sbitUP        = P1^0;
16. sbitDOWM        = P1^1;
17. sbitADDSPEED = P1^2;
18. sbitSUBSPEED        = P1^3;
19.  
20. uint tuint =65535;
21. uint tpwm =1;        //pwm周期为10000us tpwm变量表示pwm高电平时间,也相当于占空比 (仿真时,频率高时,电机反应慢。在实物上要加大频率)
22. uchart1_flag = 0;
23.  
24. uint pulse =0;
25. uint t0_flag= 0;
26. uchart2_flag = 0;
27. bit t2_over= 0;
28. bit Just_Get= 1;
29.  
30.  
31. #define        ZZ                { Q0 = 0;Q1 = 0;Q2 = 1;Q3 = 1;}        //正转
32. #define        FZ                { Q0 = 1;Q1 = 1;Q2 = 0;Q3 = 0;}        //反转
33. #define        STOP        { Q0 = 1;Q1 = 0;Q2= 1;Q3 = 0;}        //停止
34. //禁止出现 Q0 = 0;Q1 = 1;Q2 = 0;Q3 = 1; 不然会烧掉mos管
35.  
36. //************************PID *************************************
37. float now =0,bef = 0,bbef = 0;         //本次采样值,上次采样值,上上次采样值
38. floaterr_now,err_bef,err_bbef;               //当前偏差,上次偏差,上上次偏差
39. floaterror_add = 0;                               //所有偏差之和
40. float set =25;                                              //设定值
41.  
42. float kp =25;
43. float ki =25;
44. float kd =0;
45.  
46. //*****************************************************************
47.  
48. voiddelayms(uint ms)//延时?个 ms
49. {
50.    uchar a,b,c;
51.        while(ms--)
52.        {
53.          for(c=1;c>0;c--)
54.        for(b=142;b>0;b--)
55.            for(a=2;a>0;a--);
56.        }
57. }
58.  
59. void timer_init()
60. {
61.        EA = 1;
62.        ET0 = 1;
63.        ET1 = 1;
64.        ET2 = 1;
65.        
66.        TMOD = 0x15; //定时器0 计数模式 定时器1模式1
67.        T2MOD = 0x01;
68.        
69.        TH0 = TL0 = 255;
70.        TH2 = 0x3C;
71.        TL2 = 0xB0;               //50MS
72.        
73. }
74. voidtimer1() interrupt 3
75. {
76.        if(t1_flag == 0)
77.        {
78.                t1_flag = 1;
79.                PWM = 1;
80.                TH1 = (tuint - tpwm + 1)/256;
81.                TL1 = (tuint - tpwm + 1)%256;
82.               
83.        }
84.        else
85.        {
86.                t1_flag = 0;
87.                PWM = 0;
88.                TH1 = (tuint - 10000 + tpwm +1)/256;
89.                TL1 = (tuint - 10000 + tpwm +1)%256;
90.        }
91. }
92.  
93. voidtimer0() interrupt 1
94. {
95.        TH0 = TL0 = 255;
96.        t0_flag++;
97. }
98. voidtimer2() interrupt 5
99. {
100.             TF2 = 0;
101.             TH2 = 0x3C;
102.             TL2 =0xB0;                //50MS
103.            
104.             t2_flag++;
105.            
106.             if(t2_flag ==2)
107.             {
108.                    TR0 = 0;
109.                    TR2 = 0;
110.                    t2_flag = 0;
111.                    t2_over = 1;        //表示100ms时间到
112.             }
113.     }
114.     void GetPulse()
115.     {
116.             t0_flag = 0;
117.             t2_flag = 0;
118.            
119.             TH0 = TL0 =255;
120.             TH2 = 0x3C;
121.             TL2 =0xB0;                //50MS
122.            
123.             TR0 = 1;
124.             TR2 = 1;
125.     }
126.      
127.     int PID()        //增量式PID
128.     {
129.             int change;
130.      
131.             err_now = set -now;
132.             err_bef = set -bef;
133.             err_bbef = set- bbef;
134.            
135.             change =kp*(err_now - err_bef) + ki*err_now + kd*(err_now - 2*err_bef + err_bbef);
136.            
137.     /*        
138.             if(set >=now)
139.             {      
140.                    if(set - now > 1)
141.                            change = kp*(err_now - err_bef) +ki*err_now + kd*(err_now - 2*err_bef + err_bbef);
142.                    else
143.                            change = 0.2*kp*(err_now - err_bef) +0.5*ki*err_now + kd*(err_now - 2*err_bef + err_bbef);
144.             }
145.             else if(now> set)
146.             {
147.                    if(now - set > 1)
148.                            change = kp*(err_now - err_bef) +ki*err_now + kd*(err_now - 2*err_bef + err_bbef);
149.                    else
150.                            change = 0.2*kp*(err_now - err_bef) +0.5*ki*err_now + kd*(err_now - 2*err_bef + err_bbef);
151.                           
152.             }
153.     */
154.            
155.             //change = (kp+ ki + kd)*(set - now) + (-kp - 2*kd)*(set - bef) + kd*(set - bbef);
156.             //change =kp*(set - now) + ki*(set - bef) + kd*(set - bbef);
157.             if(change >0)
158.             {
159.                    printchar(1,10,'+');        
160.                    printuint(1,11,4,change);
161.                    
162.             }
163.             else if(change< 0)
164.             {      
165.                    printchar(1,10,'-');
166.                    printuint(1,11,4,-change);
167.             }
168.             else if(change== 0)
169.             {      
170.                    printchar(1,10,' ');
171.                    printword(1,11," 0  ");
172.      
173.             }
174.            
175.             return(change);
176.     }
177.      
178.     int PID2()               //位置式PID
179.     {
180.            
181.             int num = 0;
182.             static num_bef= 0;
183.            
184.             err_now = set -now;
185.             err_bef = set -bef;
186.            
187.             error_add =error_add + err_now;  //误差累加。一旦误差为0则error_add的值不变,PID输出值不变
188.      
189.             num =kp*err_now + ki*error_add + kd*(err_now - err_bef);
190.            
191.     /*        
192.             if(set - now>= 0)
193.             {      
194.                    if(set - now > 1)
195.                            num = kp*err_now + ki*error_add +kd*(err_now - err_bef);
196.                    else
197.                            num = 0.1*kp*err_now + ki*error_add +kd*(err_now - err_bef);
198.             }
199.             else
200.             {
201.                    if(now - set > 1)
202.                            num = kp*err_now + ki*error_add +kd*(err_now - err_bef);
203.                    else
204.                            num = 0.1*kp*err_now + ki*error_add +kd*(err_now - err_bef);
205.                           
206.             }
207.             */
208.            
209.             if(num >num_bef)
210.             {
211.                    printchar(1,10,'+');        
212.                    printuint(1,11,4,num - num_bef);
213.             }
214.             else if(num< num_bef)
215.             {
216.                    printchar(1,10,'-');        
217.                    printuint(1,11,4,num_bef - num);
218.             }
219.             else
220.             {      
221.                    printchar(1,10,' ');
222.                    printuint(1,11,4,0);
223.             }
224.            
225.             num_bef = num;
226.            
227.            return((uint)num);
228.     }
229.      
230.     void main()
231.     {        
232.            
233.             lcd_init();//初始化LCD
234.             timer_init();//初始化Timer
235.             TH1 = TL1 =255;
236.            
237.            printword(0,0,"P:");               //比例系数
238.            printword(0,5,"S:");               //设定值
239.            printword(1,0,"TPWM:");               //当前占空比
240.            printword(0,10,"PS:");               //当前电机反馈的每秒脉冲数
241.            
242.             while(1)
243.             {
244.                    if(GORB == 1)
245.                    {        ZZ;               }
246.                    else
247.                    {        FZ;               }
248.                    
249.                    if(ADDSPEED == 0)
250.                            set++;
251.                    if(SUBSPEED == 0)
252.                            set--;
253.                    
254.                    if(Just_Get == 1)
255.                    {        
256.                            Just_Get = 0;
257.                            GetPulse();
258.                    }
259.                    else if(t2_over == 1)
260.                    {        
261.                            t2_over = 0;
262.                            Just_Get = 1;
263.                            pulse = t0_flag;
264.                            bbef = bef;
265.                            bef = now;
266.                            now = t0_flag;
267.                           
268.                            if(set != 0)
269.                            {
270.                                    TR1 = 1;
271.                            }
272.                            else
273.                            {
274.                                    TR1 = 0;
275.                                    PWM = 0;
276.                            }
277.                           
278.                    //        tpwm = tpwm + PID();               //增量式PID
279.                            tpwm = PID2();                              //位置式PID
280.                                          
281.                    }
282.                    
283.                    if(UP == 0)
284.                            kp = kp + 1;
285.                    if(DOWM == 0)
286.                            kp = kp - 1;
287.                    
288.                    printuint(0,2,3,kp);
289.                    printuint(0,7,3,set);
290.                    printuint(1,5,4,tpwm);
291.                    printuint(0,13,5,pulse);
292.      
293.             }
294.            
295.     }
296.            

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:342294 发表于 2018-8-23 09:39 | 只看该作者
printuint(0,2,3,kp);这个函数哪里来的   为什么没有看到你的函数声明而且这个函数你只是调用  但是这个函数在哪里   你给我找出来    感觉你这是胡编乱遭的吧
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表