找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5210|回复: 0
打印 上一主题 下一主题
收起左侧

直流有刷伺服控制系统(pic单片机,pid控制)

[复制链接]
跳转到指定楼层
楼主
基于PIC18系列单片机的直流有刷伺控制系统:(来处于国外贴)
1:原理图(PDF)
2:原理图及PCB图(EAGLE)
3:带pid + 编码器的控制程序。main.c


电路原理图如下:




单片机源程序如下:
  1. // Vertical motor driver code
  2. // Oringially made by Kevin Wolfe 2009-2011
  3. // Modified by Matt Moses 2010-2011
  4. //

  5. #include <p18f1320.h>
  6. //#include <stdlib.h>
  7. //#include <delays.h>
  8. //#include <math.h>


  9. #define counterToSpeedScalar 150
  10. #define numCountsPerStep 1
  11. #define maxSpeed 255
  12. #define Kp 35.0
  13. #define Kd 0.0
  14. #define Ki 0.0
  15. #define dt 0.01
  16. #define speedStep 1
  17. #define errorTol 1
  18. #define tempADSpeed 255
  19. #define stepHomeThreshold 500
  20. #define upTorqueLimit 150
  21. #define downTorqueLimit -120

  22. #pragma config IESO = ON
  23. #pragma config FSCM = ON
  24. #pragma config OSC = INTIO2        
  25. #pragma config PWRT = OFF
  26. #pragma config BOR = OFF
  27. #pragma config WDT = OFF
  28. #pragma config MCLRE = OFF

  29. /****** DISABLE LVP (LOW-VOLTAGE Programming) ******/
  30. /* This allows RB5 to operate as an interuppt on change I/O pin */
  31. #pragma config LVP = OFF
  32. /***************************************************/

  33. void low_isr (void);
  34. void high_isr (void);
  35. void set_motor_output (unsigned char desiredPWM, unsigned char desiredDirection);

  36. #pragma code high_vector_section=0x8
  37. void high_vector (void)
  38. {
  39. _asm GOTO high_isr _endasm
  40. }
  41. #pragma code

  42. #pragma code low_vector_section=0x18
  43. void low_vector (void)
  44. {
  45. _asm GOTO low_isr _endasm
  46. }
  47. #pragma code

  48. volatile int stepHighCounter = 0;

  49. volatile char stepPulses = 0;
  50. //volatile int stepCounts;
  51. volatile int currentCounter = 0;
  52. //volatile unsigned char currentADvalue;
  53. volatile unsigned char trigger = 0;
  54. //volatile structPrevStates prevStates;
  55. //volatile enum { DIR_CW = 0, DIR_CCW = 1 } direction;
  56. volatile enum { LOW = 0, HIGH = 1} prevA = LOW;

  57. // changeToggle is a varb used for debugging
  58. volatile enum {LOW = 0, HIGH = 1} changeToggle;

  59. #pragma interrupt high_isr
  60. void high_isr(void)
  61. {
  62.         if ( INTCONbits.INT0IF ) //step pulse flag
  63.         {

  64.                 // reset stepTimerFoo
  65.                 stepHighCounter = 1;

  66.                 // do important stuff
  67.                 if ( PORTBbits.RB1 )    //Check direction pin
  68.                 {
  69.                         stepPulses++;
  70.                 }
  71.                 else
  72.                 {
  73.                         stepPulses--;
  74.                 }
  75.        
  76.                 INTCONbits.INT0IF = 0; //reset step flag
  77.         }

  78.         if ( INTCONbits.RBIF ) //PORTB change interrupt
  79.         {

  80. //                // This is a little block for debugging - toggles A every time a change on PORTB
  81. //       
  82. //                if (changeToggle) {
  83. //                        changeToggle = 0;
  84. //                        PORTAbits.RA1 = 0;
  85. //                }
  86. //                else {
  87. //                        changeToggle = 1;
  88. //                        PORTAbits.RA1 = 1;
  89. //                }

  90.                 if ( PORTBbits.RB5^prevA )          //CW Rotation
  91.                 {
  92.                         currentCounter++;
  93.                         //PORTAbits.RA1 = 0;
  94.                 }
  95.                 else                                                //CCW Rotation
  96.                 {
  97.                         currentCounter--;
  98.                         //PORTAbits.RA1 = 1;
  99. //                        if (changeToggle) {
  100. //                                changeToggle = 0;
  101. //                                PORTAbits.RA1 = 0;
  102. //                        }
  103. //                        else {
  104. //                                changeToggle = 1;
  105. //                                PORTAbits.RA1 = 1;
  106. //                        }
  107.                 }


  108.                 prevA = PORTBbits.RB4;
  109.                 PORTAbits.RA1 = PORTBbits.RB5;

  110.                 INTCONbits.RBIF = 0; //resetQuadFlag
  111.         }
  112. }

  113. #pragma interruptlow low_isr
  114. void low_isr(void)  //timer interupt
  115. {
  116.         trigger = 1;
  117.         INTCONbits.TMR0IF = 0;                         // reset TMR0 interrupt flag
  118. }


  119. void set_motor_output(unsigned char desiredPWM, unsigned char desiredDirection)
  120. {
  121.         if ( desiredDirection )
  122.         {
  123.                 PORTBbits.RB2 = 0;
  124.                 CCPR1L = desiredPWM;                          // This is the register for the 8 MSB of the PWM pin RB3.
  125.         }
  126.         else
  127.         {
  128.                 PORTBbits.RB2 = 1;
  129.                 CCPR1L = (desiredPWM );          // This is the register for the 8 MSB of the PWM pin RB3.
  130.         }
  131. }

  132. long abs(long i)
  133. {
  134.         if (i < 0)
  135.                 return -i;
  136.         else
  137.                 return i;
  138. }

  139. char sgn(long i)
  140. {
  141.         if (i < 0)
  142.                 return -1;
  143.         else if (i > 0)
  144.                 return 1;
  145.         else
  146.                 return 0;
  147. }


  148. void main (void)
  149. {
  150.         long prevCounter = 0;
  151.         unsigned char tempTrigger = 0;
  152.         char tempStepPulses = 0;
  153.         long tempCurrentCounter = 0;
  154.        
  155.         unsigned char currentADvalue = tempADSpeed;
  156.         long desiredCounter = 0;
  157.         long error = 0;
  158.         long prevError = 0;

  159.         long velocity = 0;

  160.         float integral = 0.0;
  161.         float derivative = 0.0;

  162.         long output = 0;

  163.         char testState = 0;
  164.         long testCounter = 0;



  165.         char homeFlag = 0;
  166.     enum { LOW = 0, HIGH = 1} homeDir = LOW;

  167.         /*************** SETUP INTERRUPTS ******************/
  168.         INTCONbits.GIEH = 0;                 // Temporarily disable global interrupts
  169.         INTCONbits.GIEL = 0;                 // Temporarily disable peripheral interrupts
  170.         INTCONbits.TMR0IE = 1;                 // Enable TMR0 Overflow interrupt
  171.         INTCONbits.INT0IE = 1;                 // Enable external interrupt on INT0/RB0
  172.         INTCONbits.RBIE = 1;                 // Enable Port B change interrupt

  173.         //INTCON2bits.RBPU = 0;                 // Enable Port B pull-ups
  174.         INTCON2bits.RBPU = 1;                 // Disable Port B pull-ups
  175.         INTCON2bits.INTEDG0 = 1;         // Interrupt on rising edge for INT0
  176.         INTCON2bits.TMR0IP = 0;         // Set TMR0 interrupt priority to Low
  177.         INTCON2bits.RBIP = 1;                 // Set Port B change interrupt to High

  178.         RCONbits.IPEN = 1;                        // Enable priority levels on interrupts
  179.         /****************************************************/




  180.         /***************** SETUP TMR0 ***********************/
  181.         //T0CONbits.TMR0ON = 0;         // Temporarily disable TMR0 until the end of the setup;
  182.         T0CONbits.T08BIT = 1;         // Use an 8-bit timer (1). Use a 16-bit timer (0).
  183.         T0CONbits.T0CS = 0;         // Use internal clock cycles for the timer.
  184.         T0CONbits.PSA = 0;                 // Use prescalar to adjust overflow rate (0). Do not use prescalar (1).
  185.        
  186.         /* Assign Prescalar */
  187.         T0CONbits.T0PS2 = 0;
  188.         T0CONbits.T0PS1 = 1;
  189.         T0CONbits.T0PS0 = 1;

  190.         /* This makes go slower */
  191.         //T0CONbits.T0PS2 = 1;
  192.         //T0CONbits.T0PS1 = 1;
  193.         //T0CONbits.T0PS0 = 1;

  194.         T0CONbits.TMR0ON = 1;
  195.         /***************************************************/
  196.        



  197.         /************** SETUP I/O PINS *********************/
  198.         TRISBbits.TRISB4 = 1;        // Encoder ChA input
  199.         TRISBbits.TRISB5 = 1;        // Encoder ChB input
  200.         TRISBbits.TRISB6 = 0;        // Set as output to avoid Port B interrupt on change
  201.         TRISBbits.TRISB7 = 0;        // Set as output to avoid Port B interrupt on change

  202.         TRISBbits.TRISB0 = 1;        // Step pulse input
  203.         TRISBbits.TRISB1 = 1;        // Direction input

  204.         //TRISAbits.TRISA4 = 0;         // Possible motor output pin RA4

  205.         TRISAbits.TRISA0 = 1;        // Set RA0 as input for SPEED pin (analog input for A/D)
  206.         TRISAbits.TRISA1 = 0;        // Set RA1 as output for diagnostic LED

  207.         //ADCON0bits.VCFG0 = 0;        // Set A/D to External Vref(+/-) using 1 and 1
  208.         //ADCON0bits.VCFG1 = 0;        // Set A/D to Vss and Vdd references using 0 and 0
  209.         /***************************************************/




  210.         /**************** SETUP A/D ************************/
  211.         /* Configure analog and digital pins */
  212.         ADCON1bits.PCFG0 = 1; // Set AN0 port as digital input (Home switch)
  213.         ADCON1bits.PCFG1 = 1; // RA1/AN1 diagnostic LED
  214.         ADCON1bits.PCFG2 = 1; // Reserved - test pad on AN2
  215.         ADCON1bits.PCFG3 = 1; // Reserved - test pad on AN3
  216.         ADCON1bits.PCFG4 = 1; // Set AN4/RB0 as a digital pin (Step pulse input)
  217.         ADCON1bits.PCFG5 = 1; // Set AN5/RB1 as a digital pin (Direction input)
  218.         ADCON1bits.PCFG6 = 1; // Set AN6/RB4 as a digital pin (ChA input)
  219. //
  220. //        /* Select A/D input channel as AN0 */
  221. //        ADCON0bits.CHS0 = 0;
  222. //        ADCON0bits.CHS1 = 0;
  223. //        ADCON0bits.CHS2 = 0;
  224. //
  225. //        /* Set A/D clock as Fosc/2 */
  226. //        ADCON2bits.ADCS0 = 0;
  227. //        ADCON2bits.ADCS1 = 0;
  228. //        ADCON2bits.ADCS2 = 0;
  229. //
  230. //        ADCON2bits.ADFM = 0; // Left justify A/D conversion so only the 8 MSB are read later
  231. //
  232. //        /* Turn on A/D module */
  233. //        ADCON0bits.ADON = 1;
  234.        
  235.         /* Turn off A/D module */
  236.         ADCON0bits.ADON = 0;

  237.         /***************************************************/




  238.         /**************** SETUP PWM ************************/
  239.        
  240.         /* Configure PWM pins P1A and P1B as inputs. */
  241.         TRISBbits.TRISB3 = 1;
  242.         TRISBbits.TRISB2 = 1;

  243.         /* Use PR2 to set the PWM period */
  244.         PR2 = 0xFF;

  245.         // Equation 15-1 PWM Period = [(PR2 + 1)] * 4 * TOSC * TMR2 Prescaler
  246.         // or about 1 / 490Hz

  247.         /* Set PWM Mode with P1A as a single modulated output */
  248.         CCP1CONbits.CCP1M0 = 0;
  249.         CCP1CONbits.CCP1M1 = 0;
  250.         CCP1CONbits.CCP1M2 = 1;
  251.         CCP1CONbits.CCP1M3 = 1;
  252.         CCP1CONbits.P1M0 = 0;
  253.         CCP1CONbits.P1M1 = 0;

  254.         /* LSB of the PWM duty cycle */
  255.         CCP1CONbits.DC1B1 = 0;
  256.         CCP1CONbits.DC1B0 = 0;

  257.         /* MSB of the PWM duty cycle */
  258.         CCPR1L = 0x00;
  259.        
  260.         /* Configure TMR2 */
  261.         PIR1bits.TMR2IF = 0;        // Clear interupt flag for TMR2 equal to PR2
  262.         T2CONbits.T2CKPS1 = 1;  // Set prescaler to 16 to decrease PWM frequency
  263.         T2CONbits.T2CKPS0 = 1;

  264.         T2CONbits.TMR2ON = 1; // Turn on Timer2
  265.        
  266.         /* Wait for the TMR2IF flag go high before procedding */
  267.         while (!(PIR1bits.TMR2IF))
  268.         {
  269.                 int temp = 0;
  270.         }       

  271.         /* Set the PWM pins P1A and P1B as outputs. */
  272.         TRISBbits.TRISB3 = 0;
  273.         TRISBbits.TRISB2 = 0;

  274.         ECCPASbits.ECCPASE = 0;
  275.         /*****************************************************/

  276.         /***************** SET OSC SPEED *********************/

  277.     //OSCCONbits.IRCF0 = 1;
  278.         //OSCCONbits.IRCF1 = 1;
  279.         //OSCCONbits.IRCF2 = 1;

  280.     OSCCONbits.IRCF0 = 1;
  281.         OSCCONbits.IRCF1 = 1;
  282.         OSCCONbits.IRCF2 = 1;

  283.         /*****************************************************/
  284.        


  285.         // This line is part of the initial check sequence and is not
  286.         // needed for normal operation:
  287.         desiredCounter = 0;

  288.         trigger = 0;
  289.         stepPulses = 0;
  290.         currentCounter = 0;
  291.        


  292.         set_motor_output( 0, 0 );


  293.         /****************** ENABLE INTERRUPTS *****************/
  294.         INTCONbits.GIEH = 1;                 // Enable global interrupts
  295.         INTCONbits.GIEL = 1;                 // Enable peripheral innterupts
  296.         /******************************************************/
  297.        
  298.         while (1)
  299.         {

  300.                 INTCONbits.GIEH = 0;
  301.                         tempTrigger = trigger;
  302.                 INTCONbits.GIEH = 1;
  303.                
  304.                 if ( tempTrigger )
  305.                 {       

  306.                         INTCONbits.GIEH = 0;
  307.                                 trigger = 0;
  308.                                 tempCurrentCounter = currentCounter;
  309.                                 tempStepPulses = stepPulses;
  310.                                 stepPulses = 0;

  311.                                 // Check if step pin has been held HIGH.  If it has been held HIGH
  312.                                 // long enough to indicate a HOME command, set home flag, otherwise
  313.                                 // just increment stepHighCounter.  stepHighCounter gets reset in
  314.                                 // in interrupt routine that reads step and direction lines.  
  315.                                 if (stepHighCounter) {
  316.                                         if (stepHighCounter > stepHomeThreshold) {
  317.                                                 homeFlag = 1;
  318.                                                 stepHighCounter = 0;
  319.                                                 homeDir = PORTBbits.RB1; //set home direction to direction input pin
  320.                                         }
  321.                                         else {
  322.                                                 if (PORTBbits.RB0) {
  323.                                                         stepHighCounter++;
  324.                                                 }
  325.                                         }
  326.                                 }
  327.                                 //stepTimerFoo++;
  328.                                 //tempStepTimerFoo = stepTimerFoo;
  329.                         INTCONbits.GIEH = 1;
  330.        


  331.        
  332.                         // if tempStepTimerFoo > something
  333.                         //    then set homeFlag, set homeDir

  334.                         // if homeflag
  335.                                 // if homeswitch
  336.                                 //                turn off homing
  337.                                 //        else
  338.                                 //                set motor go to home in homeDir direction
  339.                                 //        end
  340.                         //else
  341.                         //        do normal motor control
  342.                         //end
  343.                                
  344.                




  345. /*
  346.                         INTCONbits.GIEH = 0;
  347.                                 trigger = 0;
  348.                         INTCONbits.GIEH = 1;

  349.                        

  350.                         //if (PORTAbits.RA1)
  351.                         //        PORTAbits.RA1 = 0;
  352.                         //else
  353.                         //        PORTAbits.RA1 = 1;

  354.                         INTCONbits.GIEH = 0;
  355.                                 tempCurrentCounter = currentCounter;
  356.                                 tempStepPulses = stepPulses;
  357.                                 stepPulses = 0;
  358.                         INTCONbits.GIEH = 1; */

  359.                 //        velocity = (tempCurrentCounter - prevCounter)*counterToSpeedScalar;
  360.                 //        prevCounter = tempCurrentCounter;

  361.                                
  362.                         // Uncomment this for normal operation
  363.                         desiredCounter = desiredCounter + (tempStepPulses*numCountsPerStep);
  364.                        


  365.                         if (homeFlag) // If we are in homing mode
  366.                         {
  367.                                 if (PORTAbits.RA0) // if homeswitch is ON
  368.                                 {
  369.                                         // We're home!
  370.                                         set_motor_output(0,0);
  371.                                         homeFlag = 0;
  372.                                         desiredCounter = 0;
  373.                                        
  374.                                         // turn off interrupts to clear sensitive variables
  375.                                         INTCONbits.GIEH = 0;
  376.                                                 currentCounter = 0;
  377.                                         INTCONbits.GIEH = 1;
  378.                                 }
  379.                                 else // if homeswitch is OFF - we are still going home
  380.                                 {         
  381.                                         if (homeDir) // going up
  382.                                         {
  383.                                                 set_motor_output(abs(upTorqueLimit),1);
  384.                                         }
  385.                                         else // going down
  386.                                         {
  387.                                                 set_motor_output(abs(downTorqueLimit), 0);
  388.                                         }
  389.                                 }
  390.                         }
  391.                         else
  392.                         {
  393.                                 error = desiredCounter - tempCurrentCounter;
  394.                                 output =  Kp * error;

  395.                                 ////////////// Set motor output //////////////////////////////
  396.                                 //
  397.                                 // The variable "output" controls voltage to motor. Examples:
  398.                                 //
  399.                                 // this makes the motor go up:
  400.                                 // set_motor_output(30,1);
  401.                     //
  402.                                 // this makes the motor go down:
  403.                                 // set_motor_output(30,0);
  404.                                 //
  405.                                 if (output <= 0)
  406.                                 {
  407.                                         if (output < downTorqueLimit)
  408.                                         {
  409.                                                 output = downTorqueLimit;
  410.                                         }
  411.                                         set_motor_output(abs(output),0);
  412.                                 }
  413.                                 else
  414.                                 {
  415.                                         if (output > upTorqueLimit)
  416.                                         {
  417.                                                 output = upTorqueLimit;
  418.                                         }
  419.                                         set_motor_output(abs(output),1);
  420.                                 }
  421.                         }
  422.                 }
  423.         }
  424. }


