Main Page | File List | Globals

main.c File Reference


Detailed Description

Atmel Corporation

Revision
1.1
Date
Monday, October 10, 2005 11:15:46 UTC

Definition in file main.c.

#include "BLDC.h"
#include <ioavr.h>
#include <inavr.h>

Include dependency graph for main.c:

Go to the source code of this file.

Functions

static unsigned int CalculateCurrent ()
 Calculates current consumption.
static unsigned long CalculateSpeed ()
 Calculates the current speed in electrical RPM.
static unsigned long CalculateSpeedSetpoint ()
 Calculates the speed set-point in electrical RPM.
__interrupt void Commutate ()
 Commutates and prepares for new zero-cross detection.
static unsigned char CurrentControl (void)
 Current control loop.
__interrupt void CurrentMeasurementComplete ()
__interrupt void EnableZCDetection ()
 Enables zero-cross detection.
static void InitADC (void)
 Initializes the AD-converter.
static void InitAnalogComparator (void)
 Initializes the analog comparator.
static void InitPorts (void)
 Initializes I/O ports.
static void InitTimers (void)
 Initializes timers (for commutation timing and PWM).
void main (void)
 Program entry point.
static void MakeTables (void)
 Initializes arrays for motor driving and AD channel selection.
__interrupt void MotorPWMBottom ()
 Timer/counter0 bottom overflow. Used for zero-cross detection.
__interrupt void OverCurrentISR ()
 Overcurrent interrupt.
static void PWMControl (void)
static void ResetHandler (void)
 Examines the reset source and acts accordingly.
static signed int SpeedControl (void)
 Speed control loop.
static void StartMotor (void)
 Executes the motor startup sequence.
void StartupDelay (unsigned int delay)
 Generates a delay used during startup.
__interrupt void WatchdogISR ()
 Watchdog interrupt.
static void WatchdogTimerEnable (void)
 Initializes the watchdog timer.

Variables

unsigned char ADMUXTable [6]
 Array of ADC channel selections for each commutation step.
volatile unsigned char currentUpdated = FALSE
 Flag that specifies whether a new current measurement is available.
unsigned char driveTable [6]
 Array of power stage enable signals for each commutation step.
__regvar __no_init volatile
unsigned int 
filteredTimeSinceCommutation
 Filtered commutation timer variable and speed indicator. This value equals half the time of one commutation step. It is filtered through an IIR filter, so the value stored is not the most recent measuremnt. The variable is stored in registers R14-R15 for quicker access.
__regvar __no_init volatile
unsigned char 
nextCommutationStep
 The commutation step that starts at next commutation.
__regvar __no_init volatile
unsigned char 
nextDrivePattern
 The power stage enable signals that will be output to the motor drivers at next commutation.
volatile unsigned char referenceVoltageADC
 ADC reading of the known external reference voltage.
volatile unsigned char shuntVoltageADC = 0
 ADC reading of shunt voltage.
volatile unsigned char speedReferenceADC
 ADC reading of external analog speed reference.
volatile unsigned char speedUpdated = FALSE
 Flag that specifies whether a new external speed reference and a motor speed measurement is available.
unsigned int startupDelays [STARTUP_NUM_COMMUTATIONS]
 Array holding the intercommutation delays used during startup.
__regvar __no_init volatile
unsigned char 
zcPolarity
 Polarity of the expected zero crossing.


Function Documentation

static unsigned int CalculateCurrent  )  [static]
 

Calculates current consumption.

This function calculates the current consumption in milliAmperes from the global variable shuntVoltageADC. The external know reference voltage is used to compensate for varying AREF voltage.

Definition at line 719 of file main.c.

References EXTERNAL_REF_VOLTAGE, referenceVoltageADC, SHUNT_RESISTANCE, shuntVoltageADC, and UL.

00720 {
00721   unsigned long ADCref;
00722   unsigned int current;
00723 
00724   // Calculate the voltage at AREF pin (scaled down motor supply voltage),
00725   // using the known reference voltage. (In milliVolts)
00726   ADCref = EXTERNAL_REF_VOLTAGE * 256UL / referenceVoltageADC;
00727 
00728   // Calculate the current through the shunt. (In milliAmperes)
00729   current = (unsigned int)((shuntVoltageADC * ADCref * 1000UL / 256UL) / SHUNT_RESISTANCE);
00730 
00731   return current;
00732 }

static unsigned long CalculateSpeed  )  [static]
 

