main.c

Go to the documentation of this file.
00001 /* This file has been prepared for Doxygen automatic documentation generation.*/
00028 #include <ioavr.h>
00029 #include <inavr.h>
00030 #include "stdint.h"
00031 #include "PMSM.h"
00032 #include "PMSM_tables.h"
00033 #include "TinyX61_macros.h"
00034 
00035 
00036 #if (SPEED_CONTROL_METHOD == SPEED_CONTROL_CLOSED_LOOP)
00037 #include "pid.h"
00038 #endif
00039 
00040 
00047 volatile __io PMSMflags_t fastFlags                         @0x0a;
00048 
00049 
00055 __no_init __regvar volatile uint16_t sineTableIncrement     @14;
00056 
00057 
00064 __no_init __regvar volatile uint16_t sineTableIndex         @12;
00065 
00066 
00074 __no_init __regvar volatile uint16_t commutationTicks       @10;
00075 
00076 
00082 __no_init __regvar volatile uint16_t amplitude               @8;
00083 
00084 
00092 __no_init __regvar volatile uint8_t advanceCommutationSteps      @7;
00093 
00094 
00103 __no_init __regvar volatile uint8_t sineTableNextSectorStart     @6;
00104 
00105 
00111 __no_init __regvar volatile uint8_t speedControllerTimer @5;
00112 
00113 
00114 #if (SPEED_CONTROL_METHOD == SPEED_CONTROL_CLOSED_LOOP)
00116 pidData_t pidParameters;
00117 #endif
00118 
00119 
00120 void main(void)
00121 {
00122   PortsInit();
00123   PLLInit();
00124   PWMInit();
00125   PinChangeInit();
00126   ADCInit();
00127 
00128 #if (SPEED_CONTROL_METHOD == SPEED_CONTROL_CLOSED_LOOP)
00129   pid_Init(PID_K_P, PID_K_I, PID_K_D, &pidParameters);
00130 #endif
00131 
00132   speedControllerTimer= SPEED_CONTROLLER_TIME_BASE;
00133   SetAdvanceCommutation(0);
00134 
00135   //Initialize fastflags. Use temporary variable to avoid several accesses to
00136   //volatile variable.
00137   {
00138     PMSMflags_t fastFlagsInitial;
00139 
00140     // Set motorStopped to FALSE at startup. This will make sure that the motor
00141     // is not started if it is not really stopped. If it is stopped, this variable
00142     // will quickly be updated.
00143     fastFlagsInitial.motorStopped = FALSE;
00144 
00145     // Set motorSyncronized to FALSE at startup. This will prevent the motor from being
00146     // driven until the motor is in synch or stopped.
00147     fastFlagsInitial.motorSynchronized = FALSE;
00148     fastFlagsInitial.actualDirection = DIRECTION_UNKNOWN;
00149     fastFlagsInitial.desiredDirection = 0;
00150     fastFlagsInitial.driveWaveform = WAVEFORM_UNDEFINED;
00151 
00152     fastFlags = fastFlagsInitial;
00153   }
00154 
00155   DesiredDirectionUpdate();
00156 
00157   //Enable Timer/counter1 overflow.
00158   TIMSK |= (1 << TOV1);
00159 
00160   //Enable interrupts globally and let motor driver take over.
00161   __enable_interrupt();
00162 
00163   for (;;)
00164   {
00165     uint16_t speedReference;
00166 
00167     if ( !(ADCSRA & (1 << ADSC)) )
00168     {
00169       speedReference = ADC;
00170       ADCSRA |= (1 << ADSC);
00171     }
00172 
00173     if (speedControllerTimer == 0)
00174     {
00175       speedControllerTimer = SPEED_CONTROLLER_TIME_BASE;
00176       SpeedController(speedReference);
00177     }
00178   }
00179 }
00180 
00181 
00182 
00187 static void PortsInit(void)
00188 {
00189 #if (HALL_PULL_UP_ENABLE)
00190   PORTA = (1 << H1_PIN) | (1 << H2_PIN) | (1 << H3_PIN);
00191 #endif
00192 
00193   DDRA = (1 << PA4);
00194 }
00195 
00196 
00203 static void PLLInit(void)
00204 {
00205   //Wait for PLL lock
00206   while ( !(PLLCSR & (1 << PLOCK)) )
00207   {
00208 
00209   }
00210   PLLCSR = (1 << PCKE);
00211 }
00212 
00213 
00218 static void PWMInit(void)
00219 {
00220   //Start TCNT1 with prescaler 1.
00221   TCCR1B = (PWM_INVERT_OUTPUT << PWM1X) | (1 << CS10);
00222 
00223   //Enable fault protection input on INT0 pin, falling edge.
00224   TCCR1D = (1 << FPIE1) | (1 << FPEN1) | (0 << FPES1);
00225 
00226   //Set dead-time.
00227   DT1 = (DEAD_TIME << 4) | (DEAD_TIME);
00228 
00229   //Set PWM top value.
00230   TC1_WRITE_10_BIT_REGISTER(OCR1C, PWM_TOP_VALUE);
00231 }
00232 
00233 
00239 static void ADCInit(void)
00240 {
00241   //Use PA7 as ADC input, 2.56V internal voltage reference without bypass capacitor.
00242   ADMUX = (1 << REFS1) | (0 << MUX4) | (0 << MUX3) | (1 << MUX2) | (1 << MUX1) | (0 << MUX0);
00243 
00244   ADCSRA = (1 << ADEN) |                  //Enable the ADC.
00245            (1 << ADSC) |                  //Start the first converssion.
00246            (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);   // Prescaler CK/128.
00247   ADCSRB = (1 << REFS2); //2.56V internal reference.
00248 }
00249 
00250 
00255 static void PinChangeInit(void)
00256 {
00257   //Initialize hall change interrupt
00258   PCMSK0 = (1 << PCINT2) | (1 << PCINT1) | (1 << PCINT0);
00259   //Clear all other pin change interrupts.
00260   PCMSK1 = 0x00;
00261 
00262   //
00263   GIMSK |= (1 << PCIE1);
00264 
00265   //Force the pin change interrupt to be triggered.
00266   DDRA |= ((1 << PA2) | (1 << PA1) | (1 << PA0));
00267   DDRA &= ~((1 << PA2) | (1 << PA1) | (1 << PA0));
00268 }
00269 
00270 
00277 static void SpeedController(uint16_t speedReference)
00278 {
00279   #if (SPEED_CONTROL_METHOD == SPEED_CONTROL_CLOSED_LOOP)
00280 
00281   //Calculate an increment setpoint from the analog speed input.
00282   int16_t incrementSetpoint = ((uint32_t)speedReference * SPEED_CONTROLLER_MAX_INCREMENT) / SPEED_CONTROLLER_MAX_INPUT;
00283 
00284   //PID controller with feed forward from speed input.
00285   int32_t outputValue;
00286   outputValue = (uint32_t)speedReference;
00287   outputValue += pid_Controller(incrementSetpoint, (int16_t)sineTableIncrement, &pidParameters);
00288 
00289   if (outputValue < 0)
00290   {
00291     outputValue = 0;
00292   }
00293   else if (outputValue > PWM_TOP_VALUE)
00294   {
00295     outputValue = PWM_TOP_VALUE;
00296   }
00297   __disable_interrupt();
00298   amplitude = outputValue;
00299   __enable_interrupt();
00300 #else
00301   __disable_interrupt();
00302   amplitude = speedReference;
00303   __enable_interrupt();
00304 #endif
00305 }
00306 
00307 
00315 #pragma inline = forced
00316 static void TimerSetModeSinusoidal(void)
00317 {
00318   //Set PWM pins to input (Hi-Z) while changing modes.
00319   DisablePWMOutputs();
00320 
00321   //Set Timer/counter1 in phase and frequency correct mode.
00322   TCCR1A = (0 << COM1A1) | (1 << COM1A0) | (0 << COM1B1) | (1 << COM1B0) | (1 << PWM1A) | (1 << PWM1B);
00323   TCCR1C =  (0 << COM1A1S) | (1 << COM1A0S) | (0 << COM1B1S) | (1 << COM1B0S) | (0 << COM1D1) | (1 << COM1D0) | (1 << PWM1D);
00324   TCCR1D &= ~((1 << WGM11) | (1 << WGM10));
00325   TCCR1D |= (0 << WGM11) | (1 << WGM10);
00326 
00327   TC1_SET_ALL_COMPARE_VALUES(0x0000);
00328 
00329   fastFlags.driveWaveform = WAVEFORM_SINUSOIDAL;
00330 
00331   //Wait for the PWM cycle to complete.
00332   TIFR = TIFR;
00333   while ( ! (TIFR & (1 << TOV1)) )
00334   {
00335 
00336   }
00337 
00338   //Change PWM pins to output again to allow PWM control.
00339   EnablePWMOutputs();
00340 }
00341 
00342 
00351 #pragma inline = forced
00352 static void TimerSetModeBlockCommutation(void)
00353 {
00354   //Set PWM pins to input (Hi-Z) while changing modes.
00355   DisablePWMOutputs();
00356 
00357   //Set Timer/counter1 in dual slope PWM6 mode, clear on upcounting, set on downcounting (non-inverting).
00358   TCCR1A = (1 << COM1A1) | (0 << COM1A0) | (1 << COM1B1) | (0 << COM1B0) | (1 << PWM1A) | (1 << PWM1B);
00359   TCCR1C = (1 << COM1A1S) | (0 << COM1A0S) | (1 << COM1B1S) | (0 << COM1B0S) | (1 << COM1D1) | (0 << COM1D0) | (1 << PWM1D);
00360   TCCR1D |= (1 << WGM11) | (1 << WGM10);
00361 
00362   TCCR1E = 0x00;
00363 
00364   //Set output duty cycle to 0.
00365   BlockCommutationSetDuty(0x0000);
00366 
00367   fastFlags.driveWaveform = WAVEFORM_BLOCK_COMMUTATION;
00368 
00369     //Change PWM pins to output again to allow PWM control.
00370   EnablePWMOutputs();
00371 }
00372 
00373 
00382 #if (TURN_MODE == TURN_MODE_BRAKE)
00383 #pragma inline = forced
00384 static void TimerSetModeBrake(void)
00385 {
00386   //Set PWM pins to input (Hi-Z) while changing modes.
00387   DisablePWMOutputs();
00388 
00389   //Set Timer/counter1 in phase and frequency correct mode.
00390   TCCR1A = (0 << COM1A1) | (1 << COM1A0) | (0 << COM1B1) | (1 << COM1B0) | (1 << PWM1A) | (1 << PWM1B);
00391   TCCR1C =  (0 << COM1A1S) | (1 << COM1A0S) | (0 << COM1B1S) | (1 << COM1B0S) | (0 << COM1D1) | (1 << COM1D0) | (1 << PWM1D);
00392   TCCR1D &= ~((1 << WGM11) | (1 << WGM10));
00393   TCCR1D |= (0 << WGM11) | (1 << WGM10);
00394 
00395   //All output duty cycles at 0 creates a braking force. (Low side braking)
00396   TC1_SET_ALL_COMPARE_VALUES(0x0000);
00397 
00398   fastFlags.driveWaveform = WAVEFORM_BRAKING;
00399 
00400   //Change PWM pins to output again to allow PWM control.
00401   EnablePWMOutputs();
00402 }
00403 #endif
00404 
00405 
00418 #pragma inline = forced
00419 static void BlockCommutationSetDuty(const uint16_t compareValue)
00420 {
00421   TC1_PWM6_SET_DUTY_CYCLE(compareValue);
00422 }
00423 
00424 
00435 #pragma inline = forced
00436 static uint8_t GetDesiredDirection(void)
00437 {
00438   return (uint8_t)fastFlags.desiredDirection;
00439 }
00440 
00441 
00453 #pragma inline = forced
00454 static void BlockCommutate(const uint8_t direction, const uint8_t hall)
00455 {
00456   if (direction == DIRECTION_FORWARD)
00457   {
00458     TCCR1E = blockCommutationTableForward[hall];
00459   }
00460   else
00461   {
00462     TCCR1E = blockCommutationTableReverse[hall];
00463   }
00464 }
00465 
00466 
00482 #pragma inline = forced
00483 static uint8_t GetHall(void)
00484 {
00485   uint8_t hall;
00486 
00487   hall = (PINA) & ((1 << H3_PIN) | (1 << H2_PIN) | (1 << H1_PIN));
00488   hall >>= H1_PIN;
00489   return hall;
00490 }
00491 
00492 
00498 #pragma inline = forced
00499 static void DesiredDirectionUpdate(void)
00500 {
00501   if ( (PINA & (1 << DIRECTION_PIN)) != 0 )
00502   {
00503     fastFlags.desiredDirection = DIRECTION_REVERSE;
00504   }
00505   else
00506   {
00507     fastFlags.desiredDirection = DIRECTION_FORWARD;
00508   }
00509 }
00510 
00511 
00520 #pragma inline = forced
00521 static void ActualDirectionUpdate(uint8_t lastHall, const uint8_t newHall)
00522 {
00523   //Make sure that lastHall is within bounds of table. If not, set to an
00524   //illegal hall value, but legal table index.
00525   if (lastHall > 7)
00526   {
00527     lastHall = 0;
00528   }
00529   if (expectedHallSequenceForward[lastHall] == newHall)
00530   {
00531     fastFlags.actualDirection = DIRECTION_FORWARD;
00532   }
00533   else if (expectedHallSequenceReverse[lastHall] == newHall)
00534   {
00535    fastFlags.actualDirection = DIRECTION_REVERSE;
00536   }
00537   else
00538   {
00539     PMSMflags_t tempFlags = fastFlags;
00540     tempFlags.actualDirection = DIRECTION_UNKNOWN;
00541     tempFlags.motorSynchronized = FALSE;
00542     fastFlags = tempFlags;
00543   }
00544 }
00545 
00546 
00557 #pragma inline = forced
00558 static uint16_t SineTableIncrementCalculate(const uint16_t ticks)
00559 {
00560   return (uint16_t)(((SINE_TABLE_LENGTH / 6) << 8) / ticks);
00561 }
00562 
00563 
00571 #pragma inline = forced
00572 static void AdjustSineTableIndex(const uint16_t increment)
00573 {
00574   sineTableIndex += increment;
00575 
00576   // If the table index is out of bounds, wrap the index around the table end
00577   // to continue from the beginning. Also wrap the next sector start index.
00578   if ((sineTableIndex >> 8) >= SINE_TABLE_LENGTH)
00579   {
00580     sineTableIndex -= (SINE_TABLE_LENGTH << 8);
00581     sineTableNextSectorStart -= SINE_TABLE_LENGTH;
00582   }
00583 
00584   //Make copy of sineNextSectorStart to specify order of volatile access.
00585   uint8_t nextSectorStart = sineTableNextSectorStart;
00586   if ((sineTableIndex >> 8) > nextSectorStart)
00587   {
00588     sineTableIndex = (nextSectorStart << 8);
00589   }
00590 }
00591 
00592 
00604 #pragma inline = forced
00605 static void SetAdvanceCommutation(const uint8_t advanceCommutation)
00606 {
00607   advanceCommutationSteps = advanceCommutation;
00608 }
00609 
00610 
00615 #pragma inline = forced
00616 static void EnablePWMOutputs(void)
00617 {
00618   DDRB |= PWM_PIN_MASK_PORTB;
00619 }
00620 
00621 
00626 #pragma inline = forced
00627 static void DisablePWMOutputs(void)
00628 {
00629   DDRB &= (~PWM_PIN_MASK_PORTB);
00630 }
00631 
00632 
00641 #pragma inline = forced
00642 static void CommutationTicksUpdate(void)
00643 {
00644   if (commutationTicks < COMMUTATION_TICKS_STOPPED)
00645   {
00646     commutationTicks++;
00647   }
00648   else
00649   {
00650     fastFlags.motorStopped = TRUE;
00651     fastFlags.motorSynchronized = FALSE;
00652     sineTableIncrement = 0;
00653     if (fastFlags.driveWaveform != WAVEFORM_BLOCK_COMMUTATION)
00654     {
00655       TimerSetModeBlockCommutation();
00656       BlockCommutate(GetDesiredDirection(), GetHall());
00657 
00658 #if (SPEED_CONTROL_METHOD == SPEED_CONTROL_CLOSED_LOOP)
00659       pid_Reset_Integrator(&pidParameters);
00660 #endif
00661     }
00662   }
00663 }
00664 
00665 
00673 #pragma inline = forced
00674 static void MotorSynchronizedUpdate(void)
00675 {
00676   static uint8_t synchCount = 0;
00677 
00678   PMSMflags_t tempFlags;
00679 
00680   tempFlags = fastFlags;
00681 
00682   if ((tempFlags.desiredDirection == tempFlags.actualDirection) &&
00683       (tempFlags.motorStopped == FALSE) && (tempFlags.motorSynchronized == FALSE))
00684   {
00685     synchCount++;
00686     if (synchCount >= SYNCHRONIZATION_COUNT)
00687     {
00688       fastFlags.motorSynchronized = TRUE;
00689     }
00690   }
00691   else
00692   {
00693     synchCount = 0;
00694   }
00695 }
00696 
00697 
00707 #pragma inline = forced
00708 static uint8_t IsMotorSynchronized(void)
00709 {
00710   return (uint8_t)(fastFlags.motorSynchronized);
00711 }
00712 
00713 
00721 #if (SINE_TABLE_SIZE == SINE_TABLE_SIZE_SMALL)
00722 #pragma inline = forced
00723 uint8_t SineTableSmallGetValue(uint8_t index)
00724 {
00725   //The last 3rd of the table is zero.
00726   if (index >= (SINE_TABLE_LENGTH * 2 / 3) )
00727   {
00728     return 0;
00729   }
00730 
00731   //The second third of the table is a mirror of the first third.
00732   if (index >= (SINE_TABLE_LENGTH / 3) )
00733   {
00734     index = ((SINE_TABLE_LENGTH * 2 / 3) - 1) - index;
00735   }
00736 
00737   return sineTable[index];
00738 }
00739 #endif
00740 
00741 
00747 #if (SINE_TABLE_SIZE == SINE_TABLE_SIZE_LARGE)
00748 #pragma inline = forced
00749 static void SineOutputUpdate(void)
00750 {
00751   uint8_t const __flash * sineTablePtr = sineTable;
00752   uint16_t temp;
00753 
00754   //Add sine table offset to pointer. Must be multiplied by 3, since one
00755   //value for each phase is stored in the table.
00756   //sineTablePtr += (uint8_t)(sineTableIndex >> 8) * 3;
00757   {
00758     uint8_t tempIndex = (uint8_t)(sineTableIndex >> 8);
00759     sineTablePtr += tempIndex;
00760     sineTablePtr += tempIndex;
00761     sineTablePtr += tempIndex;
00762   }
00763 
00764   //Calculate output duty cycles. Since one phase is always zero, the scaling
00765   //is only performed on the two non-zero phases, saving one multiply.
00766 
00767   //Calculate U phase output duty cycle.
00768   temp = *sineTablePtr++;
00769   if (temp != 0)
00770   {
00771     temp = MultiplyUS15x8(amplitude, temp);
00772   }
00773   TC1_WRITE_10_BIT_REGISTER(COMPARE_REGISTER_PHASE_U, temp);
00774 
00775   //Calculate U + 240 degree phase output duty cycle.
00776   temp = *sineTablePtr++;
00777   if (temp != 0)
00778   {
00779     temp = MultiplyUS15x8(amplitude, temp);
00780   }
00781   if (GetDesiredDirection() == DIRECTION_FORWARD)
00782   {
00783     TC1_WRITE_10_BIT_REGISTER(COMPARE_REGISTER_PHASE_V, temp);
00784   }
00785   else
00786   {
00787     TC1_WRITE_10_BIT_REGISTER(COMPARE_REGISTER_PHASE_W, temp);
00788   }
00789 
00790   //Calculate U + 120 degree phase output duty cycle.
00791   temp = *sineTablePtr++;
00792   if (temp != 0)
00793   {
00794     temp = MultiplyUS15x8(amplitude, temp);
00795   }
00796   if (GetDesiredDirection() == DIRECTION_FORWARD)
00797   {
00798     TC1_WRITE_10_BIT_REGISTER(COMPARE_REGISTER_PHASE_W, temp);
00799   }
00800   else
00801   {
00802     TC1_WRITE_10_BIT_REGISTER(COMPARE_REGISTER_PHASE_V, temp);
00803   }
00804 }
00805 #endif
00806 
00807 
00813 #if (SINE_TABLE_SIZE == SINE_TABLE_SIZE_SMALL)
00814 #pragma inline = forced
00815 static void SineOutputUpdate(void)
00816 {
00817   uint16_t temp;
00818   uint8_t tempIndex;
00819 
00820   //Calculate U phase output duty cycle.
00821   tempIndex = (uint8_t)(sineTableIndex >> 8);
00822 
00823   temp = SineTableSmallGetValue(tempIndex);
00824   if (temp != 0)
00825   {
00826     temp = MultiplyUS15x8(amplitude, temp);
00827   }
00828   TC1_WRITE_10_BIT_REGISTER(COMPARE_REGISTER_PHASE_U, temp);
00829 
00830   //Calculate U phase + 120 degree output duty cycle.
00831   tempIndex += (SINE_TABLE_LENGTH / 3);
00832   if (tempIndex >= SINE_TABLE_LENGTH)
00833   {
00834     tempIndex -= SINE_TABLE_LENGTH;
00835   }
00836 
00837   temp = SineTableSmallGetValue(tempIndex);
00838   if (temp != 0)
00839   {
00840     temp = MultiplyUS15x8(amplitude, temp);
00841   }
00842   if (GetDesiredDirection() == DIRECTION_FORWARD)
00843   {
00844     TC1_WRITE_10_BIT_REGISTER(COMPARE_REGISTER_PHASE_W, temp);
00845   }
00846   else
00847   {
00848     TC1_WRITE_10_BIT_REGISTER(COMPARE_REGISTER_PHASE_V, temp);
00849   }
00850 
00851   //Calculate U phase + 240 degree output duty cycle.
00852   tempIndex += (SINE_TABLE_LENGTH / 3);
00853   if (tempIndex >= SINE_TABLE_LENGTH)
00854   {
00855     tempIndex -= SINE_TABLE_LENGTH;
00856   }
00857 
00858   temp = SineTableSmallGetValue(tempIndex);
00859   if (temp != 0)
00860   {
00861     temp = MultiplyUS15x8(amplitude, temp);
00862   }
00863   if (GetDesiredDirection() == DIRECTION_FORWARD)
00864   {
00865     TC1_WRITE_10_BIT_REGISTER(COMPARE_REGISTER_PHASE_V, temp);
00866   }
00867   else
00868   {
00869     TC1_WRITE_10_BIT_REGISTER(COMPARE_REGISTER_PHASE_W, temp);
00870   }
00871 }
00872 #endif
00873 
00874 
00886 #pragma vector = PCINT0_vect
00887 __interrupt void HallChangeISR()
00888 {
00889   static uint8_t lastHall = 0xff;
00890   uint8_t hall;
00891 
00892   hall = GetHall();
00893 
00894   //Make sure that the hall sensors really changed.
00895   if (hall == lastHall)
00896   {
00897     return;
00898   }
00899 
00900   MotorSynchronizedUpdate();
00901   uint8_t synch = IsMotorSynchronized();
00902   if ((fastFlags.driveWaveform != WAVEFORM_SINUSOIDAL) && (synch))
00903   {
00904     TimerSetModeSinusoidal();
00905   }
00906 
00907   //If sinusoidal driving is used, synchronize sine wave generation to the
00908   //current hall sensor value. Advance commutation (lead angle) is also
00909   //added in the process.
00910   if (fastFlags.driveWaveform == WAVEFORM_SINUSOIDAL)
00911   {
00912     uint16_t tempIndex;
00913     if (GetDesiredDirection() == DIRECTION_FORWARD)
00914     {
00915       tempIndex = (CSOffsetsForward[hall] + advanceCommutationSteps) << 8;
00916     }
00917     else
00918     {
00919       tempIndex = (CSOffsetsReverse[hall] + advanceCommutationSteps) << 8;
00920     }
00921     sineTableIndex = tempIndex;
00922 
00923     //Adjust next sector start index. It might be set to a value larger than
00924     //SINE_TABLE_LENGTH at this point. This is adjusted in AdjustSineTableIndex
00925     //and should not be done here, as it will cause problems when advance
00926     //commutation is used.
00927     sineTableNextSectorStart = (tempIndex >> 8) + TABLE_ELEMENTS_PER_COMMUTATION_SECTOR;
00928 
00929   }
00930   //If block commutation is used. Commutate according to hall signal.
00931   else if (fastFlags.driveWaveform == WAVEFORM_BLOCK_COMMUTATION)
00932   {
00933     BlockCommutate(GetDesiredDirection(), hall);
00934   }
00935 
00936   //Update the actual direction flag.
00937   ActualDirectionUpdate(lastHall, hall);
00938 
00939   lastHall = hall;
00940 
00941 
00942   //Calculate new step size for sine wave generation and reset commutation
00943   //timer.
00944   sineTableIncrement = SineTableIncrementCalculate(commutationTicks);
00945   commutationTicks = 0;
00946 
00947   //Since the hall sensors are changing, the motor can not be stopped.
00948   fastFlags.motorStopped = FALSE;
00949 }
00950 
00951 
00963 #pragma vector = TIM1_OVF_vect
00964 __interrupt void Timer1OverflowISR()
00965 {
00966   PORTA |= (1 << PA4);
00967   if (fastFlags.driveWaveform == WAVEFORM_SINUSOIDAL)
00968   {
00969     AdjustSineTableIndex(sineTableIncrement);
00970     SineOutputUpdate();
00971   }
00972   else if (fastFlags.driveWaveform == WAVEFORM_BLOCK_COMMUTATION)
00973   {
00974     uint16_t blockCommutationDuty = amplitude * BLOCK_COMMUTATION_DUTY_MULTIPLIER;
00975 
00976     if (blockCommutationDuty > PWM_TOP_VALUE)
00977     {
00978       blockCommutationDuty = PWM_TOP_VALUE;
00979     }
00980     BlockCommutationSetDuty(blockCommutationDuty);
00981   }
00982 
00983   //Update desired direction flag.
00984   DesiredDirectionUpdate();
00985 
00986   static uint8_t lastDesiredDirection = 0xff;
00987   if ( (fastFlags.desiredDirection != lastDesiredDirection))
00988   {
00989 #if (TURN_MODE == TURN_MODE_COAST)
00990     //Disable driver signals to let motor coast. The motor will automatically
00991     //start once it is synchronized or stopped.
00992     DisablePWMOutputs();
00993     fastFlags.motorSynchronized = FALSE;
00994     fastFlags.driveWaveform = WAVEFORM_UNDEFINED;
00995 #endif
00996 
00997 #if (TURN_MODE == TURN_MODE_BRAKE)
00998     //Set motor in brake mode. The motor will automatically start once it is
00999     //synchronized or stopped.
01000       fastFlags.motorSynchronized = FALSE;
01001     if (fastFlags.actualDirection != DIRECTION_UNKNOWN)
01002     {
01003       TimerSetModeBrake(); // Automatically sets driveWaveform.
01004     }
01005 #endif
01006 
01007     lastDesiredDirection = fastFlags.desiredDirection;
01008   }
01009 
01010   CommutationTicksUpdate();
01011 
01012   if (speedControllerTimer > 0)
01013   {
01014     speedControllerTimer--;
01015   }
01016   PORTA &= ~(1 << PA4);
01017 }
01018 
01019 
01027 #pragma vector = FAULT_PROTECTION
01028 __interrupt void FaultProtectionISR()
01029 {
01030   __delay_cycles(10000000);
01031   TCCR1D |= (1 << FPEN1);
01032 #if (SPEED_CONTROL_METHOD == SPEED_CONTROL_CLOSED_LOOP)
01033   pid_Reset_Integrator(&pidParameters);
01034 #endif
01035 }
01036 
01037 
01050 #pragma inline = forced
01051 static unsigned int MultiplyUS15x8(const uint16_t m15, const uint8_t m8)
01052 {
01053   unsigned int result = 0x0000;
01054 
01055   if (m8 & (1 << 0))
01056   {
01057     result += m15;
01058   }
01059   result >>= 1;
01060 
01061   if (m8 & (1 << 1))
01062   {
01063     result += m15;
01064   }
01065   result >>= 1;
01066   if (m8 & (1 << 2))
01067   {
01068     result += m15;
01069   }
01070   result >>= 1;
01071 
01072   if (m8 & (1 << 3))
01073   {
01074     result += m15;
01075   }
01076   result >>= 1;
01077 
01078   if (m8 & (1 << 4))
01079   {
01080     result += m15;
01081   }
01082   result >>= 1;
01083 
01084   if (m8 & (1 << 5))
01085   {
01086     result += m15;
01087   }
01088   result >>= 1;
01089   if (m8 & (1 << 6))
01090   {
01091     result += m15;
01092   }
01093   result >>= 1;
01094 
01095   if (m8 & (1 << 7))
01096   {
01097     result += m15;
01098   }
01099   result >>= 1;
01100 
01101   return result;
01102 }
01103 

Generated on Wed Oct 10 15:31:43 2007 for AVR449 by  doxygen 1.5.2