foc 相关算法
MTPA
为什么要用 MTPA
当电机采用 id=0 的控制策略,这种控制方法忽略了磁阻转矩的作用,电磁转钜方程如下:
\[
\tau _e = \frac{3}{2}p[k_e \cdot i_q + (L_d - L_q)\cdot i_d \cdot i_q]
\]
转矩分为永磁转矩 Tr 和磁阻转矩 Tm,而 id=0 只剩下 Tr。这会导致电流的利用率不高,系统的效率降低。所以 id=0 的控制比较适用于隐极式电机(Ld=Lq),而对于凸极式电机并不最优,所以需要重新考虑控制策略。
推导过程
电动机电压方程:
\[
\begin{aligned}
U_d = rI_d - L_qI_q\omega_e \\
U_q = rI_q + k_E\omega_e + L_dI_d\omega_e
\end{aligned}
\]
那么电动机消耗对有功功率为:
\[
P = \frac{3}{2}(U_dI_d + U_qI_q)
\]
将电动机方程代入功率方程得:
\[
P = \frac{3}{2} r (I_d^2 + I_q^2) + [k_EI_q + (L_d - L_ ...
FOC 原理
物理学基础概念
左手定则
将左手的食指,中指和拇指伸直,使其在空间内相互垂直。食指方向代表磁场的方向(从 N 级到 S 级),中指代表电流的方向(从正极到负极),那拇指所指的方向就是受力的方向。可用于判断安培力(运动导体所受到的力)和洛伦兹力(运动电荷所受的力)。
右手定则
伸开右手,使拇指与其余四个手指垂直,并且都与手掌在同一平面内;让磁感线垂直于手心进入,并使拇指指向导线运动方向,这时四指所指的方向就是感应电流的方向。用于判断导体在做切割磁场时产生的电流方向。
安培定则(右手螺旋定则)
电直导线中的安培定则(安培定则一):用右手握住通电直导线,让大拇指指向直导线中电流方向,那么四指指向就是通电导线周围磁场的方向; 通电螺线管中的安培定则(安培定则二):用右手握住通电螺线管,让四指指向电流的方向,那么大拇指所指的那一端是通电螺线管的 N 极。
安培力定则
安培力: 以电流强度为 I 的长度为 L 的直导线,置于磁感应强度为 B 的均匀外磁场中,则导线受到的安培力的大小为:
\[
F = IBLsin\alpha
\]
式中α为导线中的电流方向与 B 方向之间的夹角。 设定两 ...
openshoe 算法
概述
openshoe 是一种通过惯性测量元件 (IMU) 来对运动进行积分以得到路径的控制算法。算法的核心是 ZUPT(零速度更新算法),在只有 IMU 惯性测量元件的情况下获得路径只能通过对加速度积分得到速度,再将速度对时间进行积分得到路径,这里如果不能对积分得到的速度进行有效的校正那么这个速度误差会时刻对时间进行积分,导致路径完全失效,因此必须采取有效手段及时对速度误差进行校正以得到较为准确的路径信息,ZUPT 就是一种基于检测零速度进行路径积分校正的算法。该算法的关键是对零速度的准确检测。
零速度检测算法
openshoe 采用广义似然检测算法对零速度进行检测,以判断 IMU 是否处于静止状态。
广义似然检测原理
要理解广义似然检测原理需要先熟悉几个概率论中相关的概念,详细如下:
条件概率公式
设 A 与 B 为样本空间 Ω 中的两个事件,其中 P(B)>0。那么在事件 B 发生的条件下,事件 A 发生的条件概率为:
\[
P(A|B) = \frac{P(AB)}{P(B)}
\]
贝叶斯公式
\[
P(A|B) = \frac{P(B|A) P(A)}{P(B)}
...
IMU 误差模型及校准
传感器误差模型
对于理想的 IMU 三轴加速度计两两正交,构成一个正交的三轴直角坐标系,加速度计每一轴单独测量该轴的加速度,而陀螺仪则测量该轴的角速度。在实际的真实 IMU 中由于制造工艺的误差,三个坐标轴不可能完全两两正交,加速度计与陀螺仪的坐标系也不会完全重合,并且单个传感器也不是完全精确的。在实际器件中将数字输出量转化为实际物理量的 scale 参数在不同轴上是不同的,但是设备生产商都会提供一个默认的 scale 参数用于转换所有轴的数据,而且数字量的输出还会受到零偏(传感器在静止情况下也会有微小量的输出)的影响,这些就是造成 IMU 传感器的系统误差。
我们取实际器件的加速度计坐标系为 AF, 陀螺仪坐标系为 GF,根据 AF 和 GF 分别建立对应的正交坐标系 AOF 和 GOF,其建立约束为
AOF 的 x 轴与 AF 的 x 轴重合。
AOF 的 y 轴位于 AF 的 x 与 y 轴的平面中。
对于 GOF 的建立约束与 AOF 的约束类比建立。最后再建立一个正交机体坐标系 BF,BF 通常与 AF 和 GF 之间有一个小角度的偏差。在非正交坐标系(AF 或 GF)中 ...
IMU 姿态解算
IMU 通过加速度计解算姿态角
通过三角函数可以将加速度计三个轴的角速度解算为姿态角,其中 \(\alpha\) , \(\beta\) 和 \(\gamma\)( \(\gamma\) 是 z 轴与重力加速度之间的夹角)与三个轴之间的关系如上图所示:
\[
\begin{aligned}
&\beta = arcsin(\frac{a_x}{g}) \\
&\gamma = arcsin(\frac{a_y}{g})
\end{aligned}
\]
其中重力加速度 $ g $ 的取值使用三轴角速度的矢量和即:
\[
g = \sqrt{a_x^{2} + a_y^{2} + a_z^{2}}
\]
将 g 的值带入上式可以得到:
\[
\begin{aligned}
&\beta = arctan(\frac{a_x}{\sqrt{a_y^{2} + a_z^{2}}}) \\
&\gamma = arctan(\frac{a_y}{\sqrt{a_x^{2} + a_z^{2}}})
\end{aligned}
\]
其中 α 为俯仰角 pi ...
Buildroot 常见编译错误记录
openwrt 编译错误
you should not run configure as root (set FORCE_UNSAFE_CONFIGURE=1 in environment to bypass this check)
解决方法:
1export FORCE_UNSAFE_CONFIGURE=1
切换 gcc 版本
12sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-9 20 --slave /usr/bin/g++ g++ /usr/bin/g++-9sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-11 30 --slave /usr/bin/g++ g++ /usr/bin/g++-11
buildroot 报错:
c-stack.c:55:26: error: missing binary operator before token
12将 buildroot 的 host-m4 版本升级一下就可以使用 ...
Buildroot
Buildroot 配置
交叉编译工具链
Buildroot 为交叉编译工具链提供两种解决方案:
内部工具链后端,在配置界面中调用“Buildroot toolchain”
外部工具链后端,在配置界面中调用“External toolchain“;有三种方式来使用外部工具链:
让 Buildroot 基于预定义的外部工具链 profile 自动下载、安装。在 Toolchain 中选择已有的 profile 即可
为 Buildroot 手动指定提前安装好的、预定义了 profile 的工具链。在 Toolchain 中选择 profile 后,反选掉 Download toolchain automatically 并在 Toolchain path 中填写已有工具链路径即可
使用定制的外部工具链。通常用于使用 crosstool-NG 或 Buildroot 生成的已有定制工具链。选择 Toolchain 列表中的 Custom toolchain ,然后填写 ...
RTOS 的设计
何为实时性?
RTOS 的实时性该怎么理解呢?快速?确定性?
从中断控制器视角看实时性
我们知道一般都是 Cortex-M 跑 RTOS,Cortex-A 很少跑 RTOS,一般都是跑 Linux、Android 这些非实时系统。如果单纯从速度来看 A 核在高主频加持下一定会具有更快的速度才对呀,那 M 核的竞争力在哪里呢?实际上这就是 A 核和 M 核在设计上的两个不同方向的取舍。
首先我们看 NVIC 中断控制器的设计:
中断延迟波动很小:NVIC 支持中断嵌套,这样即使当前中断在处理中且非常耗时也没关系,因为可以通过高优先级的中断来响应更紧急的事件,这样中断延迟就不依赖与中断处理时间了,从设计上保证了延迟的确定性。
中断延迟小:NVIC 在不同的中断会跳转到不同地址运行,且可以直接在硬中断上下文中执行中断程序,这样整个 pipeline 很短,且 NVIC 还支持尾链这个概念进一步降低延迟(当高优先级的 ISR 抢占低优先级 ISR 时,处理器会跳过上下文保存和恢复,直接处理第二个 ISR,没有任何额外的开销)。通常 NVIC 中断响应时间在十几到几十 ns 之间。
NVIC ...
Linux Driver Tips
获取 ns 时间戳(已弃用)
1234567#include <linux/timekeeping32.h>struct timespec ts;u64 ns;getnstimeofday(&ts);ns = timespec_to_ns(&ts);
ktime accessors — The Linux Kernel documentation
可以使用 ktime_get_ns() 替代。 如果要获取 us 时间会涉及到 64bit 除法问题,会遇到如下问题:
1ERROR: modpost: "__aeabi_uldivmod" [common_drivers/drivers/usb/dwc_otg.ko] undefined!
调用 div_u64() 函数,需要 include <linux/math64.h>
1u64 tm = div_u64(ktime_get_raw_ns(),1000);
Dump Stack
12#include <asm/ptrace.h>dump_stack();
Linux 中根据函数指针 ...
Docker 常用命令
基本使用
设置开机自启动并启动 Docker-CE
12sudo systemctl enable dockersudo systemctl start docker
添加当前用户到 docker 用户组,可以不用 sudo 运行 docker
12sudo groupadd dockersudo usermod -aG docker $USER
获取 archlinux 镜像
1docker pull base/archlinux
镜像使用
列出所有镜像
1docker image ls -a
删除镜像
1docker image rm image_id
容器使用
新建容器并挂载本地目录
12345678docker run -it -v /home/carlyleliu/share/docker/ubuntu18:/share/ techliu/ubuntu /bin/bashdocker run -it -v /home/carlyleliu/share/docker/ubuntu20:/share/ ubuntu /bin/bashdocker run -it -v /hom ...