Get Adobe Flash player
FacebookTwitterGoogle+
English Arabic French German Italian Portuguese Russian Spanish

Did you know?

In 1906, Alice Perry was the first woman in the world to graduate with a degree in engineering. She received her qualifications from Queens College, Galway (now N.U.I. Galway).
 

Help us stay online:

small donate

Gyroscope rortation measurement Electronics-Base comAccelerometers and gyroscopes are used for various safety features in modern vehicles. In this article we used Parallax LISY300 Gyroscope Module to measure Gyroscope PCB rotation speed and current position. The complete project is available for download at the bottom of the page. Results turned out to be better than we expected. An error is only few degrees in 10 full circles turn. You can read more about this sensor in this Featured components - LISY300 Gyroscope Module article.

There are also many more simple but very useful examples of using this sensor. In our example we used it to measure rotation position and speed of rotating office chair :) this way you can have fun with your friends while measuring rotation speed, but be careful because your head will be spinning if you measure your speed too long :)
First we will make small introduction about sensor used. It is ST MEMS inertial sensor. This sensor measures rotation speed with maximum measurement speed up to ±300 °/s full scale.
Sensor power supply is from 2.7 V to 3.6 V single supply operation, but as Parallax module used has on board voltage limiter module power supply is from 3.4 VDC to 6.5 VDC (5 VDC recommended). Standard TTL voltage 5 V is used. Because of on board low pass filter, gyroscope will only update at a rate of 88 Hz. We used sample rate of 100 sps. Sampling is done inside Timer1 interrupt routine. You can see this routine here:

interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
TCNT1=0xFB7B;
// Place your code here
    led=~led; 
    cs = 0;     
    d1=spi(0);
    d2=spi(0);   
    gyro_adc=d1;
    gyro_adc<<=8;
    gyro_adc+=d2; 
    gyro_adc>>=2;
    cs = 1;   
        if((gyro_adc<GyroSteadyValue_MIN)||(gyro_adc>GyroSteadyValue_MAX))
        {
        integraled_gyro=integraled_gyro+gyro_adc-GyroSteadyValue_AVARAGE;
        }
    gyro_speed_time++;
    if(gyro_speed_time==GytoSpeed_INTERVAL)
        {
        gyro_speed_time=0;
        gyro_speed=((100/GytoSpeed_INTERVAL)*(pervious_integraled_gyro-integraled_gyro))/GyroQuantsPerDegree;  
        pervious_integraled_gyro=integraled_gyro;
        }   
}

As you can see two bytes are read and combined to get correct integer value from on board SPI ADC. Using timer interrupt ensured constant sample rate. Read gyroscope value is compared to values provided by gyroscope when no movement is present. This value varies within few ADC quants so you can see we are processing result only if it is different than these steady readout values. 

Rotation speed is calculated by comparing two summed gyro readouts in predefined time interval. Gyroscope is providing value that is proportional to rotation speed. By integrating this value, we got the position. In digital domain integration is simple sum of previous values.
Complete code with key lines highlited is shown below:

/*****************************************************
This program was produced by the
CodeWizardAVR V2.04.4a Advanced
Project : Position measurement with parallax gyroscope LISY300AL
Version : 
Date    : 9/6/2012
Author  : www.Electronics-Base.com
For more information about this code you can read full aticle on    www.Electronics-Base.com
For any aditional questions use support forum    http://www.electronics-base.com/forum/
Chip type               : ATmega16
Program type            : Application
AVR Core Clock frequency: 7.372800 MHz
Memory model            : Small
External RAM size       : 0
Data Stack size         : 256
*****************************************************/
#include <mega16.h>
// Standard Input/Output functions
#include <stdio.h>
#include <stdlib.h>
#include <spi.h>
#include <delay.h>
#define cs PORTB.4
#define led PORTB.0
#define GyroSteadyValue_MAX 520
#define GyroSteadyValue_MIN 515
#define GyroSteadyValue_AVARAGE 517
#define GyroQuantsPerDegree 103
#define GyroQuantsPerCircle (GyroQuantsPerDegree*360)
#define GytoSpeed_INTERVAL 10
                  
