CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

How to get gyro Scale Factor

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Zek_De



Joined: 13 Aug 2016
Posts: 100

View user's profile Send private message

How to get gyro Scale Factor
PostPosted: Wed Oct 12, 2016 3:40 am     Reply with quote

I got some writtings about scale factor but they are not enough. While I rotate the device at the same time I must save data until 90 degree. Then what I will do with these data ? Maybe to do scale factor I've to do division with something after the average of data ? Thanks for help.
temtronic



Joined: 01 Jul 2010
Posts: 9169
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed Oct 12, 2016 5:12 am     Reply with quote

Without knowing which PIC and compiler version you have, I can only give you general comments.
1) be sure to test hardware for hours, to confirm the data from it is stable and that EMI of any kind is not present. Until this is done NO amount of code will help, the hardware must work 100% in the real World, simulations are useless.

2) hopefully the PIC you've chosen has sufficient RAM to store the data from a 90* sweep.You don't say what 'gyroscope' you have but the analog ones are nice, encodered ones are too and integrated ones are as well. What type dictates how you code your program.

3) use INTEGER math NOT floating point. It canl be 100sX faster,save program space and is easy to 'scale', if required. Simple to make the FP numbers for humans AFTER all the math is done.

4) re: hardware...be sure proper logic level translation is done between PIC and Gyro. You cannot directly use a 3V Gyro on a 5V PIC. Check the datasheets of both devices before 'magic smoke' comes pouring out !


Jay
Zek_De



Joined: 13 Aug 2016
Posts: 100

View user's profile Send private message

PostPosted: Wed Oct 12, 2016 5:30 am     Reply with quote

Thank you Jay I solved it, but is it good solution I don't know. I solved like that
(pic18f4550 -l3g4200d) device say in datasheet if you use 2000 dps I have to 0.07 dps/digit or for another one is different. 250 dps, 500 dps whatever. As a result all values are equal. This is why I rotated the device about 90* and I got last data and this equivalent give solution.
For example on X axis my last output data with X*0.07 generate about 4150 in 90* and I use 4150 = 0.07*deltaR that deltaR = raw data - zerorate and I find deltaR = 59286. I didn't get directly this value due to some code whatever. As a result "90degree = 59286*0.07*SC", SC =0.02168, it works no problem, what do you say for this ?
Ttelmah



Joined: 11 Mar 2010
Posts: 19358

View user's profile Send private message

PostPosted: Wed Oct 12, 2016 8:03 am     Reply with quote

For the figures you quote, just use *9.0.
However you need to understand the chip. It is a _rate_ sensor, not an angle sensor. It tells you how fast it is turning. I'd suspect your code is not actually able to keep up with the read rate of the sensor, so gives you the same result whatever rate is selected.
curt2go



Joined: 21 Nov 2003
Posts: 200

View user's profile Send private message

PostPosted: Wed Oct 12, 2016 12:27 pm     Reply with quote

Depends on the chip but usually they use a signed 16 bit register. So you take your full scale and divide by 32767.

eg. 500dps scaler = 500/32767 =0.0152.

Hope that helps.
Zek_De



Joined: 13 Aug 2016
Posts: 100

View user's profile Send private message

PostPosted: Wed Oct 12, 2016 1:30 pm     Reply with quote

thanks curt2go Smile , Ttelmah you are right ,I couldnt notice to measure actually about angular rate,but this device also can give degree but How can I get angular rate because this formula contain t(time).teta=w*t ,what will I write instead of t ,device give me teta now,also then I will use to measure angle is accelerometer ,won't it?Please give light here Smile
Zek_De



Joined: 13 Aug 2016
Posts: 100

View user's profile Send private message

PostPosted: Wed Oct 12, 2016 1:32 pm     Reply with quote

Also code below
Code:

#include <L3G4200D.h>
#include <stdlib.h>
#include <lcd.c>
#include <math.h>


#define WHO_AM_I 0x0F
#define CTRL_REG1 0x20
#define CTRL_REG2 0x21
#define CTRL_REG3 0x22
#define CTRL_REG4 0x23
#define CTRL_REG5 0x24
#define CTRL_REG6 0x25
#define FIFO_CTRL_REG 0x2E
#define FIFO_SRC_REG 0x2F
#define OUT_X_L 0x28
#define OUT_X_H 0x29
#define OUT_Y_L 0x2A
#define OUT_Y_H 0x2B
#define OUT_Z_L 0x2C
#define OUT_Z_H 0x2D
#define STATUS_REG 0x27
#define REFERENCE 0x25
#define INT1_CFG  0x30
#define INT1_SRC  0x31
#define INT1_THS_XH 0x32
#define INT1_THS_XL 0x33
#define INT1_THS_YH 0x34
#define INT1_THS_YL 0x35
#define INT1_THS_ZH 0x36
#define INT1_THS_ZL 0x37
#define INT1_DURATION 0x38
#define OUT_TEMP 0x26
#define x_eksen 0
#define y_eksen 1
#define z_eksen 2

