找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 10388|回復: 10
打印 上一主題 下一主題
收起左側(cè)

基于單片機和NRF24L01的無線PID電機轉(zhuǎn)速控制器設計

  [復制鏈接]
跳轉(zhuǎn)到指定樓層
#
ID:205648 發(fā)表于 2017-6-19 17:25 | 只看該作者 |只看大圖 回帖獎勵 |正序瀏覽 |閱讀模式
基于NRF24L01的PID電機轉(zhuǎn)速控制器,采用51單片機控制,有發(fā)送端和接收端的完整圖紙和程序代碼
下面是已經(jīng)制作成功的實物圖:


原理圖:


項目介紹
在過程控制中,按偏差的比例(P)、積分(I)和微分(D)進行控制的PID控制器(亦稱PID調(diào)節(jié)器)是應用最為廣泛的一種自動控制器。它具有原理簡單,易于實現(xiàn),適用面廣,控制參數(shù)相互獨立,參數(shù)的選定比較簡單等優(yōu)點;而且在理論上可以證明,對于過程控制的典型對象──“一階滯后+純滯后二階滯后+純滯后的控制對象,PID控制器是一種最優(yōu)控制。PID調(diào)節(jié)規(guī)律是連續(xù)系統(tǒng)動態(tài)品質(zhì)校正的一種有效方法,它的參數(shù)整定方式簡便,結(jié)構改變靈活(PIPD、PID)。
然而PID算法在工業(yè)發(fā)展中也占據(jù)不小的地位,例如,液位,壓力,溫度,流量的控制都能利用PID算法進行精準控制。本項目將PID的算法用在了直流電機的控制當中,用于精準控制電機轉(zhuǎn)速,簡化電機控制難度。為了使操作者能夠簡單,方便,實時,快捷的控制電機的轉(zhuǎn)速,我又在此基礎上加上了無線模塊,使得操作者能夠更加簡單的操作本產(chǎn)品,操作者只需簡單改變主控板的設定值,接收機即可將電機轉(zhuǎn)速控制在設定值以內(nèi),誤差范圍控制在正負20r/s(轉(zhuǎn)/秒)。
一、   功能設計要點
1.        控制核心:接收和發(fā)射核心控制部分均采用STC12C5A60S2單片機進行控制
2.        顯示部分:接收機顯示采用普通的12864液晶顯示,發(fā)射部分為了減小其體積采用OLED液晶,功耗低,體積小,顯示效果好
3.        電機驅(qū)動部分:采用的是L298N電機驅(qū)動模塊,價格低,抗干擾能力強,安全性高,可靠性強,大大提高了電機的效率。
4.        速度檢測部分:采用44E開關型霍爾傳感器,成本低,電路簡單,可與單片機IO口直接連接,操作方便。
5.        無線數(shù)據(jù)傳輸采用NRF24L01無線模塊,工作在 2.4~2.5GHz 世界通用 ISM 頻段,工作電流只有 10.5mA, 接收時工作電流只有 18mA, 多種低功率工作模式, 功耗低。
6.        核心控制算法PID:此電路采用的是PID算法里的增量式算法,
file:///Z:\TEMP\msohtmlclip1\01\clip_image002.jpg
pid.voltage=pid.Kp*pid.err+pid.Ki*pid.integral+pid.Kd*(pid.err-pid.err_last);
增量式算法不需做累加, 計算誤差和計算精度問題對控制量的計算影響較小;


四、系統(tǒng)工作原理方框圖