Calculates the current speed in electrical RPM.

This function calculates the current speed in electrical rotations per minute from the global variable filteredTimeSinceCommutation.

Definition at line 672 of file main.c.

References filteredTimeSinceCommutation, and TICKS_PER_MINUTE.

00673 {
00674   // Copy used to minimize period where interrupts are disabled.
00675   unsigned int filteredTimeSinceCommutationCopy;
00676   unsigned long rotationPeriod;
00677   unsigned long speed;
00678 
00679   /*
00680   Disable interrupts to ensure that \ref filteredTimeSinceCommutation is accessed in
00681   an atomic operation.
00682   */
00683   __disable_interrupt();
00684   filteredTimeSinceCommutationCopy = filteredTimeSinceCommutation;
00685   __enable_interrupt();
00686 
00687   /*
00688   filteredTimeSinceCommutation is one half commutation time. Must be multiplied by 12 to get
00689   one full rotation.
00690   */
00691   rotationPeriod = (unsigned long)filteredTimeSinceCommutationCopy * 12;
00692   speed = (TICKS_PER_MINUTE / rotationPeriod);
00693 
00694   return speed;
00695 }

static unsigned long CalculateSpeedSetpoint  )  [static]
 

Calculates the speed set-point in electrical RPM.

This function calculates the speed set-point from the global variable speedReferenceADC.

In this implementation, the speed reference values from 0x00 to 0xff are linearly mapped into the allowable speed range, set by MIN_SPEED and MAX_SPEED.

Definition at line 707 of file main.c.

References ADC_RESOLUTION, MAX_SPEED, MIN_SPEED, and speedReferenceADC.

00708 {
00709   return (MIN_SPEED + ((MAX_SPEED - MIN_SPEED) * (unsigned int)speedReferenceADC) / ADC_RESOLUTION);
00710 }

__interrupt void Commutate  ) 
 

Commutates and prepares for new zero-cross detection.

This interrupt service routine is triggered exactly when a commutation is scheduled. The commutation is performed instantly and Timer/counter0 is reset to measure the delay between commutation and zero-cross detection.

Commutation causes large transients on all phases for a short while that could cause false zero-cross detections. A zero cross detection hold-off period is therefore used to avoid any false readings. This is performed by using Timer/counter1 compare B. The compare is set to happen after the specified hold-off period. Timer/counter1 compare B interrupt handler then enables the zero-cross detection.

Definition at line 482 of file main.c.

References CLEAR_ALL_TIMER1_INT_FLAGS, DRIVE_PORT, nextCommutationStep, nextDrivePattern, SET_TIMER1_INT_HOLDOFF, ZC_DETECTION_HOLDOFF_TIME_US, and zcPolarity.

00483 {
00484   // Commutate and clear commutation timer.
00485   DRIVE_PORT = nextDrivePattern;
00486   TCNT1 = 0;
00487 
00488   zcPolarity = nextCommutationStep & 0x01;
00489 
00490   // Set zero-cross detection holdoff time.
00491   CLEAR_ALL_TIMER1_INT_FLAGS;
00492   OCR1B = ZC_DETECTION_HOLDOFF_TIME_US;
00493   SET_TIMER1_INT_HOLDOFF;
00494 
00495   __watchdog_reset();
00496 }

static unsigned char CurrentControl void   )  [static]
 

Current control loop.

This function is called after the speed control loop. The desired duty cycle calculated by the speed control loop is available, and this function is responsible for adjusting the duty cycle to ensure that the current stays within limits.

Definition at line 767 of file main.c.

References CalculateCurrent(), CURRENT_LIMITER_CRITICAL, CURRENT_LIMITER_FACTOR, CURRENT_LIMITER_START, and DRIVE_PORT.

00768 {
00769   unsigned int current;
00770   unsigned int overCurrentCorrection = 0;
00771 
00772   current = CalculateCurrent();
00773 
00774   // Cut power to motor if current is critically high.
00775   if (current > CURRENT_LIMITER_CRITICAL)
00776   {
00777     DRIVE_PORT = 0x00;
00778     for (;;)
00779     {
00780       // Stop and let watchdog timer reset part.
00781     }
00782   }
00783 
00784   if (current > CURRENT_LIMITER_START)
00785   {
00786     overCurrentCorrection = (current - CURRENT_LIMITER_START) * CURRENT_LIMITER_FACTOR;
00787   }
00788 
00789   if (overCurrentCorrection > 255)
00790   {
00791     return 255;
00792   }
00793 
00794   return overCurrentCorrection;
00795 }

