天天看點

HaaS EDU場景式應用學習 - 電子羅盤實驗介紹涉及知識點開發環境準備硬體介紹 - QMC5883L界面開發開發者支援

實驗介紹

“電子羅盤”,作為一種非常常見的功能,目前市場上的智能手機幾乎都預設配備了。在生活中,它可以幫助我們找準方向,進行輔助定位等等。除了手機之外,電子羅盤也廣泛應用于航空、航天、機器人、航海、車輛自主導航等領域。在本實驗中,我們也來實作一個“電子羅盤”。

HaaS EDU場景式應用學習 - 電子羅盤實驗介紹涉及知識點開發環境準備硬體介紹 - QMC5883L界面開發開發者支援

從上圖中可以看到,随着方向的轉動,螢幕上的指針和度數也在發生着變化,指針指向的刻度标明了箭頭所指方向的角度度數。實作這個效果的方法很簡單,隻需要擷取電子羅盤傳感器的讀數,然後根據讀數繪制羅盤界面即可。

涉及知識點

  • QMC5883L 三軸AMR磁傳感器的原理和使用
  • OLED繪圖

開發環境準備

硬體

開發用電腦一台
HAAS EDU K1 開發闆一塊
USB2TypeC 資料線一根
           
  • 1
  • 2
  • 3

軟體

AliOS Things開發環境搭建

開發環境的搭建請參考 @ref HaaS_EDU_K1_Quick_Start (搭建開發環境章節),其中詳細的介紹了AliOS Things 3.3的IDE內建開發環境的搭建流程。
           

HaaS EDU K1 DEMO 代碼下載下傳

HaaS EDU K1 DEMO 的代碼下載下傳請參考 @ref HaaS_EDU_K1_Quick_Start (建立工程章節),其中,
選擇解決方案: 基于教育開發闆的示例
選擇開發闆: haaseduk1 board configure
           

代碼編譯、燒錄

參考 @ref HaaS_EDU_K1_Quick_Start (3.1 編譯工程章節),點選 ✅ 即可完成編譯固件。
參考 @ref HaaS_EDU_K1_Quick_Start (3.2 燒錄鏡像章節),點選 "⚡️" 即可完成燒錄固件。
           

硬體介紹 - QMC5883L

DataSheet

了解一款IC最快捷和精準的方法是查閱它的DataSheet。這款IC的DataSheet可以在以下連結擷取。

QMC5883L-Datasheet-1.0.pdf

硬體規格

QMC5883L是一款多晶片三軸磁傳感器。旨在用于無人機,機器人,移動和個人手持裝置中的指南針,導航和遊戲等高精度應用。QMC5883L 采用異相磁阻(anisotropic magnetoresistance AMR)技術,這些各向異性傳感器具有在軸向高靈敏度和線性高精度的特點。傳感器具有的對正交軸低靈敏度的固相結構能用于測量地球磁場的方向和大小,其測量範圍從毫高斯到 8 高斯。它具有低噪聲,高精度,低功耗,失調消除和溫度補償的優點。 QMC5883L可實作1°至2°的羅盤航向精度。 使用I2C串行總線簡化接口。

更詳細的硬體規格參數可以參考 DataSheet 的 2.1 Product Specifications

傳感原理

HaaS EDU場景式應用學習 - 電子羅盤實驗介紹涉及知識點開發環境準備硬體介紹 - QMC5883L界面開發開發者支援

通過這張内部原理圖我們可以很清楚地看出,在QMC5883L内部,存在三組兩兩正交的磁阻,這種特殊的電阻的阻值會随着施加的磁場而變化,是以使用模數轉換器讀取這種變化,就能夠獲得器件在磁場中的變化資訊,進而判斷器件的指向。

名詞釋義

  • AMR Bridge:三軸異相磁阻傳感器,其結構是一個電阻電橋,其電阻會随着所施加的磁場而變化。三個傳感器互相正交,進而能夠得出三個方向上的磁場強度。
  • MUX:多路複用通道,通過開關選中對應的通路,可以采集該通路的傳感器資料。
  • PGA:可程式設計控制的傳感器信号增益放大器。
  • Signal Conditioning:進行磁場信号校正及補償的數字子產品。
  • ADC:模數轉換器,用于将傳感器側得到的模拟信号轉換為數字信号。
  • NVM:用于校正的非易失性存儲器。
  • SET/RST Driver:用于初始化磁性傳感器的内部驅動。
  • Reference:用于内部偏移的電壓/電流基準。
  • Temperature Sensor:用于内部精度/偏移的溫度傳感器,也可以用于測量溫度并輸出。