單片機源程序如下(無線接收部分):
  1. #include <STC12C5A60S2.H>
  2. #include <intrins.h>
  3. #include"delay.h"
  4. #include"12864.h"
  5. #include "nrf24l01.h"
  6. #include"mian.h"
  7. #include "keyscan.h"
  8. #include"display.h"
  9. #include"display1.h"
  10. uchar code tab11[]="0123456789:";
  11. uchar RX_BUF[TX_PLOAD_WIDTH];
  12. uchar TX_BUF[TX_PLOAD_WIDTH];
  13. uchar flag;                   //讀取接收數(shù)據(jù)完成標志位
  14. uchar temp,fuck;
  15. uchar str[4];//存儲轉(zhuǎn)換的字符串
  16. int speed_change;
  17. sbit  pulse=P1^7 ;        //從此引腳輸出脈沖信號
  18. bit g_bPIDRunFlag = 0;
  19. uchar bdata sta;
  20. sbit  RX_DR         = sta^6; //接收數(shù)據(jù)中斷
  21. sbit  TX_DS         = sta^5; //數(shù)據(jù)發(fā)送完成中斷
  22. sbit  MAX_RT = sta^4; //達到最多次重發(fā)中斷
  23. //sbit led=P1^6;
  24. /**************************************************
  25. 函數(shù):Check_ACK()

  26. 描述:
  27.     檢查接收設備有無接收到數(shù)據(jù)包,設定沒有收到應答信
  28.         號是否重發(fā)
  29. /**************************************************/
  30. uchar Check_ACK(bit clear)
  31. {   
  32.         while(IRQ);                                                          //等待應答
  33.         sta = SPI_RW(NOP);                    // 返回狀態(tài)寄存器
  34.         if(MAX_RT)                                                          //如果達到最大重發(fā)次數(shù)
  35.                 if(clear)                         // 是否清除TX FIFO,沒有清除在復位MAX_RT中斷標志后重發(fā)
  36.                 SPI_RW(FLUSH_TX);                          //清除TX FIFO
  37.         SPI_RW_Reg(WRITE_REG + STATUS, sta);  // 清除TX_DS或MAX_RT中斷標志
  38.         IRQ = 1;                                                          //中斷復位
  39.         if(TX_DS)                                                          //發(fā)送完成中斷
  40.                 return(0x00);
  41.         else
  42.                 return(0xff);
  43. }

  44. /****pid***/
  45. struct _pid{
  46.     double SetSpeed;           //定義設定值
  47.     double ActualSpeed;        //定義實際值
  48.     double err;                //定義偏差值
  49.     double err_last;            //定義上一個偏差值
  50.         double err_second;            //定義上一個偏差值
  51.     double Kp,Ki,Kd;            //定義比例、積分、微分系數(shù)
  52.     double voltage;          //定義電壓值(控制執(zhí)行器的變量)
  53.     double integral;            //定義積分值
  54. }pid;


  55. void PID_init(){

  56.     pid.SetSpeed=0;                           //定義設定值
  57.     pid.ActualSpeed=0;                    //定義實際值
  58.     pid.err=0;                                            //定義偏差值
  59.     pid.err_last=0;                                  //定義上一個偏差值
  60.     pid.voltage=0;                                  //定義電壓值(控制執(zhí)行器的變量)
  61.     pid.integral=0;                                          //定義積分值
  62.     pid.Kp=0.4956;                          //                  定義比例
  63.     pid.Ki=0.000197;                  //                   積分
  64.     pid.Kd=0.0004;                          //                    微分系數(shù)
  65.   //  printf("PID_init end \n");
  66. }

  67. float PID_realize(double speed)
  68. {
  69.     pid.SetSpeed=speed;         //實際值=每分鐘電機轉(zhuǎn)速
  70.     pid.err=pid.SetSpeed-pid.ActualSpeed;  //轉(zhuǎn)速偏差=設定值-實際值
  71.     pid.integral+=pid.err;
  72.     pid.voltage=pid.Kp*pid.err+pid.Ki*pid.integral+pid.Kd*(pid.err-pid.err_last);
  73. //        pid.voltage=pid.Kp*pid.err+(0.05/pid.Ki)*pid.integral+(pid.Kd/0.05)*(pid.err-pid.err_last);
  74.     pid.err_last=pid.err;
  75.     pid.ActualSpeed=pid.voltage*1;
  76.     return pid.ActualSpeed;
  77. }

  78. void init_timer(void)
  79. {        
  80.         
  81.         TMOD = 0x01;                //設置定時器模式
  82.         TL0 = 0x00;                //設置定時初值
  83.         TH0 = 0x28;                //設置定時初值

  84.     TR0=1;                 //啟動定時器1
  85.     ET0=1;                 //Timer1中斷禁止
  86.     IT0=1;                 //下降沿觸發(fā)方式
  87.     EX0=1;                 //外部INT0中斷允許
  88.     EA=1;                  //開全局中斷
  89. }


  90. void main()
  91. {        pulse=1;
  92.     lcd_init();
  93.         display();
  94.         delay_50_ms(50);
  95.         lcd_init();
  96.         PWM_init ();
  97.         init_timer() ;
  98.     PID_init();
  99.         NRF24L01_init();
  100.         RX_Mode();
  101. display_init();
  102. // DS1302_Init();
  103.         while(1)//循環(huán)
  104.         {         

  105.             
  106.                 sta = SPI_Read(STATUS);          // 讀狀態(tài)寄存器
  107.                 temp=sta;   
  108.                 temp=(temp>>1)&0x07;  
  109.             if(RX_DR)                                  // 判斷是否接受到數(shù)據(jù)
  110.                 {
  111.                         SPI_Read_Buf(RD_RX_PLOAD, RX_BUF, TX_PLOAD_WIDTH);  // 從RX FIFO讀出數(shù)據(jù)
  112.                         flag = 1;
  113.                 }
  114.                 SPI_RW_Reg(WRITE_REG + STATUS, sta);  // 清除RX_DS中斷標志
  115.                   if(flag)                           // 接受完成
  116.                 {
  117.                         flag = 0;                                                                                                                  
  118.                          sheding=RX_BUF[0]*10+RX_BUF[1];
  119. //                                xianshi(0x92,tab11[RX_BUF[0]/10],tab11[RX_BUF[0]%10]);
  120. //                                xianshi(0x94,tab11[RX_BUF[1]/10],tab11[RX_BUF[1]%10]);
  121. //                                xianshi(0x96,tab11[0],tab11[1]);  xianshi(0x97,tab11[2],tab11[3]);
  122.        }
  123.              if(g_bPIDRunFlag)        //PID調(diào)節(jié)
  124.                              {
  125.                                    g_bPIDRunFlag=0;
  126. //                                   pulse=0;
  127.                                    pid.ActualSpeed=zhuansu;          // pid.ActualSpeed-實際值  speed_c-每分鐘電機轉(zhuǎn)速
  128.                                    speed_change=PID_realize(sheding);//pid.ActualSpeed  rad_set
  129.                            //  printf("%f\n",speed);
  130.                         //          if(speed_change<0)
  131.                         //          speed_change=speed_change*(-1);
  132.                                   pwm_1=255-PID_realize(sheding);
  133.                              if(pwm_1>255)
  134.                                           {
  135.                                             pwm_1=254;
  136.                                                           PWM0_set(pwm_1); //設置PWM占空比
  137.                                           }
  138.                                           if(pwm_1<0)
  139.                                           {
  140.                                              pwm_1=0;                                                                                                                        
  141.                                                 PWM0_set(pwm_1);    //設置PWM占空比
  142.                                              }
  143.                                         PWM0_set(pwm_1);
  144. //                                         pulse=1;
  145.                              }
  146.                                  display2();
  147.                                  keyscan();
  148.     }   
  149. }         
  150. void INIT0(void) interrupt 0
  151. {
  152.          x1++;
  153.    
  154. }
  155. void timer1(void) interrupt 1
  156. {
  157.          static uchar a = 0;
  158.            TL0 = 0x00;                //設置定時初值
  159.            TH0 = 0x28;                //設置定時初值5MS
  160. //                   TL0 = 0x00;                //設置定時初值
  161. //        TH0 = 0x04;                //設置定時初值
  162. ……………………

  163. …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼

所有資料51hei提供下載:
第二屆單片機大賽作品.zip (6.87 MB, 下載次數(shù): 154)




評分

參與人數(shù) 1黑幣 +100 收起 理由
admin + 100 共享資料的黑幣獎勵!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏5 分享淘帖 頂 踩
回復

使用道具 舉報

10#
ID:701252 發(fā)表于 2020-10-17 09:37 | 只看該作者

學習了!謝謝樓主分享,正想學習pid調(diào)節(jié)呢!
回復

使用道具 舉報

9#
ID:89217 發(fā)表于 2020-4-11 22:44 | 只看該作者
學習了。感謝分享
回復

使用道具 舉報

8#
ID:110278 發(fā)表于 2020-4-7 14:16 | 只看該作者
資料挺全的,感謝分享。
回復

使用道具 舉報

7#
ID:715082 發(fā)表于 2020-4-5 13:43 | 只看該作者
c03131401 發(fā)表于 2017-6-21 09:17
樓主為什么打開后都是問題!
NRF24L01.C(71): error C202: 'CSN': undefined identifier
NRF24L01.C(77): ...

您好,可能引腳定義丟失了,我也有問題,請問您有在軟件里找到3144霍爾P32引腳的定義嗎?萬望回復,謝謝您
回復

使用道具 舉報

6#
ID:330988 發(fā)表于 2018-5-16 14:02 | 只看該作者
很好  可以學習一下
回復

使用道具 舉報

5#
ID:288865 發(fā)表于 2018-4-22 15:05 | 只看該作者
正在學習謝謝
回復

使用道具 舉報

地板
ID:312760 發(fā)表于 2018-4-20 22:44 | 只看該作者
好東西,正好學習pid調(diào)節(jié)
回復

使用道具 舉報

板凳
ID:249545 發(fā)表于 2017-11-24 17:12 | 只看該作者
好文,好文,真不錯!
回復

使用道具 舉報

沙發(fā)
ID:163950 發(fā)表于 2017-6-21 09:17 | 只看該作者
樓主為什么打開后都是問題!
NRF24L01.C(71): error C202: 'CSN': undefined identifier
NRF24L01.C(77): error C202: 'CE': undefined identifier
NRF24L01.C(102): error C202: 'CE': undefined identifier
NRF24L01.C(156): error C202: 'CE': undefined identifier
NRF24L01.C(166): error C202: 'CE': undefined identifier
NRF24L01.C(172): error C202: 'CE': undefined identifier
NRF24L01.C(173): error C202: 'CSN': undefined identifier
NRF24L01.C(174): error C202: 'SCK': undefined identifier
NRF24L01.C(175): error C202: 'IRQ': undefined identifier
Target not created
回復

使用道具 舉報

樓主
ID:1 發(fā)表于 2017-6-19 22:13 | 只看該作者
好資料,51黑有你更精彩!!!
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復 返回頂部 返回列表