Here is the call graph for this function:

__interrupt void CurrentMeasurementComplete  ) 
 

Definition at line 544 of file main.c.

References CLEAR_ALL_TIMER0_INT_FLAGS, currentUpdated, shuntVoltageADC, and TRUE.

00545 {
00546   shuntVoltageADC = ADCH;
00547   currentUpdated = TRUE;
00548   CLEAR_ALL_TIMER0_INT_FLAGS;
00549 }

__interrupt void EnableZCDetection  ) 
 

Enables zero-cross detection.

This interrupt service routine is triggered when the zero cross detection hold-off time after commutation is over. All Timer/counter1 interrupts are disabled and Timer/counter0 (PWM) overflow interrupt is enabled to allow the ADC readings to be used for zero-cross detection.

Definition at line 507 of file main.c.

References ADMUXTable, CLEAR_ALL_TIMER0_INT_FLAGS, CLEAR_ALL_TIMER1_INT_FLAGS, DISABLE_ALL_TIMER1_INTS, driveTable, nextCommutationStep, nextDrivePattern, and SET_TIMER0_INT_ZC_DETECTION.

00508 {
00509   // Enable TCNT0 overflow ISR.
00510   CLEAR_ALL_TIMER0_INT_FLAGS;
00511   CLEAR_ALL_TIMER1_INT_FLAGS;
00512   SET_TIMER0_INT_ZC_DETECTION;
00513   DISABLE_ALL_TIMER1_INTS;
00514 
00515   // Set up ADC for zero-cross detection
00516   ADMUX = ADMUXTable[nextCommutationStep];
00517 
00518   // Wait for ADC to complete
00519   while (!(ADCSRA & (1 << ADIF)))
00520   {
00521 
00522   }
00523   ADCSRA &= ~(1 << ADIE);
00524   ADCSRA |= (1 << ADSC) | (1 << ADATE);
00525 
00526   // Rotate commutation step counter.
00527   nextCommutationStep++;
00528   if (nextCommutationStep >= 6)
00529   {
00530     nextCommutationStep = 0;
00531   }
00532   nextDrivePattern = driveTable[nextCommutationStep];
00533 }

static void InitADC void   )  [static]
 

Initializes the AD-converter.

This function initializes the AD-converter and makes a reading of the external reference voltage.

Definition at line 211 of file main.c.

References ADC_PRESCALER_16, ADC_PRESCALER_8, ADC_TRIGGER_SOURCE, ADMUX_REF_VOLTAGE, and referenceVoltageADC.

00212 {
00213   // First make a measurement of the external reference voltage.
00214   ADMUX = ADMUX_REF_VOLTAGE;
00215   ADCSRA = (1 << ADEN) | (1 << ADSC) | (1 << ADIF) | (ADC_PRESCALER_16);
00216   while (ADCSRA & (1 << ADSC))
00217   {
00218 
00219   }
00220   referenceVoltageADC = ADCH;
00221 
00222   // Initialize the ADC for autotriggered operation on PWM timer overflow.
00223   ADCSRA = (1 << ADEN) | (0 << ADSC) | (1 << ADATE) | (1 << ADIF) | (0 << ADIE) | ADC_PRESCALER_8;
00224   ADCSRB = ADC_TRIGGER_SOURCE;
00225 }

static void InitAnalogComparator void   )  [static]
 

Initializes the analog comparator.

This function initializes the analog comparator for overcurrent detection.

Definition at line 232 of file main.c.

00233 {
00234 #ifdef ANALOG_COMPARATOR_ENABLE
00235   // Enable analog comparator interrupt on rising edge.
00236   ACSR = (0 << ACBG) | (1 << ACI) | (1 << ACIE) | (1 << ACIS1) | (1 << ACIS0);
00237 #endif
00238 }

static void InitPorts void   )  [static]
 

Initializes I/O ports.

Initializes I/O ports.

Definition at line 174 of file main.c.

References DRIVE_DDR, UH, UL, VH, VL, WH, and WL.

00175 {
00176   // Init DRIVE_DDR for motor driving.
00177   DRIVE_DDR = (1 << UL) | (1 << UH) | (1 << VL) | (1 << VH) | (1 << WL) | (1 << WH);
00178 
00179   // Init PORTD for PWM on PD5.
00180   DDRD = (1 << PD5);
00181 
00182   // Disable digital input buffers on ADC channels.
00183   DIDR0 = (1 << ADC4D) | (1 << ADC3D) | (1 << ADC2D) | (1 << ADC1D) | (1 << ADC0D);
00184 }

