找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 8446|回复: 0
收起左侧

STM32平衡车程序+原理图(步进电机)

[复制链接]
ID:591632 发表于 2020-8-19 10:43 | 显示全部楼层 |阅读模式
自平衡车主控为STM32f103r
平衡车硬件总体设计,平衡车以STM32为主控芯片,通过处理从各个传感器返回的数据使小车达到动态平衡以及遥控的实现。
平衡车的软件结构分为四大部分,各个部分之间相互关联。软件总体结构:OLED显示实时数据、按键调试各项参数部分;串口和超声波部分解析有关指令部分;PID控制器输出控制部分。在串口和超声波部分获取控制指令后,传输给PID控制器,最终由PID计算控制器输出相应PWM值控制电机,以保持平衡车的平衡。主控芯片在接收MPU6050传感器返回的角度值与角加速度值后,对返回数据进行一阶互补滤波处理。一阶互补滤波算法将角度数据进行融合,降低MPU6050传感器的噪声信号的影响,从而得到准确的平衡车当前姿态。STM32主控芯片通过直立的PD控制器得到较为准确的PWM输出控制数值,控制电机转动使得小车实现基本平衡。为了减小小车的左右偏移幅度,将MPU6050返回的Z轴转动量输出到转向PD控制器进行计算,再将转向PWM增量值与直立PWM增量进行叠加输出,得到较为准确的PWM控制值,从而使小车保持直立状态。在Android手机上安装一个第三方蓝牙遥控APP,由APP发出的相应控制指令。系统通过蓝牙模块接收控制指令,再由串口中断接收蓝牙模块控制数据,之后系统进行控制指令的解析得到控制输出值,控制小车前后左右的行驶动作。在实际的测试过程中,发现蓝牙的有效控制距离为8米左右,并且手机与蓝牙模块的容易被各种因素干扰,使小车在控制距离较远的位置失去控制。建议大家使用NRF或其它控制信号较远的模块进行通讯,从而实现相对较远的距离控制。

