Arduino 驱动MT6701磁编码器并读取角度数据

Arduino通过I2C驱动MT6701磁编码器并读取角度数据


📑MT6701(基于差分霍尔的磁性角度传感器芯片)芯片特性简介

  • 🧨基于霍尔技术,0~360°绝对角度位置检测
    • 🌿3.3V~5.0V工作电压,内置EEPROM(烧写时需要保证VDD>4.5V)
    • 🌿独立输出接口: : I2C, SSI, ABZ,UVW, 模
      拟电压、PWM以及Z轴按压检测
    • 🌿支持最高转速55,000 转/分钟
    • 🌿角度输出的系统延时<5 us
    • 🌿增量ABZ输出支持1~1024脉冲/圈,任意整
      数分辨率客户可编程
    • 🌿增量UVW输出支持1~16对极,任意整数对
      极客户可编程
    • 🌿优异的抗杂散磁场干扰能力。

📙MT6701 IIC接口电路

在这里插入图片描述
在这里插入图片描述

  • 🔖 第八引脚注意是直接接到VCC,而不是使用电阻上拉。(其内部是有上拉电阻到VCC的)

⛳MT6701 I2C 读取角度操作

MT6701做为I2C从机的地址是b’0000110(这一地址可以通过编程改为b’1000110 )。14位绝对角度数据(2的14次方,16384)保存在0x03和0x04寄存器中,请按照如图-20所示的读取0x03和0x04的角度数据。
注意:要先读0x03再读0x04。
在这里插入图片描述

📒SSI接口

MT6701提供了SSI接口,上位机或MCU可以通过SSI接口接收14位的角度数据、状态位以及对应的校验位数据。SSI参考电路:

在这里插入图片描述
在这里插入图片描述在这里插入图片描述

  • 🔖如果不知道MT6701芯片的I2C地址,先对编码器设备进行扫描检测。

📘Arduino I2C扫描程序


#include <Wire.h>
 
 
void setup()
{
 // Wire.begin();
 
  Serial.begin(115200);
  while (!Serial);             // Leonardo: wait for serial monitor
  Serial.println("\nI2C Scanner");
  //   Wire.setSDA(8);
  // Wire.setSCL(9);
  Wire.begin();
}
 
 
void loop()
{
  byte error, address;
  int nDevices;
 
  Serial.println("Scanning...");
 
  nDevices = 0;
  for(address = 1; address < 127; address++ ) 
  {
    // The i2c_scanner uses the return value of
    // the Write.endTransmisstion to see if
    // a device did acknowledge to the address.
    Wire.beginTransmission(address);//从指定的地址开始向I2C从设备进行传输
    error = Wire.endTransmission();//停止与从机的数据传输
 /*
 * error返回结果:
 * 0: 成功
1: 数据量超过传送缓存容纳限制
2: 传送地址时收到 NACK
3: 传送数据时收到 NACK
4: 其它错误
 */
    if (error == 0)
    {
      Serial.print("I2C device found at address 0x");
      if (address<16) 
        Serial.print("0");
      Serial.print(address,HEX);
      Serial.println("  !");
 
      nDevices++;
    }
    else if (error==4) 
    {
      Serial.print("Unknown error at address 0x");
      if (address<16) 
        Serial.print("0");
      Serial.println(address,HEX);
    }    
  }
  if (nDevices == 0)
    Serial.println("No I2C devices found\n");
  else
    Serial.println("done\n");
 
  delay(5000);           // wait 5 seconds for next scan
}

  • 🔖检测结果:
    在这里插入图片描述

📗读取原始值

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

const unsigned int RESOLUTION = 800;

uint8_t readRegister(uint8_t address) {
    Wire.beginTransmission(6);
    Wire.write(address);
    Wire.endTransmission();
    Wire.requestFrom(6, 1);
    return Wire.read();
}

void writeRegister(uint8_t address, uint8_t value) {
    Wire.beginTransmission(6);
    Wire.write(address);
    Wire.write(value);
    Wire.endTransmission();
}

uint16_t readAbzRes() {
    uint16_t reg1 = readRegister(0x30) & 0x3;
    uint16_t reg2 = readRegister(0x31);
    return (reg2 | (reg1 << 8)) + 1;
}