static void InitTimers void   )  [static]
 

Initializes timers (for commutation timing and PWM).

This function initializes Timer/counter0 for PWM operation for motor speed control and Timer/counter1 for commutation timing.

Definition at line 192 of file main.c.

References PWM_TOP_VALUE.

00193 {
00194   // Set up Timer/counter0 for PWM, output on OCR0B, OCR0A as TOP value, prescaler = 1.
00195   TCCR0A = (0 << COM0A1) | (0 << COM0A0) | (1 << COM0B1) | (0 << COM0B0) | (0 << WGM01) | (1 << WGM00);
00196   TCCR0B = (1 << WGM02) | (0 << CS02) | (0 << CS01) | (1 << CS00);
00197   OCR0A = PWM_TOP_VALUE;
00198   TIFR0 = TIFR0;
00199   TIMSK0 = (0 << TOIE0);
00200 
00201   // Set up Timer/counter1 for commutation timing, prescaler = 8.
00202   TCCR1B = (1 << CS11) | (0 << CS10);
00203 }

void main void   ) 
 

Program entry point.

Main initializes all peripheral units used and calls the startup procedure. All commutation control from that point is done in interrupt routines.

Definition at line 88 of file main.c.

References InitADC(), InitAnalogComparator(), InitPorts(), InitTimers(), MakeTables(), PWMControl(), ResetHandler(), StartMotor(), and WatchdogTimerEnable().

00089 {
00090   // Initialize all sub-systems.
00091   ResetHandler();
00092   InitPorts();
00093   InitTimers();
00094   InitADC();
00095   MakeTables();
00096   InitAnalogComparator();
00097 
00098   // Run startup procedure.
00099   StartMotor();
00100 
00101   // Turn on watchdog for stall-detection.
00102   WatchdogTimerEnable();
00103   __enable_interrupt();
00104 
00105   for(;;)
00106   {
00107     PWMControl();
00108   }
00109 }

Here is the call graph for this function:

static void MakeTables void   )  [static]
 

Initializes arrays for motor driving and AD channel selection.

This function initializes the arrays used for motor driving and AD channel selection that changes for each commutation step.

Definition at line 262 of file main.c.

References ADMUX_U, ADMUX_V, ADMUX_W, ADMUXTable, DRIVE_PATTERN_STEP1_CCW, DRIVE_PATTERN_STEP1_CW, DRIVE_PATTERN_STEP2_CCW, DRIVE_PATTERN_STEP2_CW, DRIVE_PATTERN_STEP3_CCW, DRIVE_PATTERN_STEP3_CW, DRIVE_PATTERN_STEP4_CCW, DRIVE_PATTERN_STEP4_CW, DRIVE_PATTERN_STEP5_CCW, DRIVE_PATTERN_STEP5_CW, DRIVE_PATTERN_STEP6_CCW, DRIVE_PATTERN_STEP6_CW, driveTable, and startupDelays.

00263 {
00264 #if DIRECTION_OF_ROTATION == CCW
00265   driveTable[0] = DRIVE_PATTERN_STEP1_CCW;
00266   driveTable[1] = DRIVE_PATTERN_STEP2_CCW;
00267   driveTable[2] = DRIVE_PATTERN_STEP3_CCW;
00268   driveTable[3] = DRIVE_PATTERN_STEP4_CCW;
00269   driveTable[4] = DRIVE_PATTERN_STEP5_CCW;
00270   driveTable[5] = DRIVE_PATTERN_STEP6_CCW;
00271 
00272   ADMUXTable[0] = ADMUX_W;
00273   ADMUXTable[1] = ADMUX_V;
00274   ADMUXTable[2] = ADMUX_U;
00275   ADMUXTable[3] = ADMUX_W;
00276   ADMUXTable[4] = ADMUX_V;
00277   ADMUXTable[5] = ADMUX_U;
00278 #else
00279   driveTable[0] = DRIVE_PATTERN_STEP1_CW;
00280   driveTable[1] = DRIVE_PATTERN_STEP2_CW;
00281   driveTable[2] = DRIVE_PATTERN_STEP3_CW;
00282   driveTable[3] = DRIVE_PATTERN_STEP4_CW;
00283   driveTable[4] = DRIVE_PATTERN_STEP5_CW;
00284   driveTable[5] = DRIVE_PATTERN_STEP6_CW;
00285 
00286   ADMUXTable[0] = ADMUX_U;
00287   ADMUXTable[1] = ADMUX_V;
00288   ADMUXTable[2] = ADMUX_W;
00289   ADMUXTable[3] = ADMUX_U;
00290   ADMUXTable[4] = ADMUX_V;
00291   ADMUXTable[5] = ADMUX_W;
00292 
00293 #endif
00294 
00295   startupDelays[0] = 200;
00296   startupDelays[1] = 150;
00297   startupDelays[2] = 100;
00298   startupDelays[3] = 80;
00299   startupDelays[4] = 70;
00300   startupDelays[5] = 65;
00301   startupDelays[6] = 60;
00302   startupDelays[7] = 55;
00303 }

