eagler8 发表于 2021-1-23 11:31:58


eagler8 发表于 2021-1-23 11:55:48

GY-271 QMC5883L模块 电子指南针罗盘模块 三轴磁场传感器

采用高品质沉金pcb,机器焊接工艺,保证品质
名称:QMC5883L模块(三轴磁场模块)
型号:GY-271使用芯片:QMC5883L
供电电源:3-5v
通信方式:IIC通信协议
测量范围:±1.3-8 高斯

eagler8 发表于 2021-1-23 12:00:36

该模块包括一个最新的高分辨率QMC5883X系列磁阻传感器,一个包含放大功能的ASIC,自动消磁带驱动器,失调消除以及一个12位ADC,可实现1°至2°的罗盘 航向精度。 I2C串行总线可简化接口。电原理图如下。



eagler8 发表于 2021-1-23 12:07:51



引脚功能
VCC + 5V-电源引脚,给它3.3v-5VDC。 对于Arduino,建议5v
GND-接地引脚
SDA和SCL-这些是I2C数据和时钟引脚,用于从模块向微控制器发送和接收数据。 这些引脚上有1万上拉至3.3v引脚。 您可以将这些引脚连接到5V I2C线路,板上有电平转换器,可将引脚安全降低到3V
DRDY-这是“数据就绪”引脚输出。 如果要高速流传输数据(每秒超过100次),则可以在准备好读取数据时收听此引脚。 有关使用DRDY引脚的更多详细信息,请参见数据表,我们不使用它,因为我们读得不快!

Build the circuit
QMC5883L--------------- Uno/Mega2560
VCC------------------- 5V
GND------------------- GND
SCL------------------- A5/ pin21 mega2560
SDA------------------- A4/pin20 mega2560
DRDY------------------ N/C

eagler8 发表于 2021-1-23 13:37:05

QMC5883L模块的几个定义:
AMR Bridge:三轴磁性传感器
MUX:多路复用通道
PGA:可编程控制的传感器信号增益放大器
Signal Conditioning:进行磁场信号校正及补偿的数字模块
ADC:16位的模数转换器
I2C:总线形式
NVM:用于校正的非易失性存储器
SET/RST Driver:用于初始化磁性传感器的内部驱动
Reference:用于内部偏移的电压/电流基准
Clock Gen.:内部振荡器,用于内部操作
POR:上电复位
Temperature Sensor:用于内部精度/偏移的温度传感器,也可以用于测量温度并输出
QMC5883L有两种工作模式:连续测量模式和待命模式。

eagler8 发表于 2021-1-23 13:42:00

QMC5883L模块实验接线示意图

eagler8 发表于 2021-1-23 14:14:08

安装QMC5883库,在网上搜到不少相关的库:
keepworking /Mecha_QMC5883L
https://github.com/keepworking/mecha_qmc5883l

mprograms /QMC5883LCompass
https://github.com/mprograms/QMC5883LCompass

dthain /QMC5883L
https://github.com/dthain/QMC5883L

liyupengsGit /QMC5883LCompass
https://github.com/liyupengsGit/QMC5883LCompass

eagler8 发表于 2021-1-24 19:04:45

项目一:简易测量方位角度的实验开源代码

/*
【Arduino】168种传感器模块系列实验(资料代码+图形编程+仿真编程)
   实验一百五十八:QMC5883L电子指南针罗盘模块 三轴磁场传感器GY-271
1、安装库:IDE--工具--管理库--搜索“QMC5883L”--安装QMC5883LCompass
2、项目一:简易测量方位角度
3、实验接线:
QMC5883L-------------- UNO
VCC------------------- 5V
GND------------------- GND
SCL ------------------- A5
SDA------------------- A4
DRDY------------------ N/C
*/

#include <QMC5883LCompass.h>

QMC5883LCompass compass;

void setup() {
Serial.begin(9600);
compass.init();

}

void loop() {
int a;

// 读取罗盘值
compass.read();

// 返回方位角读数
a = compass.getAzimuth();

Serial.print("A: ");
Serial.print(a);
Serial.println();

delay(500);
}

eagler8 发表于 2021-1-24 19:11:57

实验串口返回情况

eagler8 发表于 2021-1-24 19:25:19

实验场景图

eagler8 发表于 2021-1-24 20:14:27

项目二:简易测量方位角度的实验开源代码(数值在0-11之间,每个数值间隔30度)

/*
【Arduino】168种传感器模块系列实验(资料代码+图形编程+仿真编程)
   实验一百五十八:QMC5883L电子指南针罗盘模块 三轴磁场传感器GY-271
1、安装库:IDE--工具--管理库--搜索“QMC5883L”--安装QMC5883LCompass
2、项目二:简易测量方位角度(数值在0-11之间,每个数值间隔30度)
3、实验接线:
QMC5883L-------------- UNO
VCC------------------- 5V
GND------------------- GND
SCL ------------------- A5
SDA------------------- A4
DRDY------------------ N/C
*/

