NEWTC



  • HOME
  • Customer Center
  • FAQ


hit : 4,720
title [Source] How to calculate the angle of gyro sensor
name admin 11-08-29 21:52

Hello, customer?

 

(Purpose of source)
Followings are sources that find angle using gyro sensor calculating with AD between 0~3.3V based on reference voltage 3.3V.  In case of reference voltage 5V, modify with reference of below description of source.
(Description of source)

1. If voltage scale of AVR adc is 3.3V, calculate based on vref(change to mV for calculation).

- 1024 means resolution of 1024 steps in adc

- means 3.3V which is vref in 3300mV adc.

2. Value of voltage when 1 fluctuates in 1024 resolution (Vref = 3.3V):  
    3300mV / 1024 = 3.22265625mV

 * For reference, value of voltage when 1 fluctuates in 1024 resolution (Vref = 5V) (you have to calculate the number of steps in resolution because AD is applied between 0~5V and 0~3.3V is used actually.  That is to say, 3.3/(5/1024) = 675.84 steps, approx. value of 676 is 3.3V. If you want to find the value of 0~3.3V, calculate as the value of 0~676. Value of voltage when 1 fluctuates in 1024 resolution (Vref = 5V) : 3300mV / 676 = 4.8816568mV)

3. Related with the value of Sensitivity
   Sensitivity of AM-GYRO V01 (i.e, IDG300)  2mV/degree/sec  
 
   Sensitivity of AM-GYRO V02 (i.e, IDG650)  0.5mV/degree/sec

4. Related with value of Scale vector for final angle calculation

   When you use AM-GYRO V01 ( i.e, IDG300),  
- Value of angular speed when 1 fluctuates in 1024 resolution (Vref = 3.3V) :
    3.22265625 mV  /  ( 2mV/degree/sec) = 1.611328125 degree/sec
-Value of angular speed when 1 fluctuates in 1024 resolution (Vref = 5V) :    

4.8816568mV  /  ( 2mV/degree/sec) = 2.4408284 degree/sec

When you use AM-GYRO V02 (i.e, IDG650) :
 
- Value of angular speed when 1 fluctuates in 1024 resolution(Vref =3.3V):
   
3.22265625 mV  /  ( 0.5mV/degree/sec) = 6.4453125 degree/sec. 
 
- Value of angular speed when 1 fluctuates in 1024 resolution (Vref = 5V) :
   
4.8816568mV  /  ( 0.5mV/degree/sec) = 9.7533136 degree/sec


5. So, to put above into order, basic formula finding angular speed:

(Early adc value of angular speed ? value of adc which sensor is rotated) * scale vector, if adc sampling time is accumulated here, it will be angle. (integral). If adc sampling cycle, for instance, is 0.01 sec, degree +=  (( early adc value of angular speed ? sensor-rotated adc value)
* scale vector ) * 0.01sec  

- Below ?  

#include <iom128v.h>
#include <macros.h>
#include <stdio.h>

#define SCALE_FACTOR 1.611328125
#define TIME         0.01
#define OFF_SET   458      
//590.5611

         int   value = 0;
         float  value_sum = 0;
         float  offset;
         float angular_acceleration[50];
         float angular_average = 0;
         float before_angle    = 0;
         float  after_angle    = 0;
         float angle_factor    = 0;
                 char  adc_flag        = 0;
                 char  time_flag        = 0;

void port_init(void)
{
    PORTA = 0x00;
    DDRA  = 0x00;
    PORTB = 0x00;
    DDRB  = 0x00;
    PORTC = 0x00; //m103 output only
    DDRC  = 0x00;
    PORTD = 0x00;
    DDRD  = 0x00;
    PORTE = 0x00;
    DDRE  = 0x00;
    PORTF = 0x00;
    DDRF  = 0x00;
    PORTG = 0x00;
    DDRG  = 0x03;
}

//TIMER0 initialize - prescale:64
// WGM: Normal
// desired value: 1KHz
// actual value:  1.000KHz (0.0%)
void timer0_init(void)
{
    TCCR0 = 0x00; //stop
    ASSR  = 0x00; //set async mode
    TCNT0 = 0x06; //set count
    OCR0  = 0xFA;
    TCCR0 = 0x04; //start timer
}

#pragma interrupt_handler timer0_ovf_isr:iv_TIM0_OVF
void timer0_ovf_isr(void)
{
    TCNT0 = 0x06; //reload counter value
        PORTG ^= 1;
        ADCSRA |= 0x40;
}
//TIMER1 initialize - prescale:8
// WGM: 0) Normal, TOP=0xFFFF
// desired value: 100Hz
// actual value: 100.000Hz (0.0%)
void timer1_init(void)
{
    TCCR1B = 0x00; //stop
    TCNT1H = 0xB1; //setup
    TCNT1L = 0xE0;
    OCR1AH = 0x4E;
    OCR1AL = 0x20;
    OCR1BH = 0x4E;
    OCR1BL = 0x20;
    OCR1CH = 0x4E;
    OCR1CL = 0x20;
    ICR1H  = 0x4E;
    ICR1L  = 0x20;
    TCCR1A = 0x00;
  //TCCR1B = 0x02; //start Timer
}

