AS5600磁編碼器電路與3D列印測試旋鈕(二)

前一篇貼文介紹了AS5600感測器的主要特色,具備I2C介面,感測器內部的ADC(類比數位轉換器)解析度為12位元。編寫AS5600程式之前,必須知道兩個參數:

  • AS5600元件的I2C位址:0x36。
  • AS5600感測器「偵測角度」值的暫存器資料位址

這些參數都記載於AS5600磁編碼器的技術文件。技術文件第18頁 “Register Description(暫存器描述)”單元,列舉了每一項資料的儲存位址,包含感測角度範圍設置、角度檢測值、磁力值…等。

讀取AS56000磁編碼器的角度暫存器資料

底下是根據AS5600技術文件整理的輸出角度暫存器資料,有“raw angle(原始角度)”和“angle(角度)”兩種,「原始角度」代表感測器偵測到的絕對角度值,「角度」則是程式設定的感測範圍內的感測角度(可設定18°~360°,預設為360°)。

AS56000磁編碼器的角度暫存器

以讀取「原始角度」為例,資料位於暫存器位址0x0C(高位元組)和0x0D(低位元組),兩者合併成12位元長度資料。程式首先要連接到0x36位址的I2C裝置(AS5600),然後從0x0C位址開始,連續讀取兩個位元組值。

Arduino I2C接限

改寫《超圖解Arduino互動設計入門》動手做9-5「在I2C介面上傳送整數資料」的程式,讀取AS5600感測到的磁石原始角度值程式碼:

#include <Wire.h>
#define AS5600_ADDR      0x36  // I2C位址
#define RAW_ANGLE_ADDR   0x0C  // 原始角度值的起始暫存器位址

void setup() {
  Wire.begin();
  Serial.begin(115200);
}

void loop() {
  Wire.beginTransmission(AS5600_ADDR);  // 連接AS5600
  Wire.write(RAW_ANGLE_ADDR);
  Wire.endTransmission();

  Wire.requestFrom(AS5600_ADDR, 2);     // 從AS5600請求兩個位元組值

  while (Wire.available()) {
    byte angle_h = Wire.read();           // 讀取高位元組資料
    byte angle_l = Wire.read();           // 讀取低位元組資料
    int angle = angle_h * 256 + angle_l;  // 還原12位元整數值
    Serial.println(angle);
  }
  delay(50);
}

上傳程式碼到Arduino開發板,然後把上一篇貼文製作的3D列印旋鈕蓋在AS5600模組上面,轉動旋鈕,即可從序列埠監控窗看到0~4095之間的數值。

還原12位元感測角度值

上面程式中,「還原12位元整數值」的敘述可以用底下的方式改寫,由於高位元組的前4個位元是「無意義值」,因此最好透過位元AND運算,明確將前4個位元清零,後面4個位元值保持不變,如下圖左(資料為虛構值):

還原12位元感測角度值

然後,把高位元組值左移8位元(等同乘上28,256,但計算效率較高),再和低位元組OR在一起,變數的資料型態最好也明確指定成16位元無號整數(uint16_t),因為足夠存入12位元正整數值。這個運算的敘述寫成:

uint16_t angle = (angle_h & 0x0F)  << 8 | angle_l;  // 還原12位元整數值 

指定ESP32的I2C接腳

ESP32晶片可用程式設定I2C的接腳,假設SDA腳是GPIO 9,SCL腳是GPIO 10,麵包板接線改成:

ESP32的I2C接腳

程式需要在Wire.begin()函式指定SDA和SCL的腳位編號,其餘程式碼不變:

#include <Wire.h>
#define SDA_PIN 9      // SDA腳
#define SCL_PIN 10     // SCL腳
#define AS5600_ADDR      0x36   // I2C位址
#define RAW_ANGLE_ADDR   0x0C   // 原始角度值的起始暫存器位址

void setup() {
  Wire.begin(SDA_PIN, SCL_PIN);   // 指定I2C腳位(SDA, SCL)
  Serial.begin(115200);
}