驅動方式

通訊接口

由DataSheet可知,QMC5883L采用的通訊方式為I2C。預設7bit裝置位址:0x0D (DataSheet P10 5.4)

在 AliOS Things 3.3中,對I2C的操作才用了VFS的方式,開發者隻需要open相應的device裝置,開發者隻需要關心連結到的I2C裝置号,從器件的裝置位址,從器件支援的I2C速率。知道了從裝置位址,讀寫位址也可以計算出,AliOS Things 會自動處理這些計算。是以:

I2C裝置的寫位址 = I2C裝置位址 << 1 = 0x0D << 1 = 0x1A

I2C裝置的讀位址 = (I2C裝置位址 << 1) + 1 = 0x1B

這也符合在 (DataSheet P14 I2C R/W Operation) 中給出的結論。

如果我們需要為了QMC5883L初始化I2C接口,那麼對應的代碼為:

int32_t ret = sensor_i2c_open(QMC5883L_I2C_PORT, QMC5883L_ADDR, I2C_BUS_BIT_RATES_100K, 0);
if (ret) {
    LOGE("SENSOR", "sensor i2c open failed, ret:%d\n", ret);
    return;
}
           
  • 4
  • 5

寄存器位址

一般,使用I2C通訊的器件,都是通過讀寫寄存器的方式來完成對裝置的讀取和配置,是以了解寄存器的分布就非常重要。查閱 DataSheet(from DataSheet P16 9.1 Register Map) 可以得到:

HaaS EDU場景式應用學習 - 電子羅盤實驗介紹涉及知識點開發環境準備硬體介紹 - QMC5883L界面開發開發者支援

其中,根據Access屬性的不同,我們分為隻讀寄存器和讀寫寄存器,來分析一些驅動過程中較為重要的寄存器。

隻讀寄存器(輸出寄存器)

隻讀寄存器一般用于讀取裝置的狀态和采樣資料。

Table 14. Output Data Register

HaaS EDU場景式應用學習 - 電子羅盤實驗介紹涉及知識點開發環境準備硬體介紹 - QMC5883L界面開發開發者支援
  • Data Output X Y Z LSB&MSB 00H-05H

三軸的采樣資料,每個軸輸出的資料大小均為16bit,分别存儲在2個8bit寄存器中。

讀寫寄存器(配置寄存器)

讀寫寄存器一般用于配置器件。對于QMC5883L而言,它的初始化隻需要關心這一個寄存器09H。

Table 18. Control Register 1

HaaS EDU場景式應用學習 - 電子羅盤實驗介紹涉及知識點開發環境準備硬體介紹 - QMC5883L界面開發開發者支援
  • OSR

Over Sample Ratio 過采樣率寄存器。用于控制内部數字濾波器的帶寬。較大的OSR值會帶來較小的濾波器帶寬,以及更少的帶内噪聲和更高的功耗。可以通過配置此寄存器達到噪聲和功率之間的良好平衡。

  • RNG

Range 量程選擇寄存器。可以通過寄存器RNG配置磁傳感器的感應範圍。量程的選擇應該是由具體的應用場景決定的。對于磁性清晰的環境,在弱磁場環境下,例如 +/- 2 gauss 應當選用較小的量程。量程與磁傳感器的靈敏度息息相關。在采樣位數不變的情況下,最低量程具有最高的靈敏度,是以分辨率更高。

  • ODR

Output Data Rate 輸出資料頻率寄存器。

  • MODE

模式控制寄存器。用于配置器件是否開啟連續測量模式。在連續測量模式下,Data Output X Y Z 6個寄存器會連續重新整理資料,隻需要 從Data Output 位址處連續讀取即可獲得實時的測量資料。

驅動實作

完成I2C的初始化之後,我們就可以針對QMC5883L來進行初始化。在AliOS Things 3.3中,我們已經對器件進行了部分抽象,可以在初始化時配置。

// solutions/eduk1_demo/drivers/sensor/drv_mag_honeywell_qmc5883l.c
// solutions/eduk1_demo/drivers/sensor/drv_mag_honeywell_qmc5883l.h

static void _qmc5883l_init() {
    /* This assumes the wire library has been initialized. */
    addr = QMC5883L_ADDR;
    oversampling = QMC5883L_CONFIG_OS512;        // 512倍過采樣
    range = QMC5883L_CONFIG_8GAUSS;                // 8高斯量程
    rate = QMC5883L_CONFIG_200HZ;                // 200Hz資料輸出頻率
    mode = QMC5883L_CONFIG_CONT;                // 開啟連續采樣模式
    qmc5883l_reset();
}
           
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

