极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 12065|回复: 6

求助,求助自平衡小车的问题

[复制链接]
发表于 2015-4-18 22:49:36 | 显示全部楼层 |阅读模式
  1. #include <PID_v1.h>
  2. /*陀螺仪使用的定义变量*/
  3. unsigned char Re_buf[11],counter=0;
  4. unsigned char sign=0;
  5. /*电机使用定义的变量*/
  6. int motor_a1=4;
  7. int motor_a2=5;
  8. int motor_b1=6;
  9. int motor_b2=7;
  10. int ena=10;
  11. int enb=11;
  12. /*定义PID库使用的参数*/
  13. double Setpoint, Input, Output;
  14. double kp,ki,kd;

  15. /*定义PID程序*/
  16. PID myPID(&Input, &Output, &Setpoint,kp,ki,kd, DIRECT);
  17. /*初始化*/
  18. void setup() {
  19.   Serial.begin(115200); //初始化串口速率
  20.   /*配置电机针脚为输出*/
  21.   pinMode(motor_a1,OUTPUT);
  22.   pinMode(motor_a2,OUTPUT);
  23.   pinMode(motor_b1,OUTPUT);
  24.   pinMode(motor_b2,OUTPUT);
  25.   myPID.SetMode(AUTOMATIC); //配置PID为自动模式
  26.   myPID.SetSampleTime(100); //配置PID采样率为100毫秒
  27.   Setpoint = -1; //设置小车平衡点角度
  28. }
  29. /*主函数*/
  30. void loop() {
  31.   if (sign==0)
  32.     return; //sign为数据更新标志,每隔10ms更新一次,也就是说以下代码每隔10ms控制一次
  33.   sign=0;
  34.   //  getkpkikd(&kp,&ki,&kd); //获取kp,ki,kd的值
  35.   kp=(double)analogRead(0)/1024*200;
  36.   ki=(double)analogRead(1)/10240;
  37.   kd=(double)analogRead(2)/1024*400;

  38.   myPID.Compute(); //PID运算
  39.   SetMotor(Output); //控制电机
  40. //  cout2serial() ; //串口输出需要查看的数据
  41.   Serial.print("angle:");
  42.   Serial.print(Input);Serial.print(" ");
  43.   Serial.print("output:");
  44.   Serial.print(Output);Serial.print(" ");
  45.   Serial.print("kp:");
  46.   Serial.print(kp);Serial.print(" ");
  47.   Serial.print("ki:");
  48.   Serial.print(ki);Serial.print(" ");
  49.   Serial.print("kd:");
  50.   Serial.print(kd);Serial.println(" ");
  51. }

  52. /*获取kp,ki,kd的值的函数*/
  53. /*void getkpkikd(&kp,&ki,&kd){
  54.   kp=(double)analogRead(0)/1024*200;
  55.   ki=(double)analogRead(1)/10240;
  56.   kd=(double)analogRead(2)/1024*400;
  57. }*/

  58. /*控制电机运行的函数*/
  59. void SetMotor(float Output)
  60. {
  61. if (Output>=0){
  62.   pinMode(motor_a1,HIGH);
  63.   pinMode(motor_a2,LOW);
  64.   pinMode(motor_b1,HIGH);
  65.   pinMode(motor_b2,LOW);
  66.   analogWrite(ena,Output);
  67.   analogWrite(enb,Output);
  68.   }
  69. else if (Output<0) {
  70.   pinMode(motor_a1,LOW);
  71.   pinMode(motor_a2,HIGH);
  72.   pinMode(motor_b1,LOW);
  73.   pinMode(motor_b2,HIGH);
  74.   analogWrite(ena,abs(Output));
  75.   analogWrite(enb,abs(Output));
  76.   }
  77. }

  78. /*输出串口数据的函数*/
  79. /*void cout2serial() {
  80.   Serial.print("angle:");
  81.   Serial.print(Input);Serial.print(" ");
  82.   Serial.print("output:");
  83.   Serial.print(Output);Serial.print(" ");
  84.   Serial.print("kp:");
  85.   Serial.print(kp);Serial.print(" ");
  86.   Serial.print("ki:");
  87.   Serial.print(ki);Serial.print(" ");
  88.   Serial.print("kd:");
  89.   Serial.print(kd);Serial.println(" ");
  90. }*/

  91. void serialEvent()
  92. {
  93.   while (Serial.available()) {
  94.     Re_buf[counter]=(unsigned char)Serial.read();
  95.     if(counter==0&&Re_buf[0]!=0x55) return; //第0号数据不是帧头
  96.       counter++;
  97.     if(counter==11) //接收到11个数据
  98.     {
  99.       counter=0; //重新赋值,准备下一帧数据的接收
  100.       switch(Re_buf [1])
  101.       {
  102.         case 0x51:
  103.         break;
  104.         case 0x52:
  105.         break;
  106.         case 0x53:
  107.         Input= double(short(Re_buf [3]<<8| Re_buf [2]))/32768*180;
  108.         sign=1;
  109.         break;
  110.       }
  111.     }
  112.   }
  113. }
