stm32进阶笔记

掩码

无人机工程关键代码

cpp 复制代码
void IMUupdate(float gx, float gy, float gz, float ax, float ay, float az)
{
  float norm;
  float vx, vy, vz;
  float ex, ey, ez;

  // 先把这些用得到的值算好
  float q0q0 = q0*q0;
  float q0q1 = q0*q1;
  float q0q2 = q0*q2;
// float q0q3 = q0*q3;
  float q1q1 = q1*q1;
// float q1q2 = q1*q2;
  float q1q3 = q1*q3;
  float q2q2 = q2*q2;
  float q2q3 = q2*q3;
  float q3q3 = q3*q3;
	
	if(ax*ay*az==0)
 		return;
		
  norm = sqrt(ax*ax + ay*ay + az*az);       //acc数据归一化
  ax = ax /norm;
  ay = ay / norm;
  az = az / norm;

  // estimated direction of gravity and flux (v and w)  估计重力方向和流量/变迁
  vx = 2*(q1q3 - q0q2);							//四元素中xyz的表示
  vy = 2*(q0q1 + q2q3);
  vz = q0q0 - q1q1 - q2q2 + q3q3 ;

  // error is sum of cross product between reference direction of fields and direction measured by sensors
  ex = (ay*vz - az*vy) ;   			 //向量外积在相减得到差分就是误差
  ey = (az*vx - ax*vz) ;
  ez = (ax*vy - ay*vx) ;

  exInt = exInt + ex * Ki;		 //对误差进行积分
  eyInt = eyInt + ey * Ki;
  ezInt = ezInt + ez * Ki;

  // adjusted gyroscope measurements
  gx = gx + Kp*ex + exInt;  	//将误差PI后补偿到陀螺仪,即补偿零点漂移
  gy = gy + Kp*ey + eyInt;
  gz = gz + Kp*ez + ezInt; //这里的gz由于没有观测者进行矫正会产生漂移,表现出来的就是积分自增或自减

  // integrate quaternion rate and normalise			//四元素的微分方程
  q0 = q0 + (-q1*gx - q2*gy - q3*gz)*halfT;
  q1 = q1 + ( q0*gx + q2*gz - q3*gy)*halfT;
  q2 = q2 + ( q0*gy - q1*gz + q3*gx)*halfT;
  q3 = q3 + ( q0*gz + q1*gy - q2*gx)*halfT;

  // normalise quaternion
  norm = sqrt(q0*q0 + q1*q1 + q2*q2 + q3*q3);
  q0 = q0 / norm;
  q1 = q1 / norm;
  q2 = q2 / norm;
  q3 = q3 / norm;

  Q_ANGLE.Z = GYRO_I.Z;//atan2(2 * q1 * q2 + 2 * q0 * q3, -2 * q2*q2 - 2 * q3* q3 + 1)* 57.3; // yaw
  Q_ANGLE.Y = asin(-2 * q1 * q3 + 2 * q0* q2)* 57.3; // pitch
  Q_ANGLE.X = atan2(2 * q2 * q3 + 2 * q0 * q1, -2 * q1 * q1 - 2 * q2* q2 + 1)* 57.3; // roll
}

b)PID控制部分源码:
void CONTROL(float rol_now, float pit_now, float yaw_now, float rol_tar, float pit_tar, float yaw_tar)
{
    u16 moto1 = 0, moto2 = 0, moto3 = 0, moto4 = 0;
    vs16 throttle;

    float rol = rol_tar + rol_now;
    float pit = pit_tar + pit_now;
    float yaw = yaw_tar + yaw_now;

    throttle = Rc_Get.THROTTLE - 1000;//油门 节流阀
    if (throttle < 0)  throttle = 0;

    PID_ROL.IMAX = throttle / 2;
    Get_MxMi(PID_ROL.IMAX, 1000, 0);
    PID_PIT.IMAX = PID_ROL.IMAX;

    PID_ROL.pout = PID_ROL.P * rol;
    PID_PIT.pout = PID_PIT.P * pit;

    if (rol_tar * rol_tar < 0.1 && pit_tar * pit_tar < 0.1 && rol_now * rol_now < 30 && pit_now * pit_now < 30 && throttle > 300)
    {
        PID_ROL.iout += PID_ROL.I * rol;
        PID_PIT.iout += PID_PIT.I * pit;
        PID_ROL.iout = Get_MxMi(PID_ROL.iout, PID_ROL.IMAX, -PID_ROL.IMAX);
        PID_PIT.iout = Get_MxMi(PID_PIT.iout, PID_PIT.IMAX, -PID_PIT.IMAX);
    }
    else if (throttle < 200)
    {
        PID_ROL.iout = 0;
        PID_PIT.iout = 0;
    }

    PID_ROL.dout = PID_ROL.D * MPU6050_GYRO_LAST.X;
    PID_PIT.dout = PID_PIT.D * MPU6050_GYRO_LAST.Y;

    PID_YAW.pout = PID_YAW.P * yaw;
    vs16 yaw_d;
    if (1480 > Rc_Get.YAW || Rc_Get.YAW > 1520)
    {
        yaw_d = MPU6050_GYRO_LAST.Z + (Rc_Get.YAW - 1500) * 10;
        GYRO_I.Z = 0;
    }
    else
        yaw_d = MPU6050_GYRO_LAST.Z;
    PID_YAW.dout = PID_YAW.D * yaw_d;

    PID_ROL.OUT = PID_ROL.pout + PID_ROL.iout + PID_ROL.dout;
    PID_PIT.OUT = PID_PIT.pout + PID_PIT.iout + PID_PIT.dout;
    PID_YAW.OUT = PID_YAW.pout + PID_YAW.iout + PID_YAW.dout;

		/*
		rol 翻滚
		pat 俯仰角
		yaw //偏航
		*/
    if (throttle > 200)
    {
			#define YAW_ADD (-30)
        moto1 = throttle + PID_ROL.OUT - PID_PIT.OUT +YAW_ADD+ PID_YAW.OUT/**/;
        moto2 = throttle - PID_ROL.OUT - PID_PIT.OUT -YAW_ADD- PID_YAW.OUT/**/;
        moto3 = throttle - PID_ROL.OUT + PID_PIT.OUT +YAW_ADD+ PID_YAW.OUT/**/;
        moto4 = throttle + PID_ROL.OUT + PID_PIT.OUT -YAW_ADD- PID_YAW.OUT/**/;
    }
    else
    {
        moto1 = 0;
        moto2 = 0;
        moto3 = 0;
        moto4 = 0;
    }
    if (ARMED)   Moto_PwmRflash(moto1, moto2, moto3, moto4);
    else         Moto_PwmRflash(0, 0, 0, 0);
}

