用数学公式和生活常识两种方式彻底讲透。
📐 1. 数学上是怎么算的?
在数学里(Simulink 的 mod 模块也是按这个逻辑),取模运算的公式是:
a mod n = a - n * floor(a / n)
其中 floor() 是向下取整(往负无穷大方向取整)。
把 -200 和 4000 套进去:
- -200 / 4000 = -0.05
- floor(-0.05) = -1(注意:向下取整,-0.05 变成 -1,不是0!)
- -200 - 4000 * (-1) = -200 + 4000 = 3800
所以,数学上 -200 mod 4000 = 3800。
🛣️ 2. 生活常识怎么理解?
想象一个单圈刻度尺,长度是 4000,头尾相连变成一个圆环。
刻度是 0, 1, 2, ..., 3999,然后马上又接回 0。
现在你的位置在 0。
-200 意味着你要倒着往回走 200 步。
你退 1 步到了 3999,退 2 步到了 3998......
退 200 步,你到了哪里?4000 - 200 = 3800。
所以,-200 和 3800 在这个 4000 长度的圈里,是同一个物理位置。
就像钟表上的时间:-1小时 和 11点 是一回事。
⚠️ 3. 超级大坑:C语言和Simulink的区别
这里有一个你生成代码后必须注意的死穴:
· Simulink 的 Math Function (mod) 模块:按数学定义输出 3800(结果永远是正数,与除数4000同号)。
· C 语言的 % 运算符(取余):-200 % 4000 结果是 -200!因为 C 语言的取余结果是跟着被除数的符号走的。
这就是为什么我强烈建议你在最右边的 Sum (+ -) 后面加一个 mod 4000 模块。
因为如果你不加,Simulink 算出来 -200,直接丢给后面的 Gain (0.00025),就会变成 -0.05。接着算电角度可能是负的(比如 -0.314 弧度)。虽然 sin(-0.314) 和 sin(5.97) 数学上等价,但很多 FOC 的 Park 变换模块里做了 0~2π 的限幅判断,遇到负数可能会直接输出 0,导致电机抽搐。
加上这个 mod 4000,你输出的永远是 0~3999 的正整数。后面 Gain(0.00025) 算出来就是 0~1,再乘 2π 就是 0~6.28,最后再 mod 2π,完美闭环。
一句话总结: -200 mod 4000 = 3800,这是为了把负数的相对位置,掰回单圈 0~3999 的正向刻度上,保证下游算法绝对不会因为符号问题翻车