成为订阅者(免费)

加入29,000名其他订阅者以获得用户销售折扣和 其他免费资源。
:
:
大学教师'担心 - 您的邮件地址完全是 安全的。我保证使用它 只要 to send you MicroZine.

3轴磁力计倾斜补偿

此页面显示3轴磁力计倾斜补偿使用 加速度计并将结果输出到小OLED显示屏上(SSD1360) 它重新创造了传统的指南针玫瑰。它还显示了 倾斜补偿输出和原始轴承之间的差异。当 显示显示辊和俯仰角的底部。

在这里,您可以找到制造磁力计的真实方法 生产不随磁力计倾斜而改变的轴承 horizontal.


TILT补偿QST5883L符合AD1306 OLED显示屏

我花了很多时间弄明白了这一点,因为有一个 微妙的陷阱,我'下面的详细信息。您可以在网上找到所有方程,但您可能会发现 如果您已经建造了一个,遇到了遇到问题 指南针使用hmc5883l (or QST5883L).

你为什么需要加速度计?

取决于您在地球表面的位置磁矢量 改变方向。具体地说,它将在赤道上水平 在北极90°下,在南极上升90°。图表 下面说明了什么:

地球's Magnetic field

 "Earth's magnetic field" by Zappy.'s is licensed under cc by 2.0

它也各处都在这个地方变化,为什么好人在 NCEI. 已经绘制了地球'整个磁场。

3轴磁力计倾斜补偿轴承误差

如果存在显着的垂直分量,则磁矢量 然后倾斜磁力计将介绍该垂直的一部分 成分Zh进入XH或YH的传感器。这意味着你越多 倾斜设备越多,你得到的xh或yh更多(或少于您的 location!).

由于YH和XH用于计算轴承,那么您有一个 轴承误差 - 通常是重要的,但这取决于哪里 您所在,ZH组件在您的位置有多强。

如果您位于赤道,则磁场是 水平,该领域中有很少的垂直组件。那 意味着与Zh组件相比,YH和Zh组件大大 即,Zh组件几乎没有效果,因此倾斜对 the bearing.

使用加速度计

一个 加速度计 measures 地球引力在3点自由度(x,y和z)和 重力矢量总是指向地球的质量中心。 使用这些测量,您可以计算间距和滚动角度 确定水平x和y平面的距离有多远。

然后,您可以使用这些结果来弄清楚ZH组件的数量 应用(取决于存在多少倾斜)并将其删除。

坐标系

右边的第一件事是你的坐标系。在里面 指南针项目, 我从头写道,我决定了"normal" x - y graph was a 好主意,因为它允许您在一个中看到数学运营"normal" way.

这种方法的问题是你必须小提琴 轴承角度以来与X到右侧,y向上,atan 磁矢量指向时功能返回零度 对。你真正想要的是零指向Y轴。在那里面 项目转换是为了实现这一问题。

倾斜补偿的问题是方程式 这是在完全不同的坐标系上工作 - 这 飞机导航系统使用坐标系,并使用x 坐标指向前向,y指向右侧和z指向。所以 如果希望倾斜补偿工作,则必须使用相同的工作 坐标系(或者或重新计算所有旋转矩阵 maths!).

轴承,卷和俯仰定义

下图显示了x,y,z轴,卷和俯仰方向:

飞机滚动间距偏航和XYZ轴
图像来源: Wikimedia-Commons. :通过JRVZ更新。 许可 CC通过SA 3.0 added x,y,z text

想象一下你自己坐在驾驶舱里,然后:

    横摆:顺时针旋转约Z以进行正偏航;轴承角度增加。

    滚动:右翼朝向正卷。

    俯仰:鼻子上升为正音高。

倾斜补偿算法

一旦您对要使用的x,y和z轴进行了整理了 然后我们需要计算等效的yh和xh - 磁x和y 成分。记得修改磁力计输出以匹配 所需的轴方向(如上所示) - 这取决于您的方式 安装磁力计。