void programAbzRes(uint16_t resolution) {
    resolution -= 1;
    uint8_t reg30backup = readRegister(0x30) & 0xC;

    uint8_t bottom = resolution & 0xFF;
    uint8_t up = ((resolution >> 8) & 0x03) | reg30backup;
    writeRegister(0x30, up);
    writeRegister(0x31, bottom);

    writeRegister(0x09, 0xB3);
    writeRegister(0x0A, 0x05);
    delay(600);
}

void setup() {
    Serial.begin(115200);
    Serial.println("Start");
    Wire.begin();//328PB A4:SDA   A5:SCL

    Serial.print("ABZ reg1: ");
    Serial.println(readRegister(0x30), HEX);
    Serial.print("ABZ reg2: ");
    Serial.println(readRegister(0x31), HEX);

    if (readAbzRes() != RESOLUTION) {
        programAbzRes(RESOLUTION);
        Serial.println("Finished, power cycle");
        while (true);
    }
}

void loop() {
    uint16_t reg1 = readRegister(3);
    uint16_t reg2 = readRegister(4);
    uint16_t pos = reg2 >> 2 | reg1 << 6;
    Serial.print("Pos: ");
    Serial.print(pos);
    Serial.print("\t");
    float Angle = float(pos/16384.00)*360;//*360;//换算角度
    Serial.print("Angle: ");
    Serial.println(Angle, 2);

    delay(200);
}
  • 🔖测试打印数据:
    在这里插入图片描述

📒使用MT6701库I2C读取

  • 🌿依赖库:MT6701-arduino
    在这里插入图片描述
#include <Wire.h>
#include "MT6701.h"//https://github.com/I-AM-ENGINEER/MT6701-arduino

MT6701 encoder;

void setup() {
  Serial.begin(115200);
  Wire.begin();//328p I2C: SDA:A4  ;SCL:A5
  encoder.initializeI2C();
}

void loop() {
  float angle = encoder.angleRead();
  Serial.println(angle);
  delay(100);
}

📗EEPROM编程示例

  • 📄相关寄存器:
    在这里插入图片描述

  • 🌾编程步骤:
    在这里插入图片描述

#include <Wire.h>
#include "MT6701.h"//https://github.com/I-AM-ENGINEER/MT6701-arduino

MT6701 encoder;

void setup() {
  Wire.begin();
    encoder.initializeI2C();
  
  // Configure encoder settings

  // Direction could be:
  // MT6701_DIRECTION_CW
  // MT6701_DIRECTION_CCW
  encoder.directionSet(MT6701_DIRECTION_CW);
  encoder.offsetSet(45.0f);
  encoder.pwmModeSet(MT6701_PWM_FREQ_994_4, MT6701_PWM_POL_LOW);
  // Save settings in chip EEPROM
  encoder.programmEEPROM();
}


void loop() {
  // Nothing
}

📘SPI读取方式

/*
 * Arduino UNO    |      MT6701
 *  PIN13(PB5)   <----->    CLK
 *  PIN12(PB4)   <----->    DO/SDA
 *  PINx    <----->    CSN
 * 
 * For CSN you can use any free pin, expect 0, 1, 11, in this example i use pin 9. 
 * You can connect other SPI sensors, they should functional fine.
*/

#include <Arduino.h>
#include <SPI.h>
#include "MT6701.h"//https://github.com/I-AM-ENGINEER/MT6701-arduino

// You could set any pin
#define CS_PIN  9		//328PB:PB1

MT6701 encoder;

void setup() {
  Serial.begin(115200);
  SPI.begin();
  encoder.initializeSSI(CS_PIN);
  Serial.println("Init complete");
}

void loop() {
  mt6701_status_t field_status = encoder.fieldStatusRead();
  float angle = encoder.angleRead();

  Serial.print("field: ");
  switch (field_status){
    case MT6701_STATUS_NORM: Serial.print("NORM"); break;
    case MT6701_STATUS_FIELD_STRONG: Serial.print("STRONG"); break;
    case MT6701_STATUS_FIELD_WEAK: Serial.print("WEAK"); break;
    default: Serial.print("ERROR"); break;
  }
  Serial.print("   |    angle: ");
  Serial.println(angle);

  delay(100);
}

在这里插入图片描述

  • 20
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值