硬件规划:
整体思路:
硬件模块:
硬件选型:
模块称号 |
元件称号 |
数量 |
|
单片机 |
STM32F103CBT6 |
1 |
|
惯性丈量模块(IMU) |
MPU6050(三轴加速度计+三轴陀螺仪) |
1 |
|
无线通讯模块 |
NRF24L01 |
1 |
|
电机驱动模块 |
AO3400 5.8A |
4 |
|
续流二极管 |
SS34 3A |
4 |
|
电源办理模块 |
稳压 |
TPS79333 3.3V |
1 |
充放电 |
TP4057 USB兼容5V充电 |
1 |
|
直流有刷电机 |
空心杯有刷直流电机7*16mm |
4 |
|
大电流放电电池 |
250mAh 20C |
1 |
|
遥控器 |
JOYPAD游戏手柄 |
1 |
硬件作业总述:
硬件规划功能模块图:
实践效果图与相关参数:
尺度:对角电机轴距10x10cm
重量:33.2g(带电池)
软件规划:
整体思路:
姿势解算:
以下给出笔者姿势交融的代码,该代码网上都有,笔者在这儿做了少许注释,便利了解。
- void
IMUupdata(float gx, float gy, float gz, float ax, float ay, float az) - {
float recipNorm; //平方根的倒数 float halfvx, halfvy, halfvz; //在当时载体坐标系中,重力重量在三个轴上的重量 float halfex, halfey, halfez; //当时加速度计测得的重力加速度在三个轴上的重量与当时姿势在三个轴上的重力重量的差错,这儿选用差积的办法 float qa, qb, qc; gx = gx * PI / 180; //转化为弧度制 gy = gy * PI / 180; gz = gz * PI / 180; //假如加速度计处于自由落体状况,可能会呈现这种状况,不进行姿势解算,由于会发生分母无穷大的状况 if(!((ax == 0.0f) && (ay == 0.0f) && (az == 0.0f))) { //单位化加速度计,含义在于在改变了加速度计的量程之后不需要批改Kp参数,由于这儿归一化了 recipNorm = invSqrt(ax * ax + ay * ay + az * az); ax *= recipNorm; ay *= recipNorm; az *= recipNorm; //将当时姿势的重力在三个轴上的重量别离出来 //便是方向余弦旋转矩阵的第三列,留意是地舆坐标系(n系)到载体坐标系(b系)的,不要弄反了.假如书上是b系到n系,转置即可 //惯性丈量器材丈量的都是关于b系的值,为了便利,咱们一般将b系转化到n系进行导航参数求解。可是这儿并不需要这样做,由于这儿是对陀螺仪进行补偿 halfvx = g_q1 * g_q3 – g_q0 * g_q2; halfvy = g_q0 * g_q1 + g_q2 * g_q3; halfvz = g_q0 * g_q0 – 0.5f + g_q3 * g_q3; //核算由当时姿势的重力在三个轴上的重量与加速度计测得的重力在三个轴上的重量的差,这儿选用三维空间的差积(向量积)办法求差 //核算公式由矩阵运算推导而来 公式拜见http://en.wikipedia.org/wiki/Cross_product 中的Mnemonic部分 halfex = (ay * halfvz – az * halfvy); halfey = (az * halfvx – ax * halfvz); halfez = (ax * halfvy – ay * halfvx); //积分求差错,关于当时姿势别离出的重力重量与当时加速度计测得的重力重量的差值进行积分消除差错 if(g_twoKi > 0.0f) { g_integralFBx += g_twoKi * halfex * CNTLCYCLE; //Ki积分 g_integralFBy += g_twoKi * halfey * CNTLCYCLE; g_integralFBz += g_twoKi * halfez * CNTLCYCLE; gx += g_integralFBx; //将积分差错反应到陀螺仪上,批改陀螺仪的值 gy += g_integralFBy; gz += g_integralFBz; } else //不进行积分运算,只进行份额调理 { g_integralFBx = 0.0f; g_integralFBy = 0.0f; g_integralFBz = 0.0f; } //直接使用份额调理,批改陀螺仪的值 gx += g_twoKp * halfex; gy += g_twoKp * halfey; gz += g_twoKp * halfez; } //以下为四元数微分方程.将陀螺仪和四元数结合起来,是姿势更新的中心算子 //核算办法由矩阵运算推导而来 // . 1 // q = – * q x Omega 式中左面是四元数的倒数,右边的x是四元数乘法,Omega是陀螺仪的值(即角速度) // 2 // . // [q0] [0 -wx -wy -wz] [q0] // . // [q1] [wx 0 wz -wy] [q1] // . = * // [q2] [wy -wz 0 wx ] [q2] // . // [q3] [wz wy -wx 0 ] [q3] gx *= (0.5f * CNTLCYCLE); gy *= (0.5f * CNTLCYCLE); gz *= (0.5f * CNTLCYCLE); qa = g_q0; qb = g_q1; qc = g_q2; g_q0 += (-qb * gx – qc * gy – g_q3 * gz); g_q1 += ( qa * gx + qc * gz – g_q3 * gy); g_q2 += ( qa * gy – qb * gz + g_q3 * gx); g_q3 += ( qa * gz + qb * gy – qc * gx); //单位化四元数,含义在于单位化四元数在空间旋转时是不会拉伸的,仅有旋转视点.这相似与线性代数里边的正交变换 recipNorm = invSqrt(g_q0 * g_q0 + g_q1 * g_q1 + g_q2 * g_q2 + g_q3 * g_q3); g_q0 *= recipNorm; g_q1 *= recipNorm; g_q2 *= recipNorm; g_q3 *= recipNorm; //四元数到欧拉角转化,转化次序为Z-Y-X,拜见.pdf一文,P24 //留意此刻的转化次序是1-2-3,即X-Y-Z。可是由于画图便利,作者这儿做了一个转化,即互换Z和X,所以次序没变 g_Yaw = atan2(2 * g_q1 * g_q2 + 2 * g_q0 * g_q3, g_q1 * g_q1 + g_q0 * g_q0 – g_q3 * g_q3 – g_q2 * g_q2) * 180 / PI; //Yaw g_Roll = asin(-2 * g_q1 * g_q3 + 2 * g_q0* g_q2) * 180 / PI; //Roll g_Pitch = atan2(2 * g_q2 * g_q3 + 2 * g_q0 * g_q1, -2 * g_q1 * g_q1 – 2 * g_q2* g_q2 + 1) * 180 / PI; //Pitch - }