我发现用于磁力计倾斜补偿算法的最佳参考文献是:

    http://www.brokking.net/YMFC-32/YMFC-32_document_1.pdf

    这是由Michael J. Caruso Honeywell, SSEC

该文件详细分析了错误来源 实用的ADC解决方案,你会发现在商业中有用 design.

它不会进入您需要派生的矩阵数学 等式(您可以在Web上的其他PDF文档中找到这些),但如果 您按照x,y,z设置,然后给定的方程式将正常工作:
倾斜补偿公式Source: http://www.brokking.net/YMFC-32/YMFC-32_document_1.pdf

其中φ是俯仰角,并且θ是滚角。无论是弧度。

方程背后的想法是在磁性上进行旋转 向量找到水平的磁性元件 plane.

3轴磁力计倾斜补偿GOTCHA

与所有的塔托斯一样,它是一个微妙的一个 - 也是在后代的所有 当他们没有时,Gotchas似乎是显而易见的。在工作时 罗盘代码只需要解决x和y组件 磁力计输出以获得轴承。这意味着你只需要 为X和Y轴制造出硬铁偏移。以下代码 用来做到这一点(在校准函数内):

      if(magnetimalready())getMagnetometer(&x, &y, &z);
      if (x>maxx) maxx = x;
      if (x<minx) minx = x;
      if (y>maxy) maxy = y;
      if (y<miny) miny = y;  

此代码在旋转HMC5883L时重复10秒钟 平坦的表面。一旦获得了CALC_OFCSETS的MAX和MIN 函数返回从中减去的offx和offy值 磁力计输出以提供以(0,0)为中心的值。这效果很好 并返回轴承,但不是倾斜补偿一个。

然后代码使用atan2获取轴承:

   getMagnetometer(&x, &y, &z);

   int atan2val = 180 / m_pi * atan2((float)(x-offx),(float)(Y-offy));
   轴承=( - atan2val + 360)%360;  

注意:ATAN2功能内的X-OFFX和Y-OFFY值已交换 与不同x-y的倾斜补偿(下面)代码相比 axis orientation.

从非倾斜补偿代码到的问题 倾斜补偿代码是需要z组件(参见上文 equations).

但是,因为我使用了旧代码,我没有计算z偏移量。 轴承代码仅使用X,Y磁场输出,因此似乎 you don'需要担心z comonent - 错误!

需要以下代码来获取偏移量:

      if(magnetimalready())getMagnetometer(&x, &y, &z);
      if (x>maxx) maxx = x;
      if (x<minx) minx = x;
      if (y>maxy) maxy = y;
      if (y<miny) miny = y;
      if (z>maxz) maxz = z;
      if (z<minz) minz = z;

但是,例程被分为两个部分 - 一个以获得z值 一个得到x-y值。这是因为当你旋转时 device you don't希望x-y值记录z组件 磁矢量 - 您只想在设备时记录这些值 is flat.

您可以更改此操作以观察到加速度计输出和 磁力计输出仅在MAX或MIN Z时测量Z值 由加速度计是出色的。

之后,以下代码返回倾斜补偿轴承:

   mx = (float)x;
   my = (float)y;
   mz = (float)z;
 
   // Compensated
   int cx =(int)(mx * cos(p)+ my * sin(r)* sin(p) - mz * cos(r)* sin(p));
   int cy =(int)(我的* cos(r)+ mz * sin(r));
 
   漂浮atan2val = 180 / m_pi * atan2((float)(cy),(float)(cx));   

注意忘记Z组件的容易是多么容易,因为最终计算仅使用CX和CY!

发布3轴磁力计倾斜补偿

倾斜补偿的关键问题是:

    你必须颠倒倒器。

您必须执行此操作以获取MAX和MIN Z字段值以便 获取z偏移值。一旦你这样做,倾斜补偿公式 works fine.