unsigned char d1,d2,gyro_speed_time; 
signed int gyro_adc,gyro_speed;
long angle,circle,degrees;
float     integraled_gyro,pervious_integraled_gyro,integraled_gyro_copy;
char temp[10];  
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
TCNT1=0xFB7B;
// Place your code here
    led=~led; 
    cs = 0;     
    d1=spi(0);
    d2=spi(0);   
    gyro_adc=d1;
    gyro_adc<<=8;
    gyro_adc+=d2; 
    gyro_adc>>=2;
    cs = 1;   
        if((gyro_adc<GyroSteadyValue_MIN)||(gyro_adc>GyroSteadyValue_MAX))
        {
        integraled_gyro=integraled_gyro+gyro_adc-GyroSteadyValue_AVARAGE;
        }
    gyro_speed_time++;
    if(gyro_speed_time==GytoSpeed_INTERVAL)
        {
        gyro_speed_time=0;
        gyro_speed=((100/GytoSpeed_INTERVAL)*(pervious_integraled_gyro-integraled_gyro))/GyroQuantsPerDegree;  
        pervious_integraled_gyro=integraled_gyro;
        }   
}
// Declare your global variables here
void main(void)
{
// Declare your local variables here
// Input/Output Ports initialization
// Port A initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
PORTA=0x00;
DDRA=0x00;
  
// Port B initialization
// Func7=Out Func6=In Func5=Out Func4=Out Func3=Out Func2=In Func1=In Func0=out 
// State7=0 State6=T State5=0 State4=0 State3=0 State2=T State1=T State0=0 
PORTB=0x11;
DDRB=0xb9;
// Port C initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
PORTC=0x00;
DDRC=0x00;
// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
PORTD=0x00;
DDRD=0x00;
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=FFh
// OC0 output: Disconnected
TCCR0=0x00;
TCNT0=0x00;
OCR0=0x00;
  
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 115,200 kHz
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt: On
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x03;
TCNT1H=0xFB;
TCNT1L=0x7F;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
      
// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer2 Stopped
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;
// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// INT2: Off
MCUCR=0x00;
MCUCSR=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x04;
// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud Rate: 19200
UCSRA=0x00;
UCSRB=0x18;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x17;
// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;
// SPI initialization
// SPI Type: Master
// SPI Clock Rate: 62.500 kHz
// SPI Clock Phase: Cycle Start
// SPI Clock Polarity: Low
// SPI Data Order: MSB First
SPCR=0x53;
SPSR=0x00;
putsf("Gyroscope speed and position measurement example from www.Electronics-Base.com"); 
putchar(13);
delay_ms(1000); 
putchar('3');
putchar(13);
delay_ms(1000);
putchar('2');
putchar(13);
delay_ms(1000);
putchar('1');
putchar(13);
delay_ms(1000);
putsf("Start");
putchar(13);
// Global enable interrupts
#asm("sei")
while (1)
      {
      // Place your code here 
      delay_ms(150);   
      integraled_gyro_copy=integraled_gyro;
      putsf("Gyroscope ADC readout: ");    
      itoa(gyro_adc,temp);   
      puts(temp);  
      putsf(" Gyroscope summed integral: ");
      itoa(integraled_gyro_copy,temp); 
      puts(temp);  
      putsf(" Calculated Angle: ");                      
      angle=integraled_gyro/GyroQuantsPerDegree;  
      itoa(angle,temp); 
      puts(temp);  
      putsf("°");  
      putsf(" Full circles: ");  
      circle=integraled_gyro_copy/GyroQuantsPerCircle; 
      itoa(circle,temp); 
      puts(temp); 
      putsf(" Degrees: "); 
      degrees=  integraled_gyro_copy-circle*GyroQuantsPerCircle;    
      degrees=degrees/GyroQuantsPerDegree;
      itoa(degrees,temp); 
      puts(temp);   
      putsf(" Speed: "); 
      itoa( gyro_speed,temp); 
      puts(temp);
      putsf(" °/sec"); 
      putchar(13);                           
      };
}

Complete Codevision project for Atmega16 can be downloaded form this link.
On video below you can see this code in action. Fine calibration of  GyroQuantsPerDegree and GyroQuantsPerCircle constants could be made to get better acuraccy.