一、项目描述
ADMT4000是一款高精度磁性角度传感器,广泛应用于工业自动化、机器人关节角度检测、电机转子位置测量等领域。该传感器具有绝对角度和相对角度测量功能,支持多圈计数,适用于需要精确角度测量的应用场景。
本项目基于带屏十二指神探开发板(一种基于RP2040微控制器的开发平台),实现了ADMT4000角度传感器的驱动开发、复位校准功能以及实时角度数据显示。通过外接复位电路实现传感器的角度零位校准,确保测量精度。。这套程序不仅能够准确读取旋转圈数及角度数据,还能将这些数据实时、清晰地呈现在彩色LCD屏幕上,为用户提供直观、便捷的数据查看体验。这一驱动程序的开发至关重要,它直接关系到能否准确捕获传感器输出的相关数据。借助优秀的开发平台进行的彩屏可视化展示,使得用户能够更加直观地了解旋转圈数及角度的变化情况。
方案设计:

二、硬件介绍
传感器:ADMT4000传感器板
ADMT4000 是一种磁转数传感器,即使在设备断电时也能够记录磁系统的旋转次数。通电时可以查询该套件,以报告系统的绝对位置。绝对位置通过串行外设接口 (SPI) 报告。ADMT4000 最多可计数 46 圈外部磁场,以顺时针 (CW) 方向递增绝对位置计数。该套件包括三个磁传感器,一个用于计数系统旋转次数的巨磁电阻(GMR)转数计数传感器,一个 GMR 象限检测传感器和一个各向异性磁阻(AMR)角度传感器。AMR 角度传感器与 GMR 象限检测传感器结合使用,可确定系统在 360° 范围内的绝对位置。将 GMR 转数计数传感器输出与 AMR 角度传感器输出相结合,该套件就能以高角度精度报告系统的位置。
开发平台:
带屏版的12指神探,它是在原板基础上,配备了一块240*240分辨率的LCD彩屏以及两个可程控按键和一个拨轮,丰富了人机交互功能,方便信息观察、界面切换等使用方式。此外还配备了白色外壳,精心设计的包装不仅使板卡日常使用时更加美观也便于板卡的站立以及使用安全。
三、硬件设计
结构设计:这里主要参考的是42步进电机实物的尺寸,尽量避免结构上的干涉,转动轴上设计了一个磁铁的载体,有与传感器板子的结构限制,只能通过粘接的方式实现连接。
整机连接效果如下:
四、软件流程及代码说明
采集现实流程图:
调用相应的库文件,然后配置驱动接口(屏驱动、admt4000驱动),循环采集admt4000以及刷新显示,如下图:
这里我们主要实现的是屏幕的基本控制与显示功能,传感器的接口配置与基本控制,再到数据的基本采集,然后实现数据与屏幕显示的关联。下面详细介绍一下ADMT4000驱动文件的内容,主要包括SPI接口的基本关联以及数据交互的函数。在此基础上,进行应用函数的基本设计,主要包括传感器读数据与写数据函数的关联,以及数据的读取和处理。具体来说,SPI接口的基本关联涉及初始化SPI通信协议,配置时钟极性、相位和数据位宽等参数,确保与ADMT4000传感器的正确通信。数据交互函数则负责实现数据的发送和接收,包括读取传感器返回的数据和向传感器发送控制指令。应用函数的设计则进一步封装了这些基本操作,使得用户可以更方便地调用传感器读数据与写数据的功能,包括对采集到的数据进行处理,如格式转换等,以满足实际应用的需求。
复位操作是通过按键进行的启动,
驱动文件如下:
import time
from machine import Pin, SPI
class ADMT4000:
def __init__(self, spi_bus, cs_pin):
self.spi = spi_bus
self.cs = Pin(cs_pin, Pin.OUT)
self.cs.value(1)
# Reset circuit pins - initialized to safe state
self.coil_ps = None
self.shdn = None
self.rst = None
def init_reset_pins(self, coil_ps_pin, shdn_pin, rst_pin):
"""Initialize the reset control pins for external reset circuit."""
self.coil_ps = Pin(coil_ps_pin, Pin.OUT)
self.shdn = Pin(shdn_pin, Pin.OUT)
self.rst = Pin(rst_pin, Pin.OUT)
# Default states: safe state
self.coil_ps.value(0)
self.shdn.value(1)
self.rst.value(1)
def reset(self):
"""Execute the reset sequence for angle zero calibration.
Sequence (matching Rust):
1. RST low
2. COIL_PS high (coil enable)
3. Wait 2 seconds
4. COIL_PS low (coil disable)
5. RST high
6. Wait 20ms
7. RST low (pulse)
8. RST high (final)
"""
print("[RESET] Start reset sequence")
if self.coil_ps is None or self.shdn is None or self.rst is None:
raise RuntimeError("[RESET] Error: Reset pins not initialized")
# Step 1: RST low
self.rst.value(0)
print("[RESET] Step 1: RST=0")
# Step 2: COIL_PS high (coil enable)
self.shdn.value(1)
print("[RESET] Step 2: COIL_PS=1, waiting 2s...")
# Step 3: Wait 2 seconds for coil charge
time.sleep_ms(3000)
print("[RESET] Step 3: Coil charged")
self.coil_ps.value(1)
time.sleep_ms(20)
# Step 4: COIL_PS low (coil disable)
self.coil_ps.value(0)
print("[RESET] Step 4: COIL_PS=0")
self.shdn.value(0)
time.sleep_ms(40)
# Step 5: RST high
self.rst.value(1)
print("[RESET] Step 5: RST=1")
def _select(self):
"""Select the ADMT4000 by pulling CS low"""
self.cs.value(0)
def _deselect(self):
"""Deselect the ADMT4000 by pulling CS high"""
self.cs.value(1)
def _transfer(self, data):
"""Send and receive data over SPI"""
return self.spi.write_readinto(data, data)
def read_register(self, register):
"""Read a register value from ADMT4000"""
data = bytearray(4)
data1 = bytearray(4)
data[0] = register|0x00
data[1] = 0x00
data[2] = 0x00
data[3] = 0x00
Data1 = 0x0000
self._select()
self.spi.write_readinto(data, data1)
self._deselect()
Data1 = data1[1] << 8
Data1 |= data1[2]
return int(Data1)
def read_angle(self):
"""Read the angle register (ANGLE)"""
angle = self.read_register(0x05)
return (angle>>4)*360/4096;
def read_abs_angle(self):
"""Read the absolute angle register (ABSANGLE)"""
abs_angle = self.read_register(0x03)
TurnCnt = (abs_angle>>8)/4;
return TurnCnt
在主程序中进行循环采集和显示和按键采集操作:
while True:
# Check CENTER button for reset trigger (with debounce)
if confirm_btn.value() == 0: # Button pressed (low active)
admt.reset()
# Wait for button release to avoid repeated reset
while confirm_btn.value() == 0:
time.sleep_ms(10)
TurnCnt = admt.read_abs_angle()
angle = admt.read_angle()
display.text(font2, str(int(TurnCnt))+" ", 100, 60,st7789.GREEN)
display.text(font2, str(int(angle))+" ", 100, 100,st7789.GREEN)
time.sleep(0.01)
五、功能展示
效果展示一共包括4个测试,第一个是多圈采集和显示:

断电记忆:

断电运动数据记忆:
复位操作:

六、心得体会
该传感器性能卓越,表现极为亮眼。在数据测量的专业领域中,它展现出了非凡的稳定性与可靠性,为各类测试任务构筑了坚实的数据支撑。尤为突出的是,在相对角度数据的采集上,这款传感器实现了360°无死角的全方位精准采集。此款传感器凭借其独特优势——断电记忆功能,尤其是多圈的记忆功能可以说是市场上的独一份,非常不错的设计,在机器人领域的应用会非常有优势。