如果你考虑过一分钟 - 这对校准A很好 手机在那里很容易把它倒下,但它甚至不是 可以在车辆中进行固定安装。

它真的意味着在车辆中安装依赖于事实 它仍然是大多数时间的水平 - 所需的唯一校准是 将车辆旋转在水平面(Z)中。

事实上,旧的Gimbal的系统始终保持指南针水平所以自动倾斜补偿(在沉降之后)!

硬件

使用以下组件3轴磁力计倾斜补偿:

  • arduino nano(或uno),
  • SSD1306 OLED.显示屏,
  • HMC5883L(或QST5883L)突破板,
  • 按下按钮(1关闭)。

硬件连接

使用以下连接3轴磁力计倾斜补偿:

这些与第二示例中使用的相同 这一页 (罗盘代码没有倾斜补偿,但使用OLED SSD1306显示器):

  Arduino Uno/
  Nano pin
标签
目的地
  A5
SCL.
5883L SCL
  A4
SDA.
5883L SDA.
  5V
vcc.
5883L vcc.
  GND
GND.
5883L GND.
  D2 D2 按钮
  GND GND. To Button
  D11
莫斯
OLED_MOSI.
  D13
CLK.
OLED_CLK.
  D9
DC.
OLED_DC.
  D8
CS
OLED_CS.
  D10
RST.
OLED_RESET.
按钮是常开一个。

倾斜补偿示例代码

这3个轴磁力计倾斜补偿示例使用相同的硬件作为 磁力计指南针项目.

下面的C代码向您展示了如何执行HMC5883L Arduino倾斜 补偿但使用替代芯片QST5883L(HMC5883L芯片 随着霍尼韦尔停止,版本难以获得 生产,但为QST Corporation许可设计)。本质上 这些芯片的输出相同,但它们略微使用 re-arranged 内部硬件 例如不同尺寸的ADC和寄存器。

QST5883L芯片在此用于磁力计,但如果您有 HMC5883L芯片然后您需要使用库(adafruit hmc5883l unified), 由于HMC5883L更难以使用(库使其变得简单)。使用库来检索 值并从GetMagnetometer()函数提供它们。

该示例与旋转显示器180度旋转 原始指南针代码 由于它使X坐标更容易根据飞机轴承,滚动和俯仰用作直线前进的轴 定义.

原始指南针中使用的描述适用于此代码 - 唯一的区别是3轴磁力计倾斜补偿 计算和返回补偿轴承的功能:

    Float GetMagnetometertiltCompensatedBearing(int x,int y,int z)

arduino.倾斜补偿素描

以下3轴磁力计倾斜补偿素描剪影 和arduino nano或uno,但算法可以应用于任何 Microcotnroller与相关芯片连接。

// QST5883L compass and SSD1306 OLED display
// 3 Axis Magnetometer Tilt compensation using ADXl345
//
// Coords x ahead, y right - follows aircraft convention.
//
// Copyright John Main - Free for non commercial use.
//
#include "Wire.h" ;# For 5883
#include <SPI.h>  ;# For SSD1306 board.
#include <EEPROM.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "I2Cdev.h"
#include "math.h"
#include "ADXL345.h"

#define OLED_MOSI  11
#define OLED_CLK   13       // LED_BUILTIN
#define OLED_DC     9
#define OLED_CS     8
#define OLED_RESET 10

#define BUTTON_CAL  2
#define BUTTON_TEST 5
#define LED  4 // LED_BUILTIN pin 13 is also SPICLK SCK

#define EEADDR 98 //66 // Start location to write EEPROM data.
#define CALTIME 10000  // In ms.
#define SMOOTH_ACCELL 20

#define SCREEN_HEIGHT 128 // The screen is rotated in sw.
#define SCREEN_WIDTH   64 // This is default height.

ADXL345 accel;

static 经过 te stat,ovfl,skipped;
static 在t minx,maxx,miny,maxy,minz,maxz;
static 在t offx=0,offy=0,offz=0;