__interrupt void MotorPWMBottom  ) 
 

Timer/counter0 bottom overflow. Used for zero-cross detection.

This interrupt service routine is called every time the up/down counting PWM counter reaches bottom. An ADC reading on the active channel is automatically triggered at the same time as this interrupt is triggered. This is used to detect a zero crossing.

In the event of a zero crossing, the time since last commutation is stored and Timer/counter1 compare A is set up to trigger at the next commutation instant.

Definition at line 364 of file main.c.

References ADC_PRESCALER, ADC_ZC_THRESHOLD, ADMUX_CURRENT, ADMUX_REF_VOLTAGE, ADMUX_SPEED_REF, CLEAR_ALL_TIMER1_INT_FLAGS, COMMUTATION_CORRECTION, COMMUTATION_TIMING_IIR_COEFF_A, COMMUTATION_TIMING_IIR_COEFF_B, currentUpdated, DISABLE_ALL_TIMER0_INTS, EDGE_FALLING, EDGE_RISING, filteredTimeSinceCommutation, referenceVoltageADC, SET_TIMER1_INT_COMMUTATION, shuntVoltageADC, speedReferenceADC, speedUpdated, TRUE, and zcPolarity.

00365 {
00366   unsigned char temp;
00367 
00368   // Disable ADC auto-triggering. This must be done here to avoid wrong channel being sampled on manual samples later.
00369   ADCSRA &= ~((1 << ADATE) | (1 << ADIE));
00370 
00371   // Wait for auto-triggered ADC sample to complete.
00372   while (!(ADCSRA & (1 << ADIF)))
00373   {
00374 
00375   }
00376   temp = ADCH;
00377   if (((zcPolarity == EDGE_RISING) && (temp > ADC_ZC_THRESHOLD)) || ((zcPolarity == EDGE_FALLING) && (temp < ADC_ZC_THRESHOLD)))
00378   {
00379     unsigned int timeSinceCommutation;
00380 
00381     // Find time since last commutation
00382     timeSinceCommutation = TCNT1;
00383     TCNT1 = COMMUTATION_CORRECTION;
00384 
00385     // Filter the current ZC detection with earlier measurements through an IIR filter.
00386     filteredTimeSinceCommutation = (COMMUTATION_TIMING_IIR_COEFF_A * timeSinceCommutation
00387                                 + COMMUTATION_TIMING_IIR_COEFF_B * filteredTimeSinceCommutation)
00388                                 / (COMMUTATION_TIMING_IIR_COEFF_A + COMMUTATION_TIMING_IIR_COEFF_B);
00389     OCR1A = filteredTimeSinceCommutation;
00390 
00391     speedUpdated = TRUE;
00392 
00393     SET_TIMER1_INT_COMMUTATION;
00394     CLEAR_ALL_TIMER1_INT_FLAGS;
00395 
00396     // Disable Timer/Counter0 overflow ISR.
00397     DISABLE_ALL_TIMER0_INTS;
00398 
00399     // Read speed reference.
00400 
00401     // Make sure that a sample is not in progress.
00402     while (ADCSRA & (1 << ADSC))
00403     {
00404 
00405     }
00406     // Change channel
00407     ADMUX = ADMUX_SPEED_REF;
00408 
00409     // Start conversion manually.
00410     ADCSRA |= (1 << ADSC);
00411 
00412     // Wait for conversion to complete.
00413     while((ADCSRA & (1 << ADSC)))
00414     {
00415 
00416     }
00417     speedReferenceADC = ADCH;
00418 
00419     // Read voltage reference.
00420     // Change ADC channel.
00421     ADMUX = ADMUX_REF_VOLTAGE;
00422     // Start conversion manually.
00423     ADCSRA |= (1 << ADSC);
00424     // Wait for conversion to complete.
00425     while((ADCSRA & (1 << ADSC)))
00426     {
00427 
00428     }
00429     referenceVoltageADC = ADCH;
00430 
00431     // Enable current measurements in ADC ISR.
00432     ADMUX = ADMUX_CURRENT;
00433     ADCSRA |= (1 << ADATE) | (1 << ADIE) | ADC_PRESCALER;
00434   }
00435   else
00436   {
00437     unsigned char tempADMUX;
00438 
00439     tempADMUX = ADMUX;
00440     // Read current
00441 
00442     // Make sure that a sample is not in progress
00443     while (ADCSRA & (1 << ADSC))
00444     {
00445 
00446     }
00447 
00448     // Change channel
00449     ADMUX = ADMUX_CURRENT;
00450 
00451     // Start conversion manually.
00452     ADCSRA |= (1 << ADSC);
00453     // Wait for conversion to complete.
00454     while((ADCSRA & (1 << ADSC)))
00455     {
00456 
00457     }
00458 
00459     shuntVoltageADC = ADCH;
00460     currentUpdated = TRUE;
00461 
00462     // Restore ADC channel.
00463     ADMUX = tempADMUX;
00464     ADCSRA |= (1 << ADATE) | (1 << ADIE) | ADC_PRESCALER;
00465   }
00466 }

