Arduino通过I2C驱动MT6701磁编码器并读取角度数据
Arduino通过I2C驱动MT6701磁编码器并读取角度数据
- 相关篇《Arduino通过Wire库读取AS5600编码器数据》
- 当前最新MT6701数据手册:
https://www.magntek.com.cn/upload/MT6701_Rev.1.8.pdf
MT6701(基于差分霍尔的磁性角度传感器芯片)芯片特性简介
- 🧨基于霍尔技术,0~360°绝对角度位置检测
-
- 3.3V~5.0V工作电压,内置EEPROM(烧写时需要保证VDD>4.5V)
-
- 独立输出接口: : I2C, SSI, ABZ,UVW, 模
拟电压、PWM以及Z轴按压检测
- 独立输出接口: : I2C, SSI, ABZ,UVW, 模
-
- 支持最高转速55,000 转/分钟
-
- 角度输出的系统延时<5 us
-
- 增量ABZ输出支持1~1024脉冲/圈,任意整
数分辨率客户可编程
- 增量ABZ输出支持1~1024脉冲/圈,任意整
-
- 增量UVW输出支持1~16对极,任意整数对
极客户可编程
- 增量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);
}
文章评论