四元数

没关系🙂 我再用更生活化的比喻来讲四元数旋转,帮你把公式和几何动作对上号。


🔄 1. 我们要解决的问题

你现在有一个点 P(1,0,0) ,它在 X 轴正方向 上。

你想让它绕 Z 轴90°

几何直觉告诉我们:转完应该在 Y 轴正方向,也就是 (0,1,0)。

问题:用四元数怎么计算这个结果?


🧩 2. 四元数就像"旋转的遥控器"

四元数 q 的公式:

q=cos⁡(θ2)+(uxi+uyj+uzk)sin⁡(θ2)q = \cos(\tfrac{\theta}{2}) + (u_x i + u_y j + u_z k)\sin(\tfrac{\theta}{2})

  • θ\theta:旋转角度

  • (ux,uy,uz)(u_x,u_y,u_z):旋转轴方向(必须是单位向量)

👉 可以把它想成一个"遥控器",按下去就能让东西绕某根轴旋转。


🧮 3. 套入具体数字

  • 旋转轴是 Z 轴,所以 u=(0,0,1)u=(0,0,1)

  • 旋转角度 θ = 90°,所以一半角度 = 45°

于是:

q=cos⁡45°+(0i+0j+1k)sin⁡45°=0.7071+0.7071kq = \cos 45° + (0i + 0j + 1k)\sin 45° = 0.7071 + 0.7071k

(就是一个有"实部"和"虚部"的数)


🟦 4. 点也要变成四元数

点 P(1,0,0),写成四元数:

p=0+1i+0j+0k=ip = 0 + 1i + 0j + 0k = i

(注意:点用"纯虚四元数"表示)


⚙️ 5. 旋转公式

旋转用这个公式:

p′=q p q∗p' = q \, p \, q^*

其中 q∗q^* 是 q 的"共轭"(把虚部取反)。

这里:

q=0.7071+0.7071k,q∗=0.7071−0.7071kq = 0.7071 + 0.7071k, \quad q^* = 0.7071 - 0.7071k


✍️ 6. 动手算一下(关键步骤)

  1. 先算 q * p:

    (0.7071+0.7071k)(i)=0.7071i+0.7071(ki)(0.7071 + 0.7071k)(i) = 0.7071i + 0.7071(ki)

    记住规则:
    i2=j2=k2=−1,ij=k,jk=i,ki=ji^2 = j^2 = k^2 = -1, \quad ij = k, \quad jk = i, \quad ki = j

    所以 ki=jki = j,得到:
    q⋅p=0.7071i+0.7071jq \cdot p = 0.7071i + 0.7071j

  2. 再乘上 q*:

    (0.7071i+0.7071j)(0.7071−0.7071k)(0.7071i + 0.7071j)(0.7071 - 0.7071k)

    经过展开化简,结果是:
    p′=jp' = j


✅ 7. 结果

p′=j⇒(0,1,0)p' = j \quad \Rightarrow \quad (0,1,0)

这和几何直觉完全一致:

点 (1,0,0) 绕 Z 轴转 90° → 变成 (0,1,0)。


🎯 最终一句话总结

四元数就是一个"旋转遥控器",

公式 p′=qpq∗p' = qpq^* 只是数学的写法,

算出来的结果,和你脑子里画的旋转效果是一模一样的。


要不要我帮你做一个动画演示图(小球在 XY 平面绕 Z 轴转 90°,同时写出 q、p、p' 的对应关系)?这样你一眼就能对上公式和几何动作。

指针

相关推荐
SunnyDays10114 小时前
在 C# 中将邮件转换为 PDF | MSG 转 PDF | EML 转 PDF
c#·邮件转pdf·eml转pdf·msg转pdf
La Pulga4 小时前
【STM32】ADC数模转换器
c语言·stm32·单片机·嵌入式硬件·mcu
充哥单片机设计4 小时前
【STM32项目开源】基于STM32的智能点滴输液系统
stm32·单片机·嵌入式硬件
almighty274 小时前
C# WPF实现ComboBox实时搜索与数据绑定
开发语言·c#·wpf·combobox
大飞pkz5 小时前
【设计模式】桥接模式
开发语言·设计模式·c#·桥接模式
AutomanLV6 小时前
c# datagridview添加list内容
程序人生·c#
正点原子7 小时前
正点原子 x STM32:智能加速边缘AI应用开发!
人工智能·stm32·嵌入式硬件
田甲7 小时前
【STM32】基于串口的bootloader
stm32·单片机·嵌入式硬件
杰尼君8 小时前
STM32CubeMX笔记(11)-- AD模块使用
笔记·stm32·嵌入式硬件