完成配置後,驅動程式會向對應寄存器寫入資料。

// solutions/eduk1_demo/drivers/sensor/drv_mag_honeywell_qmc5883l.c
// solutions/eduk1_demo/drivers/sensor/drv_mag_honeywell_qmc5883l.h

# define QMC5883L_CONFIG2 0x09
# define QMC5883L_CONFIG2 0x0a

static qmc5883l_write_register(uint8_t addr, uint8_t reg, uint8_t data)
{
    uint8_t write_buffer[2] = {reg, data};
    qmc5883l_i2c_master_send(write_buffer, 2, 1000);
}

static void qmc5883l_reconfig()
{
    qmc5883l_write_register(addr, QMC5883L_CONFIG, oversampling|range|rate|mode);    // 向0x09配置寄存器寫入配置資料
    qmc5883l_write_register(addr, QMC5883L_CONFIG2, 0x1);                            // 軟重新開機
}
           
  • 13
  • 14
  • 15
  • 16
  • 17

同理,如果需要讀取寄存器,則需要先向器件寫入目标讀取位址,再讀取器件資料。

// solutions/eduk1_demo/drivers/sensor/drv_mag_honeywell_qmc5883l.c
// solutions/eduk1_demo/drivers/sensor/drv_mag_honeywell_qmc5883l.h

uint8_t qmc5883l_read_len(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len)
{
    qmc5883l_i2c_master_send(&reg, 1, 1000);
    aos_msleep(20);
    qmc5883l_i2c_master_recv(buf, len, 1000);
    return 1;
}

int qmc5883l_readRaw(int16_t *x, int16_t *y, int16_t *z)
{
    uint8_t data[6];
    uint32_t timeout = 10000;

    while(!qmc5883l_ready() && (timeout--));

    if(!qmc5883l_read_len(addr, QMC5883L_X_LSB, data, 6)) return 0;
    *x = data[0] | (data[1]<<8);
    *y = data[2] | (data[3]<<8);
    *z = data[4] | (data[5]<<8);

    printf("get org data [%d,%d,%d]\n", x, y, z);

    return 1;
}
           
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

至此,就可以從QMC5883L中讀出采樣資料。由于電子羅盤隻需要平面的方向資訊,是以隻需要使用

atan2(x_fit, y_fit) * 180.0 / M_PI;
// atan2(x, y) 傳回以弧度表示的 y/x 的反正切
           

就可以得到目前的指向資訊。

但是這樣通過原始資料得到的角度,會表現出非常不準确。是以,接下來我們需要對資料進行校準。

資料校準

原始資料采樣

通過前文中實作的 int qmc5883l_readRaw(int16_t *x, int16_t *y, int16_t *z) 函數,我們可以實作對器件在各個方向上的采樣,由于我們主要關心 X,Y 軸的資料,是以我們需要将器件在水準面上周遊各個方向并讀取資料。資料通過 printf(“get org data [%d,%d,%d]\n”, x, y, z) 列印在序列槽上。

具體的做法就是,在水準面上緩緩旋轉 HaaS EDK 至少覆寫完整的一圈,并且在此過程中保證周圍沒有磁場幹擾(比如任何包含磁性的物體)。

HaaS EDU場景式應用學習 - 電子羅盤實驗介紹涉及知識點開發環境準備硬體介紹 - QMC5883L界面開發開發者支援

采集完後的資料如下:

org_list = [
    [-1438,-1690,-2665],
    [-1438,-1690,-2665],
    [-1446,-1660,-2667],
    [-1418,-1642,-2702],
    ...
]
           

我們使用matploatlib将這段資料可視化為散點圖,散點圖的X,Y軸分别代表了從QMC5883L中讀取到的X,Y軸資料,點的顔色由深到淺标記了采樣點的順序由前到後。

HaaS EDU場景式應用學習 - 電子羅盤實驗介紹涉及知識點開發環境準備硬體介紹 - QMC5883L界面開發開發者支援

可以觀察到,随着我們的旋轉,散點構成了一個較為完整的圓形,說明X,Y軸的兩個磁力傳感器對于磁場變化的靈敏度大緻一緻,即變化等量磁通量帶來的電阻變化是相似的,才能夠呈現出較為标準的圓形。而如果兩個傳感器的靈敏度差别較大,就會出現下右圖的狀況,X軸的響應更靈敏,則在X軸上測量出的間隔更大,X軸更長,類似一個橢圓。

