一、项目介绍:
本项目使用ADMT4000模块来检查磁铁的旋转圈数和角度,通过RP2040读取测量到的数据,在屏幕上使用LVGL绘制当前的角度,显示当前的速度、圈数和角度。
二、硬件介绍:
ADMT4000模块:是一个多圈磁角度(圈数)传感器模块。主芯片为ADMT4000芯片,这 是一种磁转数传感器,即使在设备断电时也能够记录磁系统的旋转次数。通电时可以查询该套件,以报告系统的绝对位置。绝对位置通过串行外设接口 (SPI) 报告。ADMT4000 最多可计数 46 圈外部磁场,以顺时针 (CW) 方向递增绝对位置计数。
带显示屏的RP2040:这是一个基于RP2040微控制器、搭配240*240分辨率的LCD彩屏的主控模块。
ADMT4000模块背面使用热熔胶粘了一个无刷电机,无刷电机轴的一端粘贴了一块径向磁铁,通过拨动无刷电机带动磁铁的旋转,ADMT4000模块读取磁力信息,获取电机的旋转角度和圈数。

三、任务选择:
选择任务为 任务一:旋转方向与转速检测。
手动旋转磁铁,通过串口实时识别旋转方向(正转/反转)并计算转速。
任务要求
- 读取 ADMT4000 角度数据,判断当前旋转方向(正转/反转),串口实时显示
- 根据角度变化量和时间计算转速(转/秒或度/秒),串口实时显示
- 静止时显示转速为 0,旋转时实时更新
- 在 46 圈范围内验证方向和转速检测的正确性
四、设计思路:

ADMT4000模块因为断电依然能够记录旋转圈数,所以在系统工作开始,先将ADMT4000模块重置,再去读取模块的圈数和角度。ADMT4000模块重置后圈数并不是回归到0,而是停留在43圈,此时电机顺时针旋转为负,逆时针为正。屏幕和串口同时显示圈数、角度和转速。
五、任务实现:
这次任务使用microphone来实现。rp2040绘图部分使用Lvgl来绘图。官方提供的rp2040的mpy固件并不包含Lvgl,我在电子森林中找了一个含Lvgl的固件进行烧录。
首先系统初始化SPI0总线连接屏幕、SPI1总线连接ADMT4000。
import struct
import admt4000 as admt4000
from machine import Pin, SPI, ADC, PWM
import time
import sys
sys.path.append('.')
from st77xx import St7789
if 0:
import rp2_dma
rp2_dma=rp2_dma.DMA(0)
else:
rp2_dma=None
import lvgl as lv
lv.init()
st7789_res = 0
st7789_dc = 1
st7789_cs = 4
spi_sck=Pin(2)
spi_tx=Pin(3)
spi0=SPI(0,baudrate=24000000, phase=1, polarity=1, sck=spi_sck, mosi=spi_tx)
lcd=St7789(rot=0,res=(240,240),spi=spi0,cs=st7789_cs,dc=st7789_dc,bl=None,rst=st7789_res,rp2_dma=rp2_dma,factor=8)
scr = lv.screen_active()
scr.set_style_bg_color(lv.color_hex(0x000000), 0) # 设置黑色背景
#ADMT4000设置
spi1_cs=25
spi1_sck=Pin(26)
spi1_tx=Pin(27)
spi1_rx=Pin(28)
接下来先给ADMT4000做个复位。根据群里老师的指导:先拉低RST引脚复位设备,COIL_RS和SHDN平时都是低电平的,先拉高SHDN引脚,使能29V电源,大概200ms后才可以用高电平脉冲触发COIL_RS引脚。
#开始前,复位
coil_rs=Pin(22, Pin.OUT)
shdn=Pin(23, Pin.OUT)
rst=Pin(24, Pin.OUT)
rst.value(0)
time.sleep(0.01)
rst.value(1)
shdn.value(1)
time.sleep(0.2)
coil_rs.value(1)
shdn.value(0)
coil_rs.value(0)
然后使用Lvgl中的弧形进度条控件来展示电机当前的角度。使用3个标签,分别展示角度、圈数和转速。
# ========== 创建圆弧形进度条 ==========
arc = lv.arc(scr)
arc.set_size(240, 240) # 设置圆弧大小
arc.align(lv.ALIGN.CENTER, 0, 0) # 居中对齐,稍向上偏移
arc.set_bg_angles(0, 360) # 背景圆弧角度(270°圆弧)
arc.set_angles(360 - int(angle), 360 - int(angle))
arc.set_value(360 - int(angle))
# ===== 修正:使用正确的样式 API =====
arc.set_range(0, 360)
arc.set_style_bg_color(lv.color_hex(0x333333), 0) # 背景圆弧颜色(灰色)
arc.set_style_arc_color(lv.color_hex(0x00FF00), 0) # 前景圆弧颜色(绿色)
arc.set_style_bg_opa(lv.OPA.COVER, 0)
arc.set_style_arc_width(20, 0) # 圆弧宽度
# ========== 创建显示标签 ==========
label_angle = lv.label(scr)
label_angle.set_text( str(int(angle)))
label_angle.align(lv.ALIGN.CENTER, 0, -35) # 居中显示
label_angle.set_style_text_color(lv.color_hex(0x00FFFF), 0) #
label_angle.set_style_text_font(lv.font_default(), 0)
label_turn = lv.label(scr)
label_turn.set_text( str(int(TurnCnt)))
label_turn.align(lv.ALIGN.CENTER, 0, -20) # 居中显示
label_turn.set_style_text_color(lv.color_hex(0xFF00FF), 0) #
label_turn.set_style_text_font(lv.font_default(), 0)
label_speed = lv.label(scr)
label_speed.set_text( str(int(TurnCnt)))
label_speed.align(lv.ALIGN.CENTER, 0, 10) # 居中显示
label_speed.set_style_text_color(lv.color_hex(0xFFFFFF), 0) #
label_speed.set_style_text_font(lv.font_default(), 0)
这里转速使用“圈/秒”单位。计算方法很简单,就是取两次获得的圈数的差值,除以时间的差值即可获得转速值。获得数据后更新进度条的状态,更新标签信息,并且通过串口输出当前的角度、圈数、速度信息。
lv.task_handler()
TurnCnt = admt.read_abs_angle()
angle = admt.read_angle()
speed=(TurnCnt-oledturn)*1000/(time.ticks_ms()-oledtime)
oledturn=TurnCnt
oledtime=time.ticks_ms()
print("圈数:",TurnCnt," 当前角度:",angle," 旋转速度:",speed,"圈/秒")
# 更新圆弧进度
arc.set_angles(360 - int(angle), 360 - int(angle))
arc.set_value(360-int(angle))
# 更新百分比文字
label_angle.set_text(str(int(angle)))
label_turn.set_text( str(int(TurnCnt)))
label_speed.set_text("speed:"+str(round(speed,1)))
time.sleep_ms(100) # 100ms 更新一次
六、效果展示:
开机复位后显示43圈。

电机旋转到0度附近。

90度附近。

180度附近。


串口显示。

七、心得体会:
ADI的这款磁转速传感器绝对属于非常顶尖的存在,能够断电记录磁铁旋转圈数,大大开阔了我的视野。非常感谢这次活动,让我们有机会可以接触到更多先进的器件。借此活动机会,体验了一把在mpy下使用lvgl的过程,学习到了更多的知识。