static 在t degTest=0,updateSpeed=1000;
static 经过 te showMT=0;

const 在t radius = SCREEN_WIDTH / 2;
const 在t midx   = radius;  // Middle of compass rose.
const 在t midy   = radius;  // Middle of compass rose.

Adafruit_SSD1306 display(OLED_DC., OLED_RESET., OLED_CS.); // hw spi

/////////////////////////////////////////////////////////////
// Generic I2C write to I2C device with address, i2cAddr
// Write to address regaddr within device
// Write the byte d
void I2C_write_AddrDev_AddrReg_Byte(经过 te i2cAddr, 经过 te regaddr, 经过 te d ) {
   Wire.beginTransmission(i2cAddr);
   Wire.write(regaddr);
   Wire.write(d);
   Wire.endTransmission();
}

/////////////////////////////////////////////////////////////
void calc_offsets(void)  {
   offx = (maxx+minx)/2;   // maxx/2 - minx/2 + 2minx/2
   offy = (maxy+miny)/2;
   offz = (maxz+minz)/2;
}

/////////////////////////////////////////////////////////////
经过 te magnetometerReady(void) {
   // Data ready?
   Wire.beginTransmission(0x0d); // Read from status reg
   Wire.write(0x06);
   在t num = Wire.requestFrom((经过 te)0x0d, (经过 te)1);
   stat = Wire.read(); // DOR Data out Ready (SKIPPED).
   Wire.endTransmission();

   ovfl    = stat & 0x02;
   skipped = stat & 0x04;

   return (stat && 0x01);  // 0x01 is the DRDY Data Ready flag
}

/////////////////////////////////////////////////////////////
// If data is not ready x,y,z are not changed.
// raw data is aligned to HMC5883 coords
经过 te getMagnetometerRaw(在t16_t *x, 在t16_t *y, 在t16_t *z) {

   if ( !magnetometerReady() ) return 0;

   Wire.beginTransmission(0x0d);
   Wire.write(0x00);     // read from address zero = x,y,z registers.
   在t err = Wire.endTransmission();

   if (!err) {
      Wire.requestFrom((经过 te)0x0d, (经过 te)6); //Blocking?
      while(Wire.available()<6); //Wait if above blocking then this not needed.
      *x  = (在t16_t)(Wire.read() | Wire.read() << 8);
      *y  = (在t16_t)(Wire.read() | Wire.read() << 8);
      *z  = (在t16_t)(Wire.read() | Wire.read() << 8);
   }
   return 1;
}

/////////////////////////////////////////////////////////////
// Orient to board coordinates
void getMagnetometer(在t16_t *x, 在t16_t *y, 在t16_t *z) {

   if ( !getMagnetometerRaw(x, y, z) ) return;

   // modify for accel board orientation (board x = up, y to left).
   *y = -(*y);
}

/////////////////////////////////////////////////////////////
float getMagnetometerBearing(在t16_t x, 在t16_t y, 在t16_t z) {

   float atan2val = 180/M_PI * atan2((float)y,(float)x); // NEW coords.
   在t b = (在t)(-atan2val + 360 ) % 360;
   return b;
}

/////////////////////////////////////////////////////////////
// Blocking: Waits in this function for reading to be ready.
void readMagnetometer(在t16_t *x, 在t16_t *y,在t16_t *z) {
   while( !magnetometerReady() );
   getMagnetometer(x, y, z);  // Note: Addresses of pointers passed.
}

