Page 5 of 8

Re: hitechnic Gyro sensor (NGY1044) noise

Posted: 07 Jul 2011, 09:58
by timpattinson

Code: Select all

float FindOffset()
{
     float tot = 0;
    repeat (1000)
    {
        tot += SensorHTGyro(S1, 0); //tot var is 1000 gyro readings
    }
    PlayTone(440,500);
    return tot / 1000;   // returns avg
}

Re: hitechnic Gyro sensor (NGY1044) noise

Posted: 07 Jul 2011, 10:07
by HaWe
Thank you, I tried this just immediately, but GyroHeading is still increasing constantly although all stands still (about up to 5° per minute), just similarily as before :(

Re: hitechnic Gyro sensor (NGY1044) noise

Posted: 07 Jul 2011, 11:33
by mightor
Did you consider using a float instead of an int?

- Xander

Re: hitechnic Gyro sensor (NGY1044) noise

Posted: 07 Jul 2011, 12:52
by HaWe
surely, but SensorHTGyro needs an integer for GyroOffset to get passed to, I guess that's why.
To my observation the Offset should be somewhere between 4.0..5.0
But
GyroValue=SensorHTGyro(port, 5) is too high => increasing integral
GyroValue=SensorHTGyro(port, 4) is too low => decreasing integral

Or do I miss anything?

Re: hitechnic Gyro sensor (NGY1044) noise

Posted: 07 Jul 2011, 13:15
by mightor
Make your own function that grabs the analogue value from the gyro and subtract the float average. If you are integrating this may make all the difference between a 1 and 5 degree/minute drift.

- Xander

Re: hitechnic Gyro sensor (NGY1044) noise

Posted: 07 Jul 2011, 14:06
by linusa
The gyro offsets are all different for each production unit (their offsets probably follow some statistical distribution). We had problems with gyro drift as well, sometimes it stabilizes after a minute, sometimes it doesn't. I think environmental temperature was one of the influences.

The best approach is to take a lot of samples, but not too rapidly. I.e. maybe 200 samples from 20 seconds, during which the sensor must be at full rest. Calc mean and standard deviation and use the mean as offset. Repeat this process after one minute and see if mean and standard dev. changed. The sensor might stabilize after some minutes of use...

Re: hitechnic Gyro sensor (NGY1044) noise

Posted: 07 Jul 2011, 14:21
by HaWe
Xander, my friend, you nailed it! ^^
Now I finally understood what's all about the offset that has to be passed to SensorHTGyro reading (I always was curious about that).
Now it's fixed! :big_thumb:

(edit: improved version, bug fixed)

Code: Select all

//--------------------------------------------------
// IO functions, sensors
//--------------------------------------------------

#define Menc(a) MotorRotationCount(a)

#define Beep(f,d) PlayTone(f,d)

#define printf1( _x, _y, _format1, _value1) { \
  string sval1 = FormatNum(_format1, _value1); \
  TextOut(_x, _y, sval1); \
}

const char LCDline[]={56,48,40,32,24,16,8,0};

const string clrln="                 ";

inline bool btnhit(){
   return ( ButtonPressed(BTN1, false) || ButtonPressed(BTN2, false)
         || ButtonPressed(BTN3, false) || ButtonPressed(BTN4, false));
}


void PressToContinue(char Button) {
   string msg;
   if (Button==BTNCENTER)   msg="press BtnCntr...";
   else
   if (Button==BTNEXIT)     msg="press BtnExit...";
   else
   if (Button==BTNRIGHT)    msg="press BtnRight...";
   else
   if (Button==BTNLEFT)     msg="press BtnLeft...";

   printf1(0,LCDline[7],"%s", msg);
   while (!ButtonPressed(Button, false)); while (btnhit());
}

//--------------------------------------------------
// math
//--------------------------------------------------

#define min(a,b) (a<b?a:b)

#define max(a,b) (a>b?a:b)


inline long round(float f)
{
  if (f>=0) return (f + 0.5);
  else  return (f - 0.5);
}

inline float ArrayMedianF(float src[], int len)
{
  float ftemp[];

  ArraySort(ftemp, src, NA, NA)
  return ftemp[(len-1)/2];
}