复制代码
不知道为什么Output 为零
回复

使用道具 举报

 楼主| 发表于 2015-4-18 22:52:50 | 显示全部楼层
本帖最后由 immortal 于 2015-4-18 23:16 编辑

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-4-18 23:19:38 | 显示全部楼层
  1. /**********************************************************************************************
  2. * Arduino PID Library - Version 1.0.1
  3. * by Brett Beauregard <[email protected]> brettbeauregard.com
  4. *
  5. * This Library is licensed under a GPLv3 License
  6. **********************************************************************************************/

  7. #if ARDUINO >= 100
  8.   #include "Arduino.h"
  9. #else
  10.   #include "WProgram.h"
  11. #endif

  12. #include <PID_v1.h>

  13. /*Constructor (...)*********************************************************
  14. *    The parameters specified here are those for for which we can't set up
  15. *    reliable defaults, so we need to have the user set them.
  16. ***************************************************************************/
  17. PID::PID(double* Input, double* Output, double* Setpoint,
  18.         double Kp, double Ki, double Kd, int ControllerDirection)
  19. {
  20.        
  21.     myOutput = Output;
  22.     myInput = Input;
  23.     mySetpoint = Setpoint;
  24.         inAuto = false;
  25.        
  26.         PID::SetOutputLimits(0, 255);                                //default output limit corresponds to
  27.                                                                                                 //the arduino pwm limits

  28.     SampleTime = 100;                                                        //default Controller Sample Time is 0.1 seconds

  29.     PID::SetControllerDirection(ControllerDirection);
  30.     PID::SetTunings(Kp, Ki, Kd);

  31.     lastTime = millis()-SampleTime;                               
  32. }


  33. /* Compute() **********************************************************************
  34. *     This, as they say, is where the magic happens.  this function should be called
  35. *   every time "void loop()" executes.  the function will decide for itself whether a new
  36. *   pid Output needs to be computed.  returns true when the output is computed,
  37. *   false when nothing has been done.
  38. **********************************************************************************/
  39. bool PID::Compute()
  40. {
  41.    if(!inAuto) return false;
  42.    unsigned long now = millis();
  43.    unsigned long timeChange = (now - lastTime);
  44.    if(timeChange>=SampleTime)
  45.    {
  46.       /*Compute all the working error variables*/
  47.           double input = *myInput;
  48.       double error = *mySetpoint - input;
  49.       ITerm+= (ki * error);
  50.       if(ITerm > outMax) ITerm= outMax;
  51.       else if(ITerm < outMin) ITerm= outMin;
  52.       double dInput = (input - lastInput);

  53.       /*Compute PID Output*/
  54.       double output = kp * error + ITerm- kd * dInput;
  55.       
  56.           if(output > outMax) output = outMax;
  57.       else if(output < outMin) output = outMin;
  58.           *myOutput = output;
  59.           
  60.       /*Remember some variables for next time*/
  61.       lastInput = input;
  62.       lastTime = now;
  63.           return true;
  64.    }
  65.    else return false;
  66. }


  67. /* SetTunings(...)*************************************************************
  68. * This function allows the controller's dynamic performance to be adjusted.
  69. * it's called automatically from the constructor, but tunings can also
  70. * be adjusted on the fly during normal operation
  71. ******************************************************************************/
  72. void PID::SetTunings(double Kp, double Ki, double Kd)
  73. {
  74.    if (Kp<0 || Ki<0 || Kd<0) return;

  75.    dispKp = Kp; dispKi = Ki; dispKd = Kd;
  76.    
  77.    double SampleTimeInSec = ((double)SampleTime)/1000;  
  78.    kp = Kp;
  79.    ki = Ki * SampleTimeInSec;
  80.    kd = Kd / SampleTimeInSec;

  81.   if(controllerDirection ==REVERSE)
  82.    {
  83.       kp = (0 - kp);
  84.       ki = (0 - ki);
  85.       kd = (0 - kd);
  86.    }
  87. }
  88.   
  89. /* SetSampleTime(...) *********************************************************
  90. * sets the period, in Milliseconds, at which the calculation is performed       
  91. ******************************************************************************/
  92. void PID::SetSampleTime(int NewSampleTime)
  93. {
  94.    if (NewSampleTime > 0)
  95.    {
  96.       double ratio  = (double)NewSampleTime
  97.                       / (double)SampleTime;
  98.       ki *= ratio;
  99.       kd /= ratio;
  100.       SampleTime = (unsigned long)NewSampleTime;
  101.    }
  102. }

  103. /* SetOutputLimits(...)****************************************************
  104. *     This function will be used far more often than SetInputLimits.  while
  105. *  the input to the controller will generally be in the 0-1023 range (which is
  106. *  the default already,)  the output will be a little different.  maybe they'll
  107. *  be doing a time window and will need 0-8000 or something.  or maybe they'll
  108. *  want to clamp it from 0-125.  who knows.  at any rate, that can all be done
  109. *  here.
  110. **************************************************************************/
  111. void PID::SetOutputLimits(double Min, double Max)
  112. {
  113.    if(Min >= Max) return;
  114.    outMin = Min;
  115.    outMax = Max;

  116.    if(inAuto)
  117.    {
  118.            if(*myOutput > outMax) *myOutput = outMax;
  119.            else if(*myOutput < outMin) *myOutput = outMin;
  120.          
  121.            if(ITerm > outMax) ITerm= outMax;
  122.            else if(ITerm < outMin) ITerm= outMin;
  123.    }
  124. }

  125. /* SetMode(...)****************************************************************
  126. * Allows the controller Mode to be set to manual (0) or Automatic (non-zero)
  127. * when the transition from manual to auto occurs, the controller is
  128. * automatically initialized
  129. ******************************************************************************/
  130. void PID::SetMode(int Mode)
  131. {
  132.     bool newAuto = (Mode == AUTOMATIC);
  133.     if(newAuto == !inAuto)
  134.     {  /*we just went from manual to auto*/
  135.         PID::Initialize();
  136.     }
  137.     inAuto = newAuto;
  138. }

  139. /* Initialize()****************************************************************
  140. *        does all the things that need to happen to ensure a bumpless transfer
  141. *  from manual to automatic mode.
  142. ******************************************************************************/
  143. void PID::Initialize()
  144. {
  145.    ITerm = *myOutput;
  146.    lastInput = *myInput;
  147.    if(ITerm > outMax) ITerm = outMax;
  148.    else if(ITerm < outMin) ITerm = outMin;
  149. }

  150. /* SetControllerDirection(...)*************************************************
  151. * The PID will either be connected to a DIRECT acting process (+Output leads
  152. * to +Input) or a REVERSE acting process(+Output leads to -Input.)  we need to
  153. * know which one, because otherwise we may increase the output when we should
  154. * be decreasing.  This is called from the constructor.
  155. ******************************************************************************/
  156. void PID::SetControllerDirection(int Direction)
  157. {
  158.    if(inAuto && Direction !=controllerDirection)
  159.    {
  160.           kp = (0 - kp);
  161.       ki = (0 - ki);
  162.       kd = (0 - kd);
  163.    }   
  164.    controllerDirection = Direction;
  165. }

  166. /* Status Funcions*************************************************************
  167. * Just because you set the Kp=-1 doesn't mean it actually happened.  these
  168. * functions query the internal state of the PID.  they're here for display
  169. * purposes.  this are the functions the PID Front-end uses for example
  170. ******************************************************************************/
  171. double PID::GetKp(){ return  dispKp; }
  172. double PID::GetKi(){ return  dispKi;}
  173. double PID::GetKd(){ return  dispKd;}
  174. int PID::GetMode(){ return  inAuto ? AUTOMATIC : MANUAL;}
  175. int PID::GetDirection(){ return controllerDirection;}
复制代码
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-4-18 23:20:49 | 显示全部楼层
immortal 发表于 2015-4-18 23:19

这是PID库函数
回复 支持 反对

使用道具 举报

发表于 2015-4-19 11:41:36 | 显示全部楼层
不懂!可能是PId问题
回复 支持 反对

使用道具 举报

发表于 2015-4-19 18:30:42 | 显示全部楼层
没看见你的PID调节值
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-4-20 13:26:10 | 显示全部楼层
suoma 发表于 2015-4-19 18:30
没看见你的PID调节值

我不太懂你的意思,PID调节值的相应程序呢,该怎样改呢。谢谢
回复 支持 反对

使用道具 举报

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

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-4-29 03:00 , Processed in 0.064211 second(s), 20 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

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