BLDC control on ATAVRMC303 with ATxMega128A1
mc_drv.c
Go to the documentation of this file.
1 
15 //_____ I N C L U D E S ___________________________________________________
16 
17 #include "config.h"
18 
19 #include "mc_drv.h"
20 #include "mc_interface.h"
21 #include "mc_control.h"
22 
23 #include "adc\adc_drv.h"
24 #include "dac\Dac_drv.h"
25 #include "pll\pll_drv.h"
26 #include "comparator\comparator_drv.h"
27 #include "awex_driver.h"
28 #include "TC_driver.h"
29 #include "hires_driver.h"
30 #include "adc_driver.h"
31 U8 count = 1; // variable "count" is use for calculate the "average" speed on 'n' samples
32 U16 average = 0;
33 U8 ovf_timer = 0; // variable "ovf_timer" is use to simulate a 16 bits timer with 8 bits timer
34 
35 Bool inrush_mask_flag = FALSE;
36 U16 inrush_delay = 0;
37 
38 Bool g_mc_read_enable = FALSE; // the speed can be read
39 Bool g_tick = FALSE;
40 Bool hall1_old_val = 1;
41 
42 Bool current_EOC = FALSE; //End Of Conversion Flag
43 
44 char State = CONV_INIT; // State of the ADC scheduler
45 char ADC_State = FREE; // ADC State : running = BUSY not running = FREE
46 
47 volatile char offset=0;
48 /******************************************************************************/
49 /******************************************************************************/
50 /* Hardware Initialization */
51 /******************************************************************************/
52 /******************************************************************************/
53 void ADC_Init()
54 {
55  /* Move stored calibration values to ADC B. */
57 
58  /* Get offset value for ADC B. */
59  offset = ADC_Offset_Get(&ADCB);
60 
61  /* Set up ADC B to have signed conversion mode and 12 bit resolution. */
62  ADC_ConvMode_and_Resolution_Config(&ADCB, true, ADC_RESOLUTION_12BIT_gc);
63 
64  /* Sample rate is CPUFREQ/16. Allow time for storing data. */
65  ADC_Prescaler_Config(&ADCB, ADC_PRESCALER_DIV16_gc);
66 
67  /* Set referance voltage on ADC B to be VCC-0.6 V.*/
68  ADC_Referance_Config(&ADCB, ADC_REFSEL_INTVCC_gc);
69 
70  /* Setup channel 0, 1, 2 and 3 to have single ended input. */
72  ADC_CH_INPUTMODE_SINGLEENDED_gc,
73  ADC_CH_GAIN_1X_gc);
74 
75  /* Set input to the channels in ADC B to be PIN 0. */
76  ADC_Ch_InputMux_Config(&ADCB.CH0, ADC_CH_MUXPOS_PIN0_gc, ADC_CH_MUXNEG_PIN0_gc);
77 
78  /* Enable ADC B with free running mode, VCC reference and signed conversion.*/
79  ADC_Enable(&ADCB);
80 
81  /* Wait until common mode voltage is stable. Default clk is 2MHz and
82  * therefore below the maximum frequency to use this function. */
83  ADC_Wait_8MHz(&ADCB);
84 
85  /* Enable free running mode. */
87 
88 }
89 
95 void mc_init_HW(void)
96 
97 {
98 
99  //Do not modify PSCOUT Configuration
100  // PORT C :
101  PORTC.DIRSET = (PIN0_bm | PIN1_bm | PIN2_bm | PIN3_bm | PIN4_bm | PIN5_bm);
102  PORTC.OUTCLR = (PIN0_bm | PIN1_bm | PIN2_bm | PIN3_bm | PIN4_bm | PIN5_bm);
103 
104  // Hall sensor input pull up activation
105  PORTE.DIRCLR = (PIN0_bm | PIN1_bm | PIN2_bm);
106 
107  //Initialization of AT90PWM3 External Interrupts
108  PORTE.INTCTRL = PORT_INT0LVL_LO_gc;
109  PORTE.INT0MASK = (PIN0_bm | PIN1_bm | PIN2_bm);
110  PORTCFG.MPCMASK = (PIN0_bm | PIN1_bm | PIN2_bm);
111  PORTE.PIN0CTRL = PORT_ISC_BOTHEDGES_gc;
112 
113 
114  // In Center Aligned Mode :
115  // => PSCx_Init(Period_Half, Dutyx0_Half, Synchro, Dutyx1_Half)
116  PWM_Init(255);
117 
118  mc_init_timer0();
119  mc_init_timer1();
120 
121  ADC_Init();
122 
123 }
124 
131 {
132 // AMP1CSR = (1<<AMP1EN) /* amplifier enable */ \
133 // | (1<<AMP1G1)|(0<<AMP1G0) /* gain = 20 */ \
134  // | (0<<AMP1TS1)|(1<<AMP1TS0) /* clock from PSC0 */ ;
135 }
136 
137 // PSC initialization depend on the PSC mode
138 // 0- One ramp Mode
139 // 1- Two ramp Mode
140 // 2- Four ramp Mode
141 // 3- Center Aligned Mode
142 void ConfigDTI( U8 deadTime )
143 {
144  /* Configure dead time insertion. */
145  AWEX_EnableDeadTimeInsertion( &AWEXC, AWEX_DTICCAEN_bm |AWEX_DTICCBEN_bm|AWEX_DTICCCEN_bm );
146  AWEX_SetOutputOverrideValue( AWEXC, 0xFF );
147  AWEX_SetDeadTimesSymmetricalUnbuffered( AWEXC, deadTime );
148 }
149 
153 void PWM_Init ( unsigned int OCRnRB)
154 {
155  ConfigDTI( 3 );
156  TCC0.PER = OCRnRB;
157  TCC0.CTRLB = TC0_CCAEN_bm | TC0_CCBEN_bm | TC0_CCCEN_bm | TC0_CCDEN_bm| TC_WGMODE_DS_T_gc;
158  TCC0.INTCTRLA = TC_OVFINTLVL_LO_gc;
159  TCC0.CTRLA = TC_CLKSEL_DIV4_gc;
160 
161  AWEX_SetOutputOverrideValue( AWEXC, 0 );
163 }
164 
165 
166 /***************************************************************************/
167 /***************************************************************************/
168 /* All functions for motor's phases commutation */
169 /***************************************************************************/
170 /***************************************************************************/
171 
179 U8 mc_get_hall(void)
180 {
181  return HALL_SENSOR_VALUE();
182 }
183 
190 #pragma vector = HALL_A()
191 __interrupt void mc_hall_a(void)
192 {
194 
195  //estimation speed on rising edge of Hall_A
196  if ((hall1_old_val == 0) && (PORTE.IN & PIN0_bm))
197  {
199  g_mc_read_enable=FALSE; // Wait 1 period
200  }
201  else
202  {
203  g_mc_read_enable=TRUE;
204  }
205  hall1_old_val = (PORTE.IN & PIN0_bm);
206 }
207 
208 
212 void mc_duty_cycle(U8 level)
213 {
214  /* Output new compare value. */
215  TC_SetCompareA( &TCC0, level );
216  TC_SetCompareB( &TCC0, level );
217  TC_SetCompareC( &TCC0, level );
218 }
219 
226 void mc_switch_commutation(U8 position)
227 {
228  // get the motor direction to commute the right switches.
229  char direction = mc_get_motor_direction();
230 
231  // Switches are commuted only if the user start the motor and
232  // the speed consign is different from 0.
233  if ((mc_motor_is_running()) && (mc_get_motor_speed()!=0))
234  {
236  switch(position)
237  {
238  // cases according to rotor position
239  case HS_001: if (direction==CCW) {Set_Q1Q6();}
240  else {Set_Q5Q2();}
241  break;
242 
243  case HS_101: if (direction==CCW) {Set_Q3Q6();}
244  else {Set_Q5Q4();}
245  break;
246 
247  case HS_100: if (direction==CCW) {Set_Q3Q2();}
248  else {Set_Q1Q4();}
249  break;
250 
251  case HS_110: if (direction==CCW) {Set_Q5Q2();}
252  else {Set_Q1Q6();}
253  break;
254 
255  case HS_010: if (direction==CCW) {Set_Q5Q4();}
256  else {Set_Q3Q6();}
257  break;
258 
259  case HS_011: if (direction==CCW) {Set_Q1Q4();}
260  else {Set_Q3Q2();}
261  break;
262  default : break;
263  }
264  }
265  else
266  {
267  Set_none(); // all switches are switched OFF
268  }
269 }
270 
271 /******************************************************************************/
272 /******************************************************************************/
273 /* TIMER 1 : generate the g_tick */
274 /******************************************************************************/
275 /******************************************************************************/
276 
283 void mc_init_timer1(void)
284 {
285  TCD1.PER = 8000;
286  TCD1.INTCTRLA = TC_OVFINTLVL_LO_gc;
287  TCD1.CTRLA = TC_CLKSEL_DIV1_gc;
288 }
289 
295 #pragma vector = TCD1_OVF_vect
296 __interrupt void launch_sampling_period(void)
297 {
298  g_tick = TRUE;
299 }
300 
301 /******************************************************************************/
302 /******************************************************************************/
303 /* TIMER 0 : Speed Measurement */
304 /******************************************************************************/
305 /******************************************************************************/
306 
313 void mc_init_timer0(void)
314 {
315  TCD0.PER = 0xFFFF;
316  TCD0.INTCTRLA = TC_OVFINTLVL_LO_gc;
317  TCD0.CTRLA = TC_CLKSEL_DIV256_gc;
318 }
319 
326 #pragma vector = TCD0_OVF_vect
327 __interrupt void ovfl_timer0(void)
328 {
330  //if the motor was turning and no stop order
331  // was given, motor run automatically.
333 
334 }
335 
343 {
344  U16 timer_value;
345  U32 new_measured_speed;
346 
347  if (g_mc_read_enable==TRUE)
348  {
349  // Two 8 bits variables are use to simulate a 16 bits timers
350  timer_value = TCD0.CNT/2;
351 
352  if (timer_value == 0) {timer_value += 1 ;} // warning DIV by 0
353  new_measured_speed = K_SPEED / timer_value;
354  if(new_measured_speed > 255) new_measured_speed = 255; // Variable saturation
355 
356 
357  #ifdef AVERAGE_SPEED_MEASURE
358  // To avoid noise an average is realized on 8 samples
359  average += new_measured_speed;
360  if(count >= n_SAMPLE)
361  {
362  count = 1;
364  average = 0;
365  }
366  else count++;
367  #else
368  // else get the real speed
369  mc_set_motor_measured_speed(new_measured_speed);
370  #endif
371 
372  // Reset Timer 0 register and variables
373  TCD0.CNT = 0x00;
374  g_mc_read_enable=FALSE;
375  }
376 }
377 
378 /******************************************************************************/
379 /******************************************************************************/
380 /* ADC use for current and potentiometer measurement */
381 /******************************************************************************/
382 /******************************************************************************/
389 {
390  do{
391  /* If the conversion on the ADCB channel 0 never is
392  * complete this will be a deadlock. */
393  }while(!ADC_Ch_Conversion_Complete(&ADCB.CH0));
394  unsigned int value;
395  value = ADC_ResultCh_GetWord(&ADCB.CH0,offset);
396 
397  value = ((value)>>4);
398  value = value + 140;
399  if ( (value&0xFF) < 150) value = 0;
400 
401  //value = ((value>>2)&0x00FF);
402  //value = (0xFF - value)*2;
404 }
405 
406 /******************************************************************************/
407 /******************************************************************************/
408 /* Over Current Configuration */
409 /******************************************************************************/
410 /******************************************************************************/
411 
415 void mc_set_Over_Current(U8 Level)
416 {
417  //Set_dac_8_bits(Level);
418 }
419 
423 {
424  inrush_delay = (U16) 1000;
425  inrush_mask_flag = TRUE;
426  //Disable_over_current();
427 }
428 
431 void mc_inrush_task(void)
432 {
433  if (inrush_mask_flag == TRUE)
434  {
435  if (inrush_delay-- == 0)
436  {
437  inrush_mask_flag = FALSE;
438  // Enable_over_current();
439  }
440  }
441 }
Bool inrush_mask_flag
Definition: mc_drv.c:35
void mc_set_Over_Current(U8 Level)
Set the Over Current threshold.
Definition: mc_drv.c:415
#define TC_SetCompareA(_tc, _compareValue)
Set new compare value for compare channel A. ( Double buffered )
Definition: TC_driver.h:169
void mc_switch_commutation(U8 position)
Set the Switching Commutation value on outputs according to sensor or estimation position.
Definition: mc_drv.c:226
Bool g_tick
Use for control the sampling period value.
Definition: mc_drv.c:39
U16 inrush_delay
Definition: mc_drv.c:36
void mc_init_timer1(void)
timer 1 Configuration Use to generate a 250us activation for sampling speed regulation ...
Definition: mc_drv.c:283
#define Set_Q1Q6()
Definition: mc_drv.h:70
uint16_t ADC_ResultCh_GetWord(ADC_CH_t *adc_ch, uint8_t offset)
This function clears the interrupt flag and returns the coversion result.
Definition: adc_driver.c:98
void ADC_Init()
Definition: mc_drv.c:53
#define Set_Q5Q2()
Definition: mc_drv.h:76
uint8_t ADC_Offset_Get(ADC_t *adc)
This function get the offset of the ADC.
Definition: adc_driver.c:241
void mc_init_timer0(void)
Timer 0 Configuration The timer 0 is used to generate an IT when an overflow occurs.
Definition: mc_drv.c:313
U8 mc_get_motor_direction(void)
Definition: mc_interface.c:148
#define CONV_INIT
Definition: mc_drv.h:119
void ADC_CalibrationValues_Set(ADC_t *adc)
This function get the calibration data from the production calibration.
Definition: adc_driver.c:77
#define AWEX_SetDeadTimesSymmetricalUnbuffered(_awex, _deadTime)
This macro sets an equal dead time for high and low side.
Definition: awex_driver.h:147
#define Set_none()
Definition: mc_drv.h:66
Bool mc_motor_is_running(void)
get the motor state
Definition: mc_interface.c:70
#define Set_Q3Q2()
Definition: mc_drv.h:72
#define ADC_ConvMode_and_Resolution_Config(_adc, _signedMode, _resolution)
This macro set the conversion mode and resolution in the selected adc.
Definition: adc_driver.h:110
Bool g_mc_read_enable
Definition: mc_drv.c:38
#define ADC_Ch_InputMode_and_Gain_Config(_adc_ch, _inputMode, _gain)
This macro configures the input mode and gain to a specific virtual channel.
Definition: adc_driver.h:197
#define AWEX_EnableCommonWaveformChannelMode(_awex)
This macro enables the Common Waveform Channel mode.
Definition: awex_driver.h:71
#define Set_Q3Q6()
Definition: mc_drv.h:74
void mci_retry_run(void)
mci_retry_run retry to run if speed is null
Definition: mc_interface.c:55
void mc_duty_cycle(U8 level)
Set the duty cycle values in the PSC according to the value calculate by the regulation loop...
Definition: mc_drv.c:212
#define ADC_Prescaler_Config(_adc, _div)
This macro set the prescaler factor in the selected adc.
Definition: adc_driver.h:127
void init_amplifier_1(void)
init Amplifier 1
Definition: mc_drv.c:130
#define ADC_Ch_Conversion_Complete(_adc_ch)
This macro returns the channel conversion complete flag..
Definition: adc_driver.h:222
#define ADC_Ch_InputMux_Config(_adc_ch, _posInput, _negInput)
This macro configures the Positiv and negativ inputs.
Definition: adc_driver.h:212
#define ADC_Referance_Config(_adc, _convRef)
This macro set the conversion referance in the selected adc.
Definition: adc_driver.h:137
XMEGA Timer/Counter driver header file.
void mc_inrush_task(void)
the purpose of this function is to manage the delay used when the overcurrent detection is disabled...
Definition: mc_drv.c:431
void PWM_Init(unsigned int OCRnRB)
Initialization of PWM generator PSC0.
Definition: mc_drv.c:153
U8 count
Definition: mc_drv.c:31
__interrupt void launch_sampling_period(void)
Launch the regulation loop (see main.c) .
Definition: mc_drv.c:296
Bool hall1_old_val
Definition: mc_drv.c:40
#define Set_Q5Q4()
Definition: mc_drv.h:78
U8 mc_get_hall(void)
Get the value of hall sensors (1 to 6)
Definition: mc_drv.c:179
void mc_set_potentiometer_value(U8 potentiometer)
Set the &#39;mc_potentiometer_value&#39; variable with the potentiometer value.
Definition: mc_interface.c:209
U16 average
Definition: mc_drv.c:32
U8 ovf_timer
Definition: mc_drv.c:33
void mc_set_motor_measured_speed(U8 measured_speed)
set Measured of speed (for initialization)
Definition: mc_interface.c:158
void AWEX_EnableDeadTimeInsertion(AWEX_t *awex, uint8_t enableMask)
Enable Dead Time Insertion.
Definition: awex_driver.c:73
U8 mc_get_Duty_Cycle()
set type of regulation
Definition: mc_control.c:197
Bool current_EOC
Definition: mc_drv.c:42
#define ADC_FreeRunning_Enable(_adc)
This macro enables the Free Running mode in the selected adc.
Definition: adc_driver.h:246
XMEGA AWeX driver header file.
void mc_disable_during_inrush(void)
the purpose of this function is to disable the overcurrent detection during startup (inrush current...
Definition: mc_drv.c:422
#define HALL_SENSOR_VALUE()
Definition: mc_drv.h:53
#define Set_Q1Q4()
Definition: mc_drv.h:68
XMEGA ADC driver header file.
void ADC_Wait_8MHz(ADC_t *adc)
This function waits until the adc common mode is settled.
Definition: adc_driver.c:182
#define K_SPEED
Definition: config_motor.h:82
void mc_ADC_Scheduler(void)
Launch the scheduler for the ADC.
Definition: mc_drv.c:388
#define n_SAMPLE
Definition: config_motor.h:43
void mc_estimation_speed(void)
estimation speed
Definition: mc_drv.c:342
void mc_init_HW(void)
init HW
Definition: mc_drv.c:95
#define TC_SetCompareB(_tc, _compareValue)
Set new compare value for compare channel B. ( Double buffered )
Definition: TC_driver.h:180
__interrupt void mc_hall_a(void)
External interruption Sensor (A) mode toggle.
Definition: mc_drv.c:191
#define FREE
Definition: mc_drv.h:123
U8 mc_get_motor_speed(void)
Definition: mc_interface.c:118
#define ADC_Enable(_adc)
This macro enables the selected adc.
Definition: adc_driver.h:83
void ConfigDTI(U8 deadTime)
Definition: mc_drv.c:142
#define AWEX_SetOutputOverrideValue(_awex, _overrideValue)
This macro sets an output override value.
Definition: awex_driver.h:100
#define TC_SetCompareC(_tc, _compareValue)
Set new compare value for compare channel C. ( Double buffered )
Definition: TC_driver.h:193
XMEGA HiRes driver header file.
char ADC_State
Definition: mc_drv.c:45
volatile char offset
Definition: mc_drv.c:47
char State
Definition: mc_drv.c:44
__interrupt void ovfl_timer0(void)
Timer0 Overflow for speed measurement.
Definition: mc_drv.c:327