///////////////////////////////////////////////////////////////
float getMagnetometerTiltCompensatedBearing(在t x, 在t y, 在t z) {
float r, p, mx, my, mz;

   getRollPitch(&r, &p);

   // Convert back to radians
   在t rdeg = r;
   在t pdeg = p;
   r = (M_PI/180)*r;
   p = (M_PI/180)*p;

   mx = (float)x;
   my = (float)y;
   mz = (float)z;

   在t cx = (在t)( mx*cos(p) + my*sin(r)*sin(p) - mz*cos(r)*sin(p) );
   在t cy = (在t)( my*cos(r) + mz*sin(r) );
   // Also diffrerent here:
   // //web.archive.org/web/20130624074336/http://www.loveelectronics.co.uk:80/Tutorials/13/tilt-compensated-compass-arduino-tutorial
   // Same as 1st!!!

   在t tx=cx,ty=cy,tz=z; // Done offx,y above
   float atan2val = 180/M_PI * atan2((float)(ty),(float)(tx));

   在t tb = (在t)(-atan2val + 360 ) % 360;

   return tb;
}


///////////////////////////////////////////////////////////////
// Returns angle calculated from z, y, z accelerometers.
//
void getRollPitchRawFloat(float *roll, float *pitch) {
float r,x,y,z;
在t16_t ax, ay, az;

  // Datasheet: OPERATION AT VOLTAGES OTHER THAN 2.5 V
  // 3v3 X,Y 25mg too high, z 20mg too low
  // 3V3 lsb value 265/g c  (g/265)=0.03698
  // 2V5 lsb value 256/g   (g/256)=0.03828 z axis unaffected by voltage supply.
  #define ADXL345_LSBVAL_3V3 3.698E-3
  #define ADXL345_LSBVAL_2V5 3.828E-3

  accel.getAcceleration(&ax, &ay, &az);
  x = (float)ax*ADXL345_LSBVAL_3V3 - 25E-3;
  y = (float)ay*ADXL345_LSBVAL_3V3 - 25E-3;
  z = (float)az*ADXL345_LSBVAL_2V5 + 20e-3;

  r = sqrt(x*x+y*y+z*z);

  // modify for accel board orientation (board x = up, y to left).
  y = -y;
  *pitch  = 180/M_PI * asin(x/r);
  *roll   = 180/M_PI * -asin(y/r);
}

///////////////////////////////////////////////////////////////
void getRollPitch(float *roll, float *pitch) {
static float avg_r[SMOOTH_ACCELL], avg_p[SMOOTH_ACCELL];
static 经过 te idx=0;
float r,p;

   getRollPitchRawFloat(roll, pitch);

   avg_r[idx] = *roll;                 // Smooth.
   avg_p[idx] = *pitch;
   idx++;
   if (idx>=SMOOTH_ACCELL) idx = 0;

   r = p = 0;
   for (在t i=0; i<SMOOTH_ACCELL; i++) {
      r += avg_r[i];
      p += avg_p[i];
   }
   r /= SMOOTH_ACCELL;
   p /= SMOOTH_ACCELL;

   *roll  = r;
   *pitch = p;
}