#include <QMC5883LCompass.h>

QMC5883LCompass compass;

void setup() {
Serial.begin(9600);
compass.init();
}

void loop() {
compass.read();

byte a = compass.getAzimuth();
// 根据方位/方位角的方向,此处的输出将是介于0到11之间的值。
byte b = compass.getBearing(a);

Serial.print("B: ");
Serial.print(b);
Serial.println();

delay(250);
}

eagler8 发表于 2021-1-24 20:25:34

实验串口返回情况

eagler8 发表于 2021-1-24 20:45:45

知识点:方位角
又称地平经度(Azimuth angle,缩写为Az),是在平面上量度物体之间的角度差的方法之一。是从某点的指北方向线起,依顺时针方向到目标方向线之间的水平夹角,用“度”和“密位”表示。常用于判定方位、指示目标和保持行进方向。

从真子午线起算的为真方位角,通常在精密测量中使用,从磁子午线起算的方磁方位角,在航空、航海、炮兵射击、军队行进时广泛使用,从地形图的坐标纵线起算的为坐标方位角,炮兵使用较多。磁方位角与真方位角的关系式为:磁方位角=真方位角-(±磁偏角)。坐标方位角与磁方位角的关系式为:坐标方位角=磁方位角+ (±磁坐偏角)。

从标准方向的北端起,顺时针方向到直线的水平角称为该直线的方位角。以北点为起算点,由北点开始按顺时针方向计量。方位角的取值范围为0~360度,北点为0°,东点为90°,南点为180°,西点为270°。

eagler8 发表于 2021-1-24 21:05:09

QMC5883L Compass是一个Arduino库,用于将QMC5583L系列模块使用指南针(电子罗盘)功能。支持:
1、获取XYZ轴的值。
2、计算方位角。
3、获得16点方位角轴承方向(0-15)。
4、获取16点方位角轴承名称(N,NNE,NE,ENE,E,ESE,SE,SSE,S,SSW,SW,WSW,W,WNW,NW,NNW)
5、通过滚动平均和最小/最大消除来平滑XYZ读数。
6、任选的芯片组模式。

QMC5883LCompass.cpp 库文件

/*
===============================================================================================================
QMC5883LCompass.h
Library for using QMC5583L series chip boards as a compass.
Learn more at
Supports:
- Getting values of XYZ axis.
- Calculating Azimuth.
- Getting 16 point Azimuth bearing direction (0 - 15).
- Getting 16 point Azimuth bearing Names (N, NNE, NE, ENE, E, ESE, SE, SSE, S, SSW, SW, WSW, W, WNW, NW, NNW)
- Smoothing of XYZ readings via rolling averaging and min / max removal.
- Optional chipset modes (see below)
===============================================================================================================
v1.0 - June 13, 2019
Written by MRPrograms
Github:
Release under the GNU General Public License v3

===============================================================================================================
FROM QST QMC5883L Datasheet
-----------------------------------------------
MODE CONTROL (MODE)
        Standby                        0x00
        Continuous                0x01
OUTPUT DATA RATE (ODR)
        10Hz              0x00
        50Hz              0x04
        100Hz               0x08
        200Hz               0x0C
FULL SCALE (RNG)
        2G                  0x00
        8G                  0x10
OVER SAMPLE RATIO (OSR)
        512                 0x00
        256                 0x40
        128                 0x80
        64                  0xC0

*/



#include "Arduino.h"
#include "QMC5883LCompass.h"
#include <Wire.h>

QMC5883LCompass::QMC5883LCompass() {
}


/**
        INIT
        Initialize Chip - This needs to be called in the sketch setup() function.
       
        @since v0.1;
**/
void QMC5883LCompass::init(){
        Wire.begin();
        _writeReg(0x0B,0x01);
        setMode(0x01,0x0C,0x10,0X00);
}


/**
        SET ADDRESS
        Set the I2C Address of the chip. This needs to be called in the sketch setup() function.
       
        @since v0.1;
**/
// Set I2C Address if different then default.
void QMC5883LCompass::setADDR(byte b){
        _ADDR = b;
}




/**
        REGISTER
        Write the register to the chip.
       
        @since v0.1;
**/
// Write register values to chip
void QMC5883LCompass::_writeReg(byte r, byte v){
        Wire.beginTransmission(_ADDR);
        Wire.write(r);
        Wire.write(v);
        Wire.endTransmission();
}


/**
        CHIP MODE
        Set the chip mode.
       
        @since v0.1;
**/
// Set chip mode
void QMC5883LCompass::setMode(byte mode, byte odr, byte rng, byte osr){
        _writeReg(0x09,mode|odr|rng|osr);
}


