Main Page | Data Structures | File List | Data Fields | Globals | Related Pages

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 "PMSMtables.h"
00033 
00034 #if (SPEED_CONTROL_METHOD == SPEED_CONTROL_CLOSED_LOOP)
00035 #include "pid.h"
00036 #endif
00037 
00044 __io volatile PMSMflags_t fastFlags                               @0x1e;
00045 
00046 
00052 __no_init __regvar volatile uint16_t sineTableIncrement           @14;
00053 
00054 
00061 __no_init __regvar volatile uint16_t sineTableIndex               @12;
00062 
00063 
00071 __no_init __regvar volatile uint16_t commutationTicks             @10;
00072 
00073 
00079 __no_init __regvar volatile uint8_t amplitude                     @9;
00080 
00081 
00089 __no_init __regvar volatile uint8_t advanceCommutationSteps              @8;
00090 
00091 
00100 __no_init __regvar volatile uint8_t sineTableNextSectorStart     @7;
00101 
00102 
00109 volatile uint8_t current;
00110 
00111 
00113 volatile uint8_t speedInput;
00114 
00119 volatile uint8_t SpeedControllerRun = FALSE;
00120 
00121 
00122 #if (SPEED_CONTROL_METHOD == SPEED_CONTROL_CLOSED_LOOP)
00123 
00124 pidData_t pidParameters;
00125 #endif
00126 
00127 
00135 void main(void)
00136 {
00137   //Initialize peripherals.
00138   PortsInit();
00139   TimersInit();
00140   PinChangeIntInit();
00141   ADCInit();
00142 
00143   SetAdvanceCommutation(0);
00144 
00145 #if (SPEED_CONTROL_METHOD == SPEED_CONTROL_CLOSED_LOOP)
00146   PID_Init(PID_K_P, PID_K_I, PID_K_D, &pidParameters);
00147 #endif
00148 
00149   //Do not start until everything is ready.
00150   CheckEmergencyShutdown();
00151 
00152   //Initialize fastflags. Use temporary variable to avoid several accesses to
00153   //volatile variable.
00154   {
00155     PMSMflags_t fastFlagsInitial;
00156 
00157     // Set motorStopped to FALSE at startup. This will make sure that the motor
00158     // is not started if it is not really stopped. If it is stopped, this variable
00159     // will quickly be updated.
00160     fastFlagsInitial.motorStopped = FALSE;
00161 
00162     // Set motorSyncronized to FALSE at startup. This will prevent the motor from being
00163     // driven until the motor is in synch or stopped.
00164     fastFlagsInitial.motorSynchronized = FALSE;
00165     fastFlagsInitial.actualDirection = DIRECTION_UNKNOWN;
00166     fastFlagsInitial.desiredDirection = 0;
00167     fastFlagsInitial.driveWaveform = WAVEFORM_UNDEFINED;
00168 
00169     fastFlags = fastFlagsInitial;
00170   }
00171 
00172   DesiredDirectionUpdate();
00173 
00174   // Enable Timer1 capture event interrupt.
00175   TIMSK1 |= (1 << ICIE1);
00176 
00177   //Enable interrupts globally and let motor driver take over.
00178   __enable_interrupt();
00179   for(;;)
00180   {
00181     if (SpeedControllerRun)
00182     {
00183       SpeedController();
00184       SpeedControllerRun = FALSE;
00185     }
00186   }
00187 }
00188 
00189 
00195 static void PortsInit(void)
00196 {
00197 #if (HALL_PULLUP_ENABLE == TRUE)
00198   // Set hall sensor pins as input, pullups enabled.
00199   PORTC = (1 << H1_PIN) | (1 << H2_PIN) | (1 << H3_PIN);
00200 #endif
00201 
00202   // PORTD outputs
00203   DDRD = (1 << REV_ROTATION_PIN) | (1 << TACHO_OUTPUT_PIN);
00204 
00205   //Enable pull-up on direction signal.
00206   PORTD |= (1 << DIRECTION_COMMAND_PIN);
00207 }
00208 
00209 
00216 static void TimersInit(void)
00217 {
00218   //Set all timers in "Phase correct mode". Do not enable outputs yet.
00219   TCCR0A = (1 << WGM00);
00220   TCCR1A = (1 << WGM11);
00221   TCCR2A = (1 << WGM20);
00222 
00223   //Set top value of Timer/counter1.
00224   ICR1 = 0xff;
00225 
00226   //Synchronize timers
00227   TCNT0 = 0;
00228   TCNT1 = 2;
00229   TCNT2 = 4;
00230 
00231   // Start all 3 timers.
00232   TCCR0B = (0 << CS01) | (1 << CS00);
00233   TCCR1B = (1 << WGM13) | (0 << CS11) | (1 << CS10);
00234   TCCR2B = (0 << CS21) | (1 << CS20);
00235 }
00236 
00237 
00244 static void PinChangeIntInit(void)
00245 {
00246   // Initialize pin change interrupt on emergency shutdown pin.
00247   PCMSK0 = (1 << PCINT5);
00248 
00249   // Initialize pin change interrupt on hall sensor inputs.
00250   PCMSK1 = (1 << PCINT10) | (1 << PCINT9) | (1 << PCINT8);
00251 
00252   // Initialize pin change interrupt on direction input pin.
00253   PCMSK2 = (1 << PCINT18);
00254 
00255   // Enable pin change interrupt on ports with pin change signals
00256   PCICR = (1 << PCIE2) | (1 << PCIE1) | (1 << PCIE0);
00257 }
00258 
00259 
00266 static void ADCInit(void)
00267 {
00268   //Select initial AD conversion channel.
00269   ADMUX = ADMUX_SPEED_REF;
00270 
00271   //Initialize ADC.
00272   ADCSRA = (1 << ADEN) | (1 << ADSC) | (1 << ADATE) | (1 << ADIF) | (1 << ADIE) | ADC_PRESCALER;
00273 
00274   //Set trigger source to Timer/Counter0 overflow.
00275   ADCSRB = (1 << ADTS2) | (0 << ADTS1) | (0 << ADTS0);
00276 }
00277 
00278 
00290 static void CheckEmergencyShutdown(void)
00291 {
00292   if ( (PINB & (1 << EMERGENCY_SHUTDOWN_PIN)) != 0)
00293   {
00294     //Insert code here to handle emercency shutdown signal at startup.
00295   }
00296 }
00297 
00298 
00305 static void SpeedController(void)
00306 {
00307 #if (SPEED_CONTROL_METHOD == SPEED_CONTROL_CLOSED_LOOP)
00308 
00309   //Calculate an increment setpoint from the analog speed input.
00310   int16_t incrementSetpoint = ((uint32_t)speedInput * SPEED_CONTROLLER_MAX_INCREMENT) / SPEED_CONTROLLER_MAX_INPUT;
00311 
00312   //PID regulator with feed forward from speed input.
00313   int32_t outputValue;
00314   outputValue = (uint32_t)speedInput;
00315   outputValue += PID_Controller(incrementSetpoint, (int16_t)sineTableIncrement, &pidParameters);
00316 
00317   if (outputValue < 0)
00318   {
00319     outputValue = 0;
00320   }
00321   else if (outputValue > 255)
00322   {
00323     outputValue = 255;
00324   }
00325 
00326   amplitude = outputValue;
00327 #else
00328   amplitude = speedInput;
00329 #endif
00330 }
00331 
00332 
00340 #pragma inline=forced
00341 static void TimersSetModeSinusoidal(void)
00342 {
00343   //Set PWM pins to input (Hi-Z) while changing modes.
00344   DisablePWMOutputs();
00345 
00346   //Sets all 3 timers in inverted pair mode.
00347   TCCR0A = (1 << COM0A1) | (0 << COM0A0) | (1 << COM0B1) | (1 << COM0B0) | (1 << WGM00);
00348   TCCR1A = (1 << COM1A1) | (0 << COM1A0) | (1 << COM1B1) | (1 << COM1B0) | (1 << WGM11);
00349   TCCR2A = (1 << COM2A1) | (0 << COM2A0) | (1 << COM2B1) | (1 << COM2B0) | (1 << WGM20);
00350 
00351   //Make sure all outputs are turned off before PWM outputs are enabled.
00352   OCR0A = OCR1AL = OCR2A = 0;
00353   OCR0B = OCR1BL = OCR2B = 0xff;
00354 
00355   //Wait for next PWM cycle to ensure that all outputs are updated.
00356   TimersWaitForNextPWMCycle();
00357 
00358   fastFlags.driveWaveform = WAVEFORM_SINUSOIDAL;
00359 
00360   //Change PWM pins to output again to allow PWM control.
00361   EnablePWMOutputs();
00362 }
00363 
00364 
00372 #pragma inline=forced
00373 static void TimersSetModeBlockCommutation(void)
00374 {
00375   //Set PWM pins to input (Hi-Z) while changing modes.
00376   DisablePWMOutputs();
00377 
00378   //Sets both outputs of all 3 timers in "clear on up-counting, set on down-counting" mode.
00379   TCCR0A = (1 << COM0A1) | (0 << COM0A0) | (1 << COM0B1) | (0 << COM0B0) | (1 << WGM00);
00380   TCCR1A = (1 << COM1A1) | (0 << COM1A0) | (1 << COM1B1) | (0 << COM1B0) | (1 << WGM11);
00381   TCCR2A = (1 << COM2A1) | (0 << COM2A0) | (1 << COM2B1) | (0 << COM2B0) | (1 << WGM20);
00382 
00383   //Set output duty cycle to zero for now.
00384   BlockCommutationSetDuty(0);
00385 
00386   //Wait for next PWM cycle to ensure that all outputs are updated.
00387   TimersWaitForNextPWMCycle();
00388 
00389   fastFlags.driveWaveform = WAVEFORM_BLOCK_COMMUTATION;
00390 
00391   //Change PWM pins to output again to allow PWM control.
00392   EnablePWMOutputs();
00393 }
00394 
00395 
00402 #if (TURN_MODE == TURN_MODE_BRAKE)
00403 #pragma inline=forced
00404 static void TimersSetModeBrake(void)
00405 {
00406   //Set PWM pins to input (Hi-Z) while changing modes.
00407   DisablePWMOutputs();
00408 
00409   //Sets both outputs of all 3 timers in "clear on up-counting, set on down-counting" mode.
00410   TCCR0A = (1 << COM0A1) | (0 << COM0A0) | (1 << COM0B1) | (0 << COM0B0) | (1 << WGM00);
00411   TCCR1A = (1 << COM1A1) | (0 << COM1A0) | (1 << COM1B1) | (0 << COM1B0) | (1 << WGM11);
00412   TCCR2A = (1 << COM2A1) | (0 << COM2A0) | (1 << COM2B1) | (0 << COM2B0) | (1 << WGM20);
00413 
00414   // High side
00415   OCR0A = OCR1A = OCR2A = 0x00;
00416 
00417   // Low side
00418   OCR0B = OCR1B = OCR2B = 0xff;
00419 
00420   //Wait for next PWM cycle to ensure that all outputs are updated.
00421   TimersWaitForNextPWMCycle();
00422 
00423   fastFlags.driveWaveform = WAVEFORM_BRAKING;
00424 
00425   EnablePWMOutputs();
00426 }
00427 #endif
00428 
00429 
00436 #pragma inline=forced
00437 static void TimersWaitForNextPWMCycle(void)
00438 {
00439   //Clear Timer1 Capture event flag.
00440   TIFR1 = (1 << ICF1);
00441 
00442   //Wait for new Timer1 Capture event flag.
00443   while ( !(TIFR1 & (1 << ICF1)) )
00444   {
00445 
00446   }
00447 }
00448 
00449 
00460 #pragma inline=forced
00461 static void BlockCommutationSetDuty(const uint8_t duty)
00462 {
00463   // Set all compare registers to new duty cycle value.
00464   OCR0A = OCR0B = OCR1AL = OCR1BL = OCR2A = OCR2B = duty;
00465 }
00466 
00467 
00478 #pragma inline=forced
00479 static uint8_t GetDesiredDirection(void)
00480 {
00481   return (uint8_t)fastFlags.desiredDirection;
00482 }
00483 
00484 
00501 #pragma inline=forced
00502 static uint8_t GetActualDirection(void)
00503 {
00504   return fastFlags.actualDirection;
00505 }
00506 
00507 
00519 #pragma inline=forced
00520 static void BlockCommutate(const uint8_t direction, uint8_t hall)
00521 {
00522   uint8_t const __flash *pattern;
00523 
00524   if (direction == DIRECTION_FORWARD)
00525   {
00526     pattern = blockCommutationTableForward;
00527   }
00528   else
00529   {
00530     pattern = blockCommutationTableReverse;
00531   }
00532   pattern += (hall * 2);
00533 
00534   DisablePWMOutputs();
00535   DDRB |= *pattern++;
00536   DDRD |= *pattern;
00537 }
00538 
00539 
00555 #pragma inline=forced
00556 static uint8_t GetHall(void)
00557 {
00558   uint8_t hall;
00559 
00560   hall = PINC & ((1 << H3_PIN) | (1 << H2_PIN) | (1 << H1_PIN));
00561   hall >>= H1_PIN;
00562   return hall;
00563 }
00564 
00565 
00571 #pragma inline=forced
00572 static void DesiredDirectionUpdate(void)
00573 {
00574   if ( (PIND & (1 << DIRECTION_COMMAND_PIN)) != 0 )
00575   {
00576     fastFlags.desiredDirection = DIRECTION_REVERSE;
00577   }
00578   else
00579   {
00580     fastFlags.desiredDirection = DIRECTION_FORWARD;
00581   }
00582 }
00583 
00584 
00593 #pragma inline=forced
00594 static void ActualDirectionUpdate(uint8_t lastHall, const uint8_t newHall)
00595 {
00596   //Make sure that lastHall is within bounds of table. If not, set to 0, which is
00597   //also an illegal hall value, but legal table index.
00598   if (lastHall > 6)
00599   {
00600     lastHall = 0;
00601   }
00602   if (expectedHallSequenceForward[lastHall] == newHall)
00603   {
00604     fastFlags.actualDirection = DIRECTION_FORWARD;
00605   }
00606   else if (expectedHallSequenceReverse[lastHall] == newHall)
00607   {
00608    fastFlags.actualDirection = DIRECTION_REVERSE;
00609   }
00610   else
00611   {
00612     PMSMflags_t tempFlags = fastFlags;
00613     tempFlags.actualDirection = DIRECTION_UNKNOWN;
00614     tempFlags.motorSynchronized = FALSE;
00615     fastFlags = tempFlags;
00616   }
00617 }
00618 
00619 
00632 #pragma inline=forced
00633 static void ReverseRotationSignalUpdate(void)
00634 {
00635 #if (REVERSE_ROTATION_SIGNAL_ENABLE)
00636   if (GetActualDirection() == GetDesiredDirection())
00637   {
00638     PORTD &= ~(1 << REV_ROTATION_PIN);
00639   }
00640   else
00641   {
00642     PORTD |= (1 << REV_ROTATION_PIN);
00643   }
00644 #endif
00645 }
00646 
00647 
00660 #pragma inline=forced
00661 static void InsertDeadband(const uint8_t compareValue, uint8_t * compareHighPtr, uint8_t * compareLowPtr)
00662 {
00663   if (compareValue <= DEAD_TIME_HALF)
00664   {
00665     *compareHighPtr = 0x00;
00666     *compareLowPtr = compareValue;
00667   }
00668   else if (compareValue >= (0xff - DEAD_TIME_HALF))
00669   {
00670     *compareHighPtr = 0xff - (2 * DEAD_TIME_HALF);
00671     *compareLowPtr = 0xff;
00672   }
00673   else
00674   {
00675     *compareHighPtr = compareValue - DEAD_TIME_HALF;
00676     *compareLowPtr = compareValue + DEAD_TIME_HALF;
00677   }
00678 }
00679 
00680 
00694 #pragma inline = forced
00695 static uint16_t SineTableIncrementCalculate(const uint16_t ticks)
00696 {
00697   if (ticks < 256)
00698   {
00699     return divisionTable[(uint8_t)ticks];
00700   }
00701   return (uint16_t)(((SINE_TABLE_LENGTH / 6) << 8) / ticks);
00702 }
00703 
00704 
00712 #pragma inline=forced
00713 static void AdjustSineTableIndex(const uint16_t increment)
00714 {
00715   sineTableIndex += increment;
00716 
00717   // If the table index is out of bounds, wrap the index around the table end
00718   // to continue from the beginning. Also wrap the next sector start index.
00719   if ((sineTableIndex >> 8) >= SINE_TABLE_LENGTH)
00720   {
00721     sineTableIndex -= (SINE_TABLE_LENGTH << 8);
00722     sineTableNextSectorStart -= SINE_TABLE_LENGTH;
00723   }
00724 
00725   //Make copy of sineNextSectorStart to specify order of volatile access.
00726   uint8_t nextSectorStart = sineTableNextSectorStart;
00727   if ((sineTableIndex >> 8) > nextSectorStart)
00728   {
00729     sineTableIndex = (nextSectorStart << 8);
00730   }
00731 }
00732 
00733 
00745 #pragma inline=forced
00746 static void SetAdvanceCommutation(const uint8_t advanceCommutation)
00747 {
00748   advanceCommutationSteps = advanceCommutation;
00749 }
00750 
00751 
00763 #pragma inline=forced
00764 static void TachoOutputUpdate(const uint8_t hall)
00765 {
00766 #if (TACHO_OUTPUT_ENABLED)
00767   if ( (hall & (uint8_t)(hall - 1)) != 0 )
00768   {
00769     PORTD &= ~(1 << TACHO_OUTPUT_PIN);
00770   }
00771   else
00772   {
00773     PORTD |= (1 << TACHO_OUTPUT_PIN);
00774   }
00775 #endif
00776 }
00777 
00778 
00785 #pragma inline=forced
00786 static void EnablePWMOutputs(void)
00787 {
00788   DDRB |= PWM_PATTERN_PORTB;
00789   DDRD |= PWM_PATTERN_PORTD;
00790 }
00791 
00792 
00799 #pragma inline=forced
00800 static void DisablePWMOutputs(void)
00801 {
00802   DDRB &= ~PWM_PATTERN_PORTB;
00803   DDRD &= ~PWM_PATTERN_PORTD;
00804 }
00805 
00806 
00815 #pragma inline=forced
00816 static void CommutationTicksUpdate(void)
00817 {
00818   if (commutationTicks < COMMUTATION_TICKS_STOPPED)
00819   {
00820     commutationTicks++;
00821   }
00822   else
00823   {
00824     fastFlags.motorStopped = TRUE;
00825     fastFlags.motorSynchronized = FALSE;
00826     if (fastFlags.driveWaveform != WAVEFORM_BLOCK_COMMUTATION)
00827     {
00828       TimersSetModeBlockCommutation();
00829       BlockCommutate(GetDesiredDirection(), GetHall());
00830 
00831 #if (SPEED_CONTROL_METHOD == SPEED_CONTROL_CLOSED_LOOP)
00832       PID_Reset_Integrator(&pidParameters);
00833 #endif
00834     }
00835   }
00836 }
00837 
00838 
00846 #pragma inline=forced
00847 static void MotorSynchronizedUpdate(void)
00848 {
00849   static uint8_t synchCount = 0;
00850 
00851   PMSMflags_t tempFlags;
00852 
00853   tempFlags = fastFlags;
00854 
00855   if ((tempFlags.desiredDirection == tempFlags.actualDirection) &&
00856       (tempFlags.motorStopped == FALSE) && (tempFlags.motorSynchronized == FALSE))
00857   {
00858     synchCount++;
00859     if (synchCount >= SYNCHRONIZATION_COUNT)
00860     {
00861       fastFlags.motorSynchronized = TRUE;
00862     }
00863   }
00864   else
00865   {
00866     fastFlags.motorSynchronized = FALSE;
00867     synchCount = 0;
00868   }
00869 }
00870 
00871 
00881 #pragma inline=forced
00882 static uint8_t IsMotorSynchronized(void)
00883 {
00884   return (uint8_t)(fastFlags.motorSynchronized);
00885 }
00886 
00887 
00900 #pragma vector=PCINT0_vect
00901 __interrupt void EmergencyInterruptISR(void)
00902 {
00903   DisablePWMOutputs();
00904   for (;;)
00905   {
00906 
00907   }
00908 }
00909 
00910 
00929 #pragma vector=PCINT1_vect
00930 __interrupt void HallChangeISR(void)
00931 {
00932   static uint8_t lastHall = 0xff;
00933   uint8_t hall;
00934 
00935   hall = GetHall();
00936 
00937   MotorSynchronizedUpdate();
00938   uint8_t synch = IsMotorSynchronized();
00939   if ((fastFlags.driveWaveform != WAVEFORM_SINUSOIDAL) && (synch))
00940   {
00941     TimersSetModeSinusoidal();
00942   }
00943 
00944   //If sinusoidal driving is used, synchronize sine wave generation to the
00945   //current hall sensor value. Advance commutation is also
00946   //added in the process.
00947   if (fastFlags.driveWaveform == WAVEFORM_SINUSOIDAL)
00948   {
00949     uint16_t tempIndex;
00950     if (GetDesiredDirection() == DIRECTION_FORWARD)
00951     {
00952       tempIndex = (CSOffsetsForward[hall] + advanceCommutationSteps) << 8;
00953     }
00954     else
00955     {
00956       tempIndex = (CSOffsetsReverse[hall] + advanceCommutationSteps) << 8;
00957     }
00958     sineTableIndex = tempIndex;
00959 
00960     //Adjust next sector start index. It might be set to a value larger than
00961     //SINE_TABLE_LENGTH at this point. This is adjusted in AdjustSineTableIndex
00962     //and should not be done here, as it will cause problems when advance
00963     //commutation is used.
00964     sineTableNextSectorStart = (tempIndex >> 8) + TABLE_ELEMENTS_PER_COMMUTATION_SECTOR;
00965   }
00966 
00967   //If block commutation is used. Commutate according to hall signal.
00968   else if (fastFlags.driveWaveform == WAVEFORM_BLOCK_COMMUTATION)
00969   {
00970     BlockCommutate(GetDesiredDirection(), hall);
00971   }
00972 
00973   //Update internal and external signals that depend on hall sensor value.
00974   TachoOutputUpdate(hall);
00975   ActualDirectionUpdate(lastHall, hall);
00976   ReverseRotationSignalUpdate();
00977 
00978   lastHall = hall;
00979 
00980   //Calculate new increment for sine wave generation and reset commutation
00981   //timer.
00982   sineTableIncrement = SineTableIncrementCalculate(commutationTicks);
00983   commutationTicks = 0;
00984 
00985   //Since the hall sensors are changing, the motor can not be stopped.
00986   fastFlags.motorStopped = FALSE;
00987 }
00988 
00989 
00998 #pragma vector=PCINT2_vect
00999 __interrupt void DirectionInputChangeISR(void)
01000 {
01001   //Update desired direction flag.
01002   DesiredDirectionUpdate();
01003 
01004 #if (TURN_MODE == TURN_MODE_COAST)
01005   //Disable driver signals to let motor coast. The motor will automatically
01006   //start once it is synchronized or stopped.
01007   DisablePWMOutputs();
01008   fastFlags.motorSynchronized = FALSE;
01009   fastFlags.motorStopped = FALSE;
01010   fastFlags.driveWaveform = WAVEFORM_UNDEFINED;
01011 #endif
01012 
01013 #if (TURN_MODE == TURN_MODE_BRAKE)
01014   //Set motor in brake mode. The motor will automatically start once it is
01015   //synchronized or stopped.
01016   fastFlags.motorSynchronized = FALSE;
01017   fastFlags.motorStopped = FALSE;
01018   TimersSetModeBrake(); // Automatically sets driveWaveform.
01019 #endif
01020 }
01021 
01022 
01029 #pragma vector=TIMER1_CAPT_vect
01030 __interrupt void Timer1CaptureISR(void)
01031 {
01032   if (fastFlags.driveWaveform == WAVEFORM_SINUSOIDAL)
01033   {
01034     uint8_t tempU, tempV, tempW;
01035     {
01036       uint8_t const __flash * sineTablePtr = sineTable;
01037 
01038       AdjustSineTableIndex(sineTableIncrement);
01039 
01040       //Add sine table offset to pointer. Must be multiplied by 3, since one
01041       //value for each phase is stored in the table.
01042       sineTablePtr += (sineTableIndex >> 8) * 3;
01043 
01044       tempU = *sineTablePtr++;
01045       if (GetDesiredDirection() == DIRECTION_FORWARD)
01046       {
01047         tempV = *sineTablePtr++;
01048         tempW = *sineTablePtr;
01049       }
01050       else
01051       {
01052         tempW = *sineTablePtr++;
01053         tempV = *sineTablePtr;
01054       }
01055     }
01056 
01057     //Scale sine modulation values to the current amplitude.
01058     tempU = ((uint16_t)(amplitude * tempU) >> 8);
01059     tempV = ((uint16_t)(amplitude * tempV) >> 8);
01060     tempW = ((uint16_t)(amplitude * tempW) >> 8);
01061 
01062     {
01063       uint8_t compareHigh, compareLow;
01064 
01065 
01066       InsertDeadband(tempU, &compareHigh, &compareLow);
01067       OCR0A = compareHigh;
01068       OCR0B = compareLow;
01069 
01070       InsertDeadband(tempV, &compareHigh, &compareLow);
01071       OCR1AL = compareHigh;
01072       OCR1BL = compareLow;
01073 
01074       InsertDeadband(tempW, &compareHigh, &compareLow);
01075       OCR2A = compareHigh;
01076       OCR2B = compareLow;
01077     }
01078   }
01079   else if (fastFlags.driveWaveform == WAVEFORM_BLOCK_COMMUTATION)
01080   {
01081     uint16_t blockCommutationDuty = amplitude * BLOCK_COMMUTATION_DUTY_MULTIPLIER;
01082 
01083     if (blockCommutationDuty > 255)
01084     {
01085       blockCommutationDuty = 255;
01086     }
01087 
01088     BlockCommutationSetDuty((uint8_t)blockCommutationDuty);
01089   }
01090 
01091   CommutationTicksUpdate();
01092 
01093   {
01094     //Run the speed regulation loop with constant intervals.
01095     static uint8_t speedRegTicks = 0;
01096     speedRegTicks++;
01097     if (speedRegTicks >= SPEED_CONTROLLER_TIME_BASE)
01098     {
01099       SpeedControllerRun = TRUE;
01100       speedRegTicks -= SPEED_CONTROLLER_TIME_BASE;
01101     }
01102   }
01103 }
01104 
01105 
01121 #pragma vector=ADC_vect
01122 __interrupt void ADCCompleteISR(void)
01123 {
01124   switch (ADMUX)
01125   {
01126   case ADMUX_SPEED_REF:
01127     speedInput = ADCH;
01128     ADMUX = ADMUX_CURRENT;
01129     break;
01130   case ADMUX_CURRENT:
01131     current = ADCH;
01132     ADMUX = ADMUX_SPEED_REF;
01133     break;
01134   default:
01135     //This is probably an error and should be handled.
01136     break;
01137   }
01138 
01139   //Clear Timer/counter0 overflow flag.
01140   TIFR0 = (1 << TOV0);
01141 }

Generated on Mon Mar 27 09:31:24 2006 for AVR447: Sine wave driving of three phase motor by  doxygen 1.4.4