After FindGyroOffset it's a stable GyroIntegral and GyroHeading. (Offset set to ~5)
Now I'm turning the robot for 2 sec and stop them, reset the GyroIntegral to 0.
But the GyroIntegral and Heading are running insanely fast off limits now! (2° per second!!)
Now after again running FindGyroOffset => Offset recalibrated to ~3, and all is stable again.
What's that??
Code: Select all
// Navigator Robot, TriBot architecture
// for NXC, tested with BricxCC 3.3.8.10 (2011-July-03)
// version 0.93
// based on:
// Odometry
// Compass
// Gyro sensor
// (still untuned)
//--------------------------------------------------
// mechanics, motors + sensors
//--------------------------------------------------
#define Menc(a) MotorRotationCount(a)
#define WheelDiameter 7.7 // Raddurchmesser
#define WheelGauge 28.8 // Achsbreite (Mittellinie Antriebsräder)
#define WheelGearRatio 0.5 // Untersetzungsgetriebe 1:2
// Radumfang
float WheelCircumference = PI*WheelDiameter; // 2*PI*r = PI*d
// Abrollstrecke pro 1° MotorEncoderTick
float WheelLegPerEncDegree = (PI*WheelDiameter*WheelGearRatio)/360;
float fMencHdgMath; // Heading to Odometry, mathematical sense
long MencHdg; // Heading to Odometry, geographical sense
//--------------------------------------------------
#define GYRO S2
#define COMPASS S3
long CompHdg, CompOffset;
float GyroHdg, GyroValue, GyroOffset=0.0, GyroIntegral;
//--------------------------------------------------
// IO functions, sensors
//--------------------------------------------------
#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);
}
float ArrayDegreesMean (float src[], int len) {
int i;
for (i=0; i<len; ++i) {
if (src[i]>180) src[i]=(src[i]-360);
}
return (ArrayMean(src, NA, NA));
}
inline float ArrayMedianF(float src[], int len)
{
float ftemp[];
ArraySort(ftemp, src, NA, NA)
return ftemp[(len-1)/2];
}
inline long ArrayMedianI(long src[], int len)
{
long itemp[];
ArraySort(itemp, src, NA, NA)
return itemp[(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;
}
inline void ArrayPushI(long &src[], long _new, int len)
{
for (int i=len; i>0; --i) {src[i]=src[i-1];} // shift up
src[0]=_new;
}
//--------------------------------------------------
// sensor calibration
//--------------------------------------------------
int OldBatteryLevel;
void FindGyroOffset()
{
float tot = 0;
OldBatteryLevel=BatteryLevel();
for (int i=0; i<500; ++i)
{
tot += SensorHTGyro(GYRO, 0); // tot var is 500 gyro readings
if (!(i%50)) Beep(880,10);
Wait(5); // 5ms between analog readings
}
Beep(440,100);
GyroOffset=tot/500;
}
//------------------------------------------------------------------------------
float fxpos=0, fypos=0;
float gyrodata[5];
task Navigator(){
long encLeft, encRight, encLeftOld, encRightOld, dEncLeft, dEncRight;
float fxold=0, fyold=0, Urk, Ulk, Uk, dMHdgRad, MencHdgRad;
encLeft =Menc(OUT_B);
encRight=Menc(OUT_C);
fMencHdgMath=0;
//-------------------------------------------//
CompHdg=CompOffset=SensorHTCompass(COMPASS);
//-------------------------------------------//
long GyroCalib=10000, // must be calibrated once!
itemp;
GyroIntegral=0;
GyroHdg=0;
//-------------------------------------------//
while(1) {
//----------------------------//
CompHdg=SensorHTCompass(COMPASS); // Compass heading //
//----------------------------//
//-------------------------------------------//
GyroValue=SensorHTGyro(GYRO,0)- GyroOffset ;
ArrayPushF(gyrodata, GyroValue, 5);
GyroValue= (ArrayMean(gyrodata, 0, 5));
GyroIntegral+=GyroValue;
GyroHdg=(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; // Gyro heading //
while (GyroHdg< 0) GyroHdg+=360; //----------------------------//
//-------------------------------------------//
encLeftOld =encLeft; // save old encoder values
encRightOld=encRight;
encLeft =Menc(OUT_B); // get new encoder values
encRight=Menc(OUT_C);
dEncLeft=encLeft-encLeftOld;
Ulk= WheelCircumference*dEncLeft; // left wheel leg way
dEncRight=encRight-encRightOld;
Urk= WheelCircumference*dEncRight; // right wheel leg way
Uk=(Urk+Ulk)/2; // intermedium leg way
dMHdgRad = atan2((Urk - Ulk), WheelGauge); // delta orientation
fxold=fxpos; fyold=fypos; // save old pos (x,y)
MencHdgRad=fMencHdgMath*PI/180; // Hdg in deg => rad
fxpos=fxold + Uk*cos(MencHdgRad + (dMHdgRad /2)); // new xpos
fypos=fyold + Uk*sin(MencHdgRad + (dMHdgRad /2)); // new ypos
MencHdgRad = MencHdgRad + dMHdgRad; // new motor enc Heading
fMencHdgMath=MencHdgRad*180/PI;
MencHdg=round(-fMencHdgMath);
//----------------------------//
while (MencHdg >=360) MencHdg-=360; // odometry heading //
while (MencHdg < 0) MencHdg+=360; //----------------------------//
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", MencHdg);
printf1(0, 8, "CompH%6d", CompHdg);
printf1(0, 0, "GyroH%6.1f", GyroHdg);
Wait(10);
}
}
task main(){
SetSensorHTGyro(GYRO);
SetSensorLowspeed(COMPASS);
start DisplayValues;
ArrayInit(gyrodata,0,5);
FindGyroOffset(); // calibrating Gyro Offset => ~5.0
start Navigator;
while(!btnhit());
OnFwd(OUT_C,80); OnRev(OUT_B,80);
Wait(2000);
Off(OUT_BC);
GyroIntegral=0;
Wait(5000); // GyroIntegral unstable (decreasing fast, ~2° per SECOND!)
FindGyroOffset(); // Recalibrating => Offset ~3.0
// now GyroIntegral stable
while(1);
}