/**
        RESET
        Reset the chip.
       
        @since v0.1;
**/
// Reset the chip
void QMC5883LCompass::setReset(){
        _writeReg(0x0A,0x80);
}

// 1 = Basic 2 = Advanced
void QMC5883LCompass::setSmoothing(byte steps, bool adv){
        _smoothUse = true;
        _smoothSteps = ( steps > 10) ? 10 : steps;
        _smoothAdvanced = (adv == true) ? true : false;
}

/**
    SET CALIBRATION
        Set calibration values for more accurate readings
               
        @author Claus Näveke - TheNitek
       
        @since v1.1.0
**/
void QMC5883LCompass::setCalibration(int x_min, int x_max, int y_min, int y_max, int z_min, int z_max){
        _calibrationUse = true;

        _vCalibration = x_min;
        _vCalibration = x_max;
        _vCalibration = y_min;
        _vCalibration = y_max;
        _vCalibration = z_min;
        _vCalibration = z_max;
}



/**
        READ
        Read the XYZ axis and save the values in an array.
       
        @since v0.1;
**/
void QMC5883LCompass::read(){
        Wire.beginTransmission(_ADDR);
        Wire.write(0x00);
        int err = Wire.endTransmission();
        if (!err) {
                Wire.requestFrom(_ADDR, (byte)6);
                _vRaw = (int)(int16_t)(Wire.read() | Wire.read() << 8);
                _vRaw = (int)(int16_t)(Wire.read() | Wire.read() << 8);
                _vRaw = (int)(int16_t)(Wire.read() | Wire.read() << 8);

                if ( _calibrationUse ) {
                        _applyCalibration();
                }
               
                if ( _smoothUse ) {
                        _smoothing();
                }
               
                //byte overflow = Wire.read() & 0x02;
                //return overflow << 2;
        }
}

/**
    APPLY CALIBRATION
        This function uses the calibration data provided via @see setCalibration() to calculate more
        accurate readings
       
        @author Claus Näveke - TheNitek
       
        Based on this awesome article:
        https://appelsiini.net/2018/calibrate-magnetometer/
       
        @since v1.1.0
       
**/
void QMC5883LCompass::_applyCalibration(){
        int x_offset = (_vCalibration + _vCalibration)/2;
        int y_offset = (_vCalibration + _vCalibration)/2;
        int z_offset = (_vCalibration + _vCalibration)/2;
        int x_avg_delta = (_vCalibration - _vCalibration)/2;
        int y_avg_delta = (_vCalibration - _vCalibration)/2;
        int z_avg_delta = (_vCalibration - _vCalibration)/2;

        int avg_delta = (x_avg_delta + y_avg_delta + z_avg_delta) / 3;

        float x_scale = (float)avg_delta / x_avg_delta;
        float y_scale = (float)avg_delta / y_avg_delta;
        float z_scale = (float)avg_delta / z_avg_delta;

        _vCalibrated = (_vRaw - x_offset) * x_scale;
        _vCalibrated = (_vRaw - y_offset) * y_scale;
        _vCalibrated = (_vRaw - z_offset) * z_scale;
}


/**
        SMOOTH OUTPUT
        This function smooths the output for the XYZ axis. Depending on the options set in
        @see setSmoothing(), we can run multiple methods of smoothing the sensor readings.
       
        First we store (n) samples of sensor readings for each axis and store them in a rolling array.
        As each new sensor reading comes in we replace it with a new reading. Then we average the total
        of all (n) readings.
       
        Advanced Smoothing
        If you turn advanced smoothing on, we will select the min and max values from our array
        of (n) samples. We then subtract both the min and max from the total and average the total of all
        (n - 2) readings.
       
        NOTE: This function does several calculations and can cause your sketch to run slower.
       
        @since v0.3;
**/
void QMC5883LCompass::_smoothing(){
        byte max = 0;
        byte min = 0;
       
        if ( _vScan > _smoothSteps - 1 ) { _vScan = 0; }
       
        for ( int i = 0; i < 3; i++ ) {
                if ( _vTotals != 0 ) {
                        _vTotals = _vTotals - _vHistory;
                }
                _vHistory = ( _calibrationUse ) ? _vCalibrated : _vRaw;
                _vTotals = _vTotals + _vHistory;
               
                if ( _smoothAdvanced ) {
                        max = 0;
                        for (int j = 0; j < _smoothSteps - 1; j++) {
                                max = ( _vHistory > _vHistory ) ? j : max;
                        }
                       
                        min = 0;
                        for (int k = 0; k < _smoothSteps - 1; k++) {
                                min = ( _vHistory < _vHistory ) ? k : min;
                        }
                                       
                        _vSmooth = ( _vTotals - (_vHistory + _vHistory) ) / (_smoothSteps - 2);
                } else {
                        _vSmooth = _vTotals/ _smoothSteps;
                }
        }
       
        _vScan++;
}


