极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 13781|回复: 0

PID电机调速求探讨

[复制链接]
发表于 2013-12-22 22:59:11 | 显示全部楼层 |阅读模式
  原帖地址:http://blog.solutions-cubed.com/pid-motor-control-with-an-arduino/
  电路接线图,电路板原理图见附件。
程序:
  1. /*
  2.   Firstbot PID code:  Implements a PID controller using
  3.   analog inputs for actual and desired positions.

  4. The circuit:
  5. * RX is digital pin 2 (connect to TX of other device)
  6. * TX is digital pin 3 (connect to RX of other device)

  7. */
  8. #include <SoftwareSerial.h>

  9. // define some constants
  10. int ActPos = A0;    // select the input pin for feedback signal
  11. int DesPos = A1;    // select the input pin for control signal

  12. byte PWMOutput;
  13. long Error[10];
  14. long Accumulator;
  15. long PID;
  16. int PTerm;
  17. int ITerm;
  18. int DTerm;
  19. byte Divider;

  20. /*
  21. The FIRSTBOT has a PIC16F1829 controller that controls the
  22. two MC33926 H-bridges on the board.  A oftware serial interface
  23. is used to control that part.
  24. */
  25. SoftwareSerial mySerial(2, 3); // Receive data on 2, send data on 3
  26. byte SerialTXBuffer[5];
  27. byte SerialRXBuffer[5];

  28. void setup()  
  29. {

  30. // Open serial communications and wait for port to open:
  31.   Serial.begin(9600);
  32.   mySerial.begin(9600);
  33. }

  34. /* GetError():
  35. Read the analog values, shift the Error array down
  36. one spot, and load the new error value into the
  37. top of array.
  38. */
  39. void GetError(void)
  40. {
  41.   byte i = 0;
  42.   // read analogs
  43.   word ActualPosition = analogRead(ActPos);  
  44. // comment out to speed up PID loop
  45. //  Serial.print("ActPos= ");
  46. //  Serial.println(ActualPosition,DEC);

  47.   word DesiredPosition = analogRead(DesPos);
  48. // comment out to speed up PID loop
  49. //  Serial.print("DesPos= ");
  50. //  Serial.println(DesiredPosition,DEC);

  51.   // shift error values
  52.   for(i=0;i<10;i++)
  53.     Error[i+1] = Error[i];
  54.   // load new error into top array spot  
  55.   Error[0] = (long)DesiredPosition-(long)ActualPosition;
  56. // comment out to speed up PID loop
  57. //  Serial.print("Error= ");
  58. //  Serial.println(Error[0],DEC);

  59. }

  60. /* CalculatePID():
  61. Error[0] is used for latest error, Error[9] with the DTERM
  62. */
  63. void CalculatePID(void)
  64. {
  65. // Set constants here
  66.   PTerm = 2000;
  67.   ITerm = 25;
  68.   DTerm = 0;
  69.   Divider = 10;

  70. // Calculate the PID  
  71.   PID = Error[0]*PTerm;     // start with proportional gain
  72.   Accumulator += Error[0];  // accumulator is sum of errors
  73.   PID += ITerm*Accumulator; // add integral gain and error accumulation
  74.   PID += DTerm*(Error[0]-Error[9]); // differential gain comes next
  75.   PID = PID>>Divider; // scale PID down with divider

  76. // comment out to speed up PID loop  
  77. //Serial.print("PID= ");
  78. //  Serial.println(PID,DEC);

  79. // limit the PID to the resolution we have for the PWM variable

  80.   if(PID>=127)
  81.     PID = 127;
  82.   if(PID<=-126)
  83.     PID = -126;

  84. //PWM output should be between 1 and 254 so we add to the PID   
  85.   PWMOutput = PID + 127;

  86. // comment out to speed up PID loop
  87. //  Serial.print("PWMOutput= ");
  88. //  Serial.println(PWMOutput,DEC);

  89. }

  90. /* WriteRegister():
  91. Writes a single byte to the PIC16F1829,
  92. "Value" to the register pointed at by "Index".  
  93. Returns the response
  94. */
  95. byte WriteRegister(byte Index, byte Value)
  96. {
  97. byte i = 0;
  98. byte checksum = 0;
  99. byte ack = 0;

  100. SerialTXBuffer[0] = 210;
  101. SerialTXBuffer[1] = 1;
  102. SerialTXBuffer[2] = 3;
  103. SerialTXBuffer[3] = Index;
  104. SerialTXBuffer[4] = Value;

  105. for (i=0;i<6;i++)
  106.   {
  107.   if (i!=5)
  108.     {
  109.     mySerial.write(SerialTXBuffer[i]);
  110.     checksum += SerialTXBuffer[i];   
  111.     }
  112.   else
  113.     mySerial.write(checksum);     
  114.   }
  115.   delay(5);

  116.   if (mySerial.available())
  117.     ack = mySerial.read();

  118.   return ack;
  119. }

  120. void loop() // run over and over
  121. {
  122.      GetError();       // Get position error
  123.      CalculatePID();   // Calculate the PID output from the error
  124.      WriteRegister(9,PWMOutput);  // Set motor speed
  125. }
复制代码

      刚刚接触PID这块,我把设计的文件都看了一遍,这个项目用了2个单片机,uno和PIC16F1829-I/ML,uno用于电机位置的检测和电机状态的控制,而pic这块对uno发出的指令进行处理从而对电机驱动给出控制,达到电机调速并且回复uno,带到串口通信的作用。我这样理解不知道对不对,在这个项目里我没有找到pic程序是怎么写的,还有一点就是可以通过软件实现电机调速和正反转。在里我提出第一个问题:就是pic的作用和功能是如何实现的,还有文章中涉及的就是固件这块的作用是什么?本人学生一枚第一次接触单片机,想把这个东西先照着这个做出来,已经打了电路板,就是想把这些都弄懂。
      另外一个问题就是uno程序部分。首先对于电路接线图有一个问题,为什么分别通过模拟脚去接滑动变阻器和编码器,为什么这样就是PID的偏差Error?Error这个为什么是Error【10】不是很懂。









本帖子中包含更多资源

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

x
回复

使用道具 举报

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

本版积分规则

Archiver|联系我们|极客工坊

GMT+8, 2026-6-14 05:43 , Processed in 0.082179 second(s), 20 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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