基于NRF24L01的PID電機轉速控制器,采用51單片機控制,有發送端和接收端的完整圖紙和程序代碼
下面是已經制作成功的實物圖:
QQ圖片20170619172417.jpg (255.76 KB, 下載次數: 150)
下載附件
2017-6-19 17:24 上傳
QQ圖片20170619172407.jpg (344.37 KB, 下載次數: 157)
下載附件
2017-6-19 17:24 上傳
原理圖:
0.png (73.31 KB, 下載次數: 155)
下載附件
2017-6-19 22:05 上傳
項目介紹
在過程控制中,按偏差的比例(P)、積分(I)和微分(D)進行控制的PID控制器(亦稱PID調節器)是應用最為廣泛的一種自動控制器。它具有原理簡單,易于實現,適用面廣,控制參數相互獨立,參數的選定比較簡單等優點;而且在理論上可以證明,對于過程控制的典型對象──“一階滯后+純滯后”與“二階滯后+純滯后”的控制對象,PID控制器是一種最優控制。PID調節規律是連續系統動態品質校正的一種有效方法,它的參數整定方式簡便,結構改變靈活(PI、PD、PID)。
然而PID算法在工業發展中也占據不小的地位,例如,液位,壓力,溫度,流量的控制都能利用PID算法進行精準控制。本項目將PID的算法用在了直流電機的控制當中,用于精準控制電機轉速,簡化電機控制難度。為了使操作者能夠簡單,方便,實時,快捷的控制電機的轉速,我又在此基礎上加上了無線模塊,使得操作者能夠更加簡單的操作本產品,操作者只需簡單改變主控板的設定值,接收機即可將電機轉速控制在設定值以內,誤差范圍控制在正負20r/s(轉/秒)。
一、 功能設計要點
1. 控制核心:接收和發射核心控制部分均采用STC12C5A60S2單片機進行控制 2. 顯示部分:接收機顯示采用普通的12864液晶顯示,發射部分為了減小其體積采用OLED液晶,功耗低,體積小,顯示效果好 3. 電機驅動部分:采用的是L298N電機驅動模塊,價格低,抗干擾能力強,安全性高,可靠性強,大大提高了電機的效率。 4. 速度檢測部分:采用44E開關型霍爾傳感器,成本低,電路簡單,可與單片機IO口直接連接,操作方便。 5. 無線數據傳輸采用NRF24L01無線模塊,工作在 2.4~2.5GHz 世界通用 ISM 頻段,工作電流只有 10.5mA, 接收時工作電流只有 18mA, 多種低功率工作模式, 功耗低。 6. 核心控制算法PID:此電路采用的是PID算法里的增量式算法, file:///Z:\TEMP\msohtmlclip1\01\clip_image002.jpg
0.png (13.73 KB, 下載次數: 139)
下載附件
2017-6-19 22:09 上傳
pid.voltage=pid.Kp*pid.err+pid.Ki*pid.integral+pid.Kd*(pid.err-pid.err_last);
增量式算法不需做累加, 計算誤差和計算精度問題對控制量的計算影響較;
四、系統工作原理方框圖
0.png (11.6 KB, 下載次數: 119)
下載附件
2017-6-19 22:07 上傳
0.png (49.19 KB, 下載次數: 163)
下載附件
2017-6-19 22:06 上傳
單片機源程序如下(無線接收部分):
- #include <STC12C5A60S2.H>
- #include <intrins.h>
- #include"delay.h"
- #include"12864.h"
- #include "nrf24l01.h"
- #include"mian.h"
- #include "keyscan.h"
- #include"display.h"
- #include"display1.h"
- uchar code tab11[]="0123456789:";
- uchar RX_BUF[TX_PLOAD_WIDTH];
- uchar TX_BUF[TX_PLOAD_WIDTH];
- uchar flag; //讀取接收數據完成標志位
- uchar temp,fuck;
- uchar str[4];//存儲轉換的字符串
- int speed_change;
- sbit pulse=P1^7 ; //從此引腳輸出脈沖信號
- bit g_bPIDRunFlag = 0;
- uchar bdata sta;
- sbit RX_DR = sta^6; //接收數據中斷
- sbit TX_DS = sta^5; //數據發送完成中斷
- sbit MAX_RT = sta^4; //達到最多次重發中斷
- //sbit led=P1^6;
- /**************************************************
- 函數:Check_ACK()
- 描述:
- 檢查接收設備有無接收到數據包,設定沒有收到應答信
- 號是否重發
- /**************************************************/
- uchar Check_ACK(bit clear)
- {
- while(IRQ); //等待應答
- sta = SPI_RW(NOP); // 返回狀態寄存器
- if(MAX_RT) //如果達到最大重發次數
- if(clear) // 是否清除TX FIFO,沒有清除在復位MAX_RT中斷標志后重發
- SPI_RW(FLUSH_TX); //清除TX FIFO
- SPI_RW_Reg(WRITE_REG + STATUS, sta); // 清除TX_DS或MAX_RT中斷標志
- IRQ = 1; //中斷復位
- if(TX_DS) //發送完成中斷
- return(0x00);
- else
- return(0xff);
- }
- /****pid***/
- struct _pid{
- double SetSpeed; //定義設定值
- double ActualSpeed; //定義實際值
- double err; //定義偏差值
- double err_last; //定義上一個偏差值
- double err_second; //定義上一個偏差值
- double Kp,Ki,Kd; //定義比例、積分、微分系數
- double voltage; //定義電壓值(控制執行器的變量)
- double integral; //定義積分值
- }pid;
- void PID_init(){
- pid.SetSpeed=0; //定義設定值
- pid.ActualSpeed=0; //定義實際值
- pid.err=0; //定義偏差值
- pid.err_last=0; //定義上一個偏差值
- pid.voltage=0; //定義電壓值(控制執行器的變量)
- pid.integral=0; //定義積分值
- pid.Kp=0.4956; // 定義比例
- pid.Ki=0.000197; // 積分
- pid.Kd=0.0004; // 微分系數
- // printf("PID_init end \n");
- }
- float PID_realize(double speed)
- {
- pid.SetSpeed=speed; //實際值=每分鐘電機轉速
- pid.err=pid.SetSpeed-pid.ActualSpeed; //轉速偏差=設定值-實際值
- pid.integral+=pid.err;
- pid.voltage=pid.Kp*pid.err+pid.Ki*pid.integral+pid.Kd*(pid.err-pid.err_last);
- // pid.voltage=pid.Kp*pid.err+(0.05/pid.Ki)*pid.integral+(pid.Kd/0.05)*(pid.err-pid.err_last);
- pid.err_last=pid.err;
- pid.ActualSpeed=pid.voltage*1;
- return pid.ActualSpeed;
- }
- void init_timer(void)
- {
-
- TMOD = 0x01; //設置定時器模式
- TL0 = 0x00; //設置定時初值
- TH0 = 0x28; //設置定時初值
- TR0=1; //啟動定時器1
- ET0=1; //Timer1中斷禁止
- IT0=1; //下降沿觸發方式
- EX0=1; //外部INT0中斷允許
- EA=1; //開全局中斷
- }
- void main()
- { pulse=1;
- lcd_init();
- display();
- delay_50_ms(50);
- lcd_init();
- PWM_init ();
- init_timer() ;
- PID_init();
- NRF24L01_init();
- RX_Mode();
- display_init();
- // DS1302_Init();
- while(1)//循環
- {
-
- sta = SPI_Read(STATUS); // 讀狀態寄存器
- temp=sta;
- temp=(temp>>1)&0x07;
- if(RX_DR) // 判斷是否接受到數據
- {
- SPI_Read_Buf(RD_RX_PLOAD, RX_BUF, TX_PLOAD_WIDTH); // 從RX FIFO讀出數據
- flag = 1;
- }
- SPI_RW_Reg(WRITE_REG + STATUS, sta); // 清除RX_DS中斷標志
- if(flag) // 接受完成
- {
- flag = 0;
- sheding=RX_BUF[0]*10+RX_BUF[1];
- // xianshi(0x92,tab11[RX_BUF[0]/10],tab11[RX_BUF[0]%10]);
- // xianshi(0x94,tab11[RX_BUF[1]/10],tab11[RX_BUF[1]%10]);
- // xianshi(0x96,tab11[0],tab11[1]); xianshi(0x97,tab11[2],tab11[3]);
- }
- if(g_bPIDRunFlag) //PID調節
- {
- g_bPIDRunFlag=0;
- // pulse=0;
- pid.ActualSpeed=zhuansu; // pid.ActualSpeed-實際值 speed_c-每分鐘電機轉速
- speed_change=PID_realize(sheding);//pid.ActualSpeed rad_set
- // printf("%f\n",speed);
- // if(speed_change<0)
- // speed_change=speed_change*(-1);
- pwm_1=255-PID_realize(sheding);
- if(pwm_1>255)
- {
- pwm_1=254;
- PWM0_set(pwm_1); //設置PWM占空比
- }
- if(pwm_1<0)
- {
- pwm_1=0;
- PWM0_set(pwm_1); //設置PWM占空比
- }
- PWM0_set(pwm_1);
- // pulse=1;
- }
- display2();
- keyscan();
- }
- }
- void INIT0(void) interrupt 0
- {
- x1++;
-
- }
- void timer1(void) interrupt 1
- {
- static uchar a = 0;
- TL0 = 0x00; //設置定時初值
- TH0 = 0x28; //設置定時初值5MS
- // TL0 = 0x00; //設置定時初值
- // TH0 = 0x04; //設置定時初值
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
所有資料51hei提供下載:
第二屆單片機大賽作品.zip
(6.87 MB, 下載次數: 154)
2017-6-19 17:18 上傳
點擊文件名下載附件
基于STC12C5A60S2的PID電機轉速控制器 下載積分: 黑幣 -5
|