/**
        GET X AXIS
        Read the X axis
       
        @since v0.1;
        @return int x axis
**/
int QMC5883LCompass::getX(){
        return _get(0);
}


/**
        GET Y AXIS
        Read the Y axis
       
        @since v0.1;
        @return int y axis
**/
int QMC5883LCompass::getY(){
        return _get(1);
}


/**
        GET Z AXIS
        Read the Z axis
       
        @since v0.1;
        @return int z axis
**/
int QMC5883LCompass::getZ(){
        return _get(2);
}

/**
        GET SENSOR AXIS READING
        Get the smoothed, calibration, or raw data from a given sensor axis
       
        @since v1.1.0
        @return int sensor axis value
**/
int QMC5883LCompass::_get(int i){
        if ( _smoothUse )
                return _vSmooth;
       
        if ( _calibrationUse )
                return _vCalibrated;

        return _vRaw;
}



/**
        GET AZIMUTH
        Calculate the azimuth (in degrees);
       
        @since v0.1;
        @return int azimuth
**/
int QMC5883LCompass::getAzimuth(){
        int a = atan2( getY(), getX() ) * 180.0 / PI;
        return a < 0 ? 360 + a : a;
}


/**
        GET BEARING
        Divide the 360 degree circle into 16 equal parts and then return the a value of 0-15
        based on where the azimuth is currently pointing.
       
        @since v1.0.1 - function now requires azimuth parameter.
        @since v0.2.0 - initial creation
       
        @return byte direction of bearing
*/
byte QMC5883LCompass::getBearing(int azimuth){
        unsigned long a = azimuth / 22.5;
        unsigned long r = a - (int)a;
        byte sexdec = 0;       
        sexdec = ( r >= .5 ) ? ceil(a) : floor(a);
        return sexdec;
}


/**
        This will take the location of the azimuth as calculated in getBearing() and then
        produce an array of chars as a text representation of the direction.
       
        NOTE: This function does not return anything since it is not possible to return an array.
        Values must be passed by reference back to your sketch.
       
        Example:
       
        ( if direction is in 1 / NNE)
       
        char myArray;
        compass.getDirection(myArray, azimuth);
       
        Serial.print(myArray); // N
        Serial.print(myArray); // N
        Serial.print(myArray); // E
       
       
        @see getBearing();
       
        @since v1.0.1 - function now requires azimuth parameter.
        @since v0.2.0 - initial creation
*/
void QMC5883LCompass::getDirection(char* myArray, int azimuth){
        int d = getBearing(azimuth);
        myArray = _bearings;
        myArray = _bearings;
        myArray = _bearings;
}

eagler8 发表于 2021-1-24 21:08:18

QMC5883LCompass.h 库文件

#ifndef QMC5883L_Compass
#define QMC5883L_Compass

#include "Arduino.h"
#include "Wire.h"


class QMC5883LCompass{
       
public:
    QMC5883LCompass();
        void init();
    void setADDR(byte b);
    void setMode(byte mode, byte odr, byte rng, byte osr);
        void setSmoothing(byte steps, bool adv);
        void setCalibration(int x_min, int x_max, int y_min, int y_max, int z_min, int z_max);
    void setReset();
    void read();
        int getX();
        int getY();
        int getZ();
        int getAzimuth();
        byte getBearing(int azimuth);
        void getDirection(char* myArray, int azimuth);
       
private:
    void _writeReg(byte reg,byte val);
        int _get(int index);
        bool _smoothUse = false;
        byte _smoothSteps = 5;
        bool _smoothAdvanced = false;
    byte _ADDR = 0x0D;
        int _vRaw = {0,0,0};
        int _vHistory;
        int _vScan = 0;
        long _vTotals = {0,0,0};
        int _vSmooth = {0,0,0};
        void _smoothing();
        bool _calibrationUse = false;
        int _vCalibration;
        int _vCalibrated;
        void _applyCalibration();
        const char _bearings ={
                {' ', ' ', 'N'},
                {'N', 'N', 'E'},
                {' ', 'N', 'E'},
                {'E', 'N', 'E'},
                {' ', ' ', 'E'},
                {'E', 'S', 'E'},
                {' ', 'S', 'E'},
                {'S', 'S', 'E'},
                {' ', ' ', 'S'},
                {'S', 'S', 'W'},
                {' ', 'S', 'W'},
                {'W', 'S', 'W'},
                {' ', ' ', 'W'},
                {'W', 'N', 'W'},
                {' ', 'N', 'W'},
                {'N', 'N', 'W'},
        };
       
       
       
};

#endif
页: 1 [2] 3
查看完整版本: 【Arduino】168种传感器模块系列实验(158)---QMC5883L三轴罗盘