__interrupt void OverCurrentISR  ) 
 

Overcurrent interrupt.

This interrupt service routine cuts power to the motor when an overcurrent situation is detected.

Definition at line 575 of file main.c.

References DISABLE_DRIVING.

00576 {
00577   DISABLE_DRIVING;
00578   for(;;)
00579   {
00580     ;
00581   }
00582 }

static void PWMControl void   )  [static]
 

Definition at line 655 of file main.c.

References ADC_RESOLUTION, MAX_PWM_COMPARE_VALUE, MIN_PWM_COMPARE_VALUE, SET_PWM_COMPARE_VALUE, speedReferenceADC, and speedUpdated.

00656 {
00657   // Only update duty cycle if a new speed reference measurement has been made. (Done right after speed measurement is ready)
00658   if (speedUpdated)
00659   {
00660     // Calculate duty cycle from speed reference value.
00661     SET_PWM_COMPARE_VALUE(MIN_PWM_COMPARE_VALUE + speedReferenceADC * (MAX_PWM_COMPARE_VALUE - MIN_PWM_COMPARE_VALUE) / ADC_RESOLUTION);
00662   }
00663 }

static void ResetHandler void   )  [static]
 

Examines the reset source and acts accordingly.

This function is called early in the program to disable watchdog timer and determine the source of reset.

Actions can be taken, based on the reset source. When the watchdog is used as stall protection, a stall can be detected here. It is possible to e.g. store a variable in EEPROM that counts the number of failed restart attempts. After a certain number of attempts, the motor could simply refuse to continue until an external action happens, indicating that the rotor lock situation could be fixed.

Definition at line 124 of file main.c.

References MAX_RESTART_ATTEMPTS.

00125 {
00126   __eeprom unsigned static int restartAttempts;
00127   // Temporary variable to avoid unnecessary reading of volatile register MCUSR.
00128   unsigned char tempMCUSR;
00129 
00130   tempMCUSR = MCUSR;
00131   MCUSR = tempMCUSR & ~((1 << WDRF) | (1 << BORF) | (1 << EXTRF) | (1 << PORF));
00132 
00133   // Reset watchdog to avoid false stall detection before the motor has started.
00134   __disable_interrupt();
00135   __watchdog_reset();
00136   WDTCSR |= (1 << WDCE) | (1 << WDE);
00137   WDTCSR = 0x00;
00138 
00139   // Examine the reset source and take action.
00140   switch (tempMCUSR & ((1 << WDRF) | (1 << BORF) | (1 << EXTRF) | (1 << PORF)))
00141   {
00142   case (1 << WDRF):
00143     restartAttempts++;
00144     if (restartAttempts >= MAX_RESTART_ATTEMPTS)
00145     {
00146       // Do something here. E.g. wait for a button to be pressed.
00147       for (;;)
00148       {
00149 
00150       }
00151     }
00152 
00153     // Put watchdog reset handler here.
00154     break;
00155   case (1 << BORF):
00156     //Put brownout reset handler here.
00157     break;
00158   case (1 << EXTRF):
00159     restartAttempts = 0;
00160     // Put external reset handler here.
00161     break;
00162   case (1 << PORF):
00163     restartAttempts = 0;
00164     // Put power-on reset handler here.
00165     break;
00166   }
00167 }