HaaS EDU場景式應用學習 - 電子羅盤實驗介紹涉及知識點開發環境準備硬體介紹 - QMC5883L界面開發開發者支援

由于我們使用 atan2 方法将 X Y 軸資料映射到極坐标系上,如果我們想得到精準的映射,我們需要保證圓心處于(0,0)位置。然而,這兩張圖可以看出,圓心都偏離了(0,0)。是以我們首先需要找到圓心(對于三軸而言是球心)坐标。

對于部分器件,可能存在不同軸靈敏度不一緻的情況,我們可以通過如下公式将三個軸縮放到同一個尺度。其中,x_min,x_max 等代表資料邊界,x_offset 等代表修正的資料球心。

\dfrac{x-x_{offset}}{x_{\max}-x_{\min }}=\dfrac{y-y_{offset}}{y_{\max}-y_{\min }}=\dfrac{z-z_{offset}}{z_{\max}-z_{\min }}
           
x_max = y_max = z_max = INT16_MIN;
 x_min = y_min = z_min = INT16_MAX;

int qmc5883l_readHeading()
{
    int16_t x_org, y_org, z_org;        // 原始資料
    float x_offset, y_offset, z_offset;    // 球心坐标偏移
    float x_fit, y_fit, z_fit;            // 修正資料

    if (!qmc5883l_readRaw(&x_org, &y_org, &z_org))
        return 0;

    // 在每次讀取資料時都更新資料邊界
    x_min = x_org < x_min ? x_org : x_min;
    x_max = x_org > x_max ? x_org : x_max;
    y_min = y_org < y_min ? y_org : y_min;
    y_max = y_org > y_max ? y_org : y_max;
    z_min = z_org < z_min ? z_org : z_min;
    z_max = z_org > z_max ? z_org : z_max;

    // 如果資料量不足以計算邊界 則退出
    if (x_min == x_max || y_min == y_max || z_max == z_min)
        return 0;

    // 通過邊界計算出圓心偏移
    x_offset = (x_max + x_min) / 2.0;
    y_offset = (y_max + y_min) / 2.0;
    z_offset = (z_max + z_min) / 2.0;

    // 修正比例
    x_fit = (x_org - x_offset) * 1000.0 / (x_max - x_min);
    y_fit = (y_org - y_offset) * 1000.0 / (y_max - y_min);
    z_fit = (z_org - z_offset) * 1000.0 / (z_max - z_min);

    printf("fix[%f,%f,%f],\n", x_fit, y_fit, z_fit);

    int heading = 180.0 * atan2(x_fit, y_fit) / M_PI;
    heading = (heading <= 0) ? (heading + 360) : heading;

    return heading;
}

           
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

下圖是添加了修正算法後得到的資料,可以看到,随着顔色變淺,資料量增加,散點逐漸拟合到一個圓形上,且圓心處于 (0,0) 位置。

HaaS EDU場景式應用學習 - 電子羅盤實驗介紹涉及知識點開發環境準備硬體介紹 - QMC5883L界面開發開發者支援

至此,我們就得到了較為準确的朝向資料。

界面開發

在本實驗的界面開發中,使用到了以下方法:

while (1)
{
    heading = qmc5883l_readHeading(); // 讀取電子羅盤資料

    OLED_Clear();                    // 清理上一次繪畫的資訊
    OLED_Icon_Draw(COMPASS_CENTER_X - 27, COMPASS_CENTER_Y - 27, &icon_compass_55_55, 0);    // 用于繪制羅盤盤面
    OLED_DrawLine_ByAngle(COMPASS_CENTER_X, COMPASS_CENTER_Y, (-heading-90), arror_len, 1);    // 用于繪制羅盤指針
    OLED_Show_String(96, 4, code_str, 24, 1);        // 用于繪制方向字元
    OLED_Show_String(78, 36, number_str, 24, 1);    // 用于繪制方向讀數
    OLED_Refresh_GRAM();            // 将畫面顯示在螢幕上

    aos_msleep(30);
}
           

開發者支援

HaaS官方:

https://haas.iot.aliyun.com/

HaaS技術社群:

https://blog.csdn.net/HaaSTech

開發者釘釘群和公衆号見下圖,開發者釘釘群每天都有技術支援同學值班。

HaaS EDU場景式應用學習 - 電子羅盤實驗介紹涉及知識點開發環境準備硬體介紹 - QMC5883L界面開發開發者支援

繼續閱讀