void loop() {
  Wire.beginTransmission(AS5600_ADDR);  // 連接AS5600
  Wire.write(RAW_ANGLE_ADDR);
  Wire.endTransmission();

  Wire.requestFrom(AS5600_ADDR, 2);     // 從AS5600請求兩個位元組值

  while (Wire.available()) {
    byte angle_h = Wire.read();    // 讀取高位元組資料
    byte angle_l = Wire.read();    // 讀取低位元組資料
    uint16_t angle = (angle_h & 0x0F) << 8 | angle_l;  // 還原12位元整數值
    Serial.println(angle);
  }
  delay(50);
}

安裝AS5600 Arduino程式庫

操作AS5600磁編碼器,最簡單的方法還是用現成的程式庫,即便沒閱讀技術文件,修改現成的範例就能用了。在Arduino IDE的「程式庫管理員」搜尋“AS5600”關鍵字,就能找到幾個程式庫,筆者選用Adafruit公司編寫的版本:

Adafruit AS5600程式庫

底下是這個程式庫附帶的AS5600_basic.ino範例原始碼,筆者將其中的輸出訊息和註解改成中文:

#include <Adafruit_AS5600.h>

Adafruit_AS5600 as5600;

void setup() {
  Serial.begin(115200);
  while (!Serial)
    delay(10);

  if (!as5600.begin()) {   // 使用開發板預設的I2C接腳連線
    Serial.println("找不到AS5600感測器,請檢查接線。");
    while (1)
      delay(10);
  }

  Serial.println("AS5600找到了!");

  as5600.enableWatchdog(false);    // 取消看門狗
  as5600.setPowerMode(AS5600_POWER_MODE_NOM);    // 普通電力模式
  // 遲滯(hysteresis)設定
  as5600.setHysteresis(AS5600_HYSTERESIS_OFF);

  // 類比電壓範圍輸出(0~100%)
  as5600.setOutputStage(AS5600_OUTPUT_STAGE_ANALOG_FULL);

  // 設置濾波器
  as5600.setSlowFilter(AS5600_SLOW_FILTER_16X);
  as5600.setFastFilterThresh(AS5600_FAST_FILTER_THRESH_SLOW_ONLY);

  // 重設位置設定
  as5600.setZPosition(0);    // 設置初始位置
  as5600.setMPosition(4095); // 設置最大位置
  as5600.setMaxAngle(4095);  // 設置最大角度

  Serial.println("偵測磁場中…");
}

void loop() {
  if (! as5600.isMagnetDetected()) {
    return;  // 若感測不到磁場,則離開迴圈。
  }

  // 連續讀取並顯示角度值
  uint16_t rawAngle = as5600.getRawAngle();
  uint16_t angle = as5600.getAngle();

  Serial.print("原始角度:");
  Serial.print(rawAngle);       // 10進位原始角度
  Serial.print(" (0x");
  Serial.print(rawAngle, HEX);  // 16進位原始角度
  Serial.print(") | 縮放角度:");
  Serial.print(angle);       // 10進位角度
  Serial.print(" (0x");
  Serial.print(angle, HEX);  // 16進位角度
  Serial.print(")");

  // 檢查感測器狀態
  if (as5600.isAGCminGainOverflow()) {
    Serial.print(" | MH: 磁場太強!");
  }
  if (as5600.isAGCmaxGainOverflow()) {
    Serial.print(" | ML: 磁場太弱~");
  }

  Serial.println();
  delay(50);
}

上傳程式到Arduino開發板,轉動旋鈕的結果如下,此例的「原始角度」和「縮放角度」值相同。

序列埠監控窗

若把磁石(旋鈕)往上移開AS5600模組,它將顯示「磁場太弱」:

序列埠監控窗

此程式庫的方法、自訂檢測角度範圍以及在此程式庫設置ESP32 I2C接腳的辦法,下一篇再說明。

Posts created 529

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

Related Posts

Begin typing your search term above and press enter to search. Press ESC to cancel.

Back To Top