Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
* main_open_loop C Source.
* Description: Kurban bu imdi A0'dan Vpot deerini okuyor
*
ardndan buna gre TimerA0 ile TimerA2'nin eitli registerlarnda buluna
n
*
deerleri deitirerek PWM duty cycle ayarlamas yapp ve P2.6,P2.3,P2.2 (
U|V|W) hall deerlerini
*
okuyarak komtasyonu salyor.
*
*
*
*
*
MSP430F552x
*
----------------*
/|\|
XIN|*
| |
|
*
--|RST
XOUT|*
|
|
(NFETs)
*
|
TA2.5|--> PWM5 --> LS_W
*
Speed |
TA2.1|--> PWM3 --> LS_V
*
Input-> |A0
TA0.4|--> PWM1 --> LS_U
*
|
TA0.3|--> PWM2 --> HS_V
*
|
TA0.2|--> PWM4 --> HS_U
*
|
TA0.1|--> PWM6 --> HS_W
*
|
|
*
|
P2.6|<-- Hall U | Hall
*
|
P2.3|<-- Hall V | Sensor
*
|
P2.2|<-- Hall W | Inputs
*
|
|
*
* ACLK = REF0, MCLK = SMCLK = 16MHz
* TimerA0 clock = SMLCK;
* TimerA2 clock = SMLCK;
*
* OKTAR KARA
* Yeditepe University.
* Nov 2014
* Built with CCS v6.0.1
********************************************************************************
/
#include
#include
#include
#include
#include
<msp430f5529.h>
"main_open_loop.h"
"..\F5xx_F6xx_Core_Lib\HAL_PMM.h"
"..\F5xx_F6xx_Core_Lib\HAL_UCS.h"
"hall_sensor.h"
/* Relation between the hall sequence 000-111 and the HS/LS pedriver
o/p - THIS IS FIXED for 120deg 3-ph BLDC Commutation
*/
#ifdef DIRECTION_CCW
// Direction = 0x01
unsigned char Hall_DIR_sequence[] = { 0x00,
HS_W|LS_V,
// Hall position
HS_V|LS_U,
// Hall position
HS_W|LS_U,
// Hall position
HS_U|LS_W,
// Hall position
HS_U|LS_V,
// Hall position
HS_V|LS_W,
// Hall position
001
010
011
100
101
110
0x00
};
#endif
#ifdef DIRECTION_CW
// Direction = 0x00
unsigned char Hall_DIR_sequence[] = { 0x00,
HS_V|LS_W,
HS_U|LS_V,
HS_U|LS_W,
HS_W|LS_U,
HS_V|LS_U,
HS_W|LS_V,
0x00 };
#endif
//
//
//
//
//
//
Hall
Hall
Hall
Hall
Hall
Hall
position
position
position
position
position
position
001
010
011
100
101
110
// Stop WDT
Init_FLL_Settle(16000, 488);
// Configure Port pins (P1.0-P1.3) as interrupt capable input pins, Fault IN
// and Hall Sensor Inputs
// P1DIR &= BIT1; //P1.1 Button to open/close the whole code
// P1REN |= BIT1;
// P1OUT |= BIT1;
// P1IE |= BIT1;
// P1IES = 0x0;
// Trigger on rising edge
// P1IFG = 0x0;
P2DIR &= ~(BIT6+BIT3+BIT2); // Input DIR
// P2REN |= BIT6+BIT3+BIT2+BIT0+BIT1;
// P2OUT |= BIT6+BIT3+BIT2+BIT1;// Enable Pull-down Resistors (Gerek kalmad e
xternally halledildi)
// P2IE |= BIT1;
P2IES = 0x0;
P2IFG = 0x0;
*/
// Variable Initializations
PWM_Update_Counter = 0x0;
Motor_Status = Stopped;
Hall_State_Unknown = true;
SampleADC = false;
// Start Motor
if ((Motor_Status == Stopped)&&(Hall_State_Unknown == true))
Start_Motor();
__enable_interrupt();
// enable interrupts
while(1)
{
if(SampleADC == true)
{
// Trigger ADC Sampling
#ifdef ANALOG_SPEEDIN
Start_ADC_Conversion();
__bis_SR_register(LPM0_bits + GIE);
__no_operation();
// For debugger
terrupts
Avg_vBUS = ADC_Results[0] >> 2;
Avg_vPOT = ADC_Results[1] >> 2;
if(Avg_vPOT>=3480){
Avg_vPOT = 3480;
// 100% Dutycyle counts = 1024
}
Temp_DutyCycle = Avg_vPOT/SPEEDIN_PWM_FACTOR;
// ADC12 => 4096 ADC cou
nts = 100% speed
// 100% Dutycyle counts
= TIMER_PWM_PERIOD
// ADC Pot Counts/SPEEDI
N_PWM_FACTOR = Dutycycle counts required
#endif
if (Temp_DutyCycle < MIN_PWM_DUTYCYCLE)
// 1023
Desired_PWM_DutyCycle = MIN_PWM_DUTYCYCLE; // < Min DutyCycle %ag
e - latch to min value, 1023
else
Desired_PWM_DutyCycle = Temp_DutyCycle;
// 1023
SampleADC = false;
}
}
}
void Start_Motor(void)
{
// Read Speed Input and update dutycycle variable
#ifdef ANALOG_SPEEDIN
Start_ADC_Conversion();
__bis_SR_register(LPM0_bits + GIE);
__no_operation();
// For debugger
unts required
#endif
// Read Hall inputs
OKTAR = P2IN;
KARA = P2IN;
OKTAR = ((OKTAR & 0x40)>>3);
KARA = ((KARA & 0x0C)>>1);
Hall_IN = OKTAR|KARA;
Hall_IN = ((Hall_IN & 0x0E)>>1);
// Start PWM TimerA0,TimerA1
PreDriver_Sequence = Hall_DIR_sequence[Hall_IN];
PWM_update(PreDriver_Sequence);
P2IFG = 0x0;
// Clear IFGs
P2IE |= BIT2+BIT3+BIT6;
// Enable Port ISRs
if(Current_PWM_DutyCycle < Desired_PWM_DutyCycle) // 1023
{
// Initially PWM dutycycle set to min dutycycle. If desired dutycycle <
min dutycycle, latch
// at min dutycycle, else compute #steps required to reach input speed v
alue in ~100ms
PWM_BucketStep = (Desired_PWM_DutyCycle-Current_PWM_DutyCycle)/(STARTUP_
STEPS); //1023
if(PWM_BucketStep <= 0)
{
PWM_BucketStep = 1;
}
Motor_Status = StartUp;
}
else
{
Motor_Status = Running;
}
TA0CCTL0 = CCIE;
TA0CTL |= MC_1;
}
void Stop_Motor(void)
{
P2IFG = 0x0;
TA0CCTL0 &= ~CCIE;
TA0CTL &= ~(MC_3);
P2IE &= ~(BIT2+BIT3+BIT6);
Motor_Status = Stopped;
}
#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void)
{
switch(__even_in_range(P1IV,16))
{
case 2: break;
case 4:
if(Motor_Status == Running)
{
Stop_Motor();
}
else if(Motor_Status == Stopped)
{
Start_Motor();
}
break;
case 6: break;
case 8: break;
case 10: break;
case 12: break;
case 14: break;
case 16: break;
default: break;
}
}
// Timer B0 interrupt service routine
#pragma vector=TIMER0_A0_VECTOR
__interrupt void Timer_A0_ISR(void)
{
// heart beat signal = PWM period
PWM_Update_Counter++;
ADC_Sample_Counter++;
if (Motor_Status == StartUp)
{
if((PWM_Update_Counter > DUTYCYCLE_CHANGE_PERIODS)&&(Current_PWM_DutyCyc
le < Desired_PWM_DutyCycle)) // 1023
{
Current_PWM_DutyCycle = Current_PWM_DutyCycle + PWM_BucketStep; //102
3
TA0CCR1 = Current_PWM_DutyCycle;
TA0CCR2 = Current_PWM_DutyCycle;
TA0CCR3 = Current_PWM_DutyCycle;
PWM_Update_Counter = 0x0;
}
else if(Current_PWM_DutyCycle >= Desired_PWM_DutyCycle)
//1023
{
Motor_Status = Running;
}
}
else if (Motor_Status == Running)
{
// Control Loop Dutycycle Update
if(ADC_Sample_Counter > ADC_SAMPLING_PWM_PERIODS)
{
ADC_Sample_Counter = 0x0;
SampleADC = true;
}
if (Desired_PWM_DutyCycle > Current_PWM_DutyCycle)
{
// Increment dutycycle or change dutycycle in +ve direction
Current_PWM_DutyCycle = Current_PWM_DutyCycle + MAIN_PWM_BUCKET_DC;
}
else if (Desired_PWM_DutyCycle < Current_PWM_DutyCycle)
{
// Decrement dutycycle or change dutycycle in -ve direction
Current_PWM_DutyCycle = Current_PWM_DutyCycle - MAIN_PWM_BUCKET_DC;
}
// if Desired_DutyCyle == Current_DutyCycle, dont change dutycycle value
// Update
TA0CCR1 =
TA0CCR2 =
TA0CCR3 =
}
}
// Port2 interrupt service routine
#pragma vector=PORT2_VECTOR
__interrupt void Port_2(void)
{
switch(__even_in_range(P2IV,16))
{
case 2:
Stop_Motor();
break;
case
case
case
case
4: break;
6:
8:
14:
ed........
P2IE |= BIT2+BIT3+BIT6;
-- is it required???????
break;
case 10: break;
PxIES "not the" same for both DIR0 and DIR1 (as the LUT picks
different PreDriver sequence for completing commutation)
Add if(Direction){} for P2IES bit setting - done
*/
void PWM_update (unsigned char Next_Hall_Sequence)
{
//Hall_U=> P2.6; Hall_V=> P2.3; Hall_W=> P2.2
//HS3=> P2.6; HS2=> P2.3; HS1=> P2.2
switch(Next_Hall_Sequence)
{
case HS_W|LS_V:
// Hall_IN DIR1_001 DIR0_110
// Next edge => HS3 rising, HS2 rising, HS1 falling DIR1
// Next edge => HS3 falling, HS2 falling, HS1 rising DIR0
#ifdef DIRECTION_CCW
P2IES = BIT2;
// DIR1
#else
P2IES = BIT3+BIT6;
// DIR0
#endif
TA0CCTL4
TA0CCTL1
TA2CCTL1
TA0CCTL2
TA2CCTL2
TA0CCTL3
break;
|= OUT;
= OUTMOD_7;
&= ~OUT;
= OUTMOD_0;
&= ~OUT;
= OUTMOD_0;
case HS_V|LS_U:
// Hall_IN DIR1_010 DIR0_101
// Next edge => HS3 rising, HS2 falling, HS1 rising DIR1
// Next edge => HS3 falling, HS2 rising, HS1 falling DIR0
#ifdef DIRECTION_CCW
P2IES = BIT3;
// DIR1
#else
P2IES = BIT2+BIT6; // DIR0
#endif
TA0CCTL4
TA0CCTL1
TA2CCTL1
TA0CCTL2
TA2CCTL2
TA0CCTL3
break;
&= ~OUT;
= OUTMOD_0;
|= OUT;
= OUTMOD_7;
&= ~OUT;
= OUTMOD_0;
case HS_W|LS_U:
// Hall_IN DIR1_011 DIR0_100
// Next edge => HS3 rising, HS2 falling, HS1 falling DIR1
// Next edge => HS3 falling, HS2 rising, HS1 rising DIR0
#ifdef DIRECTION_CCW
P2IES = BIT2+BIT3;
#else
P2IES = BIT6;
#endif
TA0CCTL4
TA0CCTL1
TA2CCTL1
TA0CCTL2
TA2CCTL2
TA0CCTL3
break;
// DIR1
// DIR0
&= ~OUT;
= OUTMOD_7;
|= OUT;
= OUTMOD_0;
&= ~OUT;
= OUTMOD_0;
case HS_U|LS_W:
// Hall_IN CCW_100 CW_011
// Next edge => HS3 falling, HS2 rising, HS1 rising DIR1
// Next edge => HS3 rising, HS2 falling, HS1 falling DIR0
#ifdef DIRECTION_CCW
P2IES = BIT6;
// DIR1
#else
P2IES = BIT2+BIT3;
// DIR0
#endif
TA0CCTL4 &= ~OUT;
TA0CCTL1 = OUTMOD_0;
TA2CCTL1 &= ~OUT;
TA0CCTL2 = OUTMOD_0;
TA2CCTL2 |= OUT;
TA0CCTL3 = OUTMOD_7;
break;
case HS_U|LS_V:
// Hall_IN CCW_101 CW_010
// Next edge => HS3 falling, HS2 rising, HS1 falling DIR1
// Next edge => HS3 rising, HS2 falling, HS1 rising DIR0
#ifdef DIRECTION_CCW
P2IES = BIT2+BIT6;
// DIR1
#else
P2IES = BIT3;
// DIR0
#endif
TA0CCTL4 |= OUT;
TA0CCTL1 = OUTMOD_0;
TA2CCTL1 &= ~OUT;
TA0CCTL2 = OUTMOD_0;
TA2CCTL2 &= ~OUT;
TA0CCTL3 = OUTMOD_7;
break;
case HS_V|LS_W:
// Hall_IN CCW_110 CW_001
// Next edge => HS3 falling, HS2 falling, HS1 rising DIR1
// Next edge => HS3 rising, HS2 rising, HS1 falling DIR0
#ifdef DIRECTION_CCW
P2IES = BIT3+BIT6;
// DIR1
#else
P2IES = BIT2;
// DIR0
#endif
TA0CCTL4 &= ~OUT;
TA0CCTL1 = OUTMOD_0;
TA2CCTL1 &= ~OUT;
TA0CCTL2 = OUTMOD_7;
TA2CCTL2 |= OUT;
TA0CCTL3 = OUTMOD_0;
break;
default:
Hall_State_Unknown = true;
// Stop_Motor();
break;
}
//TBR = TIMER_PWM_PERIOD-1;
//TBCCR0 = TIMER_PWM_PERIOD-1;
Hall_State_Unknown = false;
}
void Start_ADC_Conversion(void)
{
ADC_Results[0] = 0x0;
ADC_Results[1] = 0x0;
ADC12IE = 0x02;
L1)
ADC12CTL0 |= ADC12ON + ADC12ENC;
ADC12CTL0 |= ADC12SC;
}
#pragma vector=ADC12_VECTOR
__interrupt void ADC12ISR (void)
{
static unsigned char index = 0;
switch(__even_in_range(ADC12IV,34))
{
case 0: break;
case 2: break;
case 4: break;
case 6: break;
case 8:
ADC_Results[0] += ADC12MEM0;
ADC_Results[1] += ADC12MEM1;
index++;
if (index == 4)
{
ADC12IE = 0x0;
ADC12CTL0 &= ~ADC12ON;
index = 0;
__bic_SR_register_on_exit(LPM0_bits);
}
break;
case 10: break;
case 12: break;
case 14: break;
case 16: break;
case 18: break;
case 20: break;
case 22: break;
case 24: break;
case 26: break;
case 28: break;
case 30: break;
case 32: break;
case 34: break;
default: break;
//
//
//
//
//
//
Vector 0: No interrupt
Vector 2: ADC overflow
Vector 4: ADC timing overflow
Vector 6: ADC12IFG0
Vector 8: ADC12IFG1
Move results
Vector
Vector
Vector
Vector
Vector
Vector
Vector
Vector
Vector
Vector
Vector
Vector
Vector
10:
12:
14:
16:
18:
20:
22:
24:
26:
28:
30:
32:
34:
ADC12IFG2
ADC12IFG3
ADC12IFG4
ADC12IFG5
ADC12IFG6
ADC12IFG7
ADC12IFG8
ADC12IFG9
ADC12IFG10
ADC12IFG11
ADC12IFG12
ADC12IFG13
ADC12IFG14
}
}