/*enum eksenler {
    x_eksen = 0,
    y_eksen = 1,
    z_eksen = 2,
};*/

signed int8 xMSB=0;
signed int8 xLSB=0;
signed int8 yMSB=0;
signed int8 yLSB=0;
signed int8 zMSB=0;
signed int8 zLSB=0;

signed int16 Rm[3]={0};
float32 Ro[3]={0};
float32 Rth[3]={0};
float32 deltaR[3]={0};
signed int16 temperature = 0;
float32 angle[3]={0};
unsigned int16 timer_0=0;


void           init();  //Fonksiyon prototipleri
void           Setup_Gyro();
void           Gyroscope_Write(unsigned int8 yazilacakAdres,unsigned int8 deger);
signed int8    Gyroscope_Read(unsigned int8 okunacakAdres);
void           Gyroscope_Values_Raw();
void           Gyroscope_Values();
void           Calibrate_Gyro();
unsigned int8  Get_Temperature();
void           Interrupt_To_Temperature_and_Calibrating();

void main() //Ana Fonksiyon
{
   init();
   Setup_Gyro();
   Calibrate_Gyro();
   while(true)
   {

      Gyroscope_Values();
      printf(lcd_putc,"\f");
      lcd_gotoxy(1,1);
      printf(lcd_putc,"X:%f",angle[x_eksen]);
      lcd_gotoxy(9,1);
      printf(lcd_putc,"Y:%f",angle[y_eksen]);
      lcd_gotoxy(1,2);
      printf(lcd_putc,"Z:%f",angle[z_eksen]);
      lcd_gotoxy(9,2);
      printf(lcd_putc,"C:%Ld",temperature);
      delay_ms(5);
     
      if(timer_0 >= 1526) //20 s
      {
         printf(lcd_putc,"\f");
         lcd_gotoxy(1,1);
         printf(lcd_putc,"Stop!");
         delay_ms(1000);
         
         Calibrate_Gyro();
         temperature = Get_Temperature();
         timer_0=0;
         angle[x_eksen]=0;
         angle[y_eksen]=0;
         angle[z_eksen]=0;
         
         printf(lcd_putc,"\f");
         lcd_gotoxy(1,1);
         printf(lcd_putc,"Done...");
         delay_ms(500);
      }           
   }
}
//#############################################################################
void init() //Denetleyici ayarları
{
   setup_psp(PSP_DISABLED);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_timer_3(T3_DISABLED);
   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_CCP1(CCP_OFF);
   setup_CCP2(CCP_OFF);
   setup_comparator(NC_NC_NC_NC);
   //Timer0 kuruluyor
   setup_timer_0(RTCC_INTERNAL | RTCC_DIV_256 |RTCC_8_BIT);
   set_timer0(0);
   enable_interrupts(INT_timer0);
   enable_interrupts(GLOBAL);
   //Timer0 kuruldu.
   lcd_init();
   delay_ms(20);
   lcd_gotoxy(1,1);
   printf(lcd_putc,"Don't Move!");
}
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
void Setup_Gyro()
{
 
  Gyroscope_Write(CTRL_REG2,0b00100100);//Normal mode ,High pass filter cut off frecuency:8
  Gyroscope_Write(CTRL_REG3,0b00001000);// I2_DRDY,I2_WTM,I2_ORun,I2_Empty etkin ,push-pull--FIFO etkin olmadığı durumda push-pull hariç diğerleri geçersiz
  Gyroscope_Write(CTRL_REG4,0b10110000);//BDU:1,2000 dps,self-test disabled(normal mode)
  Gyroscope_Write(CTRL_REG5,0b00000000);//HPF disabled - Data in DataReg and FIFO are non-high-passfiltered - Data in DataReg and FIFO are non-highpass- filtered
  /*
  Gyroscope_Write(REFERENCE,0b00000000);
  Gyroscope_Write(INT1_THS_XH,0b00000000);
  Gyroscope_Write(INT1_THS_XL,0b00000000);
  Gyroscope_Write(INT1_THS_YH,0b00000000);
  Gyroscope_Write(INT1_THS_YL,0b00000000);
  Gyroscope_Write(INT1_THS_ZH,0b00000000);
  Gyroscope_Write(INT1_THS_ZL,0b00000000);
  Gyroscope_Write(INT1_DURATION,0b00000000);
  Gyroscope_Write(INT1_CFG,0b00000000);*/
  Gyroscope_Write(CTRL_REG1,0b11001111); // 800Hz,30 cut-off/ X,Y,Z etkin
  delay_ms(252);
         
}
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

