Forum Menu




 


Log in Problems?
New User? Sign Up!
AVR Freaks Forum Index

Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Author Message
asin209
PostPosted: Sep 30, 2011 - 02:34 PM
Newbie


Joined: Sep 30, 2011
Posts: 10


I am working on controlling the speed of a 3phase bldc motor. I want to measure the speed of the motor usint timer/counter 0 and external interrupt(INT0) that measures the rising edges of a hall sensor. Could anyone guide me on how do i do this? I am a beginner in avr and C programming language. Your reply is highly appreciated. Thanks in advance!
 
 View user's profile Send private message  
Reply with quote Back to top
bobgardner
PostPosted: Sep 30, 2011 - 03:41 PM
10k+ Postman


Joined: Sep 04, 2002
Posts: 23482
Location: Orlando Florida

You need help with the algorithm, or the coding? Do you want to control the speed or measure the speed? (might be a language problem)

_________________
Imagecraft compiler user
 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
asin209
PostPosted: Sep 30, 2011 - 03:48 PM
Newbie


Joined: Sep 30, 2011
Posts: 10


I would want to do both. But first i want to learn how to measure the speed of the motor. I have read stuff on the internet saying to measure the rising edges of a hall sensor. But im not so sure how do i do that in code. Some code might be able to give me a start. Thanks.
 
 View user's profile Send private message  
Reply with quote Back to top
MarioRivas
PostPosted: Sep 30, 2011 - 03:52 PM
Hangaround


Joined: Dec 29, 2010
Posts: 475


do a Google search for tachometer avr. you will find several projects with source code.
 
 View user's profile Send private message  
Reply with quote Back to top
asin209
PostPosted: Sep 30, 2011 - 03:57 PM
Newbie


Joined: Sep 30, 2011
Posts: 10


I went thorugh that. But I would have to use timer0 in my case as Timer1A/B and Timer 2 are being used to provide pwm for the high side switches. I have to use INT0 instead of AIN0 since ill be using timer0. So im not sure how to do that using timer0 and INT0
 
 View user's profile Send private message  
Reply with quote Back to top
MarioRivas
PostPosted: Sep 30, 2011 - 04:18 PM
Hangaround


Joined: Dec 29, 2010
Posts: 475


it should not be that difficult to adapt code between the different timers. It's a good way to learn about avr registers. Datasheets Datasheets.

Not many here will do the hard work for you.
 
 View user's profile Send private message  
Reply with quote Back to top
gregsmithcts
PostPosted: Sep 30, 2011 - 04:22 PM
Raving lunatic


Joined: Nov 04, 2010
Posts: 2098
Location: Bristol, UK

many=any
Wink

As a beginner, I suggest you start with (1) flash an LED at predictable rate (2) read state of switches (3) use timers/pwm to vary brightness of LED (4) control bldc motors.

_________________
--greg
Still learning, don't shout at me, educate me.
Starting the fire is easy; the hardest part is learning how to keep the flame!


Last edited by gregsmithcts on Sep 30, 2011 - 04:24 PM; edited 1 time in total
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
theusch
PostPosted: Sep 30, 2011 - 04:23 PM
10k+ Postman


Joined: Feb 19, 2001
Posts: 28223
Location: Wisconsin USA

Quote:

I would have to use timer0 in my case as Timer1A/B and Timer 2 are being used to provide pwm for the high side switches. I have to use INT0 instead of AIN0 since ill be using timer0. So im not sure how to do that using timer0 and INT0


In all this, wouldn't it be helpful to tell what AVR model you are using?

Depending on the PWM setup, ICP can still be used as long as timer1 is running during the needed sensing period.

Quote:

I am a beginner in avr and C programming language.

Then why have you cast your other (PWM) requirements in stone before considering all the app requirements as a whole?
 
 View user's profile Send private message  
Reply with quote Back to top
asin209
PostPosted: Sep 30, 2011 - 04:31 PM
Newbie


Joined: Sep 30, 2011
Posts: 10


Ill be using the pwm in phase correct mode. I want to detect the rising edges of a hall sensor.(2 rising edges will give me 1 mechanical revolution) as this is a 4pole 3phase bldc motor. Would i be able to use the ICP to measure the rising edges still? and how?

Thank You.
 
 View user's profile Send private message  
Reply with quote Back to top
theusch
PostPosted: Sep 30, 2011 - 05:24 PM
10k+ Postman


Joined: Feb 19, 2001
Posts: 28223
Location: Wisconsin USA

Quote:

In all this, wouldn't it be helpful to tell what AVR model you are using?

Quote:

Ill be using the pwm in phase correct mode. ... Would i be able to use the ICP to measure the rising edges still? and how?

