久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 4245|回復(fù): 1
打印 上一主題 下一主題
收起左側(cè)

江湖救急 如何將pid算法 寫入單片機中

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:183114 發(fā)表于 2017-3-24 17:06 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
  老師要求 機械臂中要加入智能算法 ,可是我完全是外行 ,請問 如何將pid 模糊算法加入單片機中
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏1 分享淘帖 頂 踩
回復(fù)

使用道具 舉報

沙發(fā)
ID:155507 發(fā)表于 2017-3-24 19:46 | 只看該作者

  1. //一個典型的PID處理程序,包含了最常用的PID算法的基本架構(gòu),沒有包含輸入輸出處理部分。適合新手了解PID結(jié)構(gòu),入門學(xué)習(xí)用。

  2. /*
  3. 注意:
  4. 使用不同的MCU的時候,需要進(jìn)行相應(yīng)的簡化和改寫。而且由于單片機的處理速度和ram資源的限制,一般不采用浮點數(shù)運算。而將所有參數(shù)全部用整數(shù),運算到最后再除以一個2的N次方數(shù)據(jù)(相當(dāng)于移位),作類似定點數(shù)運算。這樣可大大提高運算速度,根據(jù)控制精度的不同要求,當(dāng)精度要求很高時,注意保留移位引起的“余數(shù)”,做好余數(shù)補償就好了。
  5. */

  6. #include<reg51.h>
  7. #include<intrins.h>
  8. #include<math.h>
  9. #include<string.h>

  10. struct PID {
  11.         unsigned int SetPoint; // 設(shè)定目標(biāo) Desired Value
  12.         unsigned int Proportion; // 比例常數(shù) Proportional Const
  13.         unsigned int Integral; // 積分常數(shù) Integral Const
  14.         unsigned int Derivative; // 微分常數(shù) Derivative Const
  15.         unsigned int LastError; // Error[-1]
  16.         unsigned int PrevError; // Error[-2]
  17.         unsigned int SumError; // Sums of Errors
  18. };
  19. struct PID spid; // PID Control Structure
  20. unsigned int rout; // PID Response (Output)
  21. unsigned int rin; // PID Feedback (Input)
  22. sbit data1=P1^0;
  23. sbit clk=P1^1;
  24. sbit plus=P2^0;
  25. sbit subs=P2^1;
  26. sbit stop=P2^2;
  27. sbit output=P3^4;
  28. sbit DQ=P3^3;
  29. unsigned char flag,flag_1=0;
  30. unsigned char high_time,low_time,count=0;//占空比調(diào)節(jié)參數(shù)
  31. unsigned char set_temper=35;
  32. unsigned char temper;
  33. unsigned char i;
  34. unsigned char j=0;
  35. unsigned int s;
  36. /***********************************************************
  37.                 延時子程序,延時時間以12M晶振為準(zhǔn),延時時間為30us×time
  38.                 ***********************************************************/
  39. void delay(unsigned char time)
  40. {
  41.         unsigned char m,n;
  42.         for(n=0;n<time;n++)
  43.         for(m=0;m<2;m++){}
  44. }
  45. /***********************************************************
  46.                 寫一位數(shù)據(jù)子程序
  47.                 ***********************************************************/
  48. void write_bit(unsigned char bitval)
  49. {
  50.         EA=0;
  51.         DQ=0; /*拉低DQ以開始一個寫時序*/
  52.         if(bitval==1)
  53.         {
  54.                 _nop_();
  55.                 DQ=1; /*如要寫1,則將總線置高*/
  56.         }
  57.         delay(5); /*延時90us供DA18B20采樣*/
  58.         DQ=1; /*釋放DQ總線*/
  59.         _nop_();
  60.         _nop_();
  61.         EA=1;
  62. }
  63. /***********************************************************
  64.                 寫一字節(jié)數(shù)據(jù)子程序
  65. ***********************************************************/
  66. void write_byte(unsigned char val)
  67. {
  68.         unsigned char i;
  69.         unsigned char temp;
  70.         EA=0;
  71.         TR0=0;
  72.         for(i=0;i<8;i++) /*寫一字節(jié)數(shù)據(jù),一次寫一位*/
  73.         {
  74.                 temp=val>>i; /*移位操作,將本次要寫的位移到最低位*/
  75.                 temp=temp&1;
  76.                 write_bit(temp); /*向總線寫該位*/
  77.         }
  78.         delay(7); /*延時120us后*/
  79.         // TR0=1;
  80.         EA=1;
  81. }
  82. /***********************************************************
  83.                 讀一位數(shù)據(jù)子程序
  84. ***********************************************************/
  85. unsigned char read_bit()
  86. {
  87.         unsigned char i,value_bit;
  88.         EA=0;
  89.         DQ=0; /*拉低DQ,開始讀時序*/
  90.         _nop_();
  91.         _nop_();
  92.         DQ=1; /*釋放總線*/
  93.         for(i=0;i<2;i++){}
  94.         value_bit=DQ;
  95.         EA=1;
  96.         return(value_bit);
  97. }
  98. /***********************************************************
  99.                 讀一字節(jié)數(shù)據(jù)子程序
  100. ***********************************************************/
  101. unsigned char read_byte()
  102. {
  103.         unsigned char i,value=0;
  104.         EA=0;
  105.         for(i=0;i<8;i++)
  106.         {
  107.                 if(read_bit()) /*讀一字節(jié)數(shù)據(jù),一個時序中讀一次,并作移位處理*/
  108.                 value|=0x01<<i;
  109.                 delay(4); /*延時80us以完成此次都時序,之后再讀下一數(shù)據(jù)*/
  110.         }
  111.         EA=1;
  112.         return(value);
  113. }
  114. /***********************************************************
  115.                 復(fù)位子程序
  116. ***********************************************************/
  117. unsigned char reset()
  118. {
  119.         unsigned char presence;
  120.         EA=0;
  121.         DQ=0; /*拉低DQ總線開始復(fù)位*/
  122.         delay(30); /*保持低電平480us*/
  123.         DQ=1; /*釋放總線*/
  124.         delay(3);
  125.         presence=DQ; /*獲取應(yīng)答信號*/
  126.         delay(28); /*延時以完成整個時序*/
  127.         EA=1;
  128.         return(presence); /*返回應(yīng)答信號,有芯片應(yīng)答返回0,無芯片則返回1*/
  129. }
  130. /***********************************************************
  131.                 獲取溫度子程序
  132. ***********************************************************/
  133. void get_temper()
  134. {
  135.         unsigned char i,j;
  136.         do
  137.         {
  138.                 i=reset(); /*復(fù)位*/
  139.         }  while(i!=0); /*1為無反饋信號*/
  140.         i=0xcc; /*發(fā)送設(shè)備定位命令*/
  141.         write_byte(i);
  142.         i=0x44; /*發(fā)送開始轉(zhuǎn)換命令*/
  143.         write_byte(i);
  144.         delay(180); /*延時*/
  145.         do
  146.         {
  147.                 i=reset(); /*復(fù)位*/
  148.         }  while(i!=0);
  149.         i=0xcc; /*設(shè)備定位*/
  150.         write_byte(i);
  151.         i=0xbe; /*讀出緩沖區(qū)內(nèi)容*/
  152.         write_byte(i);
  153.         j=read_byte();   
  154.         i=read_byte();
  155.         i=(i<<4)&0x7f;
  156.         s=(unsigned int)(j&0x0f);            //得到小數(shù)部分
  157.         s=(s*100)/16;
  158.         j=j>>4;
  159.         temper=i|j; /*獲取的溫度放在temper中*/
  160. }
  161. /*====================================================================================================
  162.                 Initialize PID Structure

  163. =====================================================================================================*/
  164. void PIDInit (struct PID *pp)
  165. {
  166.         memset ( pp,0,sizeof(struct PID));           //全部初始化為0
  167. }
  168. /*====================================================================================================
  169.                 PID計算部分

  170. =====================================================================================================*/
  171. unsigned int PIDCalc( struct PID *pp, unsigned int NextPoint )
  172. {
  173.         unsigned int dError,Error;
  174.         Error = pp->SetPoint - NextPoint;          // 偏差           
  175.         pp->SumError += Error;                     // 積分                                   
  176.         dError = pp->LastError - pp->PrevError;    // 當(dāng)前微分  
  177.         pp->PrevError = pp->LastError;                           
  178.         pp->LastError = Error;                                       
  179.         return (pp->Proportion * Error             // 比例項           
  180.         + pp->Integral * pp->SumError              // 積分項
  181.         + pp->Derivative * dError);                // 微分項
  182. }
  183. /***********************************************************
  184.                 溫度比較處理子程序
  185. ***********************************************************/
  186. void compare_temper()
  187. {
  188.         unsigned char i;
  189.         if(set_temper>temper)      //是否設(shè)置的溫度大于實際溫度
  190.         {
  191.                 if(set_temper-temper>1)         //設(shè)置的溫度比實際的溫度是否是大于1度
  192.                 {
  193.                         high_time=100;                     //如果是,則全速加熱
  194.                         low_time=0;
  195.                 }
  196.                 else                                         //如果是在1度范圍內(nèi),則運行PID計算
  197.                 {
  198.                         for(i=0;i<10;i++)
  199.                         {
  200.                                 get_temper();                          //獲取溫度
  201.                                 rin = s; // Read Input
  202.                                 rout = PIDCalc ( &spid,rin ); // Perform PID Interation
  203.                         }
  204.                         if (high_time<=100)
  205.                         high_time=(unsigned char)(rout/800);
  206.                         else
  207.                         high_time=100;
  208.                         low_time= (100-high_time);
  209.                 }
  210.         }
  211.         else if(set_temper<=temper)
  212.         {
  213.                 if(temper-set_temper>0)
  214.                 {
  215.                         high_time=0;
  216.                         low_time=100;
  217.                 }
  218.                 else
  219.                 {
  220.                         for(i=0;i<10;i++)
  221.                         {
  222.                                 get_temper();
  223.                                 rin = s; // Read Input
  224.                                 rout = PIDCalc ( &spid,rin ); // Perform PID Interation
  225.                         }
  226.                         if (high_time<100)
  227.                         high_time=(unsigned char)(rout/10000);
  228.                         else
  229.                         high_time=0;
  230.                         low_time= (100-high_time);
  231.                 }
  232.         }
  233.         // else
  234.         // {}
  235. }
  236. /*****************************************************
  237.                 T0中斷服務(wù)子程序,用于控制電平的翻轉(zhuǎn) ,40us*100=4ms周期
  238. ******************************************************/
  239. void serve_T0() interrupt 1 using 1
  240. {
  241.         if(++count<=(high_time))
  242.         output=1;
  243.         else if(count<=100)
  244.         {
  245.                 output=0;
  246.         }
  247.         else
  248.         count=0;
  249.         TH0=0x2f;
  250.         TL0=0xe0;
  251. }
  252. /*****************************************************
  253.                 串行口中斷服務(wù)程序,用于上位機通訊
  254. ******************************************************/
  255. void serve_sio() interrupt 4 using 2
  256. {
  257.         /* EA=0;
  258.                 RI=0;
  259.                 i=SBUF;
  260.                 if(i==2)
  261.                 {
  262.                 while(RI==0){}
  263.                 RI=0;
  264.                 set_temper=SBUF;
  265.                 SBUF=0x02;
  266.                 while(TI==0){}
  267.                 TI=0;
  268.                 }
  269.                 else if(i==3)
  270.                 {
  271.                 TI=0;
  272.                 SBUF=temper;
  273.                 while(TI==0){}
  274.                 TI=0;
  275.                 }
  276.                 EA=1; */
  277. }
  278. void disp_1(unsigned char disp_num1[6])
  279. {
  280.         unsigned char n,a,m;
  281.         for(n=0;n<6;n++)
  282.         {
  283.                 // k=disp_num1[n];
  284.                 for(a=0;a<8;a++)
  285.                 {
  286.                         clk=0;
  287.                         m=(disp_num1[n]&1);
  288.                         disp_num1[n]=disp_num1[n]>>1;
  289.                         if(m==1)
  290.                         data1=1;
  291.                         else
  292.                         data1=0;
  293.                         _nop_();
  294.                         clk=1;
  295.                         _nop_();
  296.                 }
  297.         }
  298. }
  299. /*****************************************************
  300.                 顯示子程序
  301.                 功能:將占空比溫度轉(zhuǎn)化為單個字符,顯示占空比和測得到的溫度
  302. ******************************************************/
  303. void display()
  304. {
  305.         unsigned char code number[]={0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,0xf6};
  306.         unsigned char disp_num[6];
  307.         unsigned int k,k1;
  308.         k=high_time;
  309.         k=k%1000;
  310.         k1=k/100;
  311.         if(k1==0)
  312.         disp_num[0]=0;
  313.         else
  314.         disp_num[0]=0x60;
  315.         k=k%100;
  316.         disp_num[1]=number[k/10];
  317.         disp_num[2]=number[k%10];
  318.         k=temper;
  319.         k=k%100;
  320.         disp_num[3]=number[k/10];
  321.         disp_num[4]=number[k%10]+1;
  322.         disp_num[5]=number[s/10];
  323.         disp_1(disp_num);
  324. }
  325. /***********************************************************
  326.                 主程序
  327. ***********************************************************/
  328. void main()
  329. {
  330.         unsigned char z;
  331.         unsigned char a,b,flag_2=1,count1=0;
  332.         unsigned char phil[]={2,0xce,0x6e,0x60,0x1c,2};
  333.         TMOD=0x21;
  334.         TH0=0x2f;
  335.         TL0=0x40;
  336.         SCON=0x50;
  337.         PCON=0x00;
  338.         TH1=0xfd;
  339.         TL1=0xfd;
  340.         PS=1;
  341.         EA=1;
  342.         EX1=0;
  343.         ET0=1;
  344.         ES=1;
  345.         TR0=1;
  346.         TR1=1;
  347.         high_time=50;
  348.         low_time=50;
  349.         PIDInit ( &spid );    // Initialize Structure
  350.         spid.Proportion = 10; // Set PID Coefficients  比例常數(shù) Proportional Const
  351.         spid.Integral = 8;    //積分常數(shù) Integral Const
  352.         spid.Derivative =6;   //微分常數(shù) Derivative Const
  353.         spid.SetPoint = 100; // Set PID Setpoint 設(shè)定目標(biāo) Desired Value
  354.         while(1)
  355.         {
  356.                 if(plus==0)
  357.                 {
  358.                         EA=0;
  359.                         for(a=0;a<5;a++)
  360.                         for(b=0;b<102;b++){}
  361.                         if(plus==0)
  362.                         {
  363.                                 set_temper++;
  364.                                 flag=0;
  365.                         }
  366.                 }
  367.                 else if(subs==0)
  368.                 {
  369.                         for(a=0;a<5;a++)
  370.                         for(b=0;a<102;b++){}
  371.                         if(subs==0)
  372.                         {
  373.                                 set_temper--;
  374.                                 flag=0;
  375.                         }
  376.                 }
  377.                 else if(stop==0)
  378.                 {
  379.                         for(a=0;a<5;a++)
  380.                         for(b=0;b<102;b++){}
  381.                         if(stop==0)
  382.                         {
  383.                                 flag=0;
  384.                                 break;
  385.                         }
  386.                         EA=1;
  387.                 }
  388.                 get_temper();
  389.                 b=temper;
  390.                 if(flag_2==1)
  391.                 a=b;
  392.                 if((abs(a-b))>5)
  393.                 temper=a;
  394.                 else
  395.                 temper=b;
  396.                 a=temper;
  397.                 flag_2=0;
  398.                 if(++count1>30)
  399.                 {
  400.                         display();
  401.                         count1=0;
  402.                 }
  403.                 compare_temper();
  404.         }
  405.         TR0=0;
  406.         z=1;
  407.         while(1)
  408.         {
  409.                 EA=0;
  410.                 if(stop==0)
  411.                 {
  412.                         for(a=0;a<5;a++)
  413.                         for(b=0;b<102;b++){}
  414.                         if(stop==0)
  415.                         disp_1(phil);
  416.                         // break;
  417.                 }
  418.                 EA=1;
  419.         }
  420. }