void Calibrate_Gyro()

   float32 X[50]={0};
   float32 Y[50]={0};
   float32 Z[50]={0};
   float32 temp[3]={0};

   //50 adet çiğ değer toplanıyor ve ayrıca bu değerler hafızada tutuluyor.(standart sapma formülünde her biri tek tek kullanılacak.)
   for(unsigned int8 i=0;i<50;i++)
   {
      Gyroscope_Values_Raw();
      X[i]=Rm[x_eksen];    Y[i]=Rm[y_eksen];    Z[i]=Rm[z_eksen];
   // her döngüde farklı değerler farklı eksen dizilerine veriler atandı.
         temp[x_eksen] = temp[x_eksen] + Rm[x_eksen];
         temp[y_eksen] = temp[y_eksen] + Rm[y_eksen];
         temp[z_eksen] = temp[z_eksen] + Rm[z_eksen];
         //zero-rate için veri toplanıyor
   }
         //zero-rate belirleniyor(Moving Avarage Filter)
      Ro[x_eksen] = temp[x_eksen] / 50;
      Ro[y_eksen] = temp[y_eksen] / 50;
      Ro[z_eksen] = temp[z_eksen] / 50;
     
   for(int k=0;k<50;k++)
   {//threshold için veri toplanıyor
      Rth[x_eksen] = Rth[x_eksen] +  pow((X[k] - Ro[x_eksen]),2);
      Rth[y_eksen] = Rth[y_eksen] +  pow((Y[k] - Ro[y_eksen]),2);
      Rth[z_eksen] = Rth[z_eksen] +  pow((Z[k] - Ro[z_eksen]),2);
   }

      Rth[x_eksen] = 3*sqrt(Rth[x_eksen] / 50);
      Rth[y_eksen] = 3*sqrt(Rth[y_eksen] / 50);
      Rth[z_eksen] = 3*sqrt(Rth[z_eksen] / 50);
}
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
/*void Calibrate_Gyro() //ALLAN VARIANCE Calibrating
{
   float32 X[50]={0};
   float32 Y[50]={0};
   float32 Z[50]={0};
   float32 temp[3]={0};
   unsigned int8 i=0;
  for(i=0;i<50;i++)
   {
      Gyroscope_Values_Raw();
      X[i]=Rm[x_eksen];    Y[i]=Rm[y_eksen];    Z[i]=Rm[z_eksen];
     
      temp[x_eksen] = temp[x_eksen] + Rm[x_eksen];
      temp[y_eksen] = temp[y_eksen] + Rm[y_eksen];
      temp[z_eksen] = temp[z_eksen] + Rm[z_eksen];
   }
      Ro[x_eksen] = temp[x_eksen] / 50;  //Zero-Rate bulunuyor.
      Ro[y_eksen] = temp[y_eksen] / 50;
      Ro[z_eksen] = temp[z_eksen] / 50;
  for(i=0;i<47;i++)
  {
    temp[x_eksen] = (X[i] - 2*X[i] + X[i]) * (X[i] - 2*X[i] + X[i]);
    temp[y_eksen] = (Y[i] - 2*Y[i] + Y[i]) * (Y[i] - 2*Y[i] + Y[i]);
    temp[z_eksen] = (Z[i] - 2*Z[i] + Z[i]) * (Z[i] - 2*Z[i] + Z[i]);
  }
     
      Rth[x_eksen] = 3*(1/(2*0.01*48)) * temp[x_eksen];
      Rth[y_eksen] = 3*(1/(2*0.01*48)) * temp[y_eksen];
      Rth[z_eksen] = 3*(1/(2*0.01*48)) * temp[z_eksen];
}*/
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
void Gyroscope_Write(unsigned int8 yazilacakAdres,unsigned int8 deger)
{
   i2c_start();
   i2c_write(0xD2);
   i2c_write(yazilacakAdres);
   i2c_write(deger);
   i2c_stop();
   //delay_ms(20);
}
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
signed int8 Gyroscope_Read(unsigned int8 okunacakAdres)
{
   signed int8 gonder=0;
   i2c_start();
   i2c_write(0xD2);
   i2c_write(okunacakAdres);
   i2c_start();
   i2c_write(0xD3);

       gonder = i2c_read(0);
   
   i2c_stop();
   return(gonder);
}
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

