计算和生成正弦/余弦查找表(LUT)

计算和生成正弦/余弦查找表(LUT)主要分为以下几个步骤:


1. 确定分辨率(表长度)

  • 设你要做 N 细分(microsteps),则表长通常取 N(也可以取 N+1,方便首尾相接)。
  • 例如要 256 细分,就令 TABLE_SIZE = 256

2. 计算角度增量

每一个表项对应的电角度增量为:

\[ \Delta\theta = \frac{2\pi}{\text{TABLE_SIZE}} \]


3. 逐项计算浮点正余弦值

对每个索引 \(i = 0,1,\dots,\text{TABLE_SIZE}-1\),计算:

\[ \theta_i = i \times \Delta\theta, \quad \text{sinTbl}[i] = \sin(\theta_i), \quad \text{cosTbl}[i] = \cos(\theta_i). \]

示例(伪码):

for (int i = 0; i < TABLE_SIZE; i++) {
    float theta = 2.0f * M_PI * i / TABLE_SIZE;
    sinTbl[i] = sinf(theta);
    cosTbl[i] = cosf(theta);
}

4. 映射到定时器/PWM 占空比

单片机上用的是整数占空比,一般把 −1…+1 映射到 0…PWM_MAX:

\[ \text{CCR_value} = \bigl(\text{wave} + 1.0\bigr)\times \frac{\text{PWM_MAX}}{2} \]

其中:

  • wave 是上一步得到的 sinTbl[i] 或 cosTbl[i];
  • PWM_MAX 是定时器的自动重装载值(ARR),比如 1000、4095、65535 等。
uint16_t duty = (uint16_t)((sinTbl[i] + 1.0f) * 0.5f * PWM_MAX);

5. 数据类型与存储优化

  • 浮点表:如果 MCU 支持浮点运算,可直接存 float

  • 定点表:如果要节省 Flash,可把正余弦值乘以一个定点因子(如 32767),存为 int16_t

    \[ \text{sinQ}[i] = \text{round}\bigl(\sin(\theta_i)\times 32767\bigr) \]

    然后在运行时再通过位移或乘法映射到占空比。


6. 首尾相连与插值

  • 通常第 0 项和第 N 项都对应角度 0°(或 360°),为了避免重复存,可只存前 N 项。
  • 如果需要更高精度,也可以在运行时做线性插值,但大多数应用直接用查表即可。

7. 完整示例

// 全局或静态定义
#define TABLE_SIZE 256
#define PWM_MAX    4095
int16_t sinTblQ[TABLE_SIZE];
int16_t cosTblQ[TABLE_SIZE];

// 初始化时填充定点查表
void InitLUT(void) {
    for (int i = 0; i < TABLE_SIZE; i++) {
        float theta = 2.0f * M_PI * i / TABLE_SIZE;
        sinTblQ[i] = (int16_t)(sinf(theta) * 32767);
        cosTblQ[i] = (int16_t)(cosf(theta) * 32767);
    }
}

// 在输出时:
uint16_t GetPWMDuty(int idx, int16_t *tblQ) {
    // 先转换到 0…1,再乘 PWM_MAX
    return (uint16_t)(( (tblQ[idx] + 32767) / 65535.0f ) * PWM_MAX);
}

// 在输出时,如果你想获取 sin 相的 PWM 占空比,就这样调用:
uint16_t dutyA = GetPWMDuty(idx, sinTblQ); // A 相占空比
// 获取 cos 相:
uint16_t dutyB = GetPWMDuty(idx, cosTblQ); // B 相占空比


然后再把这两个值dutyA 和 dutyB分别写入对应的定时器比较寄存器(CCR),驱动 A4950 的两路桥臂输出相应电流,从而合成角度为 θ = idx×(2π/TABLE_SIZE) 的磁场矢量。
这样,你就能按任意细分数 N 动态生成对应的正/余弦查找表,并映射到定时器占空比,用于精确微步(Microstepping)控制。

推荐实践

硬件选型:

  • 使用 STM32 的高级定时器(TIM1 或 TIM8),它们通常具备:
    • 4 路独立 PWM 输出,或
    • 2 路互补输出(适合带死区控制的驱动)
  • 能够满足控制一台双极步进电机所需的 4 路桥臂驱动。

软件实现:

  1. 建立查表

    • 生成一个标准的 sin/cos 查找表(定点或浮点均可);
    • 可共用一组表,通过相位偏移来获得两相驱动。
  2. PWM 输出控制

    • 使用 DMA 或中断循环将占空比 dutyA+dutyA–dutyB+dutyB– 分别写入定时器比较寄存器:
      TIMx->CCR1 = dutyA_plus;
      TIMx->CCR2 = dutyA_minus;
      TIMx->CCR3 = dutyB_plus;
      TIMx->CCR4 = dutyB_minus;
      
  3. 主控只需控制步进索引

    • 通过简单的索引移动控制相位旋转(例如步进方向):
      idx = (idx ± 1) % TABLE_SIZE;
      
    • 其余部分交由 DMA 自动完成,占空比更新稳定高效。

✅ 这样,你可以实现高精度、高细分、低抖动的步进电机控制系统,尤其适合微步驱动(Microstepping)。

posted @ 2025-07-23 09:58  阿坦  阅读(117)  评论(0)    收藏  举报