复制代码

Partlist

Exported from singleAxisMotor3.sch at 2/16/2014 12:03:57 PM

EAGLE Version 6.5.0 Copyright (c) 1988-2013 CadSoft

Assembly variant:

Part     Value                Device               Package        Library             Sheet

C1       0.1uF                C-USC1206            C1206          rcl                 1
C2       0.1uF                C-USC1206            C1206          rcl                 1
C3       0.1uF                C-USC1206            C1206          rcl                 1
C4       0.1uF                C-USC1206            C1206          rcl                 1
C5       10.0uF               C-US025-024X044      C025-024X044   rcl                 1
C6       10.0uF               C-USC1206            C1206          rcl                 1
C7       10.0uF               C-USC1206            C1206          rcl                 1
C8       1000uF               C-US025-024X044      C025-024X044   rcl                 1
C9       1.0uF                C-USC1206            C1206          rcl                 1
C10      10nF                 C-USC1206            C1206          rcl                 1
C11      10nF                 C-USC1206            C1206          rcl                 1
IC2      7805L                7805L                TO92           linear              1
IC3      40106D               40106D               SO14           40xx                1
IC4      PIC18F1320_18PIN_DIP PIC18F1320_18PIN_DIP SO-18W         modular_robot_parts 1
JP1      PIC_KIT_2_CONN       PIC_KIT_2_CONN       PIC_KIT_2_CONN modular_robot_parts 1
JP2                           PINHD-2X4            2X04           pinhead             1
LED1                          LEDCHIPLED_1206      CHIPLED_1206   led                 1
P1       3PIN                 3PIN                 3PIN           custom              1
R1       1k                   R-US_0207/2V         0207/2V        rcl                 1
R2       100k                 R-US_0207/2V         0207/2V        rcl                 1
R3       1k                   R-US_0207/2V         0207/2V        rcl                 1
R4       100k                 R-US_0207/2V         0207/2V        rcl                 1
R5       330                  R-US_0207/2V         0207/2V        rcl                 1
R6       330                  R-US_0207/2V         0207/2V        rcl                 1
R7       1k                   R-US_0207/2V         0207/2V        rcl                 1
R8       1k                   R-US_0207/2V         0207/2V        rcl                 1
R9       330                  R-US_0207/2V         0207/2V        rcl                 1
R10      1k                   R-US_M1206           M1206          rcl                 1
R11      2.7k                 R-US_M1206           M1206          rcl                 1
R12      10k                  R-US_M1206           M1206          rcl                 1
R13      10k                  R-US_M1206           M1206          rcl                 1
TP1      1PAD                 1PAD                 1PAD           custom              1
TP2      1PAD                 1PAD                 1PAD           custom              1
TP3      1PAD                 1PAD                 1PAD           custom              1
TP4      1PAD                 1PAD                 1PAD           custom              1
TP5      1PAD                 1PAD                 1PAD           custom              1
U1       LMD18200             LMD18200             TO-220-WIDE    custom              1
X1       22-23-2021           22-23-2021           22-23-2021     con-molex           1
X2       22-23-2041           22-23-2041           22-23-2041     con-molex           1


所有资料51hei提供下载:
SingleAxisEmulator-master.zip (282.84 KB, 下载次数: 38)


评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏3 分享淘帖 顶 踩
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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