单片机源程序如下:
  1. /******************** (C) COPYRIGHT 2014 POWSOS Team **************************
  2. * 文件名  :main.c
  3. * 描述    :     
  4. * 实验平台:STM32F103RBT6
  5. * 库版本  :ST3.5.0
  6. * 作者    :  Powsos_Team
  7. * 版本    :V2.0
  8. * 日期    :2014.8.23
  9. * 修订历史:V2.0
  10. ******************************************************************************/

  11. #include "stm32f10x.h"
  12. #include "iic.h"
  13. #include "timer.h"
  14. #include "usart.h"
  15. #include "mpu6050.h"
  16. #include "filter.h"
  17. #include "calculate.h"
  18. #include "gpio.h"
  19. #include "time_test.h"
  20. #include "hc_sr04.h"
  21. #include "delay.h"
  22. #include <stdio.h>
  23. #include <math.h>


  24. //#define Debug  

  25. #define GX_OFFSET 0x01
  26. #define AX_OFFSET 0x01
  27. #define AY_OFFSET 0x01
  28. #define AZ_OFFSET 0x01


  29. #define duoji_offset  120

  30. extern u8  duoji_flag;
  31. extern u8 duoji_cnt;
  32. extern u16 time;
  33. extern u8 duoji_pwm;

  34. u8 hcsr04_test_flag = 0;
  35. u8 receive_data;
  36. u8 flg_get_senor_data;
  37. u8 out[35]  ={0x5f, 0x60, 0};
  38. u8 Duoji_direction = 1;  /*1,前方,2:左边   3:右边,舵机*/
  39. u8 Move_direcetion = 1;  /*1静止  2,前方, 3,后退 4:左边   5:右边 小车运行方向*/
  40. u16 distance =0 ;
  41. int  pulsewidth;
  42. float angle, angle_dot, f_angle, f_angle_dot;
  43. s16 temp;
  44. s16 gx, gy, gz, ax ,ay, az, temperature;

  45. #define FILTER_COUNT  16
  46. s16 gx_buf[FILTER_COUNT], ax_buf[FILTER_COUNT], ay_buf[FILTER_COUNT],az_buf[FILTER_COUNT];
  47. /******************************************************************************/
  48. void delay(u32 count)
  49. {
  50.   for(; count != 0; count--);
  51. }
  52. /*************************************************

  53. 名称:void acc_filter(void)
  54. 功能:加速度计数据滤波
  55. 输入参数:据滤波后的数据
  56. 输出参数:无
  57. 返回值:  无
  58. **************************************************/
  59. void acc_filter(void)
  60. {
  61.   u8 i;
  62.   s32 ax_sum = 0, ay_sum = 0, az_sum = 0;

  63.   for(i = 1 ; i < FILTER_COUNT; i++)
  64.   {
  65.     ax_buf[i - 1] = ax_buf[i];
  66.         ay_buf[i - 1] = ay_buf[i];
  67.         az_buf[i - 1] = az_buf[i];
  68.   }

  69.   ax_buf[FILTER_COUNT - 1] = ax;
  70.   ay_buf[FILTER_COUNT - 1] = ay;
  71.   az_buf[FILTER_COUNT - 1] = az;

  72.   for(i = 0 ; i < FILTER_COUNT; i++)
  73.   {
  74.     ax_sum += ax_buf[i];
  75.         ay_sum += ay_buf[i];
  76.         az_sum += az_buf[i];
  77.   }

  78.   ax = (s16)(ax_sum / FILTER_COUNT);
  79.   ay = (s16)(ay_sum / FILTER_COUNT);
  80.   az = (s16)(az_sum / FILTER_COUNT);
  81. }

  82. /* I/O口模拟输出PWM控制舵机,50hz */
  83. void servopulse(int myangle)//定义一个脉冲函数
  84. {
  85.          // EA = 0;
  86.         //  pulsewidth = (((myangle+duoji_offset)*25)+500)/1000;;// 舵机中心值可能会偏,修改20,做调整
  87.         pulsewidth =myangle;

  88. }

  89. /*****************************************************************************/
  90. int main(void)
  91. {
  92.         SystemInit();
  93.         delay_init(72);
  94.         gpio_init();       
  95.         delay(0x80000);
  96.     usart_init();                                          
  97.     iic_init();
  98.     timer_init();
  99.     TIM1_Configuration();
  100.     HCSR04_Init();
  101.     motor_init();
  102.         mpu6050_init();
  103.         STOP_TIME;
  104.         duoji_flag =1;
  105.         duoji_cnt = 0;
  106.         servopulse(3);/*上电将舵机放至中间*/
  107.          while (1)
  108.         {
  109.             if(flg_get_senor_data)
  110.             {
  111.               flg_get_senor_data = 0;
  112.               mpu6050_get_data(&gx, &gy, &gz, &ax, &ay , &az, &temperature);
  113.                   acc_filter();       

  114.                   gx-=  GX_OFFSET;
  115.                   ax -= AX_OFFSET;
  116.                   ay -=        AY_OFFSET;
  117.                   az -= AZ_OFFSET;

  118.             angle_dot = gx * GYRO_SCALE;  //+-2000  0.060975 °/LSB   //陀螺仪
  119.               angle = atan(ay / sqrt(ax * ax + az * az ));
  120.              
  121.              angle = angle * 57.295780;    //180/pi


  122.                  kalman_filter(angle, angle_dot, &f_angle, &f_angle_dot);//     加速度计计算的角度, 陀螺仪角速度 , 融合后的角度, 融合后的角速度
  123.                    receive_parameter(receive_data);

  124.                    pid(f_angle, f_angle_dot);

  125. #ifdef  Debug
  126.                               temp = (s16)(f_angle * 100);
  127.              
  128.                                  out[2] = (u8)(gx >> 8);
  129.                     out[3] = (u8)(gx);
  130.                                  out[4] = (u8)(gy >> 8);
  131.                                  out[5] = (u8)(gy);
  132.                                  out[6] = (u8)(gz >> 8);
  133.                                  out[7] = (u8)(gz);
  134.                                  out[8] = (u8)(ax >> 8);
  135.                                  out[9] = (u8)(ax);
  136.                                  out[10] = (u8)(ay >> 8);
  137.                                  out[11] = (u8)(ay);
  138.                                  out[12] = (u8)(az >> 8);
  139.                                  out[13] = (u8)(az);
  140.                            out[14] = (u8)(temp >> 8);
  141.                                  out[15] = (u8)(temp);

  142.                                 USART_SendStringData(USART1,&out[0],16);

  143. #endif
  144.           
  145.                        
  146.             }  //end if               
  147.        
  148.                
  149.     if(hcsr04_test_flag)
  150.     {
  151.                  hcsr04_test_flag=0;                 
  152.                  measure_distance(receive_data);
  153.                                          
  154.                  switch(Duoji_direction)
  155.                  {
  156.                         case Duoji_Front:        USART_printf(USART2,"Front_distance: %d cm\r\n",distance);break;
  157.                         case Duoji_Left:        USART_printf(USART2,"Left_distance: %d cm\r\n",distance);break;
  158.                         case Duoji_Right:        USART_printf(USART2,"Right_distance: %d cm\r\n",distance);break;
  159.                  }
  160.                  
  161.                  
  162.         }
  163.         #if  0
  164.         /*若前方距离小于100,并且小车行驶方向是往前的,此时小车需要停止*/       
  165.         if((distance<50)&&(Move_direcetion==Move_front))
  166.         {                               
  167.                 receive_data ='s';
  168.         }
  169.                
  170.         #endif

  171.   }  
  172.        
  173. }

  174. /*****************END OF FILE************************************************************/
复制代码

下载: STM32平衡车程序+原理图(步进电机).7z (588.1 KB, 下载次数: 173)
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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