找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 149|回复: 0
打印 上一主题 下一主题
收起左侧

小白MPU6050求助 求指点,到底是哪出问题了

[复制链接]
跳转到指定楼层
楼主
利用正点原子旧版的MPU6050程序做了一个扫频程序,想要得到PWM与姿态角的关系,但是角度出来问题很大,直接从30度内跑到100+,后面有附带情况,附件的图片读取格式是PWM偏移量-角度信息-角速度信息,现在已经知道的是MPU6050直接运行例程是没有问题的,非常灵敏。但是想办法加入控制舵机并且读取姿态角就出问题,试过很多办法了,修改IIC速率减少影响,提高主程序到100Hz匹配DMP速率,但是都会出现这种情况。下面是我的程序,请大佬们过目!
  1. #include "led.h"
  2. #include "delay.h"
  3. #include "key.h"
  4. #include "sys.h"
  5. #include "lcd.h"
  6. #include "usart.h"
  7. #include "mpu6050.h"
  8. #include "usmart.h"   
  9. #include "inv_mpu.h"
  10. #include "inv_mpu_dmp_motion_driver.h"
  11. #include "pwm.h"
  12. #include <math.h>

  13. /* ========== 通道选择 ========== */
  14. //#define SWEEP_CHANNEL_PITCH
  15. #define SWEEP_CHANNEL_ROLL

  16. /* 各通道中位值 */
  17. #define PITCH_CENTER   160
  18. #define ROLL_CENTER    150

  19. /* 舵机有效范围 */
  20. #define SERVO_MIN  50
  21. #define SERVO_MAX  250

  22. /* 扫频参数 */
  23. #define SWEEP_TOTAL      45.0f
  24. #define SWEEP_F_START    0.1f
  25. #define SWEEP_F_END      1.0f
  26. #define SWEEP_AMPLITUDE  40.0f
  27. #define SAMPLE_PERIOD_MS 50

  28. /* 系统延时对齐参数 */
  29. #define SYSTEM_DELAY_MS   100
  30. #define DELAY_BUF_LEN     20
  31. #define DELAY_STEPS       (SYSTEM_DELAY_MS / SAMPLE_PERIOD_MS)

  32. /*  陀螺仪量程换算  */
  33. // 正点原子默认 MPU_Set_Gyro_Fsr(3) → ±2000°/s → 灵敏度 16.4 LSB/(°/s)
  34. #define GYRO_SCALE 16.4f

  35. int main(void)
  36. {         
  37.     u8 t = 0;
  38.     float pitch, roll, yaw;
  39.     short aacx, aacy, aacz;
  40.     short gyrox, gyroy, gyroz;
  41.     short temp;

  42.     /* 扫频专用变量 */
  43.     float t_sweep = 0.0f;
  44.     float dt = SAMPLE_PERIOD_MS / 1000.0f;
  45.     float phase = 0.0f;
  46.     float f_current;
  47.     float sweep_ratio;
  48.     float sin_val;
  49.     u16 pwm_pitch, pwm_roll;
  50.     int32_t signed_offset, pwm;

  51.     /* 延时对齐缓存 */
  52.     int pwm_buf[DELAY_BUF_LEN];
  53.     int buf_index = 0;
  54.     int aligned_pwm;
  55.     int delayed_index;
  56.     int i;

  57.     /* 输出变量 */
  58.     int pwm_offset;
  59.     float output_angle;
  60.     float output_rate;   // ★ 新增:输出角速度

  61.     /* LCD背光 GPIO 初始化结构体 */
  62.     GPIO_InitTypeDef GPIO_InitStructure;

  63.     /* ---------- 初始化 PWM 延时缓存 ---------- */
  64.     for(i = 0; i < DELAY_BUF_LEN; i++) {
  65.         pwm_buf[i] = 0;
  66.     }

  67.     /* ---------- 系统初始化 ---------- */
  68.     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  69.     uart_init(500000);
  70.     delay_init();
  71.     usmart_dev.init(72);
  72.     LED_Init();
  73.     KEY_Init();
  74.     LCD_Init();
  75.     MPU_Init();

  76.     MPU_Set_Gyro_Fsr(3);   // 强制陀螺仪量程为 ±2000°/s, 与 GYRO_SCALE 一致

  77.     /* PWM初始化(50Hz) */
  78.     TIM3_PWM_Init(1999, 719);
  79.     TIM_SetCompare1(TIM3, ROLL_CENTER);
  80.     TIM_SetCompare2(TIM3, PITCH_CENTER);
  81.     TIM_SetCompare4(TIM3, 150);

  82.     /* LCD背光修复 */
  83.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
  84.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
  85.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  86.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  87.     GPIO_Init(GPIOB, &GPIO_InitStructure);
  88.     GPIO_SetBits(GPIOB, GPIO_Pin_0);

  89.     /* LCD 显示 */
  90.     POINT_COLOR = RED;
  91.     LCD_ShowString(30,50,200,16,16,"ELITE STM32");      
  92.     LCD_ShowString(30,70,200,16,16,"MPU6050 SWEEP");      
  93.     LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");
  94.     LCD_ShowString(30,110,200,16,16,"2026/4/28");

  95.     /* DMP初始化 */
  96.     while(mpu_dmp_init())
  97.     {
  98.         LCD_ShowString(30,130,200,16,16,"MPU6050 Error");
  99.         delay_ms(200);
  100.         LCD_Fill(30,130,239,130+16,WHITE);
  101.         delay_ms(200);
  102.     }  
  103.     LCD_ShowString(30,130,200,16,16,"MPU6050 OK");

  104. #ifdef SWEEP_CHANNEL_PITCH
  105.     LCD_ShowString(30,150,200,16,16,"Pitch Sweep");
  106. #elif defined(SWEEP_CHANNEL_ROLL)
  107.     LCD_ShowString(30,150,200,16,16,"Roll Sweep");
  108. #endif

  109.     POINT_COLOR = BLUE;
  110.     LCD_ShowString(30,170,200,16,16,"Sweeping...    ");         
  111.     LCD_ShowString(30,200,200,16,16," Temp:    . C");      
  112.     LCD_ShowString(30,220,200,16,16,"Pitch:    . C");      
  113.     LCD_ShowString(30,240,200,16,16," Roll:    . C");         
  114.     LCD_ShowString(30,260,200,16,16," Yaw :    . C");         

  115.     delay_ms(1000);

  116.     /* ---------- 主循环:相位连续扫频 ---------- */
  117.     while(1)
  118.     {
  119.         /* 1. 固定非激活通道 */
  120. #ifdef SWEEP_CHANNEL_PITCH
  121.         TIM_SetCompare1(TIM3, ROLL_CENTER);
  122.         TIM_SetCompare4(TIM3, 150);
  123. #elif defined(SWEEP_CHANNEL_ROLL)
  124.         TIM_SetCompare2(TIM3, PITCH_CENTER);
  125.         TIM_SetCompare4(TIM3, 150);
  126. #endif

  127.         /* 2. 计算当前频率 */
  128.         sweep_ratio = t_sweep / SWEEP_TOTAL;
  129.         if(sweep_ratio > 1.0f) sweep_ratio = 1.0f;
  130.         f_current = SWEEP_F_START + (SWEEP_F_END - SWEEP_F_START) * sweep_ratio;

  131.         /* 3. 相位连续的chirp信号 */
  132.         phase += 2.0f * 3.1415926f * f_current * dt;
  133.         sin_val = sinf(phase);
  134.         signed_offset = (int32_t)(SWEEP_AMPLITUDE * sin_val);

  135.         /* 4. PWM输出 */
  136. #ifdef SWEEP_CHANNEL_PITCH
  137.         pwm = PITCH_CENTER + signed_offset;
  138.         if(pwm < SERVO_MIN) pwm = SERVO_MIN;
  139.         if(pwm > SERVO_MAX) pwm = SERVO_MAX;
  140.         TIM_SetCompare2(TIM3, (u16)pwm);
  141. #elif defined(SWEEP_CHANNEL_ROLL)
  142.         pwm = ROLL_CENTER + signed_offset;
  143.         if(pwm < SERVO_MIN) pwm = SERVO_MIN;
  144.         if(pwm > SERVO_MAX) pwm = SERVO_MAX;
  145.         TIM_SetCompare1(TIM3, (u16)pwm);
  146. #endif

  147.         /* 5. 存入PWM缓存(环形缓冲区) */
  148.         pwm_buf[buf_index] = (int)signed_offset;

  149.         /* 6. 获取延时对齐后的PWM偏移量 */
  150.         delayed_index = buf_index - DELAY_STEPS;
  151.         if(delayed_index < 0) delayed_index += DELAY_BUF_LEN;
  152.         aligned_pwm = pwm_buf[delayed_index];

  153.         buf_index++;
  154.         if(buf_index >= DELAY_BUF_LEN) buf_index = 0;

  155.         /* 7. 读取IMU并输出对齐后的数据(包含角速度) */
  156.         if(mpu_dmp_get_data(&pitch, &roll, &yaw) == 0)
  157.         {
  158.             temp = MPU_Get_Temperature();
  159.             MPU_Get_Accelerometer(&aacx, &aacy, &aacz);
  160.             MPU_Get_Gyroscope(&gyrox, &gyroy, &gyroz);

  161.             // 根据实际轴映射,Pitch 用 gyro_y,Roll 用 gyro_x
  162. #ifdef SWEEP_CHANNEL_PITCH
  163.             output_angle = pitch;
  164.             output_rate  = gyroy / GYRO_SCALE;   // 对应 Pitch 轴角速度
  165. #elif defined(SWEEP_CHANNEL_ROLL)
  166.             output_angle = roll;
  167.             output_rate  = gyrox / GYRO_SCALE;   // 对应 Roll 轴角速度
  168. #endif

  169.             /* ? 核心输出:对齐后的 PWM偏移, 角度, 角速度 */
  170.             printf("%d, %.4f, %.2f\r\n", aligned_pwm, output_angle, output_rate);

  171.             /* LCD 刷新(每10次循环一次) */
  172.             if((t % 10) == 0)
  173.             {
  174.                 if(temp < 0) { LCD_ShowChar(30+48,200,'-',16,0); temp = -temp; }
  175.                 else LCD_ShowChar(30+48,200,' ',16,0);
  176.                 LCD_ShowNum(30+48+8,200,temp/100,3,16);
  177.                 LCD_ShowNum(30+48+40,200,temp%10,1,16);

  178.                 if(pitch < 0) { LCD_ShowChar(30+48,220,'-',16,0); pitch = -pitch; }
  179.                 else LCD_ShowChar(30+48,220,' ',16,0);
  180.                 LCD_ShowNum(30+48+8,220,(int)(pitch*10)/10,3,16);
  181.                 LCD_ShowNum(30+48+40,220,(int)(pitch*10)%10,1,16);

  182.                 if(roll < 0) { LCD_ShowChar(30+48,240,'-',16,0); roll = -roll; }
  183.                 else LCD_ShowChar(30+48,240,' ',16,0);
  184.                 LCD_ShowNum(30+48+8,240,(int)(roll*10)/10,3,16);
  185.                 LCD_ShowNum(30+48+40,240,(int)(roll*10)%10,1,16);

  186.                 if(yaw < 0) { LCD_ShowChar(30+48,260,'-',16,0); yaw = -yaw; }
  187.                 else LCD_ShowChar(30+48,260,' ',16,0);
  188.                 LCD_ShowNum(30+48+8,260,(int)(yaw*10)/10,3,16);
  189.                 LCD_ShowNum(30+48+40,260,(int)(yaw*10)%10,1,16);

  190.                 t = 0;
  191.                 LED0 = !LED0;
  192.             }
  193.         }
  194.         t++;

  195.         delay_ms(SAMPLE_PERIOD_MS);
  196.         t_sweep += dt;

  197.         /* 扫频结束,舵机归中 */
  198.         if(t_sweep >= SWEEP_TOTAL)
  199.         {
  200. #ifdef SWEEP_CHANNEL_PITCH
  201.             TIM_SetCompare2(TIM3, PITCH_CENTER);
  202. #elif defined(SWEEP_CHANNEL_ROLL)
  203.             TIM_SetCompare1(TIM3, ROLL_CENTER);
  204. #endif
  205.             LCD_ShowString(30,170,200,16,16,"Sweep Finished!");
  206.             while(1) { LED0 = !LED0; delay_ms(200); }
  207.         }
  208.     }        
  209. }
复制代码

90CF34F9C4BF223B0E9DE8CAAAADBF73.png (32.22 KB, 下载次数: 0)

90CF34F9C4BF223B0E9DE8CAAAADBF73.png

AF1E4A097B731E8874CA16F68938AEF4.png (40.68 KB, 下载次数: 0)

AF1E4A097B731E8874CA16F68938AEF4.png
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表