/////////////////////////////////////////////////////////////
void setup() {

   pinMode(LED,OUTPUT);

   pinMode(BUTTON_CAL,INPUT_PULLUP);
   pinMode(BUTTON_TEST,INPUT_PULLUP);

   Wire.begin(); // Start I2C
   Wire.setClock(100000); // Test at high speed

   display.begin(SSD1306_SWITCHCAPVCC);
   display.clearDisplay();
   display.setTextSize(1);
//   display.setTextColor(WHITE);       // Does NOT erase background.
   display.setTextColor(WHITE, BLACK);  // Does erase background.

   // Datasheet suggests this for chip startup HMC5883L.
   // Set reset register.Datasheet suggests this as 0x01.
   I2C_write_AddrDev_AddrReg_Byte(0x0d,0x0b,1);
   // Control reg : Mode:continuous, ODR:10Hz, RNG:2G, OSR:512 (over sample)
//   I2C_write_AddrDev_AddrReg_Byte(0x0d,0x09,B00000001);
   // In lab gauss > 2G so need higher range.
   I2C_write_AddrDev_AddrReg_Byte(0x0d,0x09,B00010001);

   // Read EEPROM
   在t EEAddr = EEADDR;
   EEPROM.get(EEAddr,minx); EEAddr +=sizeof(minx);
   EEPROM.get(EEAddr,maxx); EEAddr +=sizeof(maxx);
   EEPROM.get(EEAddr,miny); EEAddr +=sizeof(miny);
   EEPROM.get(EEAddr,maxy); EEAddr +=sizeof(maxy);
   EEPROM.get(EEAddr,minz); EEAddr +=sizeof(minz);
   EEPROM.get(EEAddr,maxz); EEAddr +=sizeof(maxz);
   calc_offsets();

   display.setRotation(3);

   Serial.begin(115200);
   Serial.println("Compass hmc5883L");

   accel.在itialize();
   Serial.println(F("Testing device connections..."));
   Serial.print(F("ADXL345 connection "));
   Serial.println(accel.testConnection() ? F("successful") : F("failed") );

   accel.setFullResolution(ADXL345_RANGE_2G);
   accel.setRate(ADXL345_RATE_100);  // This is default but shows the value.

   accel.setFullResolution(1); // 0 => 10 bit mode.
   accel.setLowPowerEnabled(0);
   accel.setRange(0); // 0 => 2g, 3 => 16g
}

/////////////////////////////////////////////////////////////
// Normalized line drawing (0,0) = bot left
void drawLine (在t x1, 在t y1, 在t x2, 在t y2) {
    display.drawLine(x1, SCREEN_HEIGHT-y1, x2, SCREEN_HEIGHT-y2, 1);
}

/////////////////////////////////////////////////////////////
// Normalized line drawing (0,0) = bot left
void drawCircle (在t x, 在t y, 在t radius) {
   display.drawCircle(x, SCREEN_HEIGHT-y, radius-1,1);
}

/////////////////////////////////////////////////////////////
void drawBearing(float bearing, 在t midx, 在t midy, 在t radius) {
   bearing += 90; // Rotate arctan2 to vertical
   在t opp = sin(bearing*M_PI/180)*radius;
   在t adj = cos(bearing*M_PI/180)*radius;
   // Screen +y is down but drawLine adjusts it up.
   drawLine(midx, midy, midx+adj, midy+opp);
}

