00001 //****************************************************************************** 00011 //****************************************************************************** 00012 00013 /* Copyright (c) 2008, Atmel Corporation All rights reserved. 00014 * 00015 * Redistribution and use in source and binary forms, with or without 00016 * modification, are permitted provided that the following conditions are met: 00017 * 00018 * 1. Redistributions of source code must retain the above copyright notice, 00019 * this list of conditions and the following disclaimer. 00020 * 00021 * 2. Redistributions in binary form must reproduce the above copyright notice, 00022 * this list of conditions and the following disclaimer in the documentation 00023 * and/or other materials provided with the distribution. 00024 * 00025 * 3. The name of ATMEL may not be used to endorse or promote products derived 00026 * from this software without specific prior written permission. 00027 * 00028 * THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED 00029 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00030 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND 00031 * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, 00032 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00033 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00034 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00035 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00036 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 00037 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00038 */ 00039 00040 //_____ I N C L U D E S ___________________________________________________ 00041 00042 00043 #include "config.h" 00044 #include "usi_twi_slave.h" 00045 #include "bldc.h" 00046 #include "TinyX61_macros.h" 00047 #include "ushell_task.h" 00048 00049 /* 00050 * Before running this application: 00051 * Make sure CKDIV8 fuse is disabled. 00052 * Set PLL as clock source. 00053 */ 00054 00055 volatile motorControlFlags_t mcFastFlags; 00056 volatile U8 ControlMode; 00057 volatile U16 SpeedMeasure; 00058 volatile U16 timer_value; 00059 volatile U16 new_measured_speed; 00060 volatile Bool is_speed_to_read=FALSE; 00061 00062 // USI Handshake variables for USI Slave to TWI Master communication 00063 Bool is_data_to_send=0; 00064 Bool is_data_received=0; 00065 unsigned char data_to_send; 00066 unsigned char data_received; 00067 00068 U16 speed; 00069 U16 current; 00070 U8 direction; 00071 00072 volatile uint8_t hall; 00073 00082 #ifndef __GNUC__ 00083 #pragma optimize=none 00084 void Set_cpu_prescaler(U8 x) 00085 { 00086 U8 save_int=SREG&0x80; 00087 Disable_interrupt(); 00088 CLKPR=(1<<CLKPCE); 00089 CLKPR=x; 00090 if(save_int) { Enable_interrupt(); } 00091 } 00092 #endif 00093 00094 void main(void) 00095 { 00096 Clear_prescaler(); 00097 PLLInit(); 00098 PWMInit(); 00099 HallSensorInit(); 00100 00101 ADCInit(); 00102 00103 // Init USI Handshake variables 00104 is_data_to_send=FALSE; 00105 is_data_received=FALSE; 00106 00107 SpeedMeasure=0; 00108 is_speed_to_read=FALSE; 00109 00110 // Initialize timer0 for Speed Measurement 00111 Timer0Init(); 00112 00113 PortsInit(); 00114 00115 // uShell init 00116 ushell_task_init(); 00117 00118 //Run Commutate() once to make sure that the right coils are activated. 00119 Commutate(); 00120 00121 //Enable interrupts. The rest will now be handled by the ADC and Pin change 00122 //interrupts. 00123 Enable_interrupt(); 00124 00125 for (;;) { 00126 if(ControlMode==MOTOR_CONTROL_CENTER) 00127 { 00128 if (mcFastFlags.state == STATE_RUN) 00129 { 00130 // Update Motor speed 00131 MotorSetDutyCycle(mcFastFlags.speed); 00132 // Start Speed measurement 00133 if(is_speed_to_read==TRUE) 00134 SpeedMeasurement(); 00135 } 00136 else 00137 { 00138 //Stop Motor 00139 MotorSetDutyCycle(0); 00140 mcFastFlags.speed=0; 00141 } 00142 00143 // Decodes new Motor Control Center command 00144 ushell_task(); 00145 00146 // Manages new low level TWI data received 00147 if(is_data_received==FALSE) 00148 { 00149 if (USI_TWI_Data_In_Receive_Buffer()) //Something new of the USI ? 00150 { 00151 data_received=USI_TWI_Receive_Byte(); 00152 is_data_received=TRUE; 00153 } 00154 } 00155 } 00156 } 00157 } 00158 00159 00160 void Commutate(void) 00161 { 00162 uint8_t temp; 00163 //Read hall sensor inputs. 00164 temp = ( PINA & ((1 << PA5) | (1 << PA4) | (1 << PA1)) ); 00165 hall = (((temp&0x30)>>3) | (temp&0x02)>>1); 00166 00167 00168 //Activate output pattern corresponding to current direction and position. 00169 if (mcFastFlags.direction == DIRECTION_FORWARD) { 00170 TCCR1E = commTableForward[hall]; 00171 } 00172 else { 00173 TCCR1E = commTableReverse[hall]; 00174 } 00175 00176 } 00177 00178 #pragma inline=forced 00179 void SpeedMeasurement(void) 00180 { 00181 // if (timer_value == 0) 00182 // {timer_value += 1 ;} // warning DIV by 0 00183 /* 00184 new_measured_speed = K_SPEED / timer_value; 00185 if(new_measured_speed > 255) new_measured_speed = 255; // Variable saturation 00186 SpeedMeasure=(U16)new_measured_speed; 00187 */ 00188 is_speed_to_read=FALSE; 00189 00190 } 00191 00192 void PLLInit(void) 00193 { 00194 //Enable fast peripheral clock (64MHz for Timer1). 00195 PLLCSR = (1 << PCKE); 00196 } 00197 00198 00199 void PWMInit(void) 00200 { 00201 00202 //Clear on up-counting. 00203 TCCR1A = (1 << COM1A1) | (0 << COM1A0) | (1 << PWM1A); 00204 00205 //Set WGM to PWM6, dual slope mode. 00206 TCCR1D = (1 << WGM11) | (1 << WGM10); 00207 00208 //Set top value. 00209 TC1_WRITE_10_BIT_REGISTER(OCR1C, PWM_TOP_VALUE); 00210 00211 //Run timer at full speed. 00212 TCCR1B = (1 << CS10); 00213 } 00214 00215 00216 void HallSensorInit(void) 00217 { 00218 //Enable pin change interrupts for PA1-PA4-PA5 (PCINT1-4-5). 00219 PCMSK0 = (1 << PCINT1) | (1 << PCINT4) | (1 << PCINT5); 00220 00221 //Zero out PCMSK1, since it is initialized to a non-zero value. 00222 PCMSK1 = 1; 00223 00224 //Enable pin change interrupt 1. 00225 GIMSK |= (1 << PCIE1); 00226 } 00227 00228 00229 void ADCInit(void) 00230 { 00231 ADMUX = (0 << REFS1) | (0 << REFS0) | //VCC as voltage reference. 00232 (0 << ADLAR) | //Right adjusted result. 00233 ADMUX_PA2; //ADC channel. MC301 rev B 00234 00235 ADCSRB = (1 << REFS2) | //Last reference selection bit. 00236 ADC_TS_FREERUNNING; //Free running mode. 00237 00238 ADCSRA = (1 << ADEN) | //Enable. 00239 (1 << ADSC) | //Start first conversion. 00240 (1 << ADATE) | //Auto triggering. 00241 (1 << ADIE) | //Enable interrupt. 00242 ADC_PRESCALER; 00243 } 00244 00245 00246 void PortsInit(void) 00247 { 00248 //Set PWM pins as output. (PWM output is still controlled through TCCR1E register.) 00249 DDRB = (1 << PB0) | (1 << PB1) | (1 << PB2) | (1 << PB3) | (1 << PB4) | (1 << PB5)| (1 << PB6) ; 00250 } 00251 00252 void TWInit(void) 00253 { 00254 // Select the Port A as USI port 00255 USIPP|=(1<<USIPOS); 00256 // Own TWI slave address 00257 USI_TWI_Slave_Initialise( TWI_SLAVE_ADDRESS ); 00258 } 00259 00260 void MotorSetDutyCycle(U16 duty) 00261 { 00262 TC1_WRITE_10_BIT_REGISTER(OCR1A, duty); 00263 } 00264 00265 #ifdef __GNUC__ 00266 ISR(PCINT_vect) 00267 #else 00268 #pragma vector = PCINT0_vect 00269 __interrupt void HallChangeISR() 00270 #endif 00271 { 00272 00273 Commutate(); 00274 00275 //estimation speed on rising edge of Hall 1 (U') 00276 if (PINA&(1<<PORTA1)) 00277 { 00278 if(is_speed_to_read==FALSE) 00279 { 00280 // Stop Timer 00281 TCCR0B &= ~((1<<CS02)|(1<<CS01) |(1<<CS00)); 00282 00283 // Read timer0 value 00284 TC0_READ_TCNT0(timer_value); 00285 } 00286 00287 // Restart timer0 00288 TCCR0B = ((1<<CS02)|(0<<CS01) |(1<<CS00)); // Timer clock = 00289 // system clock / 00290 // 128 : 16µs 00291 TC0_WRITE_TCNT0(0x0); 00292 00293 is_speed_to_read=FALSE; // Wait for a period 00294 } 00295 else 00296 { 00297 is_speed_to_read=TRUE; 00298 } 00299 } 00300 00301 #ifdef __GNUC__ 00302 ISR(ADC_vect) 00303 #else 00304 #pragma vector = ADC_vect 00305 __interrupt void ADCISR() 00306 #endif 00307 { 00308 U16 speedSetpoint; 00309 00310 //Read ADC sample. 00311 speedSetpoint = ADC; 00312 00313 if(speedSetpoint>=ADC_TWI) 00314 { 00315 ControlMode=MOTOR_CONTROL_CENTER; 00316 00317 // Clear ADC enable 00318 ADCSRA &= ~(1 << ADEN); 00319 //Disable interrupt. 00320 ADCSRA &= ~(1 << ADIE); 00321 00322 TWInit(); 00323 } 00324 else 00325 { 00326 ControlMode=POTENTIOMETER; 00327 //Extract sign. 00328 if (speedSetpoint >= ((ADC_MAX + 1) / 2)) { 00329 mcFastFlags.direction = DIRECTION_FORWARD; 00330 speedSetpoint -= ((ADC_MAX + 1) / 2); 00331 } 00332 else { 00333 mcFastFlags.direction = DIRECTION_REVERSE; 00334 speedSetpoint = ((ADC_MAX) / 2) - speedSetpoint; 00335 } 00336 00337 //Multiply speed setpoint by 2 to get full PWM range. 00338 speedSetpoint *= 2; 00339 00340 MotorSetDutyCycle(speedSetpoint); 00341 } 00342 } 00343 00344 void Timer0Init(void) 00345 { 00346 TCCR0B = ((1<<CS02)|(0<<CS01) |(1<<CS00)); // Timer clock = 00347 // system clock / 00348 // 128 : 16µs 00349 TIFR |= (1<<TOV0); //Clear TOV0 / clear 00350 00351 TC0_WRITE_TCNT0(0x0); 00352 //pending interrupts 00353 TIMSK |= (1<<TOIE0); //Enable Timer0 00354 //Overflow Interrupt 00355 } 00356 00362 #ifdef __GNUC__ 00363 ISR(TIMER0_OVF_vect) 00364 #else 00365 #pragma vector = TIM0_OVF_vect 00366 __interrupt void ovfl_timer0(void) 00367 #endif 00368 { 00369 TC0_WRITE_TCNT0(0x0); 00370 TIFR |= (1<<TOV0); //Clear TOV0 / clear 00371 //pending interrupts 00372 TIMSK |= (1<<TOIE0); //Enable Timer0 00373 }
1.5.7.1