mc_drv.c

Go to the documentation of this file.
00001 
00013 #include "config.h"
00014 #include "config_motor.h"
00015 
00016 #include "mc_drv.h"
00017 #include "mc_interface.h"
00018 #include "mc_control.h"
00019 
00020 #include "adc\adc_drv.h"
00021 #include "dac\dac_drv.h"
00022 #include "amplifier\amplifier_drv.h"
00023 #include "pll\pll_drv.h"
00024 #include "comparator\comparator_drv.h"
00025 
00026 static U8 count = 1;     
00027 static U16 average = 0;  
00028 static U8 ovf_timer = 0; 
00029 
00030 static Bool g_mc_read_enable = FALSE;  // the speed can be read
00031 Bool g_tick = FALSE;             
00032 
00033 static Bool delay_armed = FALSE;
00034 static U8 delay_30d = 0;
00035 volatile S16 comp_delay_30d = MIN_DELAY;
00036 static U8 count_sub_tick = 8;
00037 static U8 delay_mask = 0;
00038 
00039 static S32 Num_turn = 0; 
00040 static U8 hall_state = 0;
00041 
00042 static char State = CONV_INIT; 
00043 static char ADC_State = FREE;  
00044 
00045 
00046 /**********************************************************************************/
00047 /**********************************************************************************/
00048 /*               Hardware Initialization                                          */
00049 /**********************************************************************************/
00050 /**********************************************************************************/
00051 
00057 void mc_init_HW(void)
00058 {
00059   mc_init_port();
00060   mc_init_IT();
00061 
00062   // Be careful : initialize DAC and Over_Current before PWM.
00063   init_dac();
00064   mc_set_Over_Current(200); // 5 => 1A ; 8 => 40A
00065   mc_init_pwm();
00066 
00067   mc_config_time_estimation_speed();
00068   mc_config_sampling_period();
00069 
00070   init_comparator0();
00071   init_comparator1();
00072   init_comparator2();
00073 }
00074 
00080 void mc_init_SW(void)
00081 {
00082   Enable_interrupt();
00083 }
00084 
00090 void mc_init_port(void)
00091 {
00092   // Output Pin configuration
00093   // PD0 => H_A     PB7 => L_A
00094   // PC0 => H_B     PB6 => L_B
00095   // PB0 => H_C     PB1 => L_C
00096 
00097   //Do not modify PSCOUT Configuration
00098   // PORT B :
00099   DDRB = (1<<DDB7)|(1<<DDB6)|(1<<DDB3)|(1<<DDB1)|(1<<DDB0);
00100   // PORT C :
00101   DDRC = (1<<DDC0);
00102   // PORT D :
00103   DDRD = (1<<DDD0);
00104 
00105 
00106   // DDnx = 0:Input 1:Output    (n = B,C,D,E ; x = 0,1,2,3,4,5,6,7)
00107   // PB3 => EXT1                        PB4 => EXT2
00108   // PC1 => EXT3                        PC2 => EXT4
00109   // PB5 => EXT5/POT                    PE1 => EXT6
00110   // PD3 => EXT7/MOSI/LIN_TxD/TxD       PD4 => EXT8/MISO/LIN_RxD/RxD
00111   // PE0 => EXT9/NRES                   PD2 => EXT10/MISO
00112 
00113   // Modify DDnx according to your hardware implementation
00114   // PORT B :
00115   DDRB |= (0<<DDB5)|(1<<DDB4)|(0<<DDB3);
00116   // PORT C :
00117   DDRC |= (0<<DDC2)|(0<<DDC1);
00118     // PORT D :
00119   DDRD |= (0<<DDD4)|(0<<DDD3)|(0<<DDD2); // Becareful if using the UART interface or JTAGE ICE mkII.
00120   // PORT E :
00121   DDRE |= (1<<DDE2)|(0<<DDE1)|(0<<DDE0); // Becareful PE0 is you by JTAGE ICE mkII.
00122 
00123 
00124   // Warning Output Low for MOSFET Drivers
00125   PORTB &= ~(1<<PORTB7 | 1<<PORTB6 | 1<<PORTB3 |1<<PORTB1 | 1<<PORTB0);
00126   PORTC &= ~(1<<PORTC0);
00127   PORTD &= ~(1<<PORTD0);
00128 
00129   // pull up activation
00130   PORTC |= (1<<PORTC6)|(1<<PORTC1);
00131   PORTD |= (1<<PORTD7)|(1<<PORTD5)|(1<<PORTD1);
00132 
00133   // Disable Digital Input for amplifier1
00134   // Digitals Inputs for comparators are not disable.
00135   DIDR0 = (0<<ADC6D)|(0<<ADC3D)|(0<<ADC2D);
00136   DIDR1 = (0<<ACMP0D)|(0<<ACMP1D)|(1<<AMP1PD)|(1<<AMP1ND);
00137 }
00138 
00144 void mc_init_pwm()
00145 {
00146   Start_pll_32_mega();
00147   Wait_pll_ready();
00148 
00149   // In Center Aligned Mode :
00150   // => PSCx_Init(Period_Half, Dutyx0_Half, Synchro, Dutyx1_Half)
00151 #ifdef MCU_REV_B
00152   PSC0_Init(255,0,255,0);
00153   PSC1_Init(255,0,255,0);
00154   PSC2_Init(255,0,255,0);
00155 #else
00156   PSC0_Init(255,0,1,0);
00157   PSC1_Init(255,0,1,0);
00158   PSC2_Init(255,0,1,0);
00159 #endif
00160 
00161 }
00162 
00168 void mc_init_IT(void)
00169 {
00170   EICRA =(0<<ISC21)|(1<<ISC20)|(0<<ISC11)|(1<<ISC10)|(0<<ISC01)|(1<<ISC00);
00171   EIFR = (1<<INTF2)|(1<<INTF1)|(1<<INTF0); // clear possible IT due to config
00172   EIMSK=(1<<INT2)|(1<<INT1)|(1<<INT0);
00173 }
00174 
00175 // PSC initialization depend on the PSC mode
00176 //  0- One ramp Mode
00177 //  1- Two ramp Mode
00178 //  2- Four ramp Mode
00179 //  3- Center Aligned Mode
00180 
00184 void PSC0_Init ( unsigned int OCRnRB,
00185                  unsigned int OCRnSB,
00186                  unsigned int OCRnRA,
00187          unsigned int OCRnSA)
00188 {
00189   OCR0SAH = HIGH(OCRnSA);
00190   OCR0SAL = LOW(OCRnSA);
00191   OCR0RAH = HIGH(OCRnRA);
00192   OCR0RAL = LOW(OCRnRA);
00193   OCR0SBH = HIGH(OCRnSB);
00194   OCR0SBL = LOW(OCRnSB);
00195   OCR0RBH = HIGH(OCRnRB);
00196   OCR0RBL = LOW(OCRnRB);
00197 
00198   PCNF0 =  RAMP_MODE_NUMBER | (1<<PCLKSEL0) | OUTPUT_ACTIVE_HIGH ;
00199   /* use PSC 0  Input A as Fault Input */
00200   PFRC0A = (1<<PELEV0A)|(1<<PFLTE0A)|(0<<PRFM0A3)|(1<<PRFM0A2)|(1<<PRFM0A1)|(1<<PRFM0A0);
00201 //  PFRC0A = 0;
00202   PFRC0B = 0;
00203   PSOC0 = (1<<PSYNC00); //Send signal on match with OCRnSA (during counting up of PSC)
00204   PCTL0 = (0<<PAOC0A)|(1<<PARUN0)|PRESC_DIV_BY_4; /* AUTORUN !! */
00205 }
00206 
00210 void PSC1_Init ( unsigned int OCRnRB,
00211                  unsigned int OCRnSB,
00212                  unsigned int OCRnRA,
00213          unsigned int OCRnSA)
00214 {
00215   OCR1SAH = HIGH(OCRnSA);
00216   OCR1SAL = LOW(OCRnSA);
00217   OCR1RAH = HIGH(OCRnRA);
00218   OCR1RAL = LOW(OCRnRA);
00219   OCR1SBH = HIGH(OCRnSB);
00220   OCR1SBL = LOW(OCRnSB);
00221   OCR1RBH = HIGH(OCRnRB);
00222   OCR1RBL = LOW(OCRnRB);
00223 
00224   PCNF1 =  RAMP_MODE_NUMBER | (1<<PCLKSEL1) | OUTPUT_ACTIVE_HIGH ;
00225   PFRC1A = 0;
00226   PFRC1B = 0;
00227   PCTL1 = (0<<PAOC1A)|(1<<PARUN1)|PRESC_DIV_BY_4; /* AUTORUN !! */
00228 }
00229 
00230 
00234 void PSC2_Init ( unsigned int OCRnRB,
00235                  unsigned int OCRnSB,
00236                  unsigned int OCRnRA,
00237          unsigned int OCRnSA)
00238 {
00239   OCR2SAH = HIGH(OCRnSA);
00240   OCR2SAL = LOW(OCRnSA);
00241   OCR2RAH = HIGH(OCRnRA);
00242   OCR2RAL = LOW(OCRnRA);
00243   OCR2SBH = HIGH(OCRnSB);
00244   OCR2SBL = LOW(OCRnSB);
00245   OCR2RBH = HIGH(OCRnRB);
00246   OCR2RBL = LOW(OCRnRB);
00247 
00248   PCNF2 =  RAMP_MODE_NUMBER | (1<<PCLKSEL2) | OUTPUT_ACTIVE_HIGH ;
00249   PFRC2A = 0;
00250   PFRC2B = 0;
00251 //  PCTL2 = (0<<PAOC2A)|(1<<PRUN2)|PRESC_DIV_BY_4; /* RUN !! */
00252 }
00253 
00254 /**********************************************************************************/
00255 /*                   PSC Stop                                                     */
00256 /**********************************************************************************/
00257 /*  This function stops the PSCs :                                                */
00258 /**********************************************************************************/
00259 void PSC_Stop(void)
00260 {
00261    Set_none();
00262    PCTL2 = (1<<PCCYC2);
00263 }
00264 
00265 /**********************************************************************************/
00266 /*                   PSC Run                                                     */
00267 /**********************************************************************************/
00268 /*  This function starts the PSCs :                                               */
00269 /**********************************************************************************/
00270 void PSC_Run(void)
00271 {
00272   PCTL2 = (0<<PAOC2A)|(1<<PRUN2)|PRESC_DIV_BY_4; /* RUN !! */
00273 }
00274 
00275 /**********************************************************************************/
00276 /**********************************************************************************/
00277 /*         All functions for motor's phases commutation                           */
00278 /**********************************************************************************/
00279 /**********************************************************************************/
00280 
00288 U8 mc_get_hall(void)
00289 {
00290   return HALL_SENSOR_VALUE(); /* sensor */
00291 //  return ((~HALL_SENSOR_VALUE())&0x07); /* sensorless */
00292 }
00293 
00300 #pragma vector = HALL_A()
00301 __interrupt void mc_hall_a(void)
00302 {
00303 
00304   delay_armed = TRUE;
00305   delay_30d = comp_delay_30d;
00306 
00307   //estimation speed on rising edge of Hall_A
00308 #ifdef USE_INTERNAL_COMPARATORS
00309   if (ACSR&(1<<AC0O))
00310 #else
00311   if (PIND&(1<<PORTD7))
00312 #endif
00313   {
00314     mc_estimation_speed();
00315     g_mc_read_enable=FALSE; // Wait 1 period
00316   }
00317   else
00318   {
00319     g_mc_read_enable=TRUE;
00320   }
00321 
00322 
00323   switch(hall_state)
00324   {
00325   case 2 : Num_turn++;break;
00326   case 3 : Num_turn--;break;
00327   default: break;
00328   }
00329   hall_state = 1;
00330 }
00331 
00338 #pragma vector = HALL_B()
00339 __interrupt void mc_hall_b(void)
00340 {
00341 
00342   delay_armed = TRUE;
00343   delay_30d = comp_delay_30d;
00344 
00345   switch(hall_state)
00346   {
00347   case 1 : Num_turn--;break;
00348   case 3 : Num_turn++;break;
00349   default: break;
00350   }
00351   hall_state = 2;
00352 }
00353 
00360 #pragma vector = HALL_C()
00361 __interrupt void mc_hall_c(void)
00362 {
00363 
00364   delay_armed = TRUE;
00365   delay_30d = comp_delay_30d;
00366 
00367   switch(hall_state)
00368   {
00369   case 2 : Num_turn--;break;
00370   case 1 : Num_turn++;break;
00371   default: break;
00372   }
00373   hall_state = 3;
00374 }
00375 
00379 void mc_duty_cycle(U8 level)
00380 {
00381   U8 duty;
00382   duty = level;
00383 
00384   PCNF0 = SET_PLOCK | RAMP_MODE_NUMBER |(1<<PCLKSEL0)|(1<<POP0); /* set plock */
00385   PCNF1 = SET_PLOCK | RAMP_MODE_NUMBER |(1<<PCLKSEL1)|(1<<POP1); /* set plock */
00386   PCNF2 = SET_PLOCK | RAMP_MODE_NUMBER |(1<<PCLKSEL2)|(1<<POP2); /* set plock */
00387 
00388   // Duty = 0   => Duty Cycle   0%
00389   // Duty = 255 => Duty Cycle 100%
00390 
00391   // Set the duty cycle for PSCn0
00392   OCR0SAH = 0;
00393   OCR0SAL = 255 - duty;
00394 
00395   OCR1SAH = 0;
00396   OCR1SAL = 255 - duty;
00397 
00398   OCR2SAH = 0;
00399   OCR2SAL = 255 - duty;
00400 
00401   // Set the duty cycle for PSCn1 according to the PWM strategy
00402   #ifdef HIGH_AND_LOW_PWM
00403   // apply PWM on high side and low side switches
00404     OCR0SBH = 0;
00405     OCR0SBL = 255 - duty  ;
00406 
00407     OCR1SBH = 0;
00408     OCR1SBL = 255 - duty  ;
00409 
00410     OCR2SBH = 0;
00411     OCR2SBL = 255 - duty  ;
00412   #else
00413   // PWM is only applied on high side switches
00414   // 100% duty cycle on low side switches
00415     OCR0SBH = 0;
00416     OCR0SBL = 2;
00417 
00418     OCR1SBH = 0;
00419     OCR1SBL = 2;
00420 
00421     OCR2SBH = 0;
00422     OCR2SBL = 2;
00423   #endif
00424 
00425   Disable_interrupt();
00426   PCNF0 = RELEASE_PLOCK | RAMP_MODE_NUMBER |(1<<PCLKSEL0)|(1<<POP0); /* release plock */
00427   PCNF1 = RELEASE_PLOCK | RAMP_MODE_NUMBER |(1<<PCLKSEL1)|(1<<POP1); /* release plock */
00428   PCNF2 = RELEASE_PLOCK | RAMP_MODE_NUMBER |(1<<PCLKSEL2)|(1<<POP2); /* release plock */
00429   Enable_interrupt();
00430 }
00431 
00438 void mc_switch_commutation(U8 position)
00439 {
00440   // get the motor direction to commute the right switches.
00441   char direction = mci_get_motor_direction();
00442 
00443   // Switches are commuted only if the user start the motor and
00444   // the speed consign is different from 0.
00445   if ((mci_motor_is_running()) && (mci_get_motor_speed()!=0))
00446   {
00447     mc_duty_cycle(mc_get_Duty_Cycle());
00448     switch(position)
00449     {
00450     // cases according to rotor position
00451       case HS_001:  if (direction==CCW)  {Set_Q3Q2();}
00452                     else                 {Set_Q5Q2();}
00453                     break;
00454 
00455       case HS_101:  if (direction==CCW)  {Set_Q5Q2();}
00456                     else                 {Set_Q5Q4();}
00457                     break;
00458 
00459       case HS_100:  if (direction==CCW)  {Set_Q5Q4();}
00460                     else                 {Set_Q1Q4();}
00461                     break;
00462 
00463       case HS_110:  if (direction==CCW)  {Set_Q1Q4();}
00464                     else                 {Set_Q1Q6();}
00465                     break;
00466 
00467       case HS_010:  if (direction==CCW)  {Set_Q1Q6();}
00468                     else                 {Set_Q3Q6();}
00469                     break;
00470 
00471       case HS_011:  if (direction==CCW)  {Set_Q3Q6();}
00472                     else                 {Set_Q3Q2();}
00473                     break;
00474       default : break;
00475       }
00476   }
00477   else
00478   {
00479     Set_none(); // all switches are switched OFF
00480   }
00481 }
00482 
00483 /********************************************************************/
00484 /********************************************************************/
00485 /*         TIMER 1 :    Sampling time configuration                 */
00486 /********************************************************************/
00487 /********************************************************************/
00488 
00495 void mc_config_sampling_period(void)
00496 {
00497   TCCR1A = 0;         /* Normal port operation + Mode CTC */
00498   TCCR1B = 1<<WGM12 | 1<<CS11 | 1<<CS10 ; /* Mode CTC + prescaler 64 */
00499   TCCR1C = 0;
00500   OCR1AH = 0;
00501   OCR1AL = 7;         /* 31.25 µS */
00502   TIMSK1=(1<<OCIE1A); /* Output compare B Match interrupt Enable */
00503 }
00504 
00511 #pragma vector = TIMER1_COMPA_vect
00512 __interrupt void timer1_periodic_interrupt(void)
00513 {
00514   count_sub_tick --;
00515   if (count_sub_tick == 0)
00516   {
00517     g_tick = TRUE;
00518     count_sub_tick = 8;
00519   }
00520 
00521   if (delay_armed == TRUE)
00522   {
00523     delay_30d --;
00524     if (delay_30d == 0)
00525     {
00526       delay_armed = FALSE;
00527       delay_mask = MASK_DEMAG;
00528       Disable_comparator0_interrupt();
00529       Disable_comparator1_interrupt();
00530       Disable_comparator2_interrupt();
00531       mc_switch_commutation(HALL_SENSOR_VALUE());
00532     }
00533   }
00534   if (delay_mask != 0)
00535   {
00536     delay_mask --;
00537     if (delay_mask == 0)
00538     {
00539       ACSR = (1<<AC2IF)|(1<<AC1IF)|(1<<AC0IF);
00540       Enable_comparator0_interrupt();
00541       Enable_comparator1_interrupt();
00542       Enable_comparator2_interrupt();
00543     }
00544   }
00545 }
00546 
00547 /********************************************************************/
00548 /********************************************************************/
00549 /*       TIMER 0 :  Estimation speed                                */
00550 /********************************************************************/
00551 /********************************************************************/
00552 
00559 void mc_config_time_estimation_speed(void)
00560 {
00561   TCCR0A = 0;
00562   TCCR0B = (0<<CS02)|(1<<CS01)|(1<<CS00); // 64 prescaler (8us)
00563   TIMSK0 = (1<<TOIE0);
00564 }
00565 
00571 #pragma vector = TIMER0_OVF_vect
00572 __interrupt void ovfl_timer(void)
00573 {
00574   TCNT0=0x00;
00575   ovf_timer++;
00576   // if they are no commutation after 125 ms
00577   // 125 ms = (61<<8) * 8us
00578   if(ovf_timer >= 100)
00579   {
00580     ovf_timer = 0;
00581     mci_store_measured_speed(0);
00582   }
00583 }
00584 
00590 void mc_estimation_speed(void)
00591 {
00592   U16 timer_value;
00593   U32 new_measured_speed;
00594 
00595   if (g_mc_read_enable==OK)
00596   {
00597     // Two 8 bits variables are use to simulate a 16 bits timers
00598     timer_value = (ovf_timer<<8) + TCNT0;
00599 
00600     /* compute delay for 30 degres */
00601     comp_delay_30d = (timer_value / 94) - FILTER_DELAY;
00602     /* apply a saturation */
00603     if (comp_delay_30d < (S16)MIN_DELAY) comp_delay_30d = MIN_DELAY;
00604     else if (comp_delay_30d > (S16)MAX_DELAY) comp_delay_30d = MAX_DELAY;
00605 
00606     if (timer_value == 0) {timer_value += 1 ;} // warning DIV by 0
00607     new_measured_speed = K_SPEED / timer_value;
00608     if(new_measured_speed > 255) new_measured_speed = 255; // Variable saturation
00609 
00610 
00611       // To avoid noise an average is realized on 16 samples
00612       average += new_measured_speed;
00613       if(count >= 16)
00614       {
00615         count = 1;
00616         mci_store_measured_speed(average >> 4);
00617         average = 0;
00618       }
00619       else count++;
00620 
00621     // Reset Timer 0 register and variables
00622     TCNT0=0x00;
00623     ovf_timer = 0;
00624     g_mc_read_enable=KO;
00625   }
00626 }
00627 
00628 /********************************************************************/
00629 /********************************************************************/
00630 /*     ADC         use for current measure and potentiometer...     */
00631 /********************************************************************/
00632 /********************************************************************/
00633 
00639 #pragma vector = ADC_vect
00640 __interrupt void ADC_EOC(void)
00641 {
00642   if(State == CONV_CURRENT) mci_store_potentiometer_value(Adc_get_8_bits_result());
00643   if(State == CONV_POT) mci_store_measured_current(Adc_get_10_bits_result());
00644   ADC_State = FREE;
00645 }
00646 
00652 void mc_ADC_Scheduler(void)
00653 {
00654   switch(State)
00655   {
00656   case CONV_INIT :
00657     init_adc();
00658     init_amp1();
00659     ADC_State = FREE;
00660     State = CONV_POT;
00661     break;
00662 
00663   case CONV_POT :
00664     if(ADC_State == FREE)
00665     {
00666       ADC_State = BUSY;
00667       State= CONV_CURRENT;
00668       Left_adjust_adc_result();
00669       Start_conv_channel(6);
00670     }
00671     break;
00672 
00673   case CONV_CURRENT :
00674     if(ADC_State == FREE)
00675     {
00676       ADC_State = BUSY;
00677       State = CONV_POT;
00678       Right_adjust_adc_result();
00679       Start_amplified_conv_channel(12);
00680 //      Start_conv_channel(9);
00681     }
00682     break;
00683   }
00684 
00685 }
00686 /********************************************************************/
00687 /********************************************************************/
00688 /*      Over Current Detection                                      */
00689 /********************************************************************/
00690 /********************************************************************/
00691 
00692 
00698 void mc_set_Over_Current(U8 Level)
00699 {
00700   Set_dac_8_bits(Level);
00701 }
00702 
00703 
00704 /********************************************************************/
00705 /********************************************************************/
00706 /*                              Number of turns calculation         */
00707 /********************************************************************/
00708 /********************************************************************/
00709 
00715 S32 mc_get_Num_Turn()
00716 {
00717   return Num_turn;
00718 }
00719 
00725 void mc_reset_Num_Turn()
00726 {
00727   Num_turn = 0;
00728 }

Generated on Wed Jul 12 16:55:10 2006 for Atmel BLDC Sensorless on ATAVRMC100 by  doxygen 1.4.7