完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
扫一扫,分享给好友
您好,我使用的是DSIC33 FJ16MC102 AN1160源代码,它运行良好。但是我需要一些帮助,我想在没有斜坡的情况下驱动马达,因为我一开始就旋转马达。我需要一个滑板,坡道是有破坏性的。我试过一些东西,但它不成功。有人想这样做吗?谢谢你
以上来自于百度翻译 以下为原文 Hello, I use the dspic33fj16mc102 an1160 sourcecode, it works fine. But i need some help, i want to drive the motor without the ramp, because I spin the motor at the beginning. I need it for a skateboard and the ramp is disruptive. I've tried something but it was unsuccessful. Have anyone an idea to do that? Thank you /******************************************************************************/ // // Software License Agreement // // CODE OWNERSHIP AND DISCLAIMER OF LIABILITY // Microchip Technology Incorporated ("Microchip") retains // all ownership and intellectual property rights in the code // accompanying this message and in all derivatives hereto. // You may use this code, and any derivatives created by any // person or entity by or on your behalf, exclusively with // Microchip’s proprietary products. Your acceptance and/or // use of this code constitutes agreement to the terms and // conditions of this notice. // CODE ACCOMPANYING THIS MESSAGE IS SUPPLIED BY MICROCHIP "AS IS". // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, // BUT NOT LIMITED TO, IMPLIED WARRANTIES OF NON-INFRINGEMENT, // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO // THIS CODE, ITS INTERACTION WITH MICROCHIP’S PRODUCTS, COMBINATION // WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. // YOU ACKNOWLEDGE AND AGREE THAT, IN NO EVENT, SHALL MICROCHIP BE // LIABLE, WHETHER IN CONTRACT, WARRANTY, TORT (INCLUDING NEGLIGENCE // OR BREACH OF STATUTORY DUTY), STRICT LIABILITY, INDEMNITY, CONTRIBUTION, // OR OTHERWISE, FOR ANY INDIRECT, SPECIAL, PUNITIVE, EXEMPLARY, INCIDENTAL // OR CONSEQUENTIAL LOSS, DAMAGE, FOR COST OR EXPENSE OF ANY KIND WHATSOEVER // RELATED TO THE CODE, HOWSOEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED // OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT // ALLOWABLE BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY // RELATED TO THIS CODE, SHALL NOT EXCEED THE PRICE YOU PAID DIRECTLY TO // MICROCHIP SPECIFICALLY TO HAVE THIS CODE DEVELOPED. // You agree that you are solely responsible for testing the code and // determining its suitability. Microchip has no obligation to modify, // test, certify, or support the code. /*****************************************************************************/ // File: AN1160 dsPIC33FJ16MC102 dsPICDEM MCLV.c // // This program commutates a sensor less BLDC motor using closed PI loop. // The circuit and operation is as depicted in AN1160. // // Written By: Daniel Torres // Updated for MC102: Sorin Manea // Microchip Technology Inc // // // The following files should be included in the MPLAB project: // // AN1160 dsPIC33FJ16MC102 dsPICDEM MCLV.c -- Main source code file // lipdsp-coff.a -- dsp library for PID // /*****************************************************************************/ // // // Revision History // // 12/3/07 -- First Version Close Loop with BEMF sensing using the ADC // 12/10/07 -- Adding comments and modifying global variables names // 2/22/08 -- Spell Checking, Dead Variable Clean up, Ramp up bug // 5/5/08 -- DMCI with real-time data monitor added // 6/04/08 -- SW migrated to the dsPICDEM MCLV board // 6/17/08 -- Commens addded, PI coefficients recalculated, // 5/19/11 -- Code changed for dsPIC33FJ16MC102. Added defines for motor speed setting /*****************************************************************************/ #include "p33fj16mc102.h" #include "dsp.h" /********************Setting Configuration Bits *********************************/ _CONFIG2(POSCMOD_NONE & LPOL_ON & OSCIOFNC_ON & IOL1WAY_OFF & FCKSM_CSECMD & FNOSC_FRCPLL & PWMPIN_ON & PWMLOCK_ON & IESO_OFF); _CONFIG1(0x3FFF & PLLKEN_ON & FWDTEN_OFF & ICS_PGD3 & HPOL_ON & GWRP_OFF & GCP_OFF); /*****************************SYSTEM DEFINES***********************************/ /*FREQUENCY SYSTEM DEFINES*/ #define FCY 14740000 //internal FRC with x4 PLL -> 7.37MHz*4/2 = 14.740 Mhz #define MILLISEC FCY/14740 //1 mSec delay constant #define FPWM 20000 //20KHz PWM Freq #define S3 !PORTBbits.RB8 //Defines for the Push Buttons status /****************************************************************************** * OPEN LOOP DEFINITION * If defined then the compiler will add the PID controller for speed *******************************************************************************/ #define CLOSELOOPMODE /********************* Motor Control Definitions *********************************/ /*START-UP SEQUENCE PARAMETERS*/ // Maximum PWM pulses applied to motor #define MAX_PWM_TICKS 2000 //for detecting initial rotor position #define RAM_UP_DELAY 0 // Delay for the ramp up sequence, expressed in millisecond #define MAX_DUTY_CYCLE (int)(((FCY/FPWM)/2 - 1)*2) // 100% duty cycle P1DC1=P1DC2=P1DC3 = 734 #define MIN_DUTY_CYCLE 37 // 5% duty cycle P1DC1=P1DC2=P1DC3 = 37 #define PHASE_ADVANCE_DEGREES 25 //Phase advance angles to get the best motor performance #define BLANKING_COUNT 5 //Blanking count expressed in PWM periods used to avoid false zero-crossing detection after commutating motor #define POLEPAIRS 5 // Number of pole pairs of the motor #define MAX_RPM 3200 //motor RPM at 100% duty cycle //Timer2 measures the motor speed by measuring the time the rotor takes to make a 60 degree electrical rotation angle //Timer2 minimum value is: 1/(MAX_RPM/60)/POLEPAIRS*FCY/Timer2Prescaler/(360/60) #define TMR2_MIN (double)60/MAX_RPM/POLEPAIRS*FCY/64/6 //Timer2 prescaler is 64 // CONVERSION SPEED FACTOR - SPEEDMULT #define SPEEDMULT (long)((1023*3/2)*TMR2_MIN) //DesiredSpeed is 3/2 of POT value, which is a 10bit value (1023) #define DEBOUNCE_DELAY 20 // Push button debounce delay, expressed in millisecond /* Six-Step Commutation States*/ /*PHASE A is MI, PHASE B is M2, PHASE C is M3 in the dsPICDEM MCLV board*/ /* State 0x2001 Connect the PHASE A to -Vbus & PHASE C to +Vbus */ /* State 0x2004 Connect the PHASE B to -Vbus & PHASE C to +Vbus */ /* State 0x0204 Connect the PHASE B to -Vbus & PHASE A to +Vbus */ /* State 0x0210 Connect the PHASE C to -Vbus & PHASE A to +Vbus */ /* State 0x0810 Connect the PHASE C to -Vbus & PHASE B to +Vbus */ /* State 0x0801 Connect the PHASE A to -Vbus & PHASE B to +Vbus */ const unsigned int PWM_STATE[] = {0x0000,0x2001,0x2004,0x0204,0x0210,0x0810,0x0801,0x0000}; /*AND & OR operators for masking the active BEMF signal*/ const unsigned int ADC_MASK[8] = {0x0000,0x0002,0x0001,0x0004,0x0002,0x0001,0x0004,0x0000}; const unsigned int ADC_XOR[8] = {0x0000,0x0000,0xFFFF,0x0000,0xFFFF,0x0000,0xFFFF,0x0000}; /*BEMF Majority Function Filter values*/ const unsigned char ADC_BEMF_FILTER[64]= {0x00,0x02,0x04,0x06,0x08,0x0A,0x0C,0x0E,0x10,0x12,0x14,0x16,0x18,0x1A,0x1C,0x1E, 0x20,0x22,0x24,0x26,0x28,0x2A,0x2C,0x2E,0x01,0x01,0x01,0x36,0x01,0x3A,0x3C,0x3E, 0x00,0x02,0x04,0x06,0x08,0x0A,0x0C,0x0E,0x01,0x01,0x01,0x16,0x01,0x1A,0x1C,0x1E, 0x01,0x01,0x01,0x26,0x01,0x2A,0x2C,0x2E,0x01,0x01,0x01,0x36,0x01,0x3A,0x3C,0x3E}; /*Application Flags to indicate the motor status*/ struct { unsigned RunMotor : 1; unsigned RotorAlignment : 1; unsigned unused : 14; }Flags; /*Boolean variables used to save the comparison between the phases and the neutral point*/ struct { unsigned PhaseAOutput : 1; unsigned PhaseBOutput : 1; unsigned PhaseCOutput : 1; unsigned unused : 13; }Comparator; /********************* Motor Control Varaibles *********************************/ unsigned int PWMticks; unsigned char CommState; unsigned char ADCCommState; unsigned char adcBackEMFFilter; unsigned int PhaseAdvance = 0; unsigned char BlankingCounter; unsigned int MotorNeutralVoltage; unsigned int MotorPhaseA; unsigned int MotorPhaseB; unsigned int MotorPhaseC; unsigned int ComparatorOutputs; unsigned int CommutationStatus; unsigned int DesiredPWMDutyCycle; unsigned int CurrentPWMDutyCycle; unsigned char RampUpCommState; unsigned int Timer2Value; unsigned int Timer2Average; unsigned int Timer1Value; /********************* PID Varibles *********************************/ #ifdef CLOSELOOPMODE unsigned int ReferenceSpeed; int DesiredSpeed, CurrentSpeed; unsigned int SpeedControl_P = 2000; // The P term for the PI speed control loop unsigned int SpeedControl_I = 50; // The I term for the PI speed control loop unsigned int SpeedControl_D = 0; // The I term for the PI speed control loop fractional PIDGainCoefficients[3]; //Control gains for the speed control loop fractional abcCoefficients[3] __attribute__ ((space(xmemory),__aligned__(4))); fractional controlHistory[3] __attribute__ ((space(ymemory),__aligned__(4))); tPID PIDStructure; // PID Structure #endif /********************* Function Definitions *********************************/ void InitMCPWM(void); void InitADC10(void); void InitTMR2(void); void InitTMR1(void); void PreCommutationState(void); void SpeedPILoopController(void); void OpenLoopController(void); void DelayNmSec(unsigned int N); /****************************************************************************** * Function: main(void) * * Output: None * * Overview: Main function used to init the ADC, PWM and TIMER2 modules. * It also inits the global variables used in the interrupts and * PI controller. * The main task executed here is to start and stop the motor * as well as setting the ramp-up initial parameters to * spin the motor * * Note: None *******************************************************************************/ int main(void) { // Configure Oscillator to operate the device with internal FRC and PLL at 14.74Mhz __builtin_write_OSCCONH(0x01); __builtin_write_OSCCONL(0x01); while(OSCCONbits.COSC != 0b001); // Wait for PLL to lock while(OSCCONbits.LOCK != 1); /* disable wdt */ RCONbits.SWDTEN = 0; /****************** PID init **************************************/ #ifdef CLOSELOOPMODE ReferenceSpeed = (MIN_DUTY_CYCLE*2)/3; // load the PID gain coeffecients into an array; PIDGainCoefficients[0] = SpeedControl_P; PIDGainCoefficients[1] = SpeedControl_I; PIDGainCoefficients[2] = SpeedControl_D; // Initialize the PIDStructure variable before calculation the K1, K2, and K3 terms PIDStructure.abcCoefficients = abcCoefficients; PIDStructure.controlHistory = controlHistory; PIDCoeffCalc(PIDGainCoefficients, &PIDStructure); // initialize control history PIDInit(&PIDStructure); PIDStructure.controlOutput = MIN_DUTY_CYCLE; /****************************************************************/ #endif /****************** I/O port Init *********************************/ /* Configuring Digital PORTS multiplexed with PWMs as outputs*/ //PWM ports TRIS bit is set as input //Each pin is input when PWM is disabled and output when PWM is enabled LATBbits.LATB10 = 0; //PWM1H3 TRISBbits.TRISB10 = 1; LATBbits.LATB11 = 0; //PWM1L3 TRISBbits.TRISB11 = 1; LATBbits.LATB12 = 0; //PWM1H2 TRISBbits.TRISB12 = 1; LATBbits.LATB13 = 0; //PWM1L2 TRISBbits.TRISB13 = 1; LATBbits.LATB14 = 0; //PWM1H1 TRISBbits.TRISB14 = 1; LATBbits.LATB15 = 0; //PWM1L1 TRISBbits.TRISB15 = 1; /****************** Functions init *********************************/ INTCON1bits.NSTDIS = 0; // Enabling nested interrupts InitMCPWM(); //Configuring MC PWM module InitADC10(); //Configuring ADC InitTMR2(); //Configuring TIMER 3, used to measure speed InitTMR1(); //Configuring TIMER 1, used for the commutation delay /*Push Button port*/ TRISBbits.TRISB8 = 1; Flags.RotorAlignment = 0; // TURN OFF RAMP UP Flags.RunMotor = 0; // indication the run motor condition /****************** Infinite Loop *********************************/ for(;;) { while (!S3); // wait for S3 button to be hit while (S3) // wait till button is released DelayNmSec(DEBOUNCE_DELAY); T2CONbits.TON = 1; // Start TIMER , enabling speed measurement // Enable all PWMs using PWM1CON1 register // Writing to PWM1CON1 register requires unlock sequence // Use builtin function to write 0x0777 to PWM1CON1 register //if using compiler version 3.30B or later use line below //__builtin_write_PWMSFR(&PWM1CON1, 0x0777, &PWM1KEY); //else use asm("mov #0xabcd,w10"); // Load first unlock key to w10 register asm("mov #0x4321,w11"); // Load second unlock key to w11 register asm("mov #0x0777,w0"); // Load desired value of PWM1CON1 register in w0 asm("mov w10, PWM1KEY"); // Write first unlock key to PWM1KEY register asm("mov w11, PWM1KEY"); // Write second unlock key to PWM1KEY register asm("mov w0,PWM1CON1"); // Write desired value to PWM1CON1 register /*ROTOR ALIGNMENT SEQUENCE*/ Flags.RotorAlignment = 1; // TURN ON rotor alignment sequence Flags.RunMotor = 1; // Indicating that motor is running CurrentPWMDutyCycle = MIN_DUTY_CYCLE; //Init PWM values DesiredPWMDutyCycle = MIN_DUTY_CYCLE; //Init PWM values PWMticks = 0; //Init Rotor aligment counter /************* Rotor alignment sequence and ramp-up sequence ************/ for(RampUpCommState=1;RampUpCommState<7;RampUpCommState++) { while(++PWMticks P1OVDCON=PWM_STATE[RampUpCommState]; } PWMticks = 0; RampUpCommState++; } Flags.RotorAlignment = 0; // TURN OFF rotor alignment sequence PWMticks = MAX_PWM_TICKS+1; // RAMP UP for breaking the motor IDLE state DelayNmSec(RAM_UP_DELAY); // RAMP UP DELAY /****************** Motor is running *********************************/ while(Flags.RunMotor) // while motor is running { /****************** Stop Motor *********************************/ if (S3) // if S3 is pressed { while (S3) // wait for key release DelayNmSec(DEBOUNCE_DELAY); // Disable all PWMs using PWM1CON1 register // Writing to PWM1CON1 register requires unlock sequence // Use builtin function to write 0x0700 to PWM1CON1 register //if using compiler version 3.30B or later use line below // __builtin_write_PWMSFR(&PWM1CON1, 0x0700, &PWM1KEY); //else use asm("mov #0xabcd,w10"); // Load first unlock key to w10 register asm("mov #0x4321,w11"); // Load second unlock key to w11 register asm("mov #0x0700,w0"); // Load desired value of PWM1CON1 register in w0 asm("mov w10, PWM1KEY"); // Write first unlock key to PWM1KEY register asm("mov w11, PWM1KEY"); // Write second unlock key to PWM1KEY register asm("mov w0,PWM1CON1"); // Write desired value to PWM1CON1 register P1OVDCON = 0x0000; // override PWM low. Flags.RotorAlignment = 0; // turn on RAMP UP Flags.RunMotor = 0; // reset run flag CurrentPWMDutyCycle = 1; // Set PWM to the min value //Initi speed measurement variables & timer T2CONbits.TON = 0; // Stop TIMER2 TMR2 = 0; //Clear TIMER2 register Timer2Value = 0; Timer2Average = 0; #ifdef CLOSELOOPMODE //Init PI controller variables DesiredSpeed = (int)((ReferenceSpeed*3)/2); CurrentSpeed = 0; // load the PID gain coeffecients into an array; PIDGainCoefficients[0] = SpeedControl_P; PIDGainCoefficients[1] = SpeedControl_I; PIDGainCoefficients[2] = SpeedControl_D; // Initialize the PIDStructure variable before calculation the K1, K2, and K3 terms PIDStructure.abcCoefficients = abcCoefficients; PIDStructure.controlHistory = controlHistory; PIDCoeffCalc(PIDGainCoefficients, &PIDStructure); // initialize control history PIDInit(&PIDStructure); PIDStructure.controlOutput = MIN_DUTY_CYCLE; #endif } }//end of motor running loop }//end of infinite loop return 0; }//end of main function /****************************************************************************** * Function: _ADCInterrupt(void) * * Output: None * * Overview: ADC interrupt used to measure the BEMF signals, reconstruct * the Motor Virtual Neutral Point and compare the BEMF signals * against the neutral point reference to detect the zero-crossing * event * * Note: None *******************************************************************************/ void __attribute__((__interrupt__,auto_psv)) _ADC1Interrupt(void) { ReferenceSpeed = ADC1BUF0; if(ReferenceSpeed < (MIN_DUTY_CYCLE*2)/3) ReferenceSpeed = (MIN_DUTY_CYCLE*2)/3; MotorPhaseA = ADC1BUF1; //ADC CH1 holds the Phase A value MotorPhaseB = ADC1BUF2; //ADC CH2 holds the Phase B value MotorPhaseC = ADC1BUF3; //ADC CH3 holds the Phase C value //Reconstrucs Voltage at the Motor Neutral Point MotorNeutralVoltage = (MotorPhaseA + MotorPhaseB + MotorPhaseC)/3; /********************* ADC SAMPLING & BMEF signals comparison ****************/ if(BlankingCounter > BLANKING_COUNT){ ComparatorOutputs = 0; // Precondition all comparator bits as zeros if(MotorPhaseA > MotorNeutralVoltage) ComparatorOutputs += 1; // Set bit 0 when Phase C is higher than Neutural if(MotorPhaseB > MotorNeutralVoltage) ComparatorOutputs += 2; // Set bit 1 when Phase C is higher than Neutural if(MotorPhaseC > MotorNeutralVoltage) ComparatorOutputs += 4; // Set bit 2 when Phase C is higher than Neutral } AD1CON1bits.DONE = 0; IFS0bits.AD1IF = 0; } /****************************************************************************** * Function: _PWMInterrupt(void) * * Output: None * * Overview: PWM reload interrupt used to filter the BEMF signals using the * Majority detection filter to detect a valid zero-crossing event * if a valid zero-crossing event was detected then PreCommutationState. * This function also includes the start-up sequence for detecting * the initial rotor position * * Note: None *******************************************************************************/ void __attribute__((__interrupt__,auto_psv)) _MPWM1Interrupt(void) { //Sets the ADC sampling point according to the PWM duty cycle //Please refer to AN1160 for details regarding the sampling timing of the BEMF signals if(CurrentPWMDutyCycle>160) P1SECMPbits.SEVTCMP = CurrentPWMDutyCycle>>2; else if(CurrentPWMDutyCycle>76) P1SECMPbits.SEVTCMP = CurrentPWMDutyCycle>>4; else P1SECMPbits.SEVTCMP = 0; //Ramp-up period to detect the rotor position if(Flags.RotorAlignment && Flags.RunMotor) { P1DC1=P1DC2=P1DC3=CurrentPWMDutyCycle; ++PWMticks; } //Check if the Ramp-up value is disabled, if so starts sensorless operation if (++PWMticks>MAX_PWM_TICKS) PreCommutationState(); // Masking the BE MF signals according to the SECTOR in order to determine the ACTIVE BEMF signal // XOR operator helps to determine the direction of the upcoming zero-crossing slope BlankingCounter++; if(BlankingCounter > BLANKING_COUNT) { if((ComparatorOutputs^ADC_XOR[ADCCommState])& ADC_MASK[ADCCommState]) adcBackEMFFilter|=0x01; //Majority detection filter adcBackEMFFilter = ADC_BEMF_FILTER[adcBackEMFFilter]; if (adcBackEMFFilter&0b00000001) PreCommutationState(); } IFS3bits.PWM1IF = 0; } /****************************************************************************** * Function: _T1Interrupt(void) * * Output: None * * Overview: Here is where the motor commutation occurs, * Timer1 ISR is utilized as the commutation delay used to * commutate the motor windings at the right time * * Note: None *******************************************************************************/ void __attribute__((__interrupt__,auto_psv)) _T1Interrupt(void) { P1OVDCON=PWM_STATE[ADCCommState]; BlankingCounter = 0; IFS0bits.T1IF = 0; // Clear Timer 1 Interrupt Flag T1CONbits.TON = 0; // Stop TIMER1 TMR1 = 0; } /****************************************************************************** * Function: PreCommutationState(void) * * Output: None * * Overview: This function measures the 60 and 30 electrical degrees * using the TIMER2. The 60 electrical degrees is proportional * to the elpased time between zero-crossing events. * The zero-crossing events occur 30 electrical degrees in advace * of the commutation point. Hence a delay proportional to the 30 * electrical degrees is added using the TIMER1 * * Note: None *******************************************************************************/ void PreCommutationState(void) { // Calculate the time proportional to the 60 electrical degrees T2CONbits.TON = 0; // Stop TIMER2 Timer2Average = ((Timer2Average + Timer2Value + TMR2)/3); Timer2Value = TMR2; TMR2 = 0; T2CONbits.TON = 1; // Start TIMER2 //Calculate the delay in TIMER1 counts proportional to the Phase Adv angle PhaseAdvance = ((Timer2Average*PHASE_ADVANCE_DEGREES)/60); // Calculate the time proportional to the 30 electrical degrees // Load the TIMER1 with the TIMER1 counts porportional to 30 deg minus the PHASE ADV angle delay Timer1Value = (((Timer2Average)>>1)-PhaseAdvance); if(Timer1Value>1) PR1 = Timer1Value; else PR1 = Timer1Value = 1; // Start TIMER1 T1CONbits.TON = 1; //disabling rotor alignment & ramp-up sequence PWMticks = 0; RampUpCommState = 7; //if Motor is runnining in sensorless mode and the PI button is ON on DMIC window //then the PI controller is enabled if the PI button is OFF then motor runs in open loop if((!Flags.RotorAlignment) && Flags.RunMotor){ #ifdef CLOSELOOPMODE SpeedPILoopController(); #else OpenLoopController(); #endif } // Change The Six-Step Commutation Sector adcBackEMFFilter=0; if (++ADCCommState>6) ADCCommState=1; } /****************************************************************************** * Function: SpeedPILoopController(void) * * Output: None * * Overview: When the PI button is ON on the DMCI window * the motor operates in close loop mode. The Kp and Ki * parameters were determined using the HURST MOTOR shipped with * the MCLV board. These values should be modified according to * the motorand load characteristics. * * Note: None *******************************************************************************/ #ifdef CLOSELOOPMODE void SpeedPILoopController(void) { //For the HURST motor the Timer2Avg values //TIMER2 counts = 142 AT 100% dutycycle (P1DC1 = 734) //TIMER2 counts = 2139 AT 4.9% dutycycle (P1DC1 = 46) //ADC POT RANGE 0-1023 DesiredSpeed = (int)((ReferenceSpeed*3)/2); // Normalizing TIMER2 counts to electrical RPS expressed in PWM counts // Timer 2 Counts are converted to PWM counts // and then multipied by the number of sector // required to complete 1 electrical RPS CurrentSpeed = (int)((long)SPEEDMULT/(long)Timer2Average); //PID controller PIDStructure.controlReference = (fractional)DesiredSpeed; PIDStructure.measuredOutput = (fractional)CurrentSpeed; PID(&PIDStructure); //Max and Min Limits for the PID output if (PIDStructure.controlOutput < MIN_DUTY_CYCLE) // limit PID output PIDStructure.controlOutput = MIN_DUTY_CYCLE; if (PIDStructure.controlOutput > MAX_DUTY_CYCLE) PIDStructure.controlOutput = MAX_DUTY_CYCLE; CurrentPWMDutyCycle = PIDStructure.controlOutput; //set PID output P1DC1 = CurrentPWMDutyCycle; P1DC2 = CurrentPWMDutyCycle; P1DC3 = CurrentPWMDutyCycle; } /****************************************************************************** * Function: OpenLoopController(void) * * Output: None * * Overview: When the PI button is OFF on the DMCI window * the motor operates in open loop mode. * * Note: None *******************************************************************************/ #else void OpenLoopController(void) { //PWM duty cycle = pot value *3/2 DesiredPWMDutyCycle = (ReferenceSpeed*3)/2; //Update the duty cycle according to the POT value, a POT follower is implemented here if(CurrentPWMDutyCycle != DesiredPWMDutyCycle) { if(CurrentPWMDutyCycle < DesiredPWMDutyCycle) CurrentPWMDutyCycle++; if(CurrentPWMDutyCycle > DesiredPWMDutyCycle) CurrentPWMDutyCycle--; } // Max and Min PWM duty cycle limits if (CurrentPWMDutyCycle < MIN_DUTY_CYCLE) CurrentPWMDutyCycle = MIN_DUTY_CYCLE; if (CurrentPWMDutyCycle > MAX_DUTY_CYCLE) CurrentPWMDutyCycle = MAX_DUTY_CYCLE; //Assigning new duty cycles to the PWM channels P1DC1 = CurrentPWMDutyCycle; P1DC2 = CurrentPWMDutyCycle; P1DC3 = CurrentPWMDutyCycle; } #endif /****************************************************************************** * Function: InitADC10(void) * * Output: None * * Overview: Initializes the ADC module to operate in simultaneous mode * sampling terminals AN0,AN1, AN2, AN3 using MUX A. The ADC channels are * assigned as follows in the MCLV board * CH0->AN8 (POT) * CH1->AN3 PHASE A * CH2->AN4 PHASE B * CH3->AN5 PHASE C * ADC is sync with the PWM. ADC is conversion is triggered * every time a PWM reload event occurs. Tadc = 4*TCY = 271.37 nSec. * ADC resulting samples are formatted as unsigned 10-bits * Right-justified * * Note: None *******************************************************************************/ void InitADC10(void) { AD1PCFGL = 0x0; //Port pin multiplexed with AN0-AN8 in Analog mode AD1CON1 = 0x006C; //ADC is off //Continue module operation in Idle mode //10-bit, 4-channel ADC operation //Data Output Format bits Integer (0000 00dd dddd dddd) //011 = Motor Control PWM interval ends sampling and starts conversion //Samples CH0, CH1, CH2, CH3 simultaneously when CHPS<1:0> = 1x //Sampling begins immediately after last conversion SAMP bit is auto-set. AD1CHS123 = 0x0001; //MUX B CH1, CH2, CH3 negative input is VREF- //MUX B CH1 positive input is AN0, CH2 positive input is AN1, CH3 positive input is AN2 //MUX A CH1, CH2, CH3 negative input is VREF- //MUX A CH1 positive input is AN3, CH2 positive input is AN4, CH3 positive input is AN5 AD1CHS0 = 0x0001; //MUX B Channel 0 negative input is VREF- //MUX B Channel 0 positive input is AN0 //MUX A Channel 0 negative input is VREF- //MUX A Channel 0 positive input is AN1 AD1CSSL = 0x0000; //Skip all ANx channels for input scan AD1CON3 = 0x0003; //ADC Clock derived from system clock //Autosample time time bits = 0 TAD since PWM is controlling sampling time //TAD = 4*TCY, TAD = 271.37 nSec AD1CON2 = 0x0300; //ADREF+ = AVDD ADREF- = AVSS //Do not scan inputs //1x = Converts CH0, CH1, CH2 and CH3 //A/D is currently filling buffer 0x0-0x7 //Interrupts at the completion of conversion for each sample/convert sequence //Always starts filling buffer from the beginning //Always uses channel input selects for Sample A AD1CON1bits.DONE = 0; //Making sure that there is any conversion in progress IPC3bits.AD1IP = 5; //Assigning ADC ISR priority IFS0bits.AD1IF = 0; //Clearing the ADC Interrupt Flag IEC0bits.AD1IE = 1; //Enabling the ADC conversion complete interrupt AD1CON1bits.ADON = 1; //Enabling the ADC module } /****************************************************************************** * Function: InitMCPWM(void) * * Output: None * * Overview: Initializes the PWM module to operate in center-aligned mode * at 20KHz. PWM terminals are configured in independent mode. * PWM time base is 67.8 nSec. * PDCx value range is 0-1464 for 0%-100% duty cycle * ADC reload time is variable according to the PWM duty cycle * * * Note: None *******************************************************************************/ void InitMCPWM(void) { P1TPER =((FCY/FPWM)/2 - 1); //FCY 29491200...FRC w/PLL x16 //FPWM 20KHz PWM Freq // MAX_DUTY_CYCLE = 1469 // 50% duty cycle = 734 P1TCONbits.PTSIDL = 1; // PWM time base halted in CPU IDLE mode P1TCONbits.PTOPS = 0; // PWM time base 1:1 postscale P1TCONbits.PTCKPS = 0; // PWM time base 1:1 prescale P1TCONbits.PTMOD = 2; // Center Aligned with single interrupt mode per PWM period // Disable all PWMs using PWM1CON1 register // Writing to PWM1CON1 register requires unlock sequence // Use builtin function to write 0x0700 to PWM1CON1 register //if using compiler version 3.30B or later use line below // __builtin_write_PWMSFR(&PWM1CON1, 0x0700, &PWM1KEY); //else use asm("mov #0xabcd,w10"); // Load first unlock key to w10 register asm("mov #0x4321,w11"); // Load second unlock key to w11 register asm("mov #0x0700,w0"); // Load desired value of PWM1CON1 register in w0 asm("mov w10, PWM1KEY"); // Write first unlock key to PWM1KEY register asm("mov w11, PWM1KEY"); // Write second unlock key to PWM1KEY register asm("mov w0,PWM1CON1"); // Write desired value to PWM1CON1 register P1OVDCON = 0x0000; // allow control using OVD P1SECMPbits.SEVTDIR = 0; // trigger ADC when PWM counter is in upwards dir P1SECMPbits.SEVTCMP = 0; // generates a trigger event for the ADC // when PWM time base is counting upwards // just before reaching the PTPER value // causing a sampling in the middle of the // pulse PWM1CON2 = 0x0000; // 1:1 postscale values // Updates to the active PxDCy registers // are sync to the PWM time base // Output overrides via the PxOVDCON register occur // on the next TCY boundary // Updates from duty cycle and period buffer registers // are enabled IPC14bits.PWM1IP = 4; // PWM Interrupt Priority 4 IFS3bits.PWM1IF=0; // Clearing the PWM Interrupt Flag IEC3bits.PWM1IE=1; // Enabling the PWM interrupt //faultA enabled, FaultB disabled // Writing to P1FLTACON register requires unlock sequence // Use builtin function to write 0x0087 to P1FLTACON register //if using compiler version 3.30B or later use line below // __builtin_write_PWMSFR(&P1FLTACON, 0x0087, &PWM1KEY); //else use asm("mov #0xabcd,w10"); // Load first unlock key to w10 register asm("mov #0x4321,w11"); // Load second unlock key to w11 register asm("mov #0x0087,w0"); // Load desired value of P1FLTACON register in w0 asm("mov w10, PWM1KEY"); // Write first unlock key to PWM1KEY register asm("mov w11, PWM1KEY"); // Write second unlock key to PWM1KEY register asm("mov w0,P1FLTACON"); // Write desired value to P1FLTACON register // Writing to P1FLTBCON register requires unlock sequence // Use builtin function to write 0x0080 to P1FLTBCON register //if using compiler version 3.30B or later use line below //__builtin_write_PWMSFR(&P1FLTBCON, 0x0080, &PWM1KEY); //else use asm("mov #0xabcd,w10"); // Load first unlock key to w10 register asm("mov #0x4321,w11"); // Load second unlock key to w11 register asm("mov #0x0080,w0"); // Load desired value of P1FLTBCON register in w0 asm("mov w10, PWM1KEY"); // Write first unlock key to PWM1KEY register asm("mov w11, PWM1KEY"); // Write second unlock key to PWM1KEY register asm("mov w0,P1FLTBCON"); // Write desired value to P1FLTBCON register IFS3bits.FLTA1IF = 0; IFS4bits.FLTB1IF = 0; P1TCONbits.PTEN = 1; // Enabling the MC PWM module } /****************************************************************************** * Function: InitTMR2(void) * * Output: None * * Overview: Initializes the TIMER2 module to operate in free-running * up counting mode. The TIMER2 time base is Tcy*64= 4.34 uSec. * This timer is used to calculate the motor speed * * Note: None *******************************************************************************/ void InitTMR2(void) { // Tcy = 67.8 nSec TMR2 = 0; // Resetting TIMER PR2 = 0xFFFF; // Setting TIMER periond to the MAX value T2CON = 0x0020; // internal Tcy*64 } /****************************************************************************** * Function: InitTMR1(void) * * Output: None * * Overview: Initializes the TIMER1 module to operate in free-running * up counting mode. The TIMER1 time base is Tcy*64 = 4.34 uSec. * This timer is used to calculate the commutation delay * * Note: None *******************************************************************************/ void InitTMR1(void) { // Tcy = 67.8 nSec TMR1 = 0; // Resentting TIMER PR1 = 10; // Intial commutation delay value 43.4 uSeg T1CON = 0x0020; // internal Tcy*64 IPC0bits.T1IP = 5; // Set Timer 1 Interrupt Priority Level IFS0bits.T1IF = 0; // Clear Timer 1 Interrupt Flag IEC0bits.T1IE = 1; // Enable Timer1 interrupt T1CONbits.TON = 1; // Enable Timer1 } /****************************************************************************** * Function: DelayNmSec(unsigned int N) * * Output: None * * Overview: Delay funtion used for push buttons debounce loop and for the * motor start-up sequence * * Note: None *******************************************************************************/ void DelayNmSec(unsigned int N) { unsigned int j; while(N--) for(j=0;j < MILLISEC;j++); } |
|
相关推荐
1个回答
|
|
或限制在启动序列的PWM信号。因为滑板是一个非常不稳定的负载。我在代码中尝试过这样的东西,但是它没有工作。我想限制斜坡中的pwm占空比,但是当bemf信号出现时,它应该与罐一起工作。谢谢。
以上来自于百度翻译 以下为原文 Or limit the pwm singal at the start up sequence. Becaue a skateboard is a very unstable load. I tried something like this in the code, but it didn't work. I want to limit the pwm duty cycle in the ramp but when the bemf signal occurs it should be work with the pot. thank you void OpenLoopController(void) { if((!Flags.RotorAlignment) && Flags.RunMotor){ // if ramp is off an motor is on, read pot //PWM duty cycle = pot value *3/2 DesiredPWMDutyCycle =(ReferenceSpeed*3)/2; //Update the duty cycle according to the POT value, a POT follower is implemented here if(CurrentPWMDutyCycle != DesiredPWMDutyCycle) { if(CurrentPWMDutyCycle < DesiredPWMDutyCycle) CurrentPWMDutyCycle++; if(CurrentPWMDutyCycle > DesiredPWMDutyCycle) CurrentPWMDutyCycle--; } // Max and Min PWM duty cycle limits if (CurrentPWMDutyCycle < MIN_DUTY_CYCLE) CurrentPWMDutyCycle = MIN_DUTY_CYCLE; if (CurrentPWMDutyCycle > MAX_DUTY_CYCLE) CurrentPWMDutyCycle = MAX_DUTY_CYCLE; P1DC1 = CurrentPWMDutyCycle; P1DC2 = CurrentPWMDutyCycle; P1DC3 = CurrentPWMDutyCycle; } else if(Flags.RotorAlignment && Flags.RunMotor){ // if the ramp is on, set the startup duty to the pwm channels P1DC1 = STARTUP_DUTY; P1DC2 = STARTUP_DUTY; P1DC3 = STARTUP_DUTY; } } #endif void __attribute__((__interrupt__,auto_psv)) _MPWM1Interrupt(void).... //Ramp-up period to detect the rotor position if(Flags.RotorAlignment && Flags.RunMotor) { P1DC1 = P1DC2 = P1DC3 = STARTUP_DUTY; ++PWMticks; .... } |
|
|
|
只有小组成员才能发言,加入小组>>
5234 浏览 9 评论
2026 浏览 8 评论
1950 浏览 10 评论
请问是否能把一个ADC值转换成两个字节用来设置PWM占空比?
3200 浏览 3 评论
请问电源和晶体值之间有什么关系吗?PIC在正常条件下运行4MHz需要多少电压?
2253 浏览 5 评论
771浏览 1评论
659浏览 1评论
有偿咨询,关于MPLAB X IPE烧录PIC32MX所遇到的问题
588浏览 1评论
PIC Kit3出现目标设备ID(00000000)与预期的设备ID(02c20000)不匹配。是什么原因
670浏览 0评论
571浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-20 01:47 , Processed in 1.103431 second(s), Total 77, Slave 61 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号