void Gyroscope_Values_Raw()
{
   unsigned int8 cikis=0;
   //unsigned int8  hpfReset;
   cikis = Gyroscope_Read(STATUS_REG);


   while(bit_test(cikis,3)==0)
   {
      cikis = Gyroscope_Read(STATUS_REG);
   }
   
         xMSB = Gyroscope_Read(OUT_X_H);
         xLSB = Gyroscope_Read(OUT_X_L);
         yMSB = Gyroscope_Read(OUT_Y_H);
         yLSB = Gyroscope_Read(OUT_Y_L);
         zMSB = Gyroscope_Read(OUT_Z_H);
         zLSB = Gyroscope_Read(OUT_Z_L);
         //hpfReset = Gyroscope_Read(REFERENCE);
         Rm[x_eksen] = make16(xMSB,xLSB);
         Rm[y_eksen] = make16(yMSB,yLSB);
         Rm[z_eksen] = make16(zMSB,zLSB);
         //delay_ms(20);
}
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
void Gyroscope_Values()
{
   Gyroscope_Values_Raw();
   delay_us(125);
    for (int j = 0; j<3; j++)
   {
      deltaR[j] = (float32)Rm[j] - Ro[j];
     
      if (abs(deltaR[j]) > Rth[j])
      {
             
            angle[j] = angle[j] + deltaR[j] * 0.07*0.021686;

      }

   }
   
}
unsigned int8 Get_Temperature()
{
   unsigned int8 t;
   t = (25 - Gyroscope_Read(OUT_TEMP)) + 25;
   return t;
}

#INT_TIMER0
void Interrupt_To_Temperature_and_Calibrating()
{
      timer_0++;   
}


//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
/*void Gyroscope_Values_Raw(signed int16 array[])                   FIFO ile
{
   Gyroscope_Write(FIFO_CTRL_REG,0b00101010);//wtm:10 fifo mod
   unsigned int8 cikis=0;
   cikis = Gyroscope_Read(FIFO_SRC_REG);
      while(bit_test(cikis,7)==0)
        cikis = Gyroscope_Read(FIFO_SRC_REG);
       
       while(bit_test(cikis,5)==0) //empty bit 0 iken verileri alr
       {
         xMSB = Gyroscope_Read(OUT_X_H);
         xLSB = Gyroscope_Read(OUT_X_L);
         yMSB = Gyroscope_Read(OUT_Y_H);
         yLSB = Gyroscope_Read(OUT_Y_L);
         zMSB = Gyroscope_Read(OUT_Z_H);
         zLSB = Gyroscope_Read(OUT_Z_L);
         
         array[0] = make16(xMSB,xLSB);
         array[1] = make16(yMSB,yLSB);
         array[2] = make16(zMSB,zLSB);
         
         cikis = Gyroscope_Read(FIFO_SRC_REG);// empty bitini öğrenmek için güncelleme
   
      delay_ms(5);
       }
     
    Gyroscope_Write(FIFO_CTRL_REG,0b00001010);
}*/
Ttelmah



Joined: 11 Mar 2010
Posts: 19358

View user's profile Send private message

PostPosted: Wed Oct 12, 2016 2:16 pm     Reply with quote

You don't tell us your CPU clock rate or show the setup for the I2C. However I'd guess there is no way the processor is actually going to be able to keep up with the processing/sample rate.

I've pointed you to a more efficient atan. You honestly want to be using SPI, and doing everything you can to reduce the time taken for the maths. Use integer where possible. Consider perhaps an integer look-up table for the conversions. You need to be actually doing some thinking about what the maths has to contain, not just throwing functions at the problem. Little things can make a huge difference. For instance your average using 50 samples. Think again. Use 32 or 64. Both of these the processor can solve using a simple rotation, while a float /50 takes over 1600 instructions.....
curt2go



Joined: 21 Nov 2003
Posts: 200

View user's profile Send private message

PostPosted: Wed Oct 12, 2016 2:41 pm     Reply with quote

I am using the complimentary filter that takes raw data without any averaging. It seems to work good. Ttelmah is right about the SPI version. i am just trying to get things to work with I2C but them will be moving to SPI to significantly speed things up and I am running at 140MHz.
Zek_De