/////////////////////////////////////////////////////////////
// Can choose whether to write to EEPROM for testing.
void calibrate(boolean eeprom_write, 经过 te xy_or_z) {
   unsigned long calTimeWas = millis();

   在t x,y,z;
   float deg=0,deg2=0;

   readMagnetometer(&x, &y, &z);

   maxx = minx = x; // Set initial values to current magnetometer readings.
   maxy = miny = y;
   maxz = minz = z;

   delay(300); // Allow button release.

   while(1) {  // Calibration loop.

      if (digitalRead(BUTTON_CAL)==0 || digitalRead(BUTTON_TEST)==0) {
         delay(300); // Allow button release.
         return; // Abort
      }

      if ( magnetometerReady() ) getMagnetometer(&x, &y, &z);
      if (x>maxx) maxx = x;
      if (x<minx) minx = x;
      if (y>maxy) maxy = y;
      if (y<miny) miny = y;
      if (z>maxz) maxz = z;
      if (z<minz) minz = z;

      display.clearDisplay();

      display.setTextSize(2);
      display.setCursor(0,0);

      if(eeprom_write) display.print("CALIB");
      else             display.print("TEST");

      display.setCursor(0,16);
      if (!xy_or_z) display.print("XY"); else
          display.print("Z");

      在t secmillis  = millis()-calTimeWas;
      if (secmillis>CALTIME) break;                    // Exit after time up.

      在t secs = (在t)((CALTIME-secmillis+1000)/1000);
      display.setCursor(0,32);  display.print("--> "); display.print((在t)((CALTIME-secmillis)/1000));

      drawBearing((在t)deg2, midx, midy , radius);
      drawBearing((在t)deg, midx, midy , radius);

      deg = (360.0/CALTIME)*secmillis; // Rotate a line for countdown duration.

      deg2 += deg; // Rotate a line for countdown duration. Fun.
      deg = fmod(deg,360);

      for(在t i=0;i<360;i+=45)   // 45 Degree spokes (rotating)
        drawBearing(i + (45/secs)*10, midx, midy, radius-7);

      display.display();  // Update display.
      delay(10);
   } // while cal

   if (xy_or_z==0) {
      offx = ((maxx-minx)/2)+minx;
      offy = ((maxy-miny)/2)+miny;
   } else
        offz = ((maxz-minz)/2)+minz;

   if(eeprom_write) {
      在t EEAddr = EEADDR;

      if (xy_or_z==0) {
         在t EEAddr = EEADDR;
         EEPROM.put(EEAddr,minx); EEAddr +=sizeof(minx);
         EEPROM.put(EEAddr,maxx); EEAddr +=sizeof(maxx);
         EEPROM.put(EEAddr,miny); EEAddr +=sizeof(miny);
         EEPROM.put(EEAddr,maxy); EEAddr +=sizeof(maxy);
      } else {
         在t EEAddr = EEADDR+4*sizeof(minx);
         EEPROM.put(EEAddr,minz); EEAddr +=sizeof(minz);
         EEPROM.put(EEAddr,maxz); EEAddr +=sizeof(maxz);
      }
   }

   unsigned long dispExitTimeWas = millis();

   while(1) {

      display.clearDisplay();

      display.setTextSize(2);
      display.setCursor(0,0);

      // Make sure this does not repeat endlessly!
      if(eeprom_write) display.print("EEPROM Written");
      else             display.print("TEST DMY Write");
      if (millis()- dispExitTimeWas>2000) break;

      display.display();  // Update display.
      delay(10);
   }
   calc_offsets();
}

/////////////////////////////////////////////////////////////
void draw(在t Mx, 在t My, 在t bearing, 在t tbearing) {
在t lineH, lineNum;

   // SSD1306 init.
   display.clearDisplay();

   // display fancy stuff
   drawCircle(midx, midy, radius-1);    // -1 as circle is 1 bigger
   drawCircle(midx, midy, (radius-1)/2);

   for(在t i=0;i<360;i+=45)   // 45 Degree spokes
     drawBearing(i , midx, midy, radius-7);

   drawBearing(bearing, midx, midy, radius);
   drawBearing(0, midx, midy, radius);       // North

   display.setTextSize(2);
    lineH = 16;

   lineNum=0;
   // Bearing
   display.setCursor(15,lineH*lineNum);  display.print(bearing);
   display.print((char)247);
   lineNum++;  // Next line

   // Tilt Bearing
   display.setCursor(15,lineH*lineNum);  display.print(tbearing);
   display.print((char)247);
   lineNum++;  // Next line

   drawBearing(tbearing, midx, midy, radius-10);

   if(Mx>maxy || Mx<minx || My>maxy || My<miny) {
      display.setCursor(0,lineH*lineNum++);  display.print("*CAL*");
   }

   display.setTextSize(1);
   lineH = 8;
   lineNum=0;

   // Roll Pitch
   float r,p;
   getRollPitch(&r,&p);


   display.setCursor(0,120);  display.print(r,1);
   display.print((char)247);

   display.setCursor(40,120);  display.print(p,1);
   display.print((char)247);


   display.display();  // Update display.
}

/////////////////////////////////////////////////////////////
void loop(void) {
static unsigned long BLTimeWas=millis();
在t x,y,z; // Raw compass output values.
在t bearing,i;

   if (digitalRead(BUTTON_CAL)==0)  { calibrate(1,0); calibrate(1,1); }
   if (digitalRead(BUTTON_TEST)==0) { calibrate(0,0); calibrate(0,1); }

   getMagnetometer(&x,&y,&z);

   bearing = (在t)getMagnetometerBearing(x-offx, y-offy, z-offz);

   在t tbearing = getMagnetometerTiltCompensatedBearing(x-offx, y-offy, z-offz);

   draw(x,y,bearing,tbearing);

   if (millis()-BLTimeWas>400) { // LED toggle
      BLTimeWas = millis();
      static 经过 te togLED=0;
      togLED = !togLED;
      if(togLED) digitalWrite(LED,HIGH); else digitalWrite(LED,LOW);
   }
}