#pragma interrupt_handler timer1_ovf_isr:iv_TIM1_OVF
void timer1_ovf_isr(void)
{
//TIMER1 has overflowed
    TCNT1H = 0xB1; //reload counter high value
    TCNT1L = 0xE0; //reload counter low value

    //PORTG ^= 2;
        
        time_flag = 1;
}

//UART0 initialize
// desired baud rate: 115200
// actual: baud rate:111111 (3.7%)
// char size: 8 bit
// parity: Disabled
void uart0_init(void)
{
    UCSR0B = 0x00; //disable while setting baud rate
    UCSR0A = 0x00;
    UCSR0C = 0x06;
    UBRR0L = 0x08; //set baud rate lo
    UBRR0H = 0x00; //set baud rate hi
    UCSR0B = 0x18;
}

// printf ?
int putchar(char c)
{
    while (((UCSR0A>>UDRE0)&0x01) == 0) ;  // UDRE, data register empty
        
    UDR0 = c;
    return c;
}

// scanf
int getchar(void)
{
    while ((UCSR0A & 0x80) == 0);
    return UDR0;
}

//ADC initialize
// Conversion time: 104uS
void adc_init(void)
{
    ADCSRA = 0x00; //disable adc
    ADMUX  = 0x00; //select adc input 0
    ACSR   = 0x80;
    ADCSRA = 0x8F;
}

#pragma interrupt_handler adc_isr:iv_ADC
void adc_isr( void )
{
//conversion complete, read value (int) using...
    value  = ADCL;            //Read 8 low bits first (important)
    value |= ( int )ADCH << 8; //read 2 high bits and shift into top byte

        adc_flag++;
        value_sum += value;
        
        if(adc_flag >=1 )
            TCCR0 = 0x00; //stop
        //printf( "\r\n ADC = %d", value );
}


//call this routine to initialize all peripherals
void init_devices(void)
{
//stop errant interrupts until set up
    CLI(); //disable all interrupts
    XDIV  = 0x00; //xtal divider
    XMCRA = 0x00; //external memory
    port_init();
    uart0_init();
    adc_init();
    timer0_init();
    timer1_init();


    MCUCR = 0x00;
    EICRA = 0x00; //extended ext ints
    EICRB = 0x00; //extended ext ints
    EIMSK = 0x00;
    TIMSK = 0x01; //timer interrupt sources
    TIMSK = 0x04; //timer interrupt sources
    TIMSK = 0x05; //timer interrupt sources
    ETIMSK = 0x00; //extended timer interrupt sources
    SEI(); //re-enable interrupts
//all peripherals are now initialized
}

void delay ( unsigned int cnt )
{
    unsigned int i,j;
        
        for( i=0 ; i< cnt ; i++ )
                for( j=0 ; j< 1000 ; j++ );
}

void main (void)
{
    int i;
        int  temp;
    init_devices();
        
        printf( "\r\n GYRO..QQ");
        printf( "\r\n ADCSRA = 0x%x", ADCSRA );
        printf( "\r\n ADMUX  = 0x%x", ADMUX  );
        printf( "\r\n ACSR   = 0x%x", ACSR   );
        
        delay( 1000 );
        
        for( i=0 ; i<100 ; i ++ )
            angular_acceleration[i] = 0;
        ADMUX  = 0x00;
        
        
        ADCSRA |= 0x40;
        offset = 0;
        for( i=0 ; i<50 ; )
        {
            if ( adc_flag )
                {
                        temp = value;
                        offset += value;
                adc_flag = 0;
                        ADCSRA  |= 0x40;
                        //printf( "\r\n $$ = %d", value );
                        
                        i ++ ;
            }
        }
        offset = (int)(offset / 50);
        
        printf( "\r\n offset = %f", offset );

        //for( i=0 ; i<50 ; i ++ )
        //    angular_acceleration[i] = offset;
        
        delay( 2000 );
        delay( 2000 );        
        
        TCCR1B = 0x02; //start Timer
    TCCR0 = 0x05; //start timer
        value_sum = 0;
        adc_flag = 0;
        while(1)
        {
            //delay( 1000 );
                
                if( time_flag )
                {
                    
                    PORTG |= 0x02;
                        
            value_sum = value_sum / adc_flag;
             angular_acceleration[0] = (( float )( (int)(value_sum -offset ))  * SCALE_FACTOR;
            after_angle = before_angle +  ( angular_acceleration[9] + angular_acceleration[8] + angular_acceleration[7] + angular_acceleration[6] + angular_acceleration[5] + angular_acceleration[4] + angular_acceleration[3] + angular_acceleration[2] + angular_acceleration[1] + angular_acceleration[0] ) / 10;

            angle_factor = after_angle * TIME;                        
                        before_angle = after_angle;
                        for( i=0 ; i<9 ; i ++ )
                        {
                            angular_acceleration[i+1] = angular_acceleration[i];
                        //printf ( " nangle = %.2f", angular_acceleration[i]);        
                        }
                        
                        
                        printf ( "\r\n X_angle = %.2f", angle_factor);
                        angular_average = 0;
                        adc_flag = 0;
                        value_sum = 0;
                 time_flag = 0;
                TCCR0 = 0x05;
                    
                }
                PORTG &= 0xfd;
        }
}