Joined: 13 Aug 2016
Posts: 100

View user's profile Send private message

PostPosted: Wed Oct 12, 2016 4:07 pm     Reply with quote

First, Ttelmah, you said to me there is no way to get sample rate. I suppose you are right because I tried and thought on it and I didn't find anything. But you guys said to me to use SPI. Yes it is so fast and needs a clock. I know but How can I get sample time with it ? Is there a way?Also you mention about atan but I don't need it because angle[j] already gives in degree with 0.021686, and why 32 or 64 samples ? I couldn't understand sorry.
Second, curt2go, I didn't still filter my raw values. I will later, these ones are just for calibrating because the datasheet informs me the threshold is 4*sigma. Zero-rate is average and complimentary filter is better then kalman or near as far as I see. I researched it a little and it seems simple and usefull. I liked it. Most important one, how can I get sampling time in spi ? Maybe there is a way, I dont know. Maybe I'm asking a bad question. If it is bad I'm sorry, this is my inexperience.
Zek_De



Joined: 13 Aug 2016
Posts: 100

View user's profile Send private message

PostPosted: Wed Oct 12, 2016 4:08 pm     Reply with quote

Also,
Code:

#include <18F4550.h>
#device ADC=16
#FUSES WDT128        //Watch Dog Timer uses 1:128 Postscale
#fuses HS,NOWDT,NOBROWNOUT,NOLVP,NOXINST,NODEBUG,NOCPD,NOPUT,NOPROTECT
#use delay(crystal=20MHz)

#use I2C(master,scl=PIN_B1 ,sda=PIN_B0, fast=400000)
Zek_De



Joined: 13 Aug 2016
Posts: 100

View user's profile Send private message

PostPosted: Wed Oct 12, 2016 4:23 pm     Reply with quote

For angular rate, I set timerx and while device overcome threshold the timerx will work and when interrupt come true, I will subtract my start data-current (start data can have a value) and teta/(start data-current data) = w
is it ok?
curt2go



Joined: 21 Nov 2003
Posts: 200

View user's profile Send private message

PostPosted: Wed Oct 12, 2016 4:40 pm     Reply with quote

I'm not sure if your is in DegreesPerSecond but it should be ...

gyroReading += newGyroReading / (Your sample time here);

This will give you the angle. Its that simple. But the gyro will drift over time that is why we average with a little part of the Accelerometer data. The complimentary filter.
curt2go



Joined: 21 Nov 2003
Posts: 200

View user's profile Send private message

PostPosted: Wed Oct 12, 2016 5:53 pm     Reply with quote

I am a bit wrong. You do need to keep the last gyro data as well.

w = (oldData + newData)/ sample time;
oldData = newData;

Sorry for the confusion. You were more right than me.

Here's a good site.
http://www.hobbytronics.co.uk/accelerometer-gyro
Ttelmah



Joined: 11 Mar 2010
Posts: 19358

View user's profile Send private message

PostPosted: Thu Oct 13, 2016 1:43 am     Reply with quote

Zek_De wrote:
First, Ttelmah, you said to me there is no way to get sample rate. I suppose you are right because I tried and thought on it and I didn't find anything. But you guys said to me to use SPI. Yes it is so fast and needs a clock. I know but How can I get sample time with it ? Is there a way?Also you mention about atan but I don't need it because angle[j] already gives in degree with 0.021686, and why 32 or 64 samples ? I couldn't understand sorry.
Second, curt2go, I didn't still filter my raw values. I will later, these ones are just for calibrating because the datasheet informs me the threshold is 4*sigma. Zero-rate is average and complimentary filter is better then kalman or near as far as I see. I researched it a little and it seems simple and usefull. I liked it. Most important one, how can I get sampling time in spi ? Maybe there is a way, I dont know. Maybe I'm asking a bad question. If it is bad I'm sorry, this is my inexperience.


No I did not. I said you could not achieve a 400nSec resolution, and that I didn't think you would keep up with the sample rate you are trying to use.

You need to understand just how slow fp maths is. A single atan, on a 40MHz PIC18, takes about 700uSec. Even on a DSPIC is takes tens of uSecs. Your read is slow (you have not told us what clock rate you are actually using on the I2C), but by the time you have read all the data, and processed it, the next update _will_ almost certainly have been missed. You need to be optimising the code for speed, and then synchronising to the update from the chip. Otherwise the data received will effectively be garbage. I'd suspect the reason it goes badly wrong when you add Z, is that the maths is actually just coping with the 2D solution, and running out of time when you go 3D.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group