元驭机器人元驭机器人Hall Lab / 教学 Wiki
本页目录 11 个小节

固件结构

本页讲解仓库内 2026-10-27 的源码快照。原工程后来更新了直线算法及磁铁状态处理,尚未同步到这里;查看其他版本时请以对应源码为准。

我们先跟着三路 ADC 看一下代码:hall_line_read() 把它们换算成直线位置,hall_encoder_read() 用它们计算单圈角度。两种算法共用采样和 RS485,校准参数与计算方法不同。

先看直线部分,配合实物完成校准与测量,然后再看角度算法。

电路、机械和算法

  • 传感器感受局部磁场,输出模拟电压;它本身并不知道“关节转了几度”。
  • 机械结构让磁场随角度或位置有规律地变化。磁铁的充磁方向、气隙、偏心和 PCB 排布都是测量系统的一部分。
  • 解算算法用三路电压反推位置。PCB 构型改变以后,必须选择对应算法;仅仅换显示单位没有作用。

数据怎样流动

磁铁相对 PCB 运动
    ↓
U1 / U2 / U4 模拟输出
    ↓ PA0 / PA1 / PA4
ADC 规则组顺序扫描 + 64 次过采样平均
    ↓ DMA_CH0 循环写入 uint16_t[3]
直线算法 hall_line_read() / 角度算法 hall_encoder_read()
    ↓ 原码、位置、幅度、状态位
RS485 协议响应或主动上报 → Python 上位机 / 机器人主机
    └ RTT 调试输出

采样实现见 hall_encoder.c,测量模式选择见 main.c。

动画仅说明采样、计算和通信的先后关系,不代表实际时序或采样率。

从这些文件读起

  1. main.c:初始化与主循环。初始化 SysTick、RTT、状态灯、ADC、RS485;随后持续读取当前类型的结果并处理协议。
  2. hall_encoder.c:先只看 ADC 与 DMA 的共享采样层;文件名带 encoder,但直线模式也依赖它。
  3. hall_line.c:基线、相邻信号比值、直线位置、校准与零点。读完再回到 hall_encoder.c 的角度部分。
  4. rs485_proto.c:命令执行、配置保存、数据打包与上报。协议字段定义集中在 rs485_proto.h。
  5. systick.c 与 gd32e23x_it.c:毫秒时基与 USART 接收中断。

这是无 RTOS 的循环式应用。SysTick 提供 1 ms 软件时基,USART 接收通过中断进入协议缓冲区,ADC 转换由硬件持续运行。RTT 每 50 ms 打印一次,PB4 每 500 ms 翻转一次,因此完整亮灭周期约 1 s;这些时间都不能当作 ADC 更新率。依据:main.c、systick.c。

ADC 和 DMA

U1、U2、U4 分别进入 PA0/ADC_IN0、PA1/ADC_IN1、PA4/ADC_IN4。三个通道按这个顺序扫描,采样时间配置为 ADC_SAMPLETIME_55POINT5,DMA 通道 0 循环写入三项缓冲区。固件尝试开启 IRC28M 并选用其二分频作为 ADC 时钟;稳定等待失败时退回 APB2 四分频。依据:hall_encoder.c。

64 倍过采样右移 6 位,相当于硬件平均,输出仍是 12 位、0…4095。平均能减小部分随机噪声,也会影响响应速度。注释中的“1~2 个码”缺少测量记录,需复测。依据:hall_encoder.c、hall_encoder.h。

系统时钟配置为 __SYSTEM_CLOCK_72M_PLL_IRC8M_DIV2,即 72 MHz。构建目标是 GD32E230,使用 Cortex-M23、Thumb 和软件浮点参数;实际时钟和处理速度仍需测量。依据:system_gd32e23x.c、工具链文件。

直线位置怎么算

默认物理顺序是 U1、U2、U4,相邻间距 10 mm;对应坐标为 −10、0、+10 mm,正方向朝 U4。固件扣掉各路零磁场基线,选择绝对值最大的通道作为峰值;若峰为负,就把三路一起反号,因此主磁极翻转后仍使用同一正峰模型。依据:hall_line.h、hall_line.c。

算法假定局部磁场幅值可用一个高斯形状近似:

B(xi) ≈ A exp(−(xi − x)² / (2σ²))
x = (xi + xj)/2 + σ²/(xi − xj) × ln(Bi/Bj)

其中 xi、xj 是峰值与较强相邻通道的位置,σ 描述磁场曲线的有效宽度。默认 σ=8 mm,可配置 2…30 mm。它不是传感器间距、磁铁直径或自动测得的距离,需要在固定气隙和磁铁下通过参考位置拟合。实现采用 Q16 对数查表与整数运算。依据:hall_line.c、hall_line.h。

没有可用正相邻信号,或相邻值小于峰值的 1/8 时,算法退回峰值通道的坐标;若峰值在端部,同时置 OUT。插值结果超出 ±15 mm 时会钳位并置 OUT。±15 mm 是内部限幅,减机械零点后显示范围会平移;可用行程需结合误差和状态位实测。依据:hall_line.c。

当前算法只估计单个磁铁附近的位置,没有磁栅周期识别、磁极计数、跨段拼接或长行程绝对编码。

换成编码器时改什么