So, tell the AVR model and show the setup code for the timer. (But indeed, the up/down counting modes would make it difficult (not practical?) to use the ICP trips.) [It is perhaps interesting/ironic that in all of my production AVR apps over the years that use PWM, I've never once used any of the up/down modes. But you motor people will have to educate me--would this be the type of app where this mode would be useful?] [[And that brings us back to the AVR model selection--wouldn't one want to use e.g. AT90PWM3 that is intended for this type of app? Or at least one with enough 16-bit timer channels?]]



Also, tell the max speed that needs to be measured.
 
 View user's profile Send private message  
Reply with quote Back to top
asin209
PostPosted: Sep 30, 2011 - 05:43 PM
Newbie


Joined: Sep 30, 2011
Posts: 10


Code:
#include "avr/io.h"
#include "avr/interrupt.h"


ISR(TIMER0_OVF_vect)
{
   overflow++;

}


ISR(INT0_vect)
{
 //this is where the rising edges will be detected
//not sure how to put it in code


}


int main()
{

   MCUCR |= (1<<ISC01)|(1<<ISC00);//rising edges
   GICR |= (1<<INT0);
   
   TCCR0 |= (1<<CS01)|(1<<CS00);//prescaler 64
   TCNT0 = 0x00;// initialise timer counter0
   TIMSK |= (1<<TOIE0); // enable timer0 interrupt overflow

   while(1)
   {
      if(PIND & (1<<PD2))
      {
         //usart sends the speed in rpm to the hyperterminal
      }
   }
   
   return 0;
}
   
   
 
 View user's profile Send private message  
Reply with quote Back to top
asin209
PostPosted: Sep 30, 2011 - 05:44 PM
Newbie


Joined: Sep 30, 2011
Posts: 10


the max speed that needs to be measured is 5000rpm
 
 View user's profile Send private message  
Reply with quote Back to top
theusch
PostPosted: Sep 30, 2011 - 07:05 PM
10k+ Postman


Joined: Feb 19, 2001
Posts: 28223
Location: Wisconsin USA

5000 RPM; 2 counts/revolution; 10000 counts/minute. 166 counts/second max; 6ms/count. So that isn't going to stress AVR capabilities. In fact if there are clean edges a fast timer tick would allow polling, or even polling and debouncing. I poll banks of flowmeters with the max frequency in that 100Hz to 200Hz range.

But, hey, I'm out--unless you start answering questions and give the whole scenario. What AVR model? What clock speed? Type of clock source? Timer setup for PWM?
 
 View user's profile Send private message  
Reply with quote Back to top
asin209
PostPosted: Sep 30, 2011 - 10:55 PM
Newbie


Joined: Sep 30, 2011
Posts: 10


Sorry.
Im using ATmega8. The clock speed is 8Mhz and the timer setup is as follows:-
Code:
int main()
{   


   int pwm=255;

   TCCR1A |=  (1 << COM1A1) | (1 << COM1B1) | (1 << WGM10);//phase correct 8bit
   TCCR1B |= (1 << CS10);// no prescaling
   TCCR2 |= (1 << COM21)  | (1 << CS20)| (1 << WGM20);//phase correct 8bit with no prescaling
   
   OCR1A = pwm;
   OCR1B = pwm;    // initialises values for output compare of timers
   OCR2 = pwm;

   DDRB=0xff;
   PORTB=0b00001110;//toggle PB1, PB2 and PB3 for pwm
}


When you say type of clock source do you mean this?
"Int RC Osc. 8 MHz; Start-up time: 6 CK + 64 ms"

Thank You.
 
 View user's profile Send private message  
Reply with quote Back to top
bobgardner
PostPosted: Oct 01, 2011 - 12:30 AM
10k+ Postman


Joined: Sep 04, 2002
Posts: 23482
Location: Orlando Florida

Might need to run at 16mhz from a crystal so the cpu has some more hump.

_________________
Imagecraft compiler user
 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
Visovian
PostPosted: Oct 01, 2011 - 10:56 AM
Posting Freak


Joined: Aug 07, 2007
Posts: 1793
Location: Czech

