This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSP430G2553: PID controller in MSP430 for BLDC

Part Number: MSP430G2553
Other Parts Discussed in Thread: LM331,

Hi! I'm trying to use a discrete PID with PWM for a BLDC  motor, the way I obtain the speed of the motor is via an encoder that I built my self  and the frequency that is generated by the optocoupler goes to an LM331(frecuency to voltage convert), and with that voltage generated I'm trying to obtain the speed of the motor through the ADC10, but the problem is that my PID does whatever it wants, even it ignores my Set Point. I checked up other existing codes (from other microcontrollers), and they seem to work well, I want to remark that the PID is already tuned up with Ziegler-Nichols Method.


#include "io430.h"
unsigned int adc,v,out;
float sp=380; //The equivalent voltage from "x" quantity of Hz or RPM
float ak=0,ak_1=0,ek=0,ek_1=0,ek_2=0,ki=0,kp=0,kd=0,q0=0,q1=0,q2=0,ti=0,td=0;
float u=0,u_1=0;
float T=0.0002;
float thao = 1.2,theta =.5,k=.958;


int main( void )
{

BCSCTL1 = CALBC1_16MHZ;
DCOCTL = CALDCO_16MHZ;
WDTCTL = WDTPW + WDTHOLD;
__bis_SR_register(GIE);
/*P1SEL = 0X00;
P1DIR |= BIT0;*/



TACTL = TASSEL_2+MC_1+TAIE;
TACCR0 = 10666; //Sampling Frecuency 5 Khz


TA1CTL = TASSEL_1+MC_1;
TA1CCR0 =385;       //85 Hz PWM
TA1CCTL1 = OUTMOD_7;
P2SEL |= BIT1;
P2DIR |= BIT1;


kp=(1.2*thao)/(k*theta);
ti=2*theta;
td=0.5*theta;

q0=kp*(1+T/(2*ti)+td/T);
q1=-kp*(1-T/(2*ti)+(2*td)/T);
q2=(kp*td)/T;


ADC10CTL0=SREF_0+ADC10SHT_3+ADC10IE+ADC10ON;
ADC10CTL1=INCH_0+CONSEQ0;
ADC10AE0 |=BIT0;

while(1)
{


ADC10CTL0 |= ENC+ADC10SC;

}


}

#pragma vector=TIMER0_A1_VECTOR
__interrupt void Timer0(void){
switch( TAIV ){
case 2: break; // CCR1 not used
case 4: break; // CCR2 not used
case 10:

ek=sp-v;
u = u_1 + q0*ek + q1*ek_1 + q2*ek_2;
//if (u >= 3300)u=1500;
//if (u <= 0) u=0;

out = u*385/1500;

ek_2=ek_1;
ek_1=ek;
u_1=u;
TA1CCR1 = out;



break;
}
}
#pragma vector=ADC10_VECTOR
__interrupt void ADC10(void){

adc=ADC10MEM;

v=adc*3300/1024;
__delay_cycles(500);
}

  • Hi Aldo,

    MSP430 has no floating point arithmetic by HW so I could imagine that all the calculations you do in the ISRs taking too long and killing your code execution.

    I mean the G2553 also does not have a HW multiplier so all the complicated multiplications like u = u_1 + q0*ek + q1*ek_1 + q2*ek_2; are heavily CPU consuming

    See also:

  • You are right!, let me prove it, I will tell you if it works, another question if it Is posible, Do you recommend me to use volatile variables for this software? Because the MCU Is going yo change the variables constantly. Thank you very much!
  • Hi Aldo,
    I don't think this makes a big difference but adds risk then you SW needs to control when which function is changing the varialbes.
    Might make sense in such a short program where the variables are well under control but if multiple functions espeically called in interrupts access and change the same variable it is dangerous in case you cannot properly sync up the calls.
  • Hello Aldo,

    first of all,

    I have no doubts that it is possible to do very good PID on a shiny MSP430G2553.

    Two major concepts to get your PID running:

    - fast computing is needed when we contorol quickly chanching processes. If load of your BLDC is changing not more than , lets say, 5% within a one second interval and, depending on your tollerance for BLDC speed, might be possible that you would need to calculate PWM values 50, 20 or 10 times per second. In other words, you can measure rotation speed 5000 times per second, however time comes to set new PWM value, you should use an average from your last 100, 250 or 500 readings! Moreover, you should not do this calculations within an interrupt

    - you build software for a digitized world, you have ADC10 10 bits inputs and 8/16 bits outputs. It is possible to refactor your float values, like float T=0.0002, to a signed 32 bits values and to do all calculations using 32 bits long.

    Other hints:

    - remove unused variables to save fast RAM

    - locally used variables declare locally, it will put them on a stack which uses fast RAM

    - based on an available RAM, you would be able to move most CPU extencive calculations to RAM, like div32, mult32, they are small objects:

    however, it would require a dive to RTS library
    - use a CCS clock count feature to estimate a code execution time. 

    Last two issues:

    - if you post a code, use "Insert Code, Attach Files and more..." and than "</>" to utilize Syntaxhighlighter,

    - two or three days ago, I have moved from Mozilla to Chrome because TIREX and GUI composer are based on Chrome and javascript tools. Moreover, Mozilla has terrible issues memory management and probably, garbage collector, and after 5 days without restart she allocates even more then 10 GB of memory. In terms of memory handling, Chrome looks much better than Mozilla.

    My issue is that when I am writing response to you a spell checker puts 50% of my text in doubts. Under Mozilla, a spell checker was almost perfect.

    What do I need to do to have a good spell checking when using Chrome?

  • I didn't know that exists CCS for MSP, I use IAR Embedded for programming and for simulations I Will try your advices, to make a More eficiente PID, because I modified my last code and now it's working , but I want it Caster . Thanks
    You have been really helpful.
    Greetings .
  • What have you changed to get it working?
    As I remember you were not using ki.

    github.com/.../FastPID
    www.embedded.com/.../PID-without-a-PhD
  • Hi Aldo,

    I assume this thread is resolved and can be closed if there is anything open pls open a new one and refer to this one. Thanks!

**Attention** This is a public forum