直线位置和参考尺对比完成后,我们再换上编码器 PCB,逐项看一下哪些部分可以继续用,哪些需要改:

  • 保留采样层:相同的 PA0/PA1/PA4、ADC 扫描与 DMA,仍读取 U1/U2/U4 三个原码。
  • 保留通信层:设备号、CRC、查询、上报与校准命令仍可复用;先读取类型,再解释数值和校准字段。
  • 改变物理关系:直线板的三颗传感器观察沿空间移动的局部场强;旋转板需要三路随角度呈约 120° 相差的周期信号。
  • 改变解算器:hall_line_read() 用基线、相邻比值和 σ估计位置;hall_encoder_read() 用通道偏置、相对增益和二维向量相位估计角度。两个求解器独立,不能用同一套标定参数互换。
  • 改变校准动作:直线先拿走磁铁取基线;角度保留磁铁并转满一圈采极值。机械零点都是后续的坐标平移,角度还要处理 360° 环绕。

换板后先读取设备信息,用 SET_PROFILE (0x07) 选择角度或直线,再按新模式重新校准、设零、重启验证。改变类型时会清除旧校准和零点并写入 Flash;仅重新烧录通常保留配置,因此换板后不能假定程序会自动识别 PCB。依据:rs485_proto.c。

单圈角度怎么算

源码约定从上往下看逆时针为正,U1、U2、U4 的测量相位依次为 0°、120°、240°。在理想模型中,扣掉直流偏置后的三路信号为:

s0 = A cos θ
s1 = A cos(θ − 120°)
s2 = A cos(θ − 240°)

先慢转磁铁,看实际波形是否接近这个模型,再检查方向与敏感轴。旋转安装约定见 hall_encoder.h。

算法先按已保存的偏置与 Q12 增益修正每一路;若尚未校准,则直接使用原码。随后都减去三路平均值,再计算:

alpha = 2 × s0 − s1 − s2       ≈ 3A cos θ
beta  = √3 × (s1 − s2)        ≈ 3A sin θ
θ = atan2(beta, alpha)

实现使用 √3 ≈ 887/512、整数近似反正切和整数平方根。角度归一化并减去机械零点后返回 0…35999,编码单位 0.01°;幅度约为向量长度除以 3,单位是 ADC 计数。依据:hall_encoder.c。

角度只在一圈内,没有固件圈数累计、掉电圈数保存或直接转速输出。主机如何处理回绕、超时和减速比,见机器人接入。

同一字段,两种单位

hall_sample_t 定义于 hall_encoder.h:raw[3] 是原码,amplitude 是信号幅度,angle_cdeg 是位置数值。

同一个 angle_cdeg 在角度模式表示 0.01°,在直线模式表示有符号 0.01 mm。通信和应用程序必须同时读取设备类型;直接把这个字段始终解释为角度,会得到看似正常但单位错误的数据。依据:hall_line.h、rs485_proto.h。

启动和保存配置

未发现有效 Flash 配置时,设备号为 1、115200 baud、8N1、主从查询模式、上报周期参数 20 ms、角度模式、零点为 0、校准无效。角度模式初始增益是 4096,即 Q12 的 1 倍。上报周期参数存在,并不表示默认会自动上传。依据:rs485_proto.c、rs485_proto.c。

切到直线模式时,基线尚未校准就按 2048 解算,σ设为 8000 µm。改变测量类型会清除两种模式的零点与校准,并保存配置;它不会保留两套可随时来回切换的独立完整校准。依据:rs485_proto.c。

32 字节配置含校验码,放在 0x08007C00。链接脚本只向程序分配前 31 KB Flash,避免占用最后 1 KB 配置页。保存过程擦页、逐字写入,期间关中断。不要把写 Flash 命令放进每周期控制循环;目前没有磨损均衡或双副本掉电提交。依据:rs485_proto.c、链接脚本。

改代码前检查

  • 三路采样:hall_encoder_copy_raw() 只是依次读三项 volatile DMA 内存,没有完整扫描帧锁存、序号或时间戳。DMA 可能在复制途中更新某一路,高速运动时要验证跨通道时差,后续可用双缓冲或扫描完成事件建立一致快照。依据:hall_encoder.c。
  • 通道顺序:HALL_LINE_LEFT/MID/RIGHT 的注释建议改下标,但当前计算并没有用 LEFT/RIGHT 重排 raw;s_pos_um 仍固定对应 raw[0…2]。改 PCB 排列时,应检查采样映射与位置数组,不能只改这三个宏。依据:hall_line.h、hall_line.c。
  • 状态位:CAL_VALID 只说明校准数据被接受;WEAK 只比较幅度;OUT 由前述插值和限幅条件设置。没有单独的饱和检测、磁铁脱落诊断或误差上界。无磁场仍可能得到一个数,必须检查状态。详见校准与测量。
  • 处理时间:持续采样、RTT 打印、协议发送和 Flash 保存共享有限 MCU 资源,源码没有每帧时间戳或最坏响应时间报告。软件上报周期不等于端到端延迟、传感器带宽或闭环控制周期。

读完可以试什么

刚开始可以先让磁铁静止,记录三路原码,然后移动或旋转磁铁,看哪一路先增大。再分别完成两种校准,对照着看“电压偏置”和“机械零点”的区别。

如果已经做过机器人项目,可以增加样本序号与采样时间戳,在主机上计算环绕后的角速度,再对照外部参考测量延迟和误差。把这些数据记录下来,再判断它适合哪一种关节、滑台或夹爪实验。