日本ニューティーシー株式会社



  • HOME
  • Customer Center
  • よくある質問

 

検索 : 4,994
タイトル [ソース] ジャイロセンサーの角度を求める方法 (하단 내용입력불가)
お名前 administrato… 11-09-28 15:13
n    ソースの目的
下記のソースは3.3V基準電圧で0~3.3Vの間をADして計算するジャイロセンサーで、角度を求めるソースです。5V基準電圧の時には、下記のソース説明を参考にして修正してご使用ください。
n    ソース説明
1.    AVR adc電圧スケールが3.3ボルトである時、vref(計算のために mVに変更)基準に計算
します。
 - 1024はadcの1024段階の分解能を意味
- 3300mV adcのvrefの3.3Vを意味する。
2. 1024 分解能において 1変動をする時の電圧値(Vref = 3.3V) : 3300mV / 1024 = 3.22265625mV
* 参考までに、1024分解能において1変動をする時の電圧値(Vref = 5V) ( 0~5Vの間をADして、実際には0~3.3Vを使用するので、分解能の段階数を再度計算しなければなりません。つまり、3.3/(5/1024) = 675.84段階、約676の値が3.3ボルトです。0~3.3Vの値を見るには、0~676の値で計算すると値が出ます。1024分解能において1変動する時の電圧値(Vref = 5V) : 3300mV / 676 = 4.8816568mV)
3.感度(Sensitivity)値関連
AM-GYRO V01 ( つまり、IDG300)の感度(Sensitivity) 2mV/degree/sec
AM-GYRO V02 (つまり、IDG650)の感度(Sensitivity) 0.5mV/degree/sec
4. 最終的な角度計算のためのScale Vector値関連
AM-GYRO V01 ( つまり、IDG300)を利用時、
- 1024分解能において1変動する時の角速度値 (Vref = 3.3V) :
3.22265625 mV/( 2mV/degree/sec) = 1.611328125 degree/sec
- 1024分解能において1変動する時の角速度値(Vref = 5V) :  4.8816568mV/( 2mV/degree/sec) = 2.4408284 degree/sec
AM-GYRO V02 (つまり、IDG650)を利用時 :
- 1024分解能において1変動する時の角速度値(Vref = 3.3V) :
3.22265625 mV/(0.5mV/degree/sec) = 6.4453125 degree/sec.
- 1024分解能において1 変動する時の角速度値(Vref = 5V) :  4.8816568mV/( 0.5mV/degree/sec) = 9.7533136 degree/sec
5. つまり、整理してみると、角速度を求める基本式 :
( 角速度の初期adc値 – センサーが回転された adc値) * scale vector
ここでadcサンプリング時間を累積すると角度になります。(積分) adcサンプリングの周期が例えば0.01秒であれば、degree +=(( 角速度の初期adc値 – センサーが回転された adc 値 ) * scale vector ) * 0.01sec

-下記-
#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;
     }
}