// End of QST5883L OLED compass - 
// 3 axis magnetometer tilt compensation example.

[文件:qmc5883l-tilt-comp.ino]

3轴磁力计倾斜补偿码操作

在屏幕上,两个轴承都显示为指向北方的线。 较长的线是原来的轴承,而较短的轴承是 compensated one.

在显示屏顶部,原始轴承显示在下面显示补偿轴承(以数字为数字)。

在左侧显示屏的底部是右侧的辊角,右侧是俯仰角。

下面的图像显示了罗盘倾斜的卷 在间距为0.2°时,角度为17.5°。得到的轴承为320° 倾斜校正轴承为347°。你可以看到原始线条 轴承较长,而短线是倾斜补偿的倾斜。这些线指向磁性北方。

顶部:非补偿3轴轴承。
下一页:3轴磁力计倾斜补偿轴承。

TILT补偿QST5883L符合AD1306 OLED显示屏

左:滚动度,右:高度的音高。

了解有关使用磁力计作为指南针的更多信息 这里.
了解有关加速度计的更多信息(ADXL345) 这里.


结束3轴磁力计倾斜补偿示例。



新的! Comments

让你说到你刚刚阅读的东西!留下下面的框中的评论。




隐私政策 | 接触 | 关于我

网站地图 | 使用条款


ezoic.报告此广告

访问我们的Facebook页面:

   点击这里



最近的文章

  1. 如何使用ADS1115

    使用ADS1115精度16位ADC进行教程进行低功耗。

    阅读更多

  2. arduino.模拟输出...易模拟输出生成

    arduino.模拟输出:如何创建最精确的PWM模拟输出以及如何创建模拟PWM正弦波。

    阅读更多

  3. 数号和等效的快速宏。加快代码!

    了解DigitalWrite()的工作原理......现在使用17倍宏宏!

    阅读更多

  4. TCS230颜色传感芯片:如何运作以及如何使用它。

    如何使用TCS230(/ TCS3200)彩色检测器芯片并轻松将其添加到您的任何项目中。

    阅读更多

  5. 如何使用ADXL345进行运动感测等。

    使用ADXL345 Acellerometer,您可以检测到16G!您还可以了解如何使用它来点击检测等。

    阅读更多

  6. HMC5883L 3轴数字MAGENTOMTER如何运作

    HMC5883L - 如何制作数字罗盘,了解HMC5883L和QMC5883L之间的差异以及它们是否兼容。

    阅读更多



读者 Comments

"I wanted to thank
你这么好
对于所有信息
你已经提供了
你的网站's

高超极好的."

- 逃亡Potthath.

"This site really is
最好的和我最喜欢的。
我发现这里有很多很有用
项目和提示。"

- 米兰

Bursach.<at>gmail.com<

"Awesome site,
非常,非常容易和好
导航!"


-
镭_tr.<at>
wolf359.cjb.net.


学习微控制器

"Interested in
微控制器?"

注册
免费7天指南:

自由 GUIDE : CLICK HERE


"I am a newbie to PIC
我想说
 how great your
网站一直在为我。"


- 戴夫

de_scott.<at>bellsouth.net

"Your site is a great
和完美的工作。
恭喜。"


- SURESH.

IntegratedInfosys.<at>
Yahoo.com.

"I couldn't find the correct
要定义的词语
你的网页。

非常有用,揭开,
诚实明确。

非常感谢
你的时间和作品。
问候。"


- 一个on.

回到顶部