Quote:
ISR(INT0_vect)
{
//this is where the rising edges will be detected
//not sure how to put it in code

Then it is time to open the datasheet.
The behavior of Avr periferies is controlled via IO registers.
In datasheet section "External interrupts" you will find that those use 3 registers:
MCUCR
GICR
GIFR

MCUCR desription shows how to set the desired edge for an inerrupt.
In GICR you will learn how to enable and disable ext. interrupts.
In GIFR there are only interrupt flags. Need not change anything there.

So in main code set properly MCUCR and GICR so that your interrupt fires on rising edge.

In INT0 ISR clear and start timer (with prescaler)
and at next interrupt stop timer.
(You will need to note somewhere whether the current interrupt is odd or even.)

There are beter methods but you can start with this.
 
 View user's profile Send private message  
Reply with quote Back to top
asin209
PostPosted: Oct 01, 2011 - 12:00 PM
Newbie


Joined: Sep 30, 2011
Posts: 10


So, what i did in the timer overflow interrupt is right? and how do i calculate the speed of the motor using the overflow++? that should be done in the INT0 ISR?
I have already set the MCUCR and GICR. why do i have to set up GIFR?
Thank You.
 
 View user's profile Send private message  
Reply with quote Back to top
Brutte
PostPosted: Oct 01, 2011 - 02:09 PM
Raving lunatic


Joined: Oct 05, 2006
Posts: 3063
Location: Poland

asin209 wrote:
Sorry. Im using ATmega8.

You should. Hard piece of wood.
 
 View user's profile Send private message  
Reply with quote Back to top
Visovian
PostPosted: Oct 02, 2011 - 03:56 PM
Posting Freak


Joined: Aug 07, 2007
Posts: 1793
Location: Czech

Try this
Code:
// Measures RPM, pulses on INT0 (PD2)
// One pulse for revolution
// Range 30 to >10000 rpm

//Atmega8
#define F_CPU  8000000UL
#include <avr/io.h>
#include <util/delay.h>         
#include <avr/interrupt.h>     

//One timer step lasts
//timer_step[microsec] = prescaler / F_CPU[MHz]
#define TIMER_STEP  256/8

volatile uint8_t  overflow;
volatile uint32_t period;
uint16_t          rpm;

//--------------------------------------------------
ISR(TIMER0_OVF_vect)
{
   overflow++;
}

//--------------------------------------------------
ISR(INT0_vect)
{
static uint8_t odd;

   if(odd == 1)
   {
      overflow = 0;      //clear overflow counter
      TCNT0 = 0;         //clear timer
      TCCR0 = (1<<CS02); //start timer0
      odd = 0;
   }

   else
   {
      TCCR0 = 0;         //stop timer0   
      period = (overflow * 256UL + TCNT0) * TIMER_STEP ; //[microsec]
      odd = 1;
   }
}


int main(void)
{
   MCUCR |= (1<<ISC01)|(1<<ISC00);//rising edge
   GICR  |= (1<<INT0);  //enable INT0 interrupt

   TCCR0 |= (1<<CS02);  //prescaler 256
   TIMSK |= (1<<TOIE0); //enable tmr0 ovf interrupt

   while(1)
   {
      cli(); //atomic section
      rpm = 1000000UL * 60 / period;
      sei(); //atomic section end
      _delay_ms(20);

      //send rpm to the hyperterminal
   }
}
Not tested in real.

Edit:
TCCR0 = (1<<CS01); //start timer0
changed to
TCCR0 = (1<<CS02); //start timer0
Sorry.
 
 View user's profile Send private message  
Reply with quote Back to top
asin209
PostPosted: Oct 03, 2011 - 07:45 AM
Newbie


Joined: Sep 30, 2011
Posts: 10


Hey, thanks for the code.I tried it and it worked. However, when you said rpm = 1000000*60/period i get a wrong rpm. it should be *30 instead of 60
Also, you used 256UL. is that a prescaler? or just the max in TCNT0?

Thanks.
 
 View user's profile Send private message  
Reply with quote Back to top
Visovian
PostPosted: Oct 03, 2011 - 10:15 AM
Posting Freak


Joined: Aug 07, 2007
Posts: 1793
Location: Czech

Quote:
However, when you said rpm = 1000000*60/period i get a wrong rpm. it should be *30 instead of 60
It suggests that you have two pulses for one revolution.
Quote:
Also, you used 256UL. is that a prescaler? or just the max in TCNT0?
We count pulses with timer0, register TCNT0.
After 256 pulses the timer overflows and we increment the variable "overflow".
So number in "overflow" means groups of 256 pulses.
Then we find number of all pulses with
pulses = overflow*256 + TCNT0
 
 View user's profile Send private message  
Reply with quote Back to top
asin209
PostPosted: Oct 03, 2011 - 11:07 AM
Newbie


Joined: Sep 30, 2011
Posts: 10


Thank you for the explanation. It really helped.
I was wondering, does the pole pair affect the calculation of the rpm? The motor has 2 pole pairs.
 
 View user's profile Send private message  
Reply with quote Back to top
mschoeldgen
PostPosted: Oct 03, 2011 - 07:33 PM
Hangaround


Joined: Sep 22, 2011
Posts: 240


Yes, of course . The more poles the more hall sensor changes per revolution. You should see that in your block commutation routine. A typical motor with 3 sensors has 6 states which will be repeated for each pole pass. I'm working with a 36 pole motor and this generates 36 complete sequences = 72 pole changes on each hall sensor per rotation.
 
 View user's profile Send private message  
Reply with quote Back to top
Display posts from previous:     
Jump to:  
All times are GMT + 1 Hour
Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Powered by PNphpBB2 © 2003-2006 The PNphpBB Group
Credits