用智能控制的算法實現的,三角形隸屬函數,輸入為污泥度和油脂度,輸出為電動機的轉動時間,程序都有詳細標注
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
捕獲.PNG (116.79 KB, 下載次數: 46)
下載附件
2019-1-23 18:31 上傳
捕獲1.PNG (99.85 KB, 下載次數: 54)
下載附件
2019-1-23 18:31 上傳
單片機源程序如下:
- /**********
- 論域e ec u 規則r
- e[e_length] e_length 5+1 //第一個輸入變量表的長度
- ec[ec_length] ec_length 5+1 //第二個輸入變量表的長度
- u[]
- r[r_Line_width][r_Column_width] r_Line_width 5 //規則表的行
- r_Column_width 5//規則表的列
- //等級表自動生成的
- unsigned char e_level[e_length-1]={0};
- unsigned char ec_level[ec_length]={0};
- unsigned char u_level[u_level_length]={0};
- unsigned char x;//第一個電壓的等級
- unsigned char y;//第二個電壓的等級
- unsigned char z;//輸出等級
- *************/
- #include <REG52.H>//頭文件
- #include "TLC2543.h"
- #define uchar unsigned char//宏定義
- #define uint unsigned int
- /*******************************數碼表****************************/
- unsigned char code Tab[11]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; //數碼管顯示0~9的段碼表
- /************修改長度區****************************/
- //論域的長度
- #define e_length 5+1 //e的長度
- #define ec_length 5+1 //第二個輸入變量表的長度
- #define u_length 5
- //規則表的行列
- #define r_Line_width 5 //規則表的行
- #define r_Column_width 5//規則表的列
- /*************論域表****************************/
- // 0 1 2 3 4
- double code e[e_length] ={0, 0.7, 2.0, 3.0, 4.2, 5};//5個范圍6個數代表實際輸入電壓
- double code ec[ec_length]={0, 0.7, 2.0, 3.0, 4.2, 5};//5個范圍6個數
- unsigned char code u[u_length]={28,34,40,46,52};
- /*************論域等級表****************************/
- unsigned char e_level[e_length-1]={0};//等級表自動生成的
- unsigned char ec_level[ec_length-1]={0};
- unsigned char u_level[u_length]={0};
- /*****************規則表**************************/
- unsigned char r[r_Line_width][r_Column_width]= //規則表(里面的數據代表的輸出等級)
- {
- 1,1,2,3,4,
- 1,2,3,4,5,
- 2,3,3,4,5,
- 3,4,4,5,5,
- 4,5,5,5,5
- };
- //兩個輸入和一個輸出得等級
- unsigned char x;//第一個電壓的等級
- unsigned char y;//第二個電壓的等級
- unsigned char z;//輸出等級
- //兩個真實的電壓
- double e_u;
- double ec_u;
- unsigned char u_t;//電動機轉動時間
- //tlc2543讀取的兩個電壓
- uint ad_value1=0;
- uint ad_value2=0;
- unsigned char int_time; //記錄中斷次數
- unsigned char second; //儲存秒
- unsigned char second1; //儲存秒
- uint t=0,tt=0;
- uint t1=0,tt1=0;
- //按鍵定義
- sbit k_start=P0^7;
- sbit k_stop=P0^6;
- sbit k3=P0^2;
- sbit sg=P0^3;
- sbit Upper_leve=P0^4;//上液位
- sbit Lower_level=P0^5;//下液位
- sbit ledon=P0^7;
- sbit washing_led=P2^0;//洗滌燈
- sbit drying_led=P2^1;//甩干燈
- sbit in_led=P2^5;//進水燈
- sbit out_led=P2^6;//排水燈
- sbit p30=P3^0;
- sbit p31=P3^1;
- sbit beepon=P2^7;//蜂鳴器
- sbit sm1=P3^6;//進水閥門
- sbit sm2=P3^7;//出水閥門
- void DisplaySecond(unsigned char k);
- unsigned char rule_process(double e_local[e_length] ,double ec_local[ec_length],unsigned char r_local[r_Line_width][r_Column_width])
- {
- //將兩個輸入的論域分為等級存在兩個表中分別為01234....
- uchar i=0;
- uchar j=0;
- uchar t;
- //等級i分為01234
- for(i=0;i<e_length-1;i++)//循環01234
- {
- e_level[i]=i; //存進去表01234
- if ( (e_local[i]<e_u) && (e_u<=e_local[i+1]) ) //e電壓大于第0個數小于第一個數
- x=i; // x等級為0
- }
-
- //等級j分為01234
- for(j=0;j<ec_length-1;j++)
- {
- ec_level[j]=j;
- if ( (ec_local[j]<ec_u) && (ec_u<=ec_local[j+1]) ) //ec電壓大于第0個數小于第一個數
- y=j; // y等級為0
- }
- z=r_local[x][y];//確定輸出z的等級(查找規則)等級輸出為12345
- t=u[z-1];//輸出電動機轉動的時間//等級輸出01234所對應的時間
- return t;
- }
- //延時函數
- void delay2(void)
- {
- unsigned char m;
- for(m=0;m<200;m++);
- }
- void delay1(int s)
- {
- int i;
- for(;s>0;s--)
- for(i=0;i<65;i++);
- }
-
- void delay(uint i)
- {
- uchar j;
- for(i;i>0;i--)
- for(j=255;j>0;j--);
- }
- //顯示函數
- void DisplaySecond(unsigned char k)
- {
-
- sm1=0; //P2.6引腳輸出低電平, DS6點亮
- P1=Tab[k/10]; //顯示十位
- delay2();
- delay2();
- sm1=1;
- sm2=0; //P2.7引腳輸出低電平, DS7點亮
- P1=Tab[k%10]; //顯示個位
- delay2();
- delay2();
- P3=0xff; //關閉所有數碼管
- P1=1; //顯示個位
- delay2();
- delay2();
- }
- //響蜂鳴器程序
- void beep()
- {
- p30=0;
- p31=0;
- t=0;
- while(1)
- {
- beepon^=1;
- delay(300);
- if(t>=80) break;
- }
- beepon=0;
- }
-
- void Washing(uint Washing_time_sec)
- {
- t=0;
- tt=0;
- int_time=0;
- second=Washing_time_sec;
- //洗滌的時間
- while(1)
- {
- //每20代表真實的一秒
- if(tt>=Washing_time_sec*20) break; //洗滌時間總共是Washing_time_sec秒 時間到了退出循環
- t=0;
- //正轉2s
- while(t<40&&tt<=Washing_time_sec*20)
- {
- p31=0;
- p30=1; //正轉 2s
- DisplaySecond(second);
- }
- t=0;
- //反轉 2s
- while(t<40&&tt<=400)
- {
- p30=0;
- p31=1;
- DisplaySecond(second);
- }
- }
- //停止轉動
- p30=0;
- p31=0;
- }
- void out_water()
- {
- p30=0;
- p31=0;
- out_led=1; //排水閥燈亮 等待霍爾開關2
- while(Lower_level);
- if(Lower_level==0) //如果閉合
- out_led=0; //排水燈滅
- }
- void in_water()
- {
- p30=0;
- p31=0;
- in_led=1;//進水燈亮起
- while(Upper_leve);//等待
- if(Upper_leve==0)//進水完畢
- in_led=0;//進水燈關閉
- }
- void drying(uint Drying_time)
- {
- t=0;
- int_time=0;
- DisplaySecond(0);
- second=Drying_time;
- while(t<=Drying_time*20)
- {
- p31=0;
- p30=1;
- if(second>=0)
- DisplaySecond(second);
- }
- }
- void work()
- {
- //甩干占4s 兩次占8s 兩次進出水共計6s 所以兩次洗滌 (u_t-14)/2
- in_water(); //等待進水完畢才往下走
- Washing((u_t-14)/2); //洗滌10S
- out_water(); //洗滌結束開始排水//等待排水排干再繼續往下走
- drying(4); //甩干4s
- in_water(); //進水開始等待進水結束
- Washing((u_t-14)/2); //漂洗10S
- out_water(); //漂洗結束開始排水//等待排水排干再繼續往下走
- drying(4);
- beep();
- }
- void Read_voltage()
- {
- // e_u=3; //輸入電壓
- // ec_u=4; //輸入電壓
- // u_t=rule_process(e,ec,r);//輸入參數為e ec 和r
- //真實得到電壓小數 第一個電壓
- //小數兩位b=(uint)(e_u*1000)%1000/10
- //整數一位a=(uint)(e_u*1000)/1000
- ad_value1=(read2543(0)*5000.0)/4095;//第一通道//輸出電壓是一個4位整數
- e_u=ad_value1/1000.0;
- ad_value2=(read2543(1)*5000.0)/4095;//第二通道//輸出電壓是一個4位整數
- ec_u=ad_value2/1000.0; //第二個電壓
- }
- int main(void)
- {
- TMOD=0x01; //方式1 16位計數器
- TH0=-50000/256; //設定初值
- TL0=-50000%256;
- EA=1; //開總中斷
- ET0=1; //開定時器0中斷
- TR0=1; //啟動定時器0
- P2=0;
- int_time=0; //中斷次數初始化
- second=00; //秒初始化
- while(1)
- {
- if(k_start==0)
- {
- while(1)
- {
- Read_voltage(); //將兩個的電壓讀入到e_u ec_u
- u_t=rule_process(e,ec,r); //輸入參數為e ec 和r
- work();
- }
-
- }
-
-
- // DisplaySecond(u_t); //顯示出應該輸出的電機轉動的時間
- }
- return 0;
- }
- void time0() interrupt 1 using 1
- {
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
所有資料51hei提供下載:
程序加仿真洗衣機版本五.rar
(161.4 KB, 下載次數: 150)
2019-1-23 18:31 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|