此页面显示3轴磁力计倾斜补偿使用
加速度计并将结果输出到小OLED显示屏上(SSD1360)
它重新创造了传统的指南针玫瑰。它还显示了
倾斜补偿输出和原始轴承之间的差异。当
显示显示辊和俯仰角的底部。
在这里,您可以找到制造磁力计的真实方法 生产不随磁力计倾斜而改变的轴承 horizontal.
我花了很多时间弄明白了这一点,因为有一个
微妙的陷阱,我'下面的详细信息。您可以在网上找到所有方程,但您可能会发现
如果您已经建造了一个,遇到了遇到问题 指南针使用hmc5883l (or QST5883L).
取决于您在地球表面的位置磁矢量
改变方向。具体地说,它将在赤道上水平
在北极90°下,在南极上升90°。图表
下面说明了什么:
"Earth's magnetic field" by Zappy.'s is licensed under cc by 2.0
它也各处都在这个地方变化,为什么好人在 NCEI. 已经绘制了地球'整个磁场。
如果存在显着的垂直分量,则磁矢量
然后倾斜磁力计将介绍该垂直的一部分
成分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轴,卷和俯仰方向:
想象一下你自己坐在驾驶舱里,然后:
横摆:顺时针旋转约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.
与所有的塔托斯一样,它是一个微妙的一个 - 也是在后代的所有
当他们没有时,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!
倾斜补偿的关键问题是:
你必须颠倒倒器。
您必须执行此操作以获取MAX和MIN Z字段值以便
获取z偏移值。一旦你这样做,倾斜补偿公式
works fine.
如果你考虑过一分钟 - 这对校准A很好
手机在那里很容易把它倒下,但它甚至不是
可以在车辆中进行固定安装。
它真的意味着在车辆中安装依赖于事实
它仍然是大多数时间的水平 - 所需的唯一校准是
将车辆旋转在水平面(Z)中。
事实上,旧的Gimbal的系统始终保持指南针水平所以自动倾斜补偿(在沉降之后)!
使用以下组件3轴磁力计倾斜补偿:
使用以下连接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)
以下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]
在屏幕上,两个轴承都显示为指向北方的线。 较长的线是原来的轴承,而较短的轴承是 compensated one.
在显示屏顶部,原始轴承显示在下面显示补偿轴承(以数字为数字)。
下面的图像显示了罗盘倾斜的卷
在间距为0.2°时,角度为17.5°。得到的轴承为320°
倾斜校正轴承为347°。你可以看到原始线条
轴承较长,而短线是倾斜补偿的倾斜。这些线指向磁性北方。
顶部:非补偿3轴轴承。
下一页:3轴磁力计倾斜补偿轴承。
左:滚动度,右:高度的音高。
了解有关使用磁力计作为指南针的更多信息 这里.
了解有关加速度计的更多信息(ADXL345) 这里.
结束3轴磁力计倾斜补偿示例。
使用ADS1115精度16位ADC进行教程进行低功耗。
arduino.模拟输出:如何创建最精确的PWM模拟输出以及如何创建模拟PWM正弦波。
了解DigitalWrite()的工作原理......现在使用17倍宏宏!
如何使用TCS230(/ TCS3200)彩色检测器芯片并轻松将其添加到您的任何项目中。
使用ADXL345 Acellerometer,您可以检测到16G!您还可以了解如何使用它来点击检测等。
HMC5883L - 如何制作数字罗盘,了解HMC5883L和QMC5883L之间的差异以及它们是否兼容。
新的! Comments
让你说到你刚刚阅读的东西!留下下面的框中的评论。