復(fù)制代碼
回復(fù)

使用道具 舉報

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

本版積分規(guī)則

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

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

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 日韩国产中文字幕 | 天天想天天干 | 羞羞视频在线观看免费观看 | 国产成人精品一区二区三区在线 | 亚洲一区二区在线视频 | 不卡一二区 | 免费在线观看成人av | 欧美日韩视频在线 | 久久三区| 成人亚洲一区 | 羞羞视频免费在线 | 国产伦精品一区二区三区照片91 | 妞干网视频 | 九色91视频 | 久久国产精品久久久久 | 欧美性jizz18性欧美 | 性做久久久久久免费观看欧美 | 九九久久这里只有精品 | 青久草视频 | 一区二区三区不卡视频 | 日韩美女在线看免费观看 | 嫩草影院黄 | 久久精品亚洲欧美日韩精品中文字幕 | 四虎影音| 国产午夜精品一区二区三区四区 | 在线色网| 日本久久久一区二区三区 | 久久亚洲二区 | 97视频久久 | 久久99精品久久久久久秒播九色 | 精品国产伦一区二区三区观看说明 | 亚洲欧美综合精品久久成人 | 成人片免费看 | 亚洲欧洲一区 | 久久精品国产亚洲 | 国产黄色在线 | 在线视频 亚洲 | 免费在线成人网 | 国产综合久久 | 麻豆视频在线免费观看 | 国产精品成人一区二区三区夜夜夜 |