inline void ArrayPushF(float &src[], float _new, int len)
{
  for (int i=len; i>0; --i) {src[i]=src[i-1];} // shift up
  src[0]=_new;
}


//--------------------------------------------------
// sensors
//--------------------------------------------------

#define GYRO    S2
#define COMPASS S3

long  GyroHeading,
      CompHeading, CompOffset,
      MencHeading ;
float GyroOffset=0.0,  GyroValue, GyroIntegral;


//--------------------------------------------------
// sensor calibration
//--------------------------------------------------

void FindGyroOffset()
{
    float tot = 0;
    for (int i=0; i<500; ++i)
    {
       tot += SensorHTGyro(GYRO, 0); // tot var is 500 gyro readings
       if (!(i%100)) Beep(1760,10);
       Wait(5);                     // Wait 5 ms (analog sensor)
    }
    PlayTone(440,100);
    GyroOffset= (tot/500);           //  avg
}


//------------------------------------------------------------------------------


task GetRotation(){

  long  GyroCalib=10500, temp;
  float gyrodata[5];
  
  CompHeading=CompOffset=SensorHTCompass(COMPASS);

  FindGyroOffset();           // approximation of Gyro Offset

  temp=0;
  GyroIntegral=0;

  while(1) {
     GyroValue=SensorHTGyro(GYRO,0)-GyroOffset;
     ArrayPushF(gyrodata, GyroValue, 5);
     GyroValue= (ArrayMean(gyrodata, 0, 5));

     GyroIntegral+=GyroValue;

     GyroHdg=round(GyroIntegral*(360.0/GyroCalib));

     if (ButtonPressed(BTNLEFT, false)) {   // press  BTNLEFT:
        GyroIntegral=0;                     // reset GyroIntegral
        while (btnhit()); Beep(1000,10);
                                            // now turn robot 360°
     }                                      // then press BTNRIGHT:
     if (ButtonPressed(BTNRIGHT, false)) {  // reset GyroCalib after 360° turn
        GyroCalib=abs(GyroIntegral);
        while (btnhit());  Beep(1000,10);
     }

     while (GyroHdg>=360) GyroHdg-=360;
     while (GyroHdg<  0)  GyroHdg+=360;
     
     CompHeading=SensorHTCompass(COMPASS);
     
     Wait(20);
  }
}

task DisplayValues() {
  while (1) {
     printf1(0, 56, "mot_B%6d", Menc(OUT_B));
     printf1(0, 48, "mot_C%6d", Menc(OUT_C));

     printf1(0, 40, "GValu%6.1f", GyroValue);
     printf1(0, 32, "GIntg%6.1f", GyroIntegral);
     printf1(0, 24, "GOffs%6.1f", GyroOffset);

     printf1(0, 16, "MotoH%6d", MencHeading);
     printf1(0,  8, "CompH%6d", CompHeading);
     printf1(0,  0, "GyroH%6d", GyroHeading);
     Wait(10);
  }
}

task main(){

  SetSensorHTGyro(GYRO);
  SetSensorLowspeed(COMPASS);

  start DisplayValues;
  start GetRotation;

  while(1);
}



Re: hitechnic Gyro sensor (NGY1044) noise

Posted: 07 Jul 2011, 21:09
by mightor
Glad I was able to help :)

- Xander

Re: hitechnic Gyro sensor (NGY1044) noise

Posted: 07 Jul 2011, 21:16
by afanofosc
BTW, the Gyro sensor is an analog device - so your comment about waiting 20 ms in FindGyroOffset doesn't make sense.

John Hansen

Re: hitechnic Gyro sensor (NGY1044) noise

Posted: 07 Jul 2011, 22:05
by mattallen37
You should also note, that some "drift" is actually very correct. The earth rotates 360*/24 hours (once a day). That means that you should see a "drift" of 1 degree every 4 minutes. However, if the axis of the gyro is perfectly parallel to the axis of the earth, you should see no "drift".

In the case of the HT Gyro, and most other hobby gyros, this would be of almost no consequence. Almost all micro gyros (IC gyros) are based on relative position (rate of rotation), and not absolute position. Just about any filter should discard this small effect as an error.