03-12-2009, 11:50 AM
|
#551 (permalink)
|
Master EcoModder
Join Date: Jun 2008
Location: London, Ontario
Posts: 1,096
Thanks: 0
Thanked 17 Times in 14 Posts
|
dcb, he was talking about the cheapo chinese breadboards, I think. In reality, I think the cost of developing with this chip or that is not relevant, because i think that we should be developing a "standard" interconnect between controller and drive boards. This way, any processor or architecture (fpga, maybe?) can be put on the control board and plugged into any power board. After Paul is done, an AC or BLDC open-source controller could be made and the same control board plugged into it. With this done, anybody's simple and cheap or fancy and expensive control board could be attached to anybody's simple and cheap or fancy and expensive power board. Sure wish i could drop a cheap imported honda motor into my mazda when the engine poops out, or move my motor into a new vehicle when the car rusts through.
|
|
|
Today
|
|
|
Other popular topics in this forum...
|
|
|
03-12-2009, 11:53 AM
|
#552 (permalink)
|
Master EcoModder
Join Date: Jun 2008
Location: London, Ontario
Posts: 1,096
Thanks: 0
Thanked 17 Times in 14 Posts
|
So their compiler is free if you don't have optimization? You don't really need optimization if you code carefully. This sort of motor control is not THAT intensive to a DSC. Honestly, i don't turn on optimization on any project that i've worked on using freescale microcontrollers (5213, 5282, 908)
|
|
|
03-12-2009, 11:56 AM
|
#553 (permalink)
|
needs more cowbell
Join Date: Feb 2008
Location: ˙
Posts: 5,038
Thanks: 158
Thanked 269 Times in 212 Posts
|
Is the free version compatable with the fancy chip? Reading a hall sensor is childs play, there is something to be said for having a working development environment too. That path is guaranteed success, while much time could be wasted chasing the freescale toolchain.
__________________
WINDMILLS DO NOT WORK THAT WAY!!!
|
|
|
03-12-2009, 11:59 AM
|
#554 (permalink)
|
Master EcoModder
Join Date: Jun 2008
Location: London, Ontario
Posts: 1,096
Thanks: 0
Thanked 17 Times in 14 Posts
|
I would assume so. There is actually a seperate Codewarrior version for each processor core that they offer (something that they plan on merging into one Eclipse-base IDE later this year). So you'd just go and get the DSC Codewarrior free version.
EDIT:
Here is a direct link to the DSC product page, rather than the demo kit page:
http://www.freescale.com/webapp/sps/...dG1729b7fBcKzP
|
|
|
03-12-2009, 12:00 PM
|
#555 (permalink)
|
needs more cowbell
Join Date: Feb 2008
Location: ˙
Posts: 5,038
Thanks: 158
Thanked 269 Times in 212 Posts
|
It is your idea, you can validate that it works. I don't assume anything.
__________________
WINDMILLS DO NOT WORK THAT WAY!!!
|
|
|
03-12-2009, 12:04 PM
|
#556 (permalink)
|
Master EcoModder
Join Date: Jun 2008
Location: London, Ontario
Posts: 1,096
Thanks: 0
Thanked 17 Times in 14 Posts
|
Okay, i looked further, the free version is all you need. The most beautiful thing is that it supports Processor Expert. It is a processor setup utility that generates a basic project with port inits and some fairly advanced software modules customized to work as you want them to.
|
|
|
03-12-2009, 12:25 PM
|
#557 (permalink)
|
needs more cowbell
Join Date: Feb 2008
Location: ˙
Posts: 5,038
Thanks: 158
Thanked 269 Times in 212 Posts
|
just FYI, Here is an AVR paper on hall effects and BLDC, it really is trivial stuff, not worth jumping ship for. And doesn't introduce proprietary tools into an open source project (always a red flag):
http://www.atmel.com/dyn/resources/p...ts/doc2596.pdf
They use a mega88 in the examples, which is just like the 168 in the *duinos and the mpguino, obduino, air flap thing, etc. etc. so there will be some local expertise too. Here is the C source (ISR needs some help for faster RPMs) (would need porting to GCC)
PHP Code:
/* This file has been prepared for Doxygen automatic documentation generation.*/ /*! \file ********************************************************************* * * \brief A brief description of the file is written here. * * A more detailed description of the file should written here. * * \par Application note: * AVR443: Sensorbased control of three-phase BLDC motor * \par * For comprehensive code documentation, supported compilers, compiler settings * and supported devices see readme.html\n * Target device: ATmega48/88/168 * * \author Atmel Corporation: http://www.atmel.com \n * Support email: avr@atmel.com * * $Name$ * $Revision: 2441 $ * $RCSfile$ * $Date: 2007-09-18 07:56:18 +0200 (ti, 18 sep 2007) $ \n ******************************************************************************/ #include <ioavr.h> #include <inavr.h> #include "sensor_three_phase_BLDC.h" /*! \brief CCW rotation patterns. * * Configuration of pin drive levels * and timer COM bits in different * phases for CounterClockWise rotation. */ unsigned char drvPatternsCCW[] = { 0, //Stop // MC_PORT drive config PDP2_CCW, //Phase2 PDP4_CCW, //Phase4 PDP3_CCW, //Phase3 PDP6_CCW, //Phase6 PDP1_CCW, //Phase1 PDP5_CCW, //Phase5 // Configuration of Output Compare operation for timer 0 COM0P2_CCW, //Phase2 COM0P4_CCW, //Phase4 COM0P3_CCW, //Phase3 COM0P6_CCW, //Phase6 COM0P1_CCW, //Phase1 COM0P5_CCW, //Phase5 // Configuration of Output Compare operation for timer 2 COM2P2_CCW, //Phase2 COM2P4_CCW, //Phase4 COM2P3_CCW, //Phase3 COM2P6_CCW, //Phase6 COM2P1_CCW, //Phase1 COM2P5_CCW //Phase5 }; /*! \brief CW rotation patterns. * * Configuration of pin drive levels * and timer COM bits in different * phases for ClockWise rotation. */ unsigned char drvPatternsCW[] = { 0, //Stop // MC_PORT drive config PDP2_CW, //Phase2 PDP6_CW, //Phase6 PDP1_CW, //Phase1 PDP4_CW, //Phase4 PDP3_CW, //Phase3 PDP5_CW, //Phase5 // Configuration of Output Compare operation for timer 0 COM0P2_CW, //Phase2 COM0P6_CW, //Phase6 COM0P1_CW, //Phase1 COM0P4_CW, //Phase4 COM0P3_CW, //Phase3 COM0P5_CW, //Phase5 // Configuration of Output Compare operation for timer 2 COM2P2_CW, //Phase2 COM2P6_CW, //Phase6 COM2P1_CW, //Phase1 COM2P4_CW, //Phase4 COM2P3_CW, //Phase3 COM2P5_CW //Phase5 }; //! Stores the current motor driver pattern. __regvar __no_init unsigned char *pDrvPattern @14; //__regvar __no_init unsigned char *pComPattern @12; //! Used for optimized temporary varables. __regvar __no_init union _fastTemp{ unsigned int word; struct{ unsigned char LByte; unsigned char HByte; //Hbyte = Zero }; } fastTemp @12; __regvar __no_init unsigned char hallMask @11; //!< Workaround for internal compiler error __regvar __no_init unsigned char count @10; //!< Optimized variable decremented every pin change int. /*! \brief Pin Change Interrupt Service Routine. * * Updates the PWM outputs controlling the low side of the driver and * the IO controlling the high side of the driver. To ensure a speed * optimal interrupt the variables used in the interrupt are placed * in reserved registers (locked for this purpose only). Further, the * information required to do the commutation is placed in tables that * are accessed very efficiently using the Hall sensor input signals * as offset. * * \param void * * \return void */ #pragma vector = PCINT0_vect //! __interrupt void PCINT0_ISR( void ) { unsigned char *pTemp; fastTemp.word = ((PIN_HALL & hallMask)>>1); // Read Hall, Mask Pins, shift to use as pointer offset // Line below is desirable performance wise, but causes an internal error in compiler // fastTemp.LByte = (PIN_HALL & HALL_MASK)>>1; // Read Hall, Mask Pins, shift to use as pointer offset pTemp = pDrvPattern + fastTemp.word; // TCCR0A = fastTemp.HByte; //Disable PWM outputs (and thereby close low side FET) // TCCR2A = fastTemp.HByte; //Disable PWM output (and thereby close low side FET) PORT_MC = *(pTemp); //Change drive levels on high side TCCR0A = *(pTemp + PATTERN_COM0_OFFSET); // Reconfigure output compare operation for T0 TCCR2A = *(pTemp + PATTERN_COM2_OFFSET); // Reconfigure output compare operation for T2 count--; } /*! \brief Initialize pin change interrupts for PORTB pin 1, 2 and 3. * * Sets up the pins used to sense the Hall sensor signals to generate * interrupt if the pin level changes (both rising and falling edge). * * \param void * * \return void */ static void Init_MC_pin_change_interrupt( void ) { PCMSK0 = (1<<PCINT1)|(1<<PCINT2)|(1<<PCINT3); //Enable pin change interrupt on PB1:3 PCICR = 1<<PCIE0; // Enable pin change interrupt0 (PORTB) } /*! \brief Start an AD convertion and return result. * * Starts an AD conversion on the specified ADC channel and returns * the result when the conversin is completed. Uses polling to wait for * the AD conversion to complete. * * \param channel Specify the ADMUX register settings to access the correct channel. * * \return adcResult 8-bit result (high byte of AD convertion). */ unsigned char Get_ADC8(unsigned char muxSetting) { ADMUX = muxSetting; // Start AD conversion. ADCSRA |= (1 << ADSC); // Wait for ADC conversion to complete. while ( ADCSRA & (1 << ADSC) ); return ADCH; } //! /*! \brief Initialize motor control timers. * * Initialize the Timer 1 and timer 2 to run in phase and frequency correct * PWM mode (symmetric PWM). The base frequency is set to 32kHz (can be * reduced at the expense of lower resolution on the speed control). The * functions also ensures that the timers are counting in synch. * * \param void * * \return void */ static void Init_MC_timers( void ) { //Timer Counter 0. OCRA and OCRB used for motor TCCR0A = (1<<COM0A1)|(0<<COM0A0)| // Clear OCRA on compare match (1<<COM0B1)|(0<<COM0B0)| // Clear OCRB on compare match (1<<WGM01)|(1<<WGM00); // Fast PWM mode TCCR0B = (0<<FOC0A)|(0<<FOC0B)| (0<<WGM02)| // Fast PWM mode (0<<CS02)|(0<<CS01)|(1<<CS00); // Prescaler = CLK/1 //Timer Counter 2. OCRA and OCRB used for motor TCCR2A = (0<<COM2A1)|(0<<COM2A0)| // OCRA not connected (1<<COM2B1)|(0<<COM2B0)| // Clear OCRB on compare match (1<<WGM01)|(1<<WGM00); // Fast PWM mode TCCR2B = (0<<FOC2A)|(0<<FOC2B)| (0<<WGM22)| // Fast PWM mode (0<<CS22)|(0<<CS21)|(1<<CS20); // Prescaler = CLK/1 // Synchronize timers TCNT0 = 0; TCNT2 = 3; TIFR0 = TIFR0; // Clear TC0 interrupt flags TIFR1 = TIFR1; // Clear TC2 interrupt flags } /*! \brief Initialize ADC module. * * Sets up the ADC with prescaler value 4, which means a maximum sample speed * of CPU frequency divided by 52 (13*4). With the ADC measuring the speed set * point and shunt voltage, this gives a reaction time of two samples for * detecting over-current. * * \param void * * \return void */ static void Init_ADC( void ) { ADCSRA = (1 << ADEN) | (1 << ADPS1); // Enable ADC, clock prescaler = 4 } /*! \brief Set motor speed. * * Updates the output compare registers of the timer 0 and timer 2 which * control the duty cycle of the PWM output and thereby the speed of the * motor. The method used ensures that that all PWM channels are behaving * same duty cycle. * * \param speed Compare match value that defines PWM duty cycle. * * \return void */ static void Set_Speed(unsigned char speed) { TIFR0 = TIFR0; // Clear TC0 interrupt flags while( !(TIFR0 & (1<<TOV0))); // Wait for TOV to ensure that all registers are // updated in the same timer cycle __disable_interrupt(); OCR0A = speed; // Change the duty cycle OCR0B = speed; OCR2B = speed; __enable_interrupt(); } /*! \brief Set motor direction, CW og CCW. * * Set the commutation table pointer up to point at either the clockwise * or counter clockwise direction table. Note that it is not recommended * to change direction without first reducing the speed of the motor, * preferably stopping it fully. * * \param direction Direction is given as Clockwise or Counter Clockwise. * * \return void */ static void Set_Direction(unsigned char direction) { if(direction == CLOCKWISE) { __disable_interrupt(); //Variable also used in interrupt and access most be protected pDrvPattern = drvPatternsCW; // Set dir to CW, by pointing to CW pattern __enable_interrupt(); } else { __disable_interrupt(); //Variable also used in interrupt and access most be protected pDrvPattern = drvPatternsCCW; // Set dir to CCW, by pointing to CCW pattern __enable_interrupt(); } } /*! \brief Main function for motor control example. * * Initialize speed variables to zero speed, and enabled operation in clockwise * direction. Hence a speed reference input is read from ADC_MUX_SPEED_REF. If * Current exeeds the MAX_CURRENT_ADC limit the speed (PWM duty cycle) is reduced. * * \param void * * \return void */ void main( void ) { unsigned char speed = 0; unsigned char setspeed = 0; signed int current; MCUCR |= (1<<PUD); // Disable all pull-ups hallMask = HALL_MASK; // Initialize hallMask variable //Set initial direction. Set_Direction( CLOCKWISE ); Init_MC_timers(); Init_MC_pin_change_interrupt(); Init_ADC(); DDR_HALL |= HALL_MASK; //Lock HALL sensor by driving Hall lines PORT_HALL |= HALL_MASK; PORT_HALL &= ~HALL_MASK; //Release HALL sensor lines and trigger PC interrupt DDR_HALL &= ~HALL_MASK; __enable_interrupt(); Set_Speed(speed); DDR_MC = MC_MASK; // Enable outputs DDRC |= (1<<PC1); for(;;) { // Get shunt voltage (current measurement) current = Get_ADC8(ADC_MUX_SHUNT_H); // If current consumption is too high, limit current if (current > MAX_CURRENT_ADC ) { PORTC &= ~(1<<OVERCURRENT_PIN); //Turn on over-current LED (active low) if( speed >= 2 ) { speed -= 2; // Slow down if too fast. } } else { PORTC |= (1<<OVERCURRENT_PIN); // Turn off over-current LED (active low) // Get speed reference voltage (Assumes 2.5V to be maximum analog input, // multiplied by 2 to convert to PWM range). setspeed = Get_ADC8(ADC_MUX_SPEED_REF)*2; // Approach speed set point. if( setspeed > speed ) { ++speed; } else { if( setspeed < speed ) { --speed; } } } Set_Speed(speed); } }
__________________
WINDMILLS DO NOT WORK THAT WAY!!!
Last edited by dcb; 03-12-2009 at 12:32 PM..
|
|
|
03-12-2009, 12:40 PM
|
#558 (permalink)
|
Master EcoModder
Join Date: Jun 2008
Location: London, Ontario
Posts: 1,096
Thanks: 0
Thanked 17 Times in 14 Posts
|
Great example, thanks. I'll look further into opensource tools for freescale products when I have the time to actually work on something. At least codewarrior is free and has a HUGE support network (freescale forums are excellent because they have paid moderators who are experts with their products). I'd probably stick to freescale because that's what i've used at work since graduation.
|
|
|
03-12-2009, 12:55 PM
|
#559 (permalink)
|
needs more cowbell
Join Date: Feb 2008
Location: ˙
Posts: 5,038
Thanks: 158
Thanked 269 Times in 212 Posts
|
Just FYI, here is some more avr motor related documents/sources
Atmel Products - Microcontrollers - AVRŽ 8-Bit RISC - Applications
and http://avrfreaks.net is a good resource also.
Certainly knowing about multiple microcontroller platforms isn't a bad thing, especially if you do it for a living.
__________________
WINDMILLS DO NOT WORK THAT WAY!!!
|
|
|
03-12-2009, 01:00 PM
|
#560 (permalink)
|
Master EcoModder
Join Date: Jun 2008
Location: London, Ontario
Posts: 1,096
Thanks: 0
Thanked 17 Times in 14 Posts
|
You are absolutely correct about that. So far, though, i've been sampling across the freescale domain... there's enough to learn moving from 908 to coldfire to dsc, not to mention iMX. I've also done pic16 and pic18 deveopment before graduating. I am going to look into dsPIC for motor control as well as I like their dev environment. I've also learned of a company that has developed stepper motor drive control entirely based within an FPGA - that would be interesting to do for AC/BLDC as well. The sky is the limit!
|
|
|
|