sensor_three_phase_BLDC.c

Go to the documentation of this file.
00001 /* This file has been prepared for Doxygen automatic documentation generation.*/
00023 #include <ioavr.h>
00024 #include <inavr.h>
00025 #include "sensor_three_phase_BLDC.h"
00026 
00033 unsigned char drvPatternsCCW[] = {
00034   0,    //Stop
00035   // MC_PORT drive config
00036   PDP2_CCW, //Phase2
00037   PDP4_CCW, //Phase4
00038   PDP3_CCW, //Phase3
00039   PDP6_CCW, //Phase6
00040   PDP1_CCW, //Phase1
00041   PDP5_CCW, //Phase5
00042   // Configuration of Output Compare operation for timer 0
00043   COM0P2_CCW, //Phase2
00044   COM0P4_CCW, //Phase4
00045   COM0P3_CCW, //Phase3
00046   COM0P6_CCW, //Phase6
00047   COM0P1_CCW, //Phase1
00048   COM0P5_CCW, //Phase5
00049   // Configuration of Output Compare operation for timer 2
00050   COM2P2_CCW, //Phase2
00051   COM2P4_CCW, //Phase4
00052   COM2P3_CCW, //Phase3
00053   COM2P6_CCW, //Phase6
00054   COM2P1_CCW, //Phase1
00055   COM2P5_CCW  //Phase5
00056 };
00057 
00058 
00059 
00066 unsigned char drvPatternsCW[] = {
00067   0,    //Stop
00068   // MC_PORT drive config
00069   PDP2_CW, //Phase2
00070   PDP6_CW, //Phase6
00071   PDP1_CW, //Phase1
00072   PDP4_CW, //Phase4
00073   PDP3_CW, //Phase3
00074   PDP5_CW,  //Phase5
00075   // Configuration of Output Compare operation for timer 0
00076   COM0P2_CW, //Phase2
00077   COM0P6_CW, //Phase6
00078   COM0P1_CW, //Phase1
00079   COM0P4_CW, //Phase4
00080   COM0P3_CW, //Phase3
00081   COM0P5_CW,  //Phase5
00082   // Configuration of Output Compare operation for timer 2
00083   COM2P2_CW, //Phase2
00084   COM2P6_CW, //Phase6
00085   COM2P1_CW, //Phase1
00086   COM2P4_CW, //Phase4
00087   COM2P3_CW, //Phase3
00088   COM2P5_CW  //Phase5
00089 };
00090 
00091 
00092 
00094 __regvar __no_init unsigned char *pDrvPattern @14;
00095 //__regvar __no_init unsigned char *pComPattern @12;
00096 
00097 
00098 
00100 __regvar __no_init union _fastTemp{
00101   unsigned int word;
00102   struct{
00103     unsigned char LByte;
00104     unsigned char HByte;  //Hbyte = Zero
00105   };
00106 } fastTemp @12;
00107 
00108 __regvar __no_init unsigned char hallMask @11; 
00109 __regvar __no_init unsigned char count @10; 
00110 
00111 
00112 
00127 #pragma vector = PCINT0_vect
00129 __interrupt void PCINT0_ISR( void )
00130 {
00131   unsigned char *pTemp;
00132   fastTemp.word = ((PIN_HALL & hallMask)>>1);  // Read Hall, Mask Pins, shift to use as pointer offset
00133 //  Line below is desirable performance wise, but causes an internal error in compiler
00134 //  fastTemp.LByte = (PIN_HALL & HALL_MASK)>>1;   // Read Hall, Mask Pins, shift to use as pointer offset
00135 
00136   pTemp = pDrvPattern + fastTemp.word;
00137 //  TCCR0A = fastTemp.HByte; //Disable PWM outputs (and thereby close low side FET)
00138 //  TCCR2A = fastTemp.HByte; //Disable PWM output (and thereby close low side FET)
00139 
00140   PORT_MC = *(pTemp);    //Change drive levels on high side
00141 
00142   TCCR0A = *(pTemp + PATTERN_COM0_OFFSET);    // Reconfigure output compare operation for T0
00143   TCCR2A = *(pTemp + PATTERN_COM2_OFFSET); // Reconfigure output compare operation for T2
00144   count--;
00145 }
00146 
00147 
00148 
00158 static void Init_MC_pin_change_interrupt( void )
00159 {
00160   PCMSK0 = (1<<PCINT1)|(1<<PCINT2)|(1<<PCINT3); //Enable pin change interrupt on PB1:3
00161   PCICR = 1<<PCIE0;    // Enable pin change interrupt0 (PORTB)
00162 }
00163 
00164 
00165 
00176 unsigned char Get_ADC8(unsigned char muxSetting)
00177 {
00178     ADMUX = muxSetting;
00179     // Start AD conversion.
00180     ADCSRA |= (1 << ADSC);
00181     // Wait for ADC conversion to complete.
00182     while ( ADCSRA & (1 << ADSC) );
00183     return ADCH;
00184 }
00185 
00186 
00188 
00199 static void Init_MC_timers( void )
00200 {
00201   //Timer Counter 0. OCRA and OCRB used for motor
00202   TCCR0A = (1<<COM0A1)|(0<<COM0A0)|        // Clear OCRA on compare match
00203            (1<<COM0B1)|(0<<COM0B0)|        // Clear OCRB on compare match
00204            (1<<WGM01)|(1<<WGM00);         // Fast PWM mode
00205   TCCR0B = (0<<FOC0A)|(0<<FOC0B)|
00206            (0<<WGM02)|                     // Fast PWM mode
00207            (0<<CS02)|(0<<CS01)|(1<<CS00); // Prescaler = CLK/1
00208 
00209   //Timer Counter 2. OCRA and OCRB used for motor
00210   TCCR2A = (0<<COM2A1)|(0<<COM2A0)|        // OCRA not connected
00211            (1<<COM2B1)|(0<<COM2B0)|        // Clear OCRB on compare match
00212            (1<<WGM01)|(1<<WGM00);         // Fast PWM mode
00213   TCCR2B = (0<<FOC2A)|(0<<FOC2B)|
00214            (0<<WGM22)|                     // Fast PWM mode
00215            (0<<CS22)|(0<<CS21)|(1<<CS20); // Prescaler = CLK/1
00216 
00217   // Synchronize timers
00218   TCNT0 = 0;
00219   TCNT2 = 3;
00220 
00221   TIFR0 = TIFR0;    // Clear TC0 interrupt flags
00222   TIFR1 = TIFR1;    // Clear TC2 interrupt flags
00223 }
00224 
00225 
00226 
00238 static void Init_ADC( void )
00239 {
00240   ADCSRA = (1 << ADEN) | (1 << ADPS1); // Enable ADC, clock prescaler = 4
00241 }
00242 
00243 
00244 
00256 static void Set_Speed(unsigned char speed)
00257 {
00258   TIFR0 = TIFR0;    // Clear TC0 interrupt flags
00259   while( !(TIFR0 & (1<<TOV0)));  // Wait for TOV to ensure that all registers are
00260                             //  updated in the same timer cycle
00261   __disable_interrupt();
00262   OCR0A = speed;        // Change the duty cycle
00263   OCR0B = speed;
00264   OCR2B = speed;
00265   __enable_interrupt();
00266 }
00267 
00268 
00269 
00281 static void Set_Direction(unsigned char direction)
00282 {
00283   if(direction == CLOCKWISE)
00284   {
00285     __disable_interrupt();        //Variable also used in interrupt and access most be protected
00286     pDrvPattern = drvPatternsCW;   // Set dir to CW, by pointing to CW pattern
00287     __enable_interrupt();
00288   }
00289   else
00290   {
00291     __disable_interrupt();        //Variable also used in interrupt and access most be protected
00292     pDrvPattern = drvPatternsCCW;   // Set dir to CCW, by pointing to CCW pattern
00293     __enable_interrupt();
00294   }
00295 }
00296 
00297 
00308 void main( void )
00309 {
00310   unsigned char speed = 0;
00311   unsigned char setspeed = 0;
00312   signed int current;
00313   MCUCR |= (1<<PUD);  // Disable all pull-ups
00314   hallMask = HALL_MASK; // Initialize hallMask variable
00315   //Set initial direction.
00316   Set_Direction( CLOCKWISE );
00317 
00318   Init_MC_timers();
00319   Init_MC_pin_change_interrupt();
00320   Init_ADC();
00321 
00322   DDR_HALL |= HALL_MASK;    //Lock HALL sensor by driving Hall lines
00323   PORT_HALL |= HALL_MASK;
00324   PORT_HALL &= ~HALL_MASK;  //Release HALL sensor lines and trigger PC interrupt
00325   DDR_HALL &= ~HALL_MASK;
00326   __enable_interrupt();
00327   Set_Speed(speed);
00328   DDR_MC = MC_MASK;        // Enable outputs
00329 
00330   DDRC |= (1<<PC1);
00331   for(;;) {
00332     // Get shunt voltage (current measurement)
00333     current = Get_ADC8(ADC_MUX_SHUNT_H);
00334     // If current consumption is too high, limit current
00335     if (current > MAX_CURRENT_ADC )
00336     {
00337       PORTC &= ~(1<<OVERCURRENT_PIN);   //Turn on over-current LED (active low)
00338       if( speed >= 2 )
00339       {
00340         speed -= 2; // Slow down if too fast.
00341       }
00342     }
00343     else
00344     {
00345       PORTC |= (1<<OVERCURRENT_PIN); // Turn off over-current LED (active low)
00346       // Get speed reference voltage (Assumes 2.5V to be maximum analog input,
00347       // multiplied by 2 to convert to PWM range).
00348       setspeed = Get_ADC8(ADC_MUX_SPEED_REF)*2;
00349       // Approach speed set point.
00350       if( setspeed > speed )
00351       {
00352         ++speed;
00353       }
00354       else
00355       {
00356         if( setspeed < speed )
00357         {
00358           --speed;
00359         }
00360       }
00361     }
00362 
00363     Set_Speed(speed);
00364   }
00365 }
00366 

Generated on Tue Sep 18 08:53:11 2007 for AVR443 Sensor-based control of three phase Brushless DC Motor by  doxygen 1.4.7