static signed int SpeedControl void   )  [static]
 

Speed control loop.

This function runs a simple P-regulator speed control loop. The duty cycle is only updated each time a new speed measurement is ready (on each zero-crossing). The time step is thus variable, so the P-gain of the P-regulator corresponds to a speed-varying P-gain for the continous system.

Definition at line 742 of file main.c.

References CalculateSpeed(), CalculateSpeedSetpoint(), P_REG_K_P, and P_REG_SCALING.

00743 {
00744   unsigned long speedSetpoint;
00745   unsigned long currentSpeed;
00746   signed long speedError;
00747   signed long dutyChange;
00748 
00749 
00750 
00751   speedSetpoint = CalculateSpeedSetpoint();
00752   currentSpeed = CalculateSpeed();
00753   speedError = (speedSetpoint - currentSpeed);
00754   dutyChange = speedError * P_REG_K_P / P_REG_SCALING;
00755 
00756   return dutyChange;
00757 }

Here is the call graph for this function:

static void StartMotor void   )  [static]
 

Executes the motor startup sequence.

This function locks the motor into a known position and fires off a commutation sequence controlled by the Timer/counter1 overflow interrupt.

Definition at line 311 of file main.c.

References ADMUXTable, DRIVE_PORT, driveTable, filteredTimeSinceCommutation, nextCommutationStep, nextDrivePattern, SET_PWM_COMPARE_VALUE, STARTUP_DELAY_MULTIPLIER, STARTUP_LOCK_DELAY, STARTUP_NUM_COMMUTATIONS, STARTUP_PWM_COMPARE_VALUE, StartupDelay(), startupDelays, and zcPolarity.

00312 {
00313   unsigned char i;
00314 
00315   SET_PWM_COMPARE_VALUE(STARTUP_PWM_COMPARE_VALUE);
00316 
00317   nextCommutationStep = 0;
00318 
00319   //Preposition.
00320   DRIVE_PORT = driveTable[nextCommutationStep];
00321   StartupDelay(STARTUP_LOCK_DELAY);
00322   nextCommutationStep++;
00323   nextDrivePattern = driveTable[nextCommutationStep];
00324 
00325   for (i = 0; i < STARTUP_NUM_COMMUTATIONS; i++)
00326   {
00327     DRIVE_PORT = nextDrivePattern;
00328     StartupDelay(startupDelays[i]);
00329 
00330     ADMUX = ADMUXTable[nextCommutationStep];
00331 
00332     // Use LSB of nextCommutationStep to determine zero crossing polarity.
00333     zcPolarity = nextCommutationStep & 0x01;
00334 
00335     nextCommutationStep++;
00336     if (nextCommutationStep >= 6)
00337     {
00338       nextCommutationStep = 0;
00339     }
00340     nextDrivePattern = driveTable[nextCommutationStep];
00341   }
00342 
00343   // Switch to sensorless commutation.
00344   TCNT1 = 0;
00345   TIMSK1 = (1 << OCIE1A);
00346 
00347   // Set filteredTimeSinceCommutation to the time to the next commutation.
00348   filteredTimeSinceCommutation = startupDelays[STARTUP_NUM_COMMUTATIONS - 1] * (STARTUP_DELAY_MULTIPLIER  / 2);
00349 }

Here is the call graph for this function:

void StartupDelay unsigned int  delay  ) 
 

Generates a delay used during startup.

This functions is used to generate a delay during the startup procedure. The length of the delay equals delay * STARTUP_DELAY_MULTIPLIER microseconds. Since Timer/Counter1 is used in this function, it must never be called when sensorless operation is running.

Definition at line 593 of file main.c.

References CLEAR_ALL_TIMER1_INT_FLAGS, and STARTUP_DELAY_MULTIPLIER.

Referenced by StartMotor().

00594 {
00595   CLEAR_ALL_TIMER1_INT_FLAGS;
00596   do
00597   {
00598     TCNT1 = 0xffff - STARTUP_DELAY_MULTIPLIER;
00599     // Wait for timer to overflow.
00600     while (!(TIFR1 & (1 << TOV1)))
00601     {
00602 
00603     }
00604 
00605     CLEAR_ALL_TIMER1_INT_FLAGS;
00606     delay--;
00607   } while (delay);
00608 }

__interrupt void WatchdogISR  ) 
 

Watchdog interrupt.

This ISR is called before the watchdog timer resets the device because of a stall. It simply disables driving, but other tasks that must be done before a watchdog reset, such as storage of variables in non-volatile memory can be done here.

Definition at line 559 of file main.c.

References DISABLE_DRIVING.

00560 {
00561   DISABLE_DRIVING;
00562   for(;;)
00563   {
00564     ;
00565   }
00566 }

static void WatchdogTimerEnable void   )  [static]
 

Initializes the watchdog timer.

This function initializes the watchdog timer for stall restart.

Definition at line 245 of file main.c.

00246 {
00247   __disable_interrupt();
00248   __watchdog_reset();
00249 
00250   WDTCSR |= (1 << WDCE) | (1 << WDE);
00251 
00252   WDTCSR = (1 << WDIF) | (1 << WDIE) | (1 << WDE) | (1 << WDP2);
00253   __enable_interrupt();
00254 }


Variable Documentation

unsigned char ADMUXTable[6]
 

Array of ADC channel selections for each commutation step.

Definition at line 32 of file main.c.

Referenced by EnableZCDetection(), MakeTables(), and StartMotor().

volatile unsigned char currentUpdated = FALSE
 

Flag that specifies whether a new current measurement is available.

Definition at line 80 of file main.c.

Referenced by CurrentMeasurementComplete(), and MotorPWMBottom().

unsigned char driveTable[6]
 

Array of power stage enable signals for each commutation step.

Definition at line 29 of file main.c.

Referenced by EnableZCDetection(), MakeTables(), and StartMotor().

__regvar __no_init volatile unsigned int filteredTimeSinceCommutation
 

Filtered commutation timer variable and speed indicator. This value equals half the time of one commutation step. It is filtered through an IIR filter, so the value stored is not the most recent measuremnt. The variable is stored in registers R14-R15 for quicker access.

Definition at line 42 of file main.c.

Referenced by CalculateSpeed(), MotorPWMBottom(), and StartMotor().

__regvar __no_init volatile unsigned char nextCommutationStep
 

The commutation step that starts at next commutation.

The commutation step that starts at next commutation. This is used to keep track on where in the commutation cycle we are. Stored in register R11 for quick access

Definition at line 65 of file main.c.

Referenced by Commutate(), EnableZCDetection(), and StartMotor().

__regvar __no_init volatile unsigned char nextDrivePattern
 

The power stage enable signals that will be output to the motor drivers at next commutation.

This variable holds the pattern of enable signals that will be output to the power stage at next commutation. It is stored in register R13 for quick access.

Definition at line 50 of file main.c.

Referenced by Commutate(), EnableZCDetection(), and StartMotor().

volatile unsigned char referenceVoltageADC
 

ADC reading of the known external reference voltage.

Definition at line 74 of file main.c.

Referenced by CalculateCurrent(), InitADC(), and MotorPWMBottom().

volatile unsigned char shuntVoltageADC = 0
 

ADC reading of shunt voltage.

Definition at line 71 of file main.c.

Referenced by CalculateCurrent(), CurrentMeasurementComplete(), and MotorPWMBottom().

volatile unsigned char speedReferenceADC
 

ADC reading of external analog speed reference.

Definition at line 68 of file main.c.

Referenced by CalculateSpeedSetpoint(), MotorPWMBottom(), and PWMControl().

volatile unsigned char speedUpdated = FALSE
 

Flag that specifies whether a new external speed reference and a motor speed measurement is available.

Definition at line 77 of file main.c.

Referenced by MotorPWMBottom(), and PWMControl().

unsigned int startupDelays[STARTUP_NUM_COMMUTATIONS]
 

Array holding the intercommutation delays used during startup.

Definition at line 35 of file main.c.

Referenced by MakeTables(), and StartMotor().

__regvar __no_init volatile unsigned char zcPolarity
 

Polarity of the expected zero crossing.

The polarity of the expected zero crossing. Could be eiter EDGE_FALLING or EDGE_RISING.

Definition at line 57 of file main.c.

Referenced by Commutate(), MotorPWMBottom(), and StartMotor().


Generated on Tue Oct 11 10:57:04 2005 for Sensorless control of 3-phase brushless DC motors by  doxygen 1.4.4