单片机基于BNO055的九轴姿态控制

BNO055 使用三个三轴传感器同时测量切向加速度(通过加速度计),旋转加速度(通过陀螺仪)和局部磁场强度(通过磁力计)。然后,可以将数据发送到外部微处理器,或使用运行专有融合算法的 M0+微处理器在传感器内部进行分析。然后,用户可以选择以各种格式从传感器请求数据。

该芯片还具有中断功能,可以在发生某些运动(方向变化、突然加速等)时通知主机微控制器。

图片

 博世传感器BNO055智能9轴的绝对方向传感器是在封装(SiP)一个系统,整合了三轴14位加速度计,三轴16位陀螺仪与一系列每秒±2000度,三轴地磁传感器和一个32比特的ARM Cortex M0 +微控制器上运行博世传感器传感器融合软件,在单一封装中。相应的芯片集被集成到一个单一的28引脚的LGA3.8毫米点x5.2毫米点x1.1毫米壳体。为了获得最佳的系统集成BNO055配有数字双向I²C和UART接口。该I²C接口进行编程与HID-I²C协议打开BNO055到插件和播放传感器集线器解决方案运行Windows 8.0或8.1的操作系统的设备上运行。主要特征:输出融合传感器数据先进的三轴16位陀螺仪LGA封装28个引脚低功耗,并暂停提供模式电压范围:2.4V至3.6V工作温度:-40°C至+ 85°C加速度计特点:加速度范围:±2G /±4G /±8G /±16G低通滤波器带宽:1kHz时 - <8HZ陀螺仪功能:范围切换从±125°/ s至±2000°/秒低通滤波器带宽:523Hz - 12赫兹磁力特性磁场范围:±典型1300μT(X,Y轴);±2500μT(z轴)磁场分辨率:〜0.3μT

两个定时器使用8个PWM通道驱动4个电机驱动芯片,使用PWM占空比调节输出电压和正反转。

/**
  ******************************************************************************
  * File Name          : TIM.h
  * Description        : This file provides code for the configuration
  *                      of the TIM instances.
  ******************************************************************************
  ** This notice applies to any and all portions of this file
  * that are not between comment pairs USER CODE BEGIN and
  * USER CODE END. Other portions of this file, whether 
  * inserted by the user or by software development tools
  * are owned by their respective copyright owners.
  *
  * COPYRIGHT(c) 2018 STMicroelectronics
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __tim_H
#define __tim_H
#ifdef __cplusplus
 extern "C" {
#endif

/* Includes ------------------------------------------------------------------*/
#include "stm32f2xx_hal.h"
#include "comtypes.h"
	 
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

#define bool  BOOLEAN
	 
extern TIM_HandleTypeDef htim3;
extern TIM_HandleTypeDef htim4;

/* USER CODE BEGIN Private defines */

/* USER CODE END Private defines */

void MX_TIM3_Init(void);
void MX_TIM4_Init(void);
                        
void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim);
                                        
/* USER CODE BEGIN Prototypes */

/* USER CODE END Prototypes */

#ifdef __cplusplus
}
#endif
#endif /*__ tim_H */

/**
  * @}
  */

/**
  * @}
  */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

/**
  ******************************************************************************
  * File Name          : TIM.c
  * Description        : This file provides code for the configuration
  *                      of the TIM instances.
  ******************************************************************************
  ** This notice applies to any and all portions of this file
  * that are not between comment pairs USER CODE BEGIN and
  * USER CODE END. Other portions of this file, whether 
  * inserted by the user or by software development tools
  * are owned by their respective copyright owners.
  *
  * COPYRIGHT(c) 2018 STMicroelectronics
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "tim.h"

/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

TIM_HandleTypeDef htim3;
TIM_HandleTypeDef htim4;



static void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */

  /* USER CODE END Error_Handler_Debug */
	while(1);
}



/* TIM3 init function */
void MX_TIM3_Init(void)
{
  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_OC_InitTypeDef sConfigOC = {0};

  htim3.Instance = TIM3;
  htim3.Init.Prescaler = 2-1;
  htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim3.Init.Period = 5040-1;
  htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
  if (HAL_TIM_PWM_Init(&htim3) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 0;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_4) != HAL_OK)
  {
    Error_Handler();
  }
  HAL_TIM_MspPostInit(&htim3);

}
/* TIM4 init function */
void MX_TIM4_Init(void)
{
  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_OC_InitTypeDef sConfigOC = {0};

  htim4.Instance = TIM4;
  htim4.Init.Prescaler = 2-1;
  htim4.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim4.Init.Period = 5040-1;
  htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
  if (HAL_TIM_PWM_Init(&htim4) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim4, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 0;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  if (HAL_TIM_PWM_ConfigChannel(&htim4, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_ConfigChannel(&htim4, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_ConfigChannel(&htim4, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_ConfigChannel(&htim4, &sConfigOC, TIM_CHANNEL_4) != HAL_OK)
  {
    Error_Handler();
  }
  HAL_TIM_MspPostInit(&htim4);

}

void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef* tim_pwmHandle)
{

  if(tim_pwmHandle->Instance==TIM3)
  {
    __HAL_RCC_TIM3_CLK_ENABLE();
  }
  else if(tim_pwmHandle->Instance==TIM4)
  {
    __HAL_RCC_TIM4_CLK_ENABLE();
  }
	
}

void HAL_TIM_MspPostInit(TIM_HandleTypeDef* timHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(timHandle->Instance==TIM3)
  {
  /* USER CODE BEGIN TIM3_MspPostInit 0 */

  /* USER CODE END TIM3_MspPostInit 0 */
    __HAL_RCC_GPIOB_CLK_ENABLE();
    __HAL_RCC_GPIOC_CLK_ENABLE();
    /**TIM3 GPIO Configuration    
    PB1     ------> TIM3_CH4
    PC6     ------> TIM3_CH1
    PC7     ------> TIM3_CH2
    PC8     ------> TIM3_CH3 
    */
    GPIO_InitStruct.Pin = GPIO_PIN_1;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF2_TIM3;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF2_TIM3;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

  /* USER CODE BEGIN TIM3_MspPostInit 1 */

  /* USER CODE END TIM3_MspPostInit 1 */
  }
  else if(timHandle->Instance==TIM4)
  {
  /* USER CODE BEGIN TIM4_MspPostInit 0 */

  /* USER CODE END TIM4_MspPostInit 0 */
  
    __HAL_RCC_GPIOB_CLK_ENABLE();
    /**TIM4 GPIO Configuration    
    PB6     ------> TIM4_CH1
    PB7     ------> TIM4_CH2
    PB8     ------> TIM4_CH3
    PB9     ------> TIM4_CH4 
    */
    GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF2_TIM4;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /* USER CODE BEGIN TIM4_MspPostInit 1 */

  /* USER CODE END TIM4_MspPostInit 1 */
  }

}

void HAL_TIM_PWM_MspDeInit(TIM_HandleTypeDef* tim_pwmHandle)
{

  if(tim_pwmHandle->Instance==TIM3)
  {
    __HAL_RCC_TIM3_CLK_DISABLE();
  }
  else if(tim_pwmHandle->Instance==TIM4)
  {
    __HAL_RCC_TIM4_CLK_DISABLE();

  }
} 

/* USER CODE BEGIN 1 */

/* USER CODE END 1 */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

BNO055寄存器读写配置驱动。

#ifndef __BMO_055_H
#define __BMO_055_H	 

#include "mpuiic.h"
#include "stm32f2xx_hal.h"

#define BNO055_I2C_ADDR2  (0X29)
#define SYS_TRIGGER       (0X3F)

//BNO055电源模式
#define PWR_MODE          (0X3E)
#define NORMAL_MODE       (0X00)
#define LOW_POWER_MODE    (0X01)
#define SUSPEND_MODE      (0X02)

//传感器切换模式
#define OPR_MODE          (0X3D)
//传感器配置模式
#define CONFIG_MODE       (0X00)
//NON_FUSION_MODE
#define ACCONLY           (0X01)
#define MAGONLY           (0X02)
#define GRYOONOL          (0X03)
#define ACCMAG            (0X04)
#define ACCGYRO           (0X05)
#define MAGGYRO           (0X06)
#define AMG               (0X07)
//FUSION MODE
#define IMU               (0X80)
#define COMPASS           (0X90)
#define M4G               (0X0A)
#define NODF_FMC_OFF      (0X0B)
#define NODF              (0x0C)

//传感器校准状态查询
#define CALIB_STAT        (0X35)

//传感器温度数据地址
#define TEMP              (0X34)

//传感器数据地址
#define ACC_DATA_X_LSB    (0X08)
#define ACC_DATA_X_MSB    (0X09)
#define ACC_DATA_Y_LSB    (0X0A)
#define ACC_DATA_Y_MSB    (0X0B)
#define ACC_DATA_Z_LSB    (0X0C)
#define ACC_DATA_Z_MSB    (0X0D)

#define MAG_DATA_X_LSB    (0X0E)
#define MAG_DATA_X_MSB    (0X0F)
#define MAG_DATA_Y_LSB    (0X10)
#define MAG_DATA_Y_MSB    (0X11)
#define MAG_DATA_Z_LSB    (0X12)
#define MAG_DATA_Z_MSB    (0X13)

#define GYR_DATA_X_LSB    (0X14)
#define GYR_DATA_X_MSB    (0X15)
#define GYR_DATA_Y_LSB    (0X16)
#define GYR_DATA_Y_MSB    (0X17)
#define GYR_DATA_Z_LSB    (0X18)
#define GYR_DATA_Z_MSB    (0X19)

#define EUL_Heading_LSB   (0X1A)
#define EUL_Heading_MSB   (0X1B)
#define EUL_Roll_LSB      (0X1C)
#define EUL_Roll_MSB      (0X1D)
#define EUL_Pitch_LSB     (0X1E)
#define EUL_Pitch_MSB     (0X1F)

#define QUA_Data_w_LSB    (0X20)
#define QUA_Data_w_MSB    (0X21)
#define QUA_Data_x_LSB    (0X22)
#define QUA_Data_x_MSB    (0X23)
#define QUA_Data_y_LSB    (0X24)
#define QUA_Data_y_MSB    (0X25)
#define QUA_Data_z_LSB    (0X26)
#define QUA_Data_z_MSB    (0X27)

#define LIA_Data_X_LSB    (0X28)
#define LIA_Data_X_MSB    (0X29)
#define LIA_Data_Y_LSB    (0X2A)
#define LIA_Data_Y_MSB    (0X2B)
#define LIA_Data_Z_LSB    (0X2C)
#define LIA_Data_Z_MSB    (0X2D)

#define GRV_Data_X_LSB    (0X2E)
#define GRV_Data_X_MSB    (0X2F)
#define GRV_Data_Y_LSB    (0X30)
#define GRV_Data_Y_MSB    (0X31)
#define GRV_Data_Z_LSB    (0X32)
#define GRV_Data_Z_MSB    (0X33)

//传感器配置地址
#define ACC_Config        (0x08)
#define MAG_Config        (0x09)
#define GYR_Config_0      (0x0A)
#define GYR_Config_1      (0x0B)
#define ACC_Sleep_Config  (0x0C)
#define GYR_Sleep_Config  (0x0D)

extern uint8_t mag_need_cal_flag;
extern uint8_t acc_need_cal_flag;
extern uint8_t gry_need_cal_flag;

/**********传感器复位*********************
    
    请勿调用该函数。
    无返回值
******************************************/
void SET_BNO055_REST(void);    

/**********设置传感器模式*********************
    k:寄存器数值
    
    请勿调用该函数。
    无返回值
******************************************/
void SET_BNO055_OPR_MODE(uint8_t k);

/**********设置传感器电源模式*********************
    k:寄存器数值
    
    请勿调用该函数。
    无返回值
******************************************/
void SET_BNO055_POWER_MODE(uint8_t k);              

/**********输出四元数数据*********************
    *q:输出的数据数组
    
    请勿调用该函数。
    无返回值
******************************************/
void READ_QUA_FROM_BNO055(float *q);  

/**********输出欧拉角数据*********************
    *q:输出的数据数组
    
    请勿调用该函数。
    无返回值
******************************************/
void READ_EUL_FROM_BNO055(float *q); 

/**********输出加速度数据*********************
    *q:输出的数据数组
    
    请勿调用该函数。
    无返回值
******************************************/
void READ_ACC_FROM_BNO055(float *q);               

/**********输出陀螺仪数据*********************
    *q:输出的数据数组
    
    请勿调用该函数。
    无返回值
******************************************/
void READ_GRY_FROM_BNO055(float *q);                

/**********输出磁罗盘数据*********************
    *q:输出的数据数组
    
    请勿调用该函数。
    无返回值
******************************************/
void READ_MAG_FROM_BNO055(float *q);             

/**********加载传感器校准数据*********************
    
    请勿调用该函数。
    无返回值
******************************************/
void load_cal_data(void);                          

/**********获取传感器温度数据*********************
    
    请勿调用该函数。
    返回传感器温度值
******************************************/
uint8_t READ_TEMP_BNO055(void);

/**********获取传感器校准状态*********************
    
    允许调用该函数。
    返回传感器校准状态值
******************************************/
uint8_t CHECK_CALIB_STAT(void);                     

/**********获取传感器磁罗盘校准状态*********************
    
    请勿调用该函数。
    返回传感器磁罗盘校准状态值
******************************************/
uint8_t CHECK_MAG_CALIB_STAT(void);                

/**********获取传感器加速度校准状态*********************
    
    请勿调用该函数。
    返回加速度计校准状态值
******************************************/
uint8_t CHECK_ACC_CALIB_STAT(void);   

/**********获取传感器陀螺仪校准状态*********************
    
    请勿调用该函数。
    返回陀螺仪校准状态值
******************************************/
uint8_t CHECK_GRY_CALIB_STAT(void);                 

/**********校准传感器*********************
    
    请勿调用该函数。
    无返回值
******************************************/
void CALIB_SENSOR(void);                            

/**********传感器初始化*********************
    
    请勿调用该函数。
    无返回值
******************************************/
void BNO055_INIT(void);                           

/**********输出yaw数据*********************
    
    允许调用该函数。
    返回yaw数据
    机体启动方向为0度
******************************************/
int32_t Yaw_out(void);

#endif


#include "bmo_055.h"

uint8_t mag_need_cal_flag = 0;
uint8_t acc_need_cal_flag = 0;
uint8_t gry_need_cal_flag = 0;

void bno_055_delay()
{
    uint16_t i,k;
    
    for(i = 0; i < 100; i++){
        for(k = 0; k < 100; k++);     
    }
    
}

//复位BNO055
void SET_BNO055_REST()
{
	uint8_t r = 0x20;
    WriteData(BNO055_I2C_ADDR2,SYS_TRIGGER,&r,1);
}
	
//设置BNO055的电源模式
void SET_BNO055_POWER_MODE(uint8_t k)
{
	WriteData(BNO055_I2C_ADDR2,PWR_MODE,&k,1);		
}

//设置传感器操作模式
void SET_BNO055_OPR_MODE(uint8_t k)	
{
	WriteData(BNO055_I2C_ADDR2,OPR_MODE,&k,1);	
}

//传感器四元数
void READ_QUA_FROM_BNO055(float *q)
{
	float w,x,y,z;	
	uint8_t qua_data[8];
	
	ReadData(BNO055_I2C_ADDR2,QUA_Data_w_LSB,qua_data,8);
	
	w=(int16_t)((int16_t)qua_data[1]<<8|(int16_t)qua_data[0])/16384.0;
	x=(int16_t)((int16_t)qua_data[3]<<8|(int16_t)qua_data[2])/16384.0;
	y=(int16_t)((int16_t)qua_data[5]<<8|(int16_t)qua_data[4])/16384.0;
	z=(int16_t)((int16_t)qua_data[7]<<8|(int16_t)qua_data[6])/16384.0;
	
	q[0] = w;
	q[1] = x;
	q[2] = y;
	q[3] = z;
	
}

//读取传感器欧拉角,单位度
void READ_EUL_FROM_BNO055(float *q)
{
	float pitch,roll,yaw;	
	uint8_t eul_data[6];
	
	ReadData(BNO055_I2C_ADDR2,EUL_Heading_LSB,eul_data,6);
	
	yaw 	=	(int16_t)((int16_t)eul_data[1]<<8|(int16_t)eul_data[0])/16.0f;
	roll  = (int16_t)((int16_t)eul_data[3]<<8|(int16_t)eul_data[2])/16.0f;
	pitch = (int16_t)((int16_t)eul_data[5]<<8|(int16_t)eul_data[4])/16.0f;
	
	q[0] = pitch;
	q[1] = roll;
	q[2] = yaw;
	
}

//读取加速度计数据,单位m/s^2
void READ_ACC_FROM_BNO055(float *q)
{
	float acc_x,acc_y,acc_z;	
	uint8_t acc_data[6];
	
	ReadData(BNO055_I2C_ADDR2,ACC_DATA_X_LSB,acc_data,6);
	
	acc_x =(int16_t)((int16_t)acc_data[1]<<8|(int16_t)acc_data[0])/100.0f;
	acc_y =(int16_t)((int16_t)acc_data[3]<<8|(int16_t)acc_data[2])/100.0f;
	acc_z =(int16_t)((int16_t)acc_data[5]<<8|(int16_t)acc_data[4])/100.0f;
	
	q[0] = acc_x;
	q[1] = acc_y;
	q[2] = acc_z;
	
}

//读取陀螺仪数据,单位DPS
void READ_GRY_FROM_BNO055(float *q)
{
	float gry_x,gry_y,gry_z;	
	uint8_t gry_data[6];
	
	ReadData(BNO055_I2C_ADDR2,GYR_DATA_X_LSB,gry_data,6);
	
	gry_x =(int16_t)((int16_t)gry_data[1]<<8|(int16_t)gry_data[0])/16.0f;
	gry_y =(int16_t)((int16_t)gry_data[3]<<8|(int16_t)gry_data[2])/16.0f;
	gry_z =(int16_t)((int16_t)gry_data[5]<<8|(int16_t)gry_data[4])/16.0f;
	
	q[0] = gry_x;
	q[1] = gry_y;
	q[2] = gry_z;
	
	
}

//读取磁罗盘数据,单位UT
void READ_MAG_FROM_BNO055(float *q)
{
	float mag_x,mag_y,mag_z;	
	uint8_t mag_data[6];
	
	ReadData(BNO055_I2C_ADDR2,MAG_DATA_X_LSB,mag_data,6);
	
	mag_x =(int16_t)((int16_t)mag_data[1]<<8|(int16_t)mag_data[0])/16.0f;
	mag_y =(int16_t)((int16_t)mag_data[3]<<8|(int16_t)mag_data[2])/16.0f;
	mag_z =(int16_t)((int16_t)mag_data[5]<<8|(int16_t)mag_data[4])/16.0f;
	
	q[0] = mag_x;
	q[1] = mag_y;
	q[2] = mag_z;
	
			
}

//读取传感器线性加速度数据
void READ_LINER_ACC_FROM_BNO055(float *q)
{
	float liner_acc_x,liner_acc_y,liner_acc_z;	
	uint8_t liner_acc_data[6];
	
	ReadData(BNO055_I2C_ADDR2,LIA_Data_X_LSB,liner_acc_data,6);
	
	liner_acc_x =(int16_t)((int16_t)liner_acc_data[1]<<8|(int16_t)liner_acc_data[0])/100.0f;
	liner_acc_y =(int16_t)((int16_t)liner_acc_data[3]<<8|(int16_t)liner_acc_data[2])/100.0f;
	liner_acc_z =(int16_t)((int16_t)liner_acc_data[5]<<8|(int16_t)liner_acc_data[4])/100.0f;
	
	q[0] = liner_acc_x;
	q[1] = liner_acc_y;
	q[2] = liner_acc_z;
	
}

//读取传感器重力矢量数据
void READ_GRAVITY_VECTOR_FROM_BNO055(float *q)
{
	float gv_x,gv_y,gv_z;	
	uint8_t gv_data[6];
	
	ReadData(BNO055_I2C_ADDR2,GRV_Data_X_LSB,gv_data,6);
	
	gv_x =(int16_t)((int16_t)gv_data[1]<<8|(int16_t)gv_data[0])/100.0f;
	gv_y =(int16_t)((int16_t)gv_data[3]<<8|(int16_t)gv_data[2])/100.0f;
	gv_z =(int16_t)((int16_t)gv_data[5]<<8|(int16_t)gv_data[4])/100.0f;
	
	q[0] = gv_x;
	q[1] = gv_y;
	q[2] = gv_z;
	
}



//检查传感器校准状态
uint8_t CHECK_CALIB_STAT()
{
	uint8_t calib_stat;
	uint8_t mag_calib_stat;
	uint8_t acc_calib_stat;
	uint8_t gry_calib_stat;
	
	ReadData(BNO055_I2C_ADDR2,CALIB_STAT ,&calib_stat,1);
	
	mag_calib_stat = calib_stat & 0x03;
	acc_calib_stat = (calib_stat & 0x0C) >> 2;
	gry_calib_stat = (calib_stat & 0x20) >> 4;
	
	if(mag_calib_stat < 2){
		mag_need_cal_flag = 1;
		return 1;
	}
	
	if(acc_calib_stat<2){		
		acc_need_cal_flag = 1;
		return 1;
	}
	
	if(gry_calib_stat<2){		
		gry_need_cal_flag = 1;
		return 1;
	}
	
	return 0;
}

uint8_t CHECK_MAG_CALIB_STAT()
{
	uint8_t calib_stat;
	uint8_t mag_calib_stat;
	
	ReadData(BNO055_I2C_ADDR2,CALIB_STAT ,&calib_stat,1);
	
	mag_calib_stat = calib_stat & 0x03;
	
	if(mag_calib_stat < 2){
		mag_need_cal_flag = 1;
		return 1;
	}
	
	mag_need_cal_flag = 0;
	return 0;
}

uint8_t CHECK_ACC_CALIB_STAT()
{
	uint8_t calib_stat;
	uint8_t acc_calib_stat;
	
	ReadData(BNO055_I2C_ADDR2,CALIB_STAT ,&calib_stat,1);
	
	acc_calib_stat = (calib_stat & 0x0C) >> 2;
	
	if(acc_calib_stat < 2){
		acc_need_cal_flag = 1;
		return 1;
	}
	
	acc_need_cal_flag = 0;
	return 0;
}

uint8_t CHECK_GRY_CALIB_STAT()
{
	uint8_t calib_stat;
	uint8_t gry_calib_stat;
	
	ReadData(BNO055_I2C_ADDR2,CALIB_STAT ,&calib_stat,1);
	
	gry_calib_stat = (calib_stat & 0x20) >> 4;
	
	if(gry_calib_stat < 2){
		gry_need_cal_flag = 1;
		return 1;
	}
	
	gry_need_cal_flag = 0;
	return 0;
}



//读取传感器温度数据,单位度
uint8_t READ_TEMP_BNO055()
{
	uint8_t t;
	ReadData(BNO055_I2C_ADDR2,TEMP,&t,1);
	return t;
}

//初始化传感器
void BNO055_INIT()
{
	 uint8_t acc_config = 0x0F;
	 uint8_t mag_config = 0x1F;
	 
	 IIC1_Init(0x30);

     HAL_Delay(1000);
    
	 SET_BNO055_POWER_MODE(NORMAL_MODE);
	
	 WriteData(BNO055_I2C_ADDR2,ACC_Config,&acc_config,1);  //配置加速度计量程为+/-16g
	 WriteData(BNO055_I2C_ADDR2,MAG_Config,&mag_config,1);  //配置磁罗盘刷新速度为30hz,
	
	 SET_BNO055_OPR_MODE(NODF);

	 bno_055_delay();
    
	 CHECK_CALIB_STAT();	         //检测传感器校准状态
}


BNO055 IIC总线驱动。

#ifndef __MPUIIC_H
#define __MPUIIC_H
#include "bmo_055.h"
#include "stm32f2xx_hal.h"

void IIC1_Init(uint8_t Addr);

void BNO055_WriteByte(uint8_t DevID,uint8_t ByteAddr,uint8_t Data);
int BNO055_ReadByte(uint8_t DevID,uint8_t ByteAddr);

void WriteData(uint8_t DevID,uint8_t Addr,uint8_t *Dat,uint8_t Num);
void ReadData(uint8_t DevID,uint8_t Addr,uint8_t *Pbuf,uint8_t Num);

#endif



#include "mpuiic.h"

void IIC1_Init(uint8_t Addr)
{   
    GPIO_InitTypeDef GPIO_InitStruct;  
 
    __HAL_RCC_I2C3_CLK_ENABLE();    
    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOC_CLK_ENABLE();

    GPIO_InitStruct.Pin = GPIO_PIN_8;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF4_I2C3;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
    GPIO_InitStruct.Pin = GPIO_PIN_9;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF4_I2C3;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    
	RCC->APB1ENR |= 2<<21; 
	RCC->APB1RSTR |= 2<<21; 
	RCC->APB1RSTR &= ~(2<<21);   

	I2C3->CR1 |= 1<<15; 
	I2C3->CR1 &= ~(1<<15); 

	I2C3->CR2 |= 36 ; 

	I2C3->CCR &= ~(1<<15); 

	I2C3->CCR |= 90<<0; 

	I2C3->TRISE |= 37; 
 
	I2C3->CR1 |= 1<<6; 
	I2C3->CR1 &= ~(1<<1);

	I2C3->OAR1 &= ~(1<<15);
	I2C3->OAR1 |= 1<<14; 
	I2C3->OAR1 |= Addr<<1; 

 
	I2C3->CR2 |= 1<<8; 

	I2C3->CR1 |= 1<<0;	
		
	HAL_GPIO_WritePin(GPIOC,GPIO_PIN_9,GPIO_PIN_SET);
	HAL_GPIO_WritePin(GPIOA,GPIO_PIN_8,GPIO_PIN_SET);
}

void BNO055_WriteByte(uint8_t DevID,uint8_t ByteAddr,uint8_t Data)
{
	int clear;

	clear=clear;
	
	while(I2C3->SR2&=1<<1);
	I2C3->CR1 |= 1<<8; 

	while(!(I2C3->SR1&=1<<0));
	I2C3->SR1 &= ~(1<<10);
	I2C3->DR = DevID << 1|0;

	while(!(I2C3->SR1&=1<<1));
	clear=I2C3->SR1;
	clear=I2C3->SR2;
	I2C3->DR = ByteAddr;

	while(!(I2C3->SR1&=1<<2));
	clear=I2C3->SR1;
	I2C3->DR = Data;

	while(!(I2C3->SR1&=1<<2));

	I2C3->CR1 |= 1<<9; 
}

int BNO055_ReadByte(uint8_t DevID,uint8_t ByteAddr)
{
	int clear;
	clear=clear;
	while(I2C3->SR2&=1<<1);             
	I2C3->CR1 |= 1<<8;                 

	while(!(I2C3->SR1&=1<<0));          
	I2C3->SR1 &= ~(1<<10);              
	I2C3->DR = DevID <<1|0;            

	while(!(I2C3->SR1&=1<<1));          
	clear=I2C3->SR1;
	clear=I2C3->SR2;                    
	I2C3->DR = ByteAddr;                

	I2C3->CR1 |= 1<<8;                  

	while(!(I2C3->SR1&=1<<0));          
	I2C3->SR1 &= ~(1<<10);              
	I2C3->DR = DevID <<1|1;            

	while(!(I2C3->SR1&=1<<1));          
	clear=I2C3->SR1;                    
	clear=I2C3->SR2;                    

	while(!(I2C3->SR1&=1<<6));         
	I2C3->CR1 |= 1<<9;                 
	return I2C3->DR;
}

void I2C3_ER_IRQHandler(void)
{
	if(I2C3->SR1 & 1<<10) 
	{
		I2C3->SR1 &=~(1<<10); 
	}

	if(I2C3->SR1 & 1<<14)
	{
		I2C3->SR1 &=~(1<<14); 
	}

	if(I2C3->SR1 & 1<<11) 
	{
		I2C3->SR1 &=~(1<<11); 
	}

	if(I2C3->SR1 & 1<<9) 
	{
		I2C3->SR1 &=~(1<<9); 
	}

	if(I2C3->SR1 & 1<<8) 
	{
		I2C3->SR1 &=~(1<<8); 
	}
}

void ReadData(uint8_t DevID,uint8_t Addr,uint8_t *Pbuf,uint8_t Num)
{
	uint8_t i,x_addr;
	x_addr = Addr;
	
	for( i = 0;i < Num; i++){		
		Pbuf[i] = BNO055_ReadByte(DevID,x_addr);
		x_addr++;		
	}
	
}

void WriteData(uint8_t DevID,uint8_t Addr,uint8_t *Dat,uint8_t Num)
{
	uint8_t i,a_addr;
    a_addr = Addr;
	
	for(i = 0 ;i < Num; i++){
		
		BNO055_WriteByte(DevID,a_addr,Dat[i]);
		a_addr++;
	}	
	
}



运动姿态控制。

#ifndef __MOTION_CONTROL_H
#define __MOTION_CONTROL_H

#include "stm32f2xx_hal.h"
#include "attitude_pid.h"
#include "stdlib.h"
#include "publish.h"

#define MOTION_MAX_SPEED_LIMIT  5040
#define MOTION_MAX_SPEED        5000

#define FRAME_HEAD_1            0XB5                      //帧头1
#define FRAME_HEAD_2            0X5B                      //帧头2
#define FRAME_TAIL              0XFF                      //帧尾
#define MOVE                    0X70                      //移动控制标志位
#define REPORT                  0X80                      //汇报标志位
#define HEAD_UNLOCK             0X90                      //解锁航向锁定
#define HEAD_LOCK               0XA0                      //启动航向锁定
#define ZERO_POINT_SET          0XB0                      //航向零点设置标志位


/
#define  MIN_GLOBAL_MOTOR_SPEED       (0.0f)
#define  DEFAULT_MOTOR_SPEED          (3500.0f)
#define  MAX_GLOBAL_MOTOR_SPEED       (4000.0f)



extern bool HEADING_LOCK_FLAG;
extern bool power_on;

extern bool motion_state;
extern bool test_flag;
extern bool zero_point_set_flag;

///
extern __IO uint16_t global_motor_speed;
//


/**********底盘控制数据解析函数***********
    *buf :输入接收到的数据包
    l:数据包的长度
    
    请勿调用改函数
    无返回值
******************************************/
void Motion_control_data_analysis(uint8_t * buf,uint8_t l);         

/**********动力混合器*********************
    x:机体x轴方向控制数据
    y:机体Y轴方向控制数据
    z:航向控制数据
    
    允许调用该函数。
    无返回值
******************************************/
void Motor_mixer(int16_t x,int16_t y,int16_t z);                    

/**********底盘控制系统主要执行函数*********************  

    允许调用该函数
    无返回值
******************************************/
void Attitude_system(void);                                        

/**********底盘控制系统初始化函数*********************  

    允许调用该函数
    无返回值
******************************************/
void System_init(void);

/**********底盘复位程序*********************  
    调用该函数,底盘将会回到0度。
    
    允许调用该函数
    无返回值
******************************************/
void Reset_body_yaw(void);

/**********底盘停止*********************  
    调用该函数,底盘将会停止移动。
    
    允许调用该函数
    无返回值
******************************************/
void Body_stop(void);

/**********底盘前进与后退*********************  
    调用该函数,底盘将会前进或后退
    speed:正数前进,负数后退,范围+-3600
    
    允许调用该函数
    无返回值
******************************************/
void Body_move_FB(int16_t speed);

/**********底盘左右移动*********************  
    调用该函数,底盘将会前进或后退
    speed:正数前进,负数后退,范围+-3600
    
    允许调用该函数
    无返回值
******************************************/
void Body_move_LR(int16_t speed);

/**********底盘旋转功能*********************  
    调用该函数,底盘将会前进或后退
    speed:正数顺时针,负数逆时针,范围+-360
    
    允许调用该函数
    无返回值
******************************************/
void Body_rotate(int16_t speed);





/*直线运动通过对X,Y 赋值操作来完成,确保走的直*/
void moveFront(uint8_t speedLevel);
void moveBack (uint8_t speedLevel);
void moveLeft (uint8_t speedLevel);
void moveRight(uint8_t speedLevel);
/*旋转:只要4个轮子方向相同即可,直接控制PWM*/
void rotateClockWise(uint8_t speedLevel);
void rotageAntiClock(uint8_t speedLevel);
/*停止:马达驱动芯片输入高电平,刹车*/
void bottomStop(void);
/*复位:芯片RESET并把角度等参数置0*/
void bottomReset(void);

void wheelTest(uint8_t data);

void Move_control(void);

#endif






#include "tim.h"
#include "Motion_control.h"
#include "motor_control.h"
#include "publish.h"
#include "bmo_055.h"

#include "protocol.h"
#include "version.h"


#ifdef BUSINESS_SHOP_VERSION_ENABLE	
		 //使能倒下检测 
		#define FALL_DOWN_CHECK
#endif


bool HEADING_LOCK_FLAG = FALSE;
bool power_on = (BOOLEAN)0;
bool motion_state = (BOOLEAN)0;
bool test_flag = (BOOLEAN)0;
bool zero_point_set_flag = (BOOLEAN)0;


float euler_angle[3];
float angular_velocity[3];



void System_init()
{     
    BNO055_INIT();
	
    AttitudeControlInit(); 
}



void Attitude_system()
{
	  
	  static float gry_z_old[4]; 
	
    int32_t age = 0;
    
    float gry_z = 0;
    
	  #ifdef FALL_DOWN_CHECK
	  static int fall_down_cnt = 0;
	  uint8_t usrdata[2] = {FALLDOWN,0x00};
		#endif
	
		//printCMDxyz(robot_attitude_data.x_speed,robot_attitude_data.y_speed,robot_attitude_data.desiredAngle);
	
    if(HEADING_LOCK_FLAG == FALSE)
		{
        
			  READ_EUL_FROM_BNO055(euler_angle);//yaw:euler_angle[2] 范围为[0~359],上电为0 _20190111
			  //	printCMDxyz(99, 99,euler_angle[2]);
			
        READ_GRY_FROM_BNO055(angular_velocity);       
        
        age = Transformation_angle_mode(euler_angle[2]);//直接使用读取的yaw
			  //转换后范围:[-180~179],第一调用计0。  顺时针增大,逆时针减小。 _20190111    
        //printCMDxyz(robot_attitude_data.x_speed, robot_attitude_data.y_speed,age);
			
        robot_attitude_data.actualAngle = age;
        gry_z = angular_velocity[2];//陀螺仪数据
        
        if(power_on == 0){
            gry_z_old[0] = 0;
            gry_z_old[1] = 0;
            gry_z_old[2] = 0;          
        }
                    
        robot_attitude_data.actualRate = ( gry_z + gry_z_old[0] + gry_z_old[1] + gry_z_old[2] ) / 4;
        
        gry_z_old[0] = gry_z_old[1];
        gry_z_old[1] = gry_z_old[0];//多余代码? _paul 20190116
        gry_z_old[2] = robot_attitude_data.actualRate;    
        
//        printf("a = %d,  s = %d  Rate = %d\r\n",robot_attitude_data.actualAngle,robot_attitude_data.desiredAngle,robot_attitude_data.actualRate);
        
        if(power_on == 0){            
            robot_attitude_data.desiredAngle = age;         
        }				
				
        StateControl(&robot_attitude_control,&robot_attitude_data);
    
        Move_control();
	
        //motor_move_flag = (BOOLEAN)1;          
        
        power_on = (BOOLEAN)1;

				
        //机器倒下检测 
        #ifdef FALL_DOWN_CHECK 
//				{
//					 
//					 uint8_t datas[30] = {0};
//					 sprintf(datas,"pitch=%f\troll=%f\n",euler_angle[0],euler_angle[1]);
//					 USART1_SendBuf(datas,strlen(datas));
//					
//					 uint8_t datas[30] = {0};
//					 sprintf(datas,"roll=%f\n",euler_angle[1]);
//					 USART1_SendBuf(datas,strlen(datas));
//				}

				/**
				统一机体从后背包往前看,euler_angle[0]:pitch,euler_angle[1]:roll
				经测试发现 pitch以当前竖直为0度,向前仰为0--(-180°),向后仰为0--(+180°)
				            roll以当前竖直为0度,向左为0--(-90°)---0,向右为0--(+90°)---0
				**/
				
				//前边倒,后边倒
				if(euler_angle[0] < -45.0f || euler_angle[0] > 45.0f ||
					//左边倒,右边倒
					euler_angle[1] < -45.0f || euler_angle[1] > 45.0f)
				{
					  //1s = 20 * 50
					  if(!(++fall_down_cnt % 50))
				    {							
	             usrdata[1] = 0x01;
							
							 Build_Send_Protocol(SENSOR_ECHO_CTL,usrdata,sizeof(usrdata));							  
						}
				}
				else{
					
					  if(fall_down_cnt >= 50)
						{
							  usrdata[1] = 0x00;
							
							  Build_Send_Protocol(SENSOR_ECHO_CTL,usrdata,sizeof(usrdata));
							  //try send once
							  Build_Send_Protocol(SENSOR_ECHO_CTL,usrdata,sizeof(usrdata));
						}
					
					  fall_down_cnt = 0;
				}
        #endif				
    }    
      
}




void Move_control(void)
{
    int16_t turn_speed = 0;  
    
    if(robot_attitude_control.yaw < 800  && robot_attitude_control.yaw > -800){        
        turn_speed = 0;        
    }else {
			  //旋转速度特殊定义  
        turn_speed = robot_attitude_control.yaw * 0.11f;
    } 
    
    if(robot_attitude_data.x_speed > 4500) robot_attitude_data.x_speed = 1700;
    if(robot_attitude_data.x_speed < -4500) robot_attitude_data.x_speed = -1700;
    if(robot_attitude_data.y_speed > 4500) robot_attitude_data.y_speed = 1700;
    if(robot_attitude_data.y_speed < -4500) robot_attitude_data.y_speed = -1700;    

    Motor_mixer(robot_attitude_data.x_speed,robot_attitude_data.y_speed,turn_speed);    
        
}



void Motor_mixer(int16_t x,int16_t y,int16_t z)
{
    float set_corrct_Percentage = 0;
//    float k = 0.045;
//    static int16_t x_last = 0,y_last = 0;
    static int16_t err = 0;
    
    int16_t motor_1_power = 0;
    int16_t motor_2_power = 0;
    int16_t motor_3_power = 0;
    int16_t motor_4_power = 0;   
    
	  //
	  float speed_factor    = global_motor_speed / MAX_GLOBAL_MOTOR_SPEED;
	  //
	
    if(x == 0 && y == 0){ 
         
		//旋转速度区分点 
        set_corrct_Percentage = 1;
        
        if(z > 0){
            z = z + 500;
        }else if(z < 0){  
            z = z - 500;         
        }   
        
//        x_last = 0;
//        y_last = 0;
        
        err = 0;
        
		//旋转速度不可调速 
		speed_factor = 1.0f;
				
    }else {  
        
        set_corrct_Percentage = 1.27; 
        
//        x = x * k + x_last * (1 - k);
//        y = y * k + y_last * (1 - k);
			  
			  //取消渐加速 
        x = x;
		y = y;
			  
			
//        x_last = x;
//        y_last = y;  

        if(x > 0){
            x = x + 200;
        }else if(x < 0){
            x = x - 200; 
        }
        
        if(y > 0){
            y = y + 200;
        }else if(y < 0){
            y = y - 200; 
        }
        
    }    
    
    
     motor_1_power = x     -  y  +  z  *  set_corrct_Percentage;
     motor_2_power = (-x)  -  y  +  z  *  set_corrct_Percentage;
     motor_3_power = (-x)  +  y  +  z  *  set_corrct_Percentage;
     motor_4_power = x     +  y  +  z  *  set_corrct_Percentage;       
    


    /**
		 通过手机app调整转速,调整区间为0--4000
		 */
    if(motor_1_power >= 0){       
        motor_p.MOTOR_1.turn_x = 2;
        motor_p.MOTOR_1.speed                                = (motor_1_power - err) * speed_factor;
    }else {
        motor_p.MOTOR_1.turn_x = 1;
        motor_p.MOTOR_1.speed                                = (- motor_1_power + err) * speed_factor;                
    }

		
    if(motor_2_power >= 0){       
        motor_p.MOTOR_2.turn_x = 2;
        motor_p.MOTOR_2.speed                                = (motor_2_power) * speed_factor;
    }else {
        motor_p.MOTOR_2.turn_x = 1;
        motor_p.MOTOR_2.speed                                = (- motor_2_power) * speed_factor;                
    }

		
    if(motor_3_power >= 0){       
        motor_p.MOTOR_3.turn_x = 2;
        motor_p.MOTOR_3.speed                                = (motor_3_power - err) * speed_factor;
    }else {
        motor_p.MOTOR_3.turn_x = 1;
        motor_p.MOTOR_3.speed                                = (- motor_3_power + err) * speed_factor;                
    }

		
    if(motor_4_power >= 0){       
        motor_p.MOTOR_4.turn_x = 2;
        motor_p.MOTOR_4.speed                                = (motor_4_power) * speed_factor;
    }else {
        motor_p.MOTOR_4.turn_x = 1;
        motor_p.MOTOR_4.speed                                = (- motor_4_power) * speed_factor;                
    } 

    
    if(motor_p.MOTOR_1.speed > MOTION_MAX_SPEED_LIMIT) motor_p.MOTOR_1.speed = MOTION_MAX_SPEED;
    if(motor_p.MOTOR_2.speed > MOTION_MAX_SPEED_LIMIT) motor_p.MOTOR_2.speed = MOTION_MAX_SPEED;
    if(motor_p.MOTOR_3.speed > MOTION_MAX_SPEED_LIMIT) motor_p.MOTOR_3.speed = MOTION_MAX_SPEED;
    if(motor_p.MOTOR_4.speed > MOTION_MAX_SPEED_LIMIT) motor_p.MOTOR_4.speed = MOTION_MAX_SPEED;
    
    if(x == 0 && y == 0){      
        Motor_control(motor_p,0); 
    }else {
        Motor_control(motor_p,0);
    }        
} 
    



/*
 IN1  IN2     功能
  L    L    待机/滑行
  H    H      刹车
 PWM   L      正转
  L   PWM     反转  
*/

void bottomReset(void);
void moveFront(uint8_t speedLevel);
void moveBack (uint8_t speedLevel);
void moveLeft (uint8_t speedLevel);
void moveRight(uint8_t speedLevel);
/*旋转:只要4个轮子方向相同即可,直接控制PWM*/
void rotateClockWise(uint8_t speedLevel);
void rotageAntiClock(uint8_t speedLevel);
/*停止:马达驱动芯片输入高电平,刹车*/
void bottomStop(void);




static void wheelSpeedZero(void)
{
    TIM3->CCR1 = 0;    TIM3->CCR2 = 0;    TIM3->CCR3 = 0;      TIM3->CCR4 = 0;
    TIM4->CCR1 = 0;    TIM4->CCR2 = 0;    TIM4->CCR3 = 0;      TIM4->CCR4 = 0; 
}


void bottomReset(void)
{
	   zero_piont_set_flag = FALSE;
}


#define SPEED_TEST_VAL 4900

void wheelTest(uint8_t data)
{
		  uint8_t uWhellNum = (data&0xF0) >>4;
		  uint8_t uDirs = data&0x0F;	
		  if(uWhellNum>4 ||  uDirs>1 )
				return ;
	
			wheelSpeedZero();
			
			if(uWhellNum ==1){     //1号电机——已经测试20190125
				if(!uDirs)TIM3->CCR4 = SPEED_TEST_VAL;  //CD1010--逆时针
				else 			TIM3->CCR3 = SPEED_TEST_VAL;  //CD1011--顺时针
			}
			else if(uWhellNum ==2){ //2号电机——已经测试20190125
				if(!uDirs)TIM3->CCR2 = SPEED_TEST_VAL;  //CD1020--逆时针
				else 			TIM3->CCR1 = SPEED_TEST_VAL;	//CD1021--顺时针		
			}
			else if(uWhellNum ==3){ //3号电机——已经测试20190125
				if(!uDirs)TIM4->CCR4 = SPEED_TEST_VAL;	//CD1030--逆时针
				else 			TIM4->CCR3 = SPEED_TEST_VAL;	//CD1031--顺时针
			}
			else if(uWhellNum ==4){ //4号电机
				if(!uDirs)TIM4->CCR2 = SPEED_TEST_VAL;	//CD1040--逆时针
				else 			TIM4->CCR1 = SPEED_TEST_VAL;	//CD1041--顺时针	
			}
	
}


void rotateClockWise(uint8_t speedLevel)
{//顺时针
//	  uint16_t speedABS = MOTOR_MAX_SPPPE*speedLevel/10;	
//		Motor_stop();	
//    TIM4->CCR1 = speedABS;   //4号电机
//    TIM4->CCR2 = 0;
//    
//    TIM3->CCR1 = speedABS;	 //2号电机
//    TIM3->CCR2 = 0;   			

//    TIM4->CCR3 = speedABS;   //3号电机
//    TIM4->CCR4 = 0;
//    
//    TIM3->CCR3 = speedABS;   //1号电机
//    TIM3->CCR4 = 0; 
}



void rotageAntiClock(uint8_t speedLevel)
{//逆时针
//	  uint16_t speedABS = MOTOR_MAX_SPPPE*speedLevel/10;	
//		Motor_stop();
//    TIM4->CCR1 = 0;   //4号电机
//    TIM4->CCR2 = speedABS;
//    
//    TIM3->CCR1 = 0;   //2号电机
//    TIM3->CCR2 = speedABS;

//    TIM4->CCR3 = 0;   //3号电机
//    TIM4->CCR4 = speedABS;
//    
//    TIM3->CCR3 = 0;   //1号电机
//    TIM3->CCR4 = speedABS;
}



//MOTOR_MAX_SPPPE?
void moveFront(uint8_t speedLevel)
{
	  uint16_t speedABS = MOTOR_MAX_SPPPE*speedLevel/10;
		robot_attitude_data.y_speed = 0;   	
		robot_attitude_data.x_speed = speedABS;
}


void moveBack (uint8_t speedLevel)
{
	  uint16_t speedABS = MOTOR_MAX_SPPPE*speedLevel/10;
		robot_attitude_data.y_speed = 0;   	
		robot_attitude_data.x_speed = 0-speedABS;
}


void moveRight (uint8_t speedLevel)
{
	  uint16_t speedABS = MOTOR_MAX_SPPPE*speedLevel/10;
		robot_attitude_data.x_speed = 0;   	
		robot_attitude_data.y_speed = speedABS;	
}


void moveLeft (uint8_t speedLevel)
{
	  uint16_t speedABS = MOTOR_MAX_SPPPE*speedLevel/10;
		robot_attitude_data.x_speed = 0;   	
		robot_attitude_data.y_speed = 0-speedABS;	
}



void bottomStop(void)
{	
#if 1
		Motor_stop();
		bottomReset();
	
		robot_attitude_data.x_speed      = 0;   	
		robot_attitude_data.y_speed      = 0;	
		robot_attitude_data.desiredAngle = 0;	
#else		
	//关闭定时器,PWM全输出高电平,轮子刹车	
	//HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_1);	
#endif
		
}
#ifndef __ATTITUDE_PID_H
#define __ATTITUDE_PID_H

#include "stm32f2xx_hal.h"
#include "pid.h"
#include "Heading_lock.h"
#include "publish.h"

#define SENSOR9_UPDATE_RATE   	50                                    //底盘PID执行频率
#define SENSOR9_UPDATE_DT     	(1/SENSOR9_UPDATE_RATE)               //底盘PID执行周期


//#pragma pack(1)
typedef struct 
{
	int32_t x;
	int32_t y;
	int32_t z;
} Axis3f;


//#pragma pack(1)
typedef struct                          //底盘主要数据结构体
{
		uint32_t timestamp;	                //时间戳    
		int32_t DesiredRate_z;              //目标角速度
		int32_t angle_err;                  //角度差
	
		int16_t actualRate;                 //当前机体角速度	
	
		int16_t actualAngle;                //当前机体角度
	
__IO	int16_t desiredAngle;              //目标角度,改变此角度可以旋转机体,范围+-180度                   



__IO int16_t x_speed;                    //机体前进与后退的速度值,范围+-4000,前进为正值。

__IO int16_t y_speed;                    //机体左右移动的速度值,范围+-4000,右移为正值。
    
} attitude_t;


//#pragma pack(1)
typedef struct
{
	int16_t roll;
	int16_t pitch;
	int16_t yaw;
    
} control_t;


extern attitude_t robot_attitude_data;
extern control_t robot_attitude_control;
extern control_t robot_rc_control;

/**********底盘姿态控制初始化*********************  
    
    请勿调用该函数
    无返回值
******************************************/
void AttitudeControlInit(void);  

/**********底盘姿态PID算法*********************  
    *attitude_data:底盘数据结构体

    请勿调用该函数
    无返回值
******************************************/
void AttitudeAnglePID(attitude_t *attitude_data);	 

/*******************************  
    *attitude_data:底盘数据结构体
    *control:控制数据的结构体
    
    请勿调用该函数
    无返回值
******************************************/
void StateControl(control_t *control,attitude_t *attitude_data);   //姿态控制主函数     


#endif

#include "attitude_pid.h"
#include "publish.h"

PidObject pidAngleYaw;
PidObject pidRateYaw;

pidInit_t AngleYaw;
pidInit_t RateYaw;

attitude_t robot_attitude_data;

control_t robot_attitude_control;

int16_t pidOutLimit(int32_t in)
{
	if (in > INT16_MAX)
		return INT16_MAX;
	else if (in < -INT16_MAX)
		return -INT16_MAX;
	else
		return (int16_t)in;
}

void AttitudeControlInit()
{
	AngleYaw.kp = 11.7;
	AngleYaw.ki = 0.0;
	AngleYaw.kd = 12.5;                                                      

	RateYaw.kp = 36.5;
	RateYaw.ki = 6.0;
	RateYaw.kd = 0.0;	
    
	pidInit(&pidAngleYaw, 0, AngleYaw, SENSOR9_UPDATE_DT);	            /*yaw   角度PID初始化*/
	pidSetIntegralLimit(&pidAngleYaw, PID_ANGLE_YAW_INTEGRATION_LIMIT);		/*yaw   角度积分限幅设置*/
	
	pidInit(&pidRateYaw, 0, RateYaw, SENSOR9_UPDATE_DT);	            /*yaw   角速度PID初始化*/
	pidSetIntegralLimit(&pidRateYaw, PID_RATE_YAW_INTEGRATION_LIMIT);		/*yaw   角速度积分限幅设置*/
}


void AttitudeAnglePID(attitude_t *attitude_data)	/* 角度环PID */    
{   
    attitude_data->DesiredRate_z =  pidUpdate(&pidAngleYaw, attitude_data->angle_err);
}

void AttitudeRatePID(attitude_t *attitude_data,control_t *output)	/* 角速度环PID */
{    
    output->yaw = pidOutLimit(pidUpdate(&pidRateYaw, attitude_data->DesiredRate_z - attitude_data->actualRate));
    
}

void StateControl(control_t *control,attitude_t *attitude_data)
{	
    
	Calculating_angle_error(attitude_data->desiredAngle, attitude_data->actualAngle);
    
	AttitudeRatePID(attitude_data, control);				/* 角速度(内环)PID */    

}

双环PID控制。

#ifndef __PID_H
#define __PID_H
#include "stm32f2xx_hal.h"
#include "publish.h"

/*角度环积分限幅*/
#define PID_ANGLE_YAW_INTEGRATION_LIMIT     167

/*角速度环积分限幅*/
#define PID_RATE_YAW_INTEGRATION_LIMIT		360

#define DEFAULT_PID_INTEGRATION_LIMIT  		4000

typedef struct 
{
	float kp;
	float ki;
	float kd;
} pidInit_t;

typedef struct
{
	int32_t desired;		//< set point
	int32_t error;        //< error
	int32_t prevError;    //< previous error
	int32_t integ;        //< integral
	int32_t deriv;        //< derivative
	int32_t kp;           //< proportional gain
	int32_t ki;           //< integral gain
	int32_t kd;           //< derivative gain
	int32_t outP;         //< proportional output (debugging)
	int32_t outI;         //< integral output (debugging)
	int32_t outD;         //< derivative output (debugging)
	int32_t iLimit;       //< integral limit
	int32_t iLimitLow;    //< integral limit
	int32_t dt;           //< delta-time dt
} PidObject;

/*********PID积分限幅*********************
    pid:pid数据结构体
    limit:限制值

    请勿调用该函数。
    无返回值
******************************************/
void pidSetIntegralLimit(PidObject* pid, int32_t limit);

/*********PID初始化函数*********************
    pid:pid数据结构体
    desired:目标值
    pidParam:pid参数结构体
    dt:积分时间

    请勿调用该函数。
    无返回值
******************************************/
void pidInit(PidObject* pid, int32_t desired, const pidInit_t pidParam, int32_t dt);

/**********PID计算函数*********************
    pid:pid数据结构体
    error:误差

    请勿调用该函数。
    返回计算结果
******************************************/
int32_t pidUpdate(PidObject* pid, int32_t error);			                              

/**********姿态控制初始化*********************
    pid:pid数据结构体
    error:误差

    请勿调用该函数。
    返回计算结果
******************************************/
void attitudeControlInit(void);

#endif /* __PID_H */
#include "pid.h"

void pidInit(PidObject* pid, int32_t desired, const pidInit_t pidParam, int32_t dt)
{
	pid->error     = 0;
	pid->prevError = 0;
	pid->integ     = 0;
	pid->deriv     = 0;
	pid->desired = desired;
	pid->kp = pidParam.kp;
	pid->ki = pidParam.ki;
	pid->kd = pidParam.kd;
	pid->iLimit    = DEFAULT_PID_INTEGRATION_LIMIT;
	pid->iLimitLow = -DEFAULT_PID_INTEGRATION_LIMIT;
	pid->dt        = dt;
}

int32_t pidUpdate(PidObject* pid, int32_t error)
{
	float output;

	pid->error = error;   

	pid->integ += pid->error * pid->dt;
	if (pid->integ > pid->iLimit)
	{
		pid->integ = pid->iLimit;
	}
	else if (pid->integ < pid->iLimitLow)
	{
		pid->integ = pid->iLimitLow;
	}

	pid->deriv = (pid->error - pid->prevError) / pid->dt;

	pid->outP = pid->kp * pid->error;
	pid->outI = pid->ki * pid->integ;
	pid->outD = pid->kd * pid->deriv;

	output = pid->outP + pid->outI + pid->outD;

	pid->prevError = pid->error;

	return output;
}

void pidSetIntegralLimit(PidObject* pid, int32_t limit) 
{
    pid->iLimit = limit;
}

void pidSetIntegralLimitLow(PidObject* pid, int32_t limitLow) 
{
    pid->iLimitLow = limitLow;
}

void pidReset(PidObject* pid)
{
	pid->error     = 0;
	pid->prevError = 0;
	pid->integ     = 0;
	pid->deriv     = 0;
}

void pidSetError(PidObject* pid, int32_t error)
{
	pid->error = error;
}

void pidSetDesired(PidObject* pid, int32_t desired)
{
	pid->desired = desired;
}

int32_t pidGetDesired(PidObject* pid)
{
	return pid->desired;
}

uint8_t pidIsActive(PidObject* pid)
{
	uint8_t isActive = 1;

	if (pid->kp < 0.0001f && pid->ki < 0.0001f && pid->kd < 0.0001f)
	{
		isActive = 0;
	}

	return isActive;
}

void pidSetKp(PidObject* pid, int32_t kp)
{
	pid->kp = kp;
}

void pidSetKi(PidObject* pid, int32_t ki)
{
	pid->ki = ki;
}

void pidSetKd(PidObject* pid, int32_t kd)
{
	pid->kd = kd;
}

void pidSetDt(PidObject* pid, int32_t dt) 
{
    pid->dt = dt;
}

电机运动方式控制。

#ifndef __motor_control_h
#define __motor_control_h

#include "stm32f2xx_hal.h"
#include "publish.h"

#define MOTOR_MAX_SPPPE  5040                //马达最大限速

typedef struct 
{
   uint8_t turn_x;
   uint16_t speed;
} _MOTOR;

typedef struct 
{
   _MOTOR MOTOR_1;
   _MOTOR MOTOR_2;
   _MOTOR MOTOR_3;
   _MOTOR MOTOR_4;
    
} _MOTOR_CONTROL;

extern _MOTOR_CONTROL motor_c;
extern _MOTOR_CONTROL motor_p;
extern _MOTOR_CONTROL motor_A;

extern uint16_t last_m1,last_m2,last_m3,last_m4;

/*******马达控制程序***********************
    m:马达控制数据结构体
    x:马达使能标志位

    请勿调用该函数。
    无返回值
******************************************/
void Motor_control(_MOTOR_CONTROL m,uint8_t x);             //马达控制函数

/*********马达停止*********************

    请勿调用该函数。
    无返回值
******************************************/
void Motor_stop(void);                                      //刹车函数

#endif

#include "motor_control.h"
#include "Motion_control.h"

_MOTOR_CONTROL motor_c;
_MOTOR_CONTROL motor_p;

_MOTOR_CONTROL motor_A;

uint16_t last_m1 = 0 ,last_m2 = 0 ,last_m3 = 0 ,last_m4 = 0;

void Motor_control(_MOTOR_CONTROL m,uint8_t x)
{                                           
    float k = 0.045;
 
    uint16_t m1_set = 0,m2_set = 0,m3_set = 0, m4_set = 0; 
                                                                                                            
    uint16_t m1_T1 = 0, m2_T1 = 0, m3_T1 = 0, m4_T1 = 0;                                                                   
    uint16_t m1_T2 = 0, m2_T2 = 0, m3_T2 = 0, m4_T2 = 0; 
    
    if(x == 1){
        
        m1_set = last_m1 * (1 - k) +  m.MOTOR_1.speed * k;
        m2_set = last_m2 * (1 - k) +  m.MOTOR_2.speed * k;
        m3_set = last_m3 * (1 - k) +  m.MOTOR_3.speed * k;                  
        m4_set = last_m4 * (1 - k) +  m.MOTOR_4.speed * k;
                                                                                                          
        last_m1 = m1_set;
        last_m2 = m2_set;
        last_m3 = m3_set;
        last_m4 = m4_set;
    }
    
    if(x == 0){

        m1_set = m.MOTOR_1.speed;
        m2_set = m.MOTOR_2.speed;
        m3_set = m.MOTOR_3.speed;
        m4_set = m.MOTOR_4.speed; 
 
        last_m1 = 0;
        last_m2 = 0;
        last_m3 = 0;
        last_m4 = 0;        
        
    }
        
//**************电机1**********************     
   if(m.MOTOR_1.turn_x == 1){

        m1_T1 = MOTOR_MAX_SPPPE;
        m1_T2 = MOTOR_MAX_SPPPE - m1_set;
               
    }
   if(m.MOTOR_1.turn_x == 2){
        
        m1_T1 = MOTOR_MAX_SPPPE - m1_set;
        m1_T2 = MOTOR_MAX_SPPPE;        
    }
    

//*************电机2***********************    
    if(m.MOTOR_2.turn_x == 1){

        m2_T1 = MOTOR_MAX_SPPPE - m2_set;
        m2_T2 = MOTOR_MAX_SPPPE;        
                
    }
    if(m.MOTOR_2.turn_x == 2){
        
        m2_T1 = MOTOR_MAX_SPPPE;
        m2_T2 = MOTOR_MAX_SPPPE - m2_set;   
        
    }  

//***********电机3*****************************
    if(m.MOTOR_3.turn_x == 1){
        
        m3_T1 = MOTOR_MAX_SPPPE;
        m3_T2 = MOTOR_MAX_SPPPE - m3_set; 
  
    }
    if(m.MOTOR_3.turn_x == 2){
        
        m3_T1 = MOTOR_MAX_SPPPE - m3_set;
        m3_T2 = MOTOR_MAX_SPPPE;        
    }

//*****************电机4*************************
    
    if(m.MOTOR_4.turn_x == 1){
        
        m4_T1 = MOTOR_MAX_SPPPE - m4_set;
        m4_T2 = MOTOR_MAX_SPPPE;  
        
    }
    if(m.MOTOR_4.turn_x == 2){
        
        m4_T1 = MOTOR_MAX_SPPPE;
        m4_T2 = MOTOR_MAX_SPPPE - m4_set; 
        
    }

//**********************************************   
    
    TIM4->CCR1 = m1_T1;   //4号电机
    TIM4->CCR2 = m1_T2;
    
    TIM3->CCR2 = m2_T1;   //2号电机
    TIM3->CCR1 = m2_T2;

    TIM4->CCR3 = m3_T1;   //3号电机
    TIM4->CCR4 = m3_T2;
    
    TIM3->CCR4 = m4_T1;   //1号电机
    TIM3->CCR3 = m4_T2;   
}



void Motor_stop()
{
    TIM3->CCR1 = MOTOR_MAX_SPPPE;
    TIM3->CCR2 = MOTOR_MAX_SPPPE;
    
    TIM4->CCR1 = MOTOR_MAX_SPPPE;
    TIM4->CCR2 = MOTOR_MAX_SPPPE;

    TIM3->CCR3 = MOTOR_MAX_SPPPE;
    TIM3->CCR4 = MOTOR_MAX_SPPPE;

    TIM4->CCR3 = MOTOR_MAX_SPPPE;
    TIM4->CCR4 = MOTOR_MAX_SPPPE;        
}


芯片校准。

#ifndef __BNO055_CALIBRATION__
#define __BNO055_CALIBRATION__

#include "stm32f2xx.h"
#include "mpuiic.h"
#include "delay.h"
#include "boot_act.h"
#include "at24c02.h"


#define  BNO055_CALIB_STAT_ADDR     (0x35)
#define  BNO055_OPR_MODE_ADDR       (0x3D)
#define  ACCEL_OFFSET_X_LSB_ADDR    (0x55)
#define  MAG_OFFSET_X_LSB_ADDR      (0x5B)

#define IS_CALIBRATE_OK_CNT         (1000)




typedef struct
{
	uint8_t cali_mag[6]; 
	uint8_t cali_acc[6]; 
}cali_msg_t;

typedef enum
{
	/* Operation mode settings*/
	OPERATION_MODE_CONFIG                                   = 0x00,
	OPERATION_MODE_ACCONLY                                  = 0x01,
	OPERATION_MODE_MAGONLY                                  = 0x02,
	OPERATION_MODE_GYRONLY                                  = 0x03,
	OPERATION_MODE_ACCMAG                                   = 0x04,
	OPERATION_MODE_ACCGYRO                                  = 0x05,
	OPERATION_MODE_MAGGYRO                                  = 0x06,
	OPERATION_MODE_AMG                                      = 0x07,
	OPERATION_MODE_IMUPLUS                                  = 0x08,
	OPERATION_MODE_COMPASS                                  = 0x09,
	OPERATION_MODE_M4G                                      = 0x0A,
	OPERATION_MODE_NDOF_FMC_OFF                             = 0x0B,
	OPERATION_MODE_NDOF                                     = 0x0C
}bno055_opmode_t;



void calibrate_init(void);


void calibrate_loop(void);


void calibrate_execute(void);


#endif //__BNO055_CALIBRATION__

/

#include "calibration.h"


#define  BOTTOM_9AXIS_CALI_ADDR                               (105)

#define  BOTTOM_9AXUS_CALI_DATA_LEN                           (12)


static uint8_t is_calibrate_ok_flag = 0;

static cali_msg_t cali_msg_data;



static uint8_t fupdataEEPROM_YawCali(void)
{	  
	
	  uint8_t  retval,trycnt = 0;
	  uint8_t  data[BOTTOM_9AXUS_CALI_DATA_LEN] = {0x00};
		
	  memcpy(data,&cali_msg_data,sizeof(data));
		
RETRY:		
	  retval = AT24_Write(data,BOTTOM_9AXIS_CALI_ADDR,sizeof(data));
	  if(HAL_OK != retval)
	  {
			if(trycnt++ > MAX_TRY_CNT){
				 return 1;
			}
				 
		    goto RETRY;
	  }
	  
	  return 0;
}




static BOOLEAN getEEData4YawCali(uint8_t *uBuf,uint8_t Len)
{

	  const uint8_t  data_00[BOTTOM_9AXUS_CALI_DATA_LEN / 2] = {0x00,0x00,0x00,0x00,0x00,0x00};
	  const uint8_t  data_ff[BOTTOM_9AXUS_CALI_DATA_LEN / 2] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
	
	  BOOLEAN  ret           = FALSE;
	  uint8_t  retval,trycnt = 0;
	
      if(Len != BOTTOM_9AXUS_CALI_DATA_LEN){
		    return FALSE;
	  }

		
RETRY:	
	 retval = AT24_Read(uBuf,BOTTOM_9AXIS_CALI_ADDR,Len);
     if(HAL_OK == retval)
	 {					 
					 
		 if(!memcmp(uBuf,data_00,sizeof(data_00))){
			return FALSE;
	 }
					
	 if(!memcmp(uBuf,data_ff,sizeof(data_ff))){
				return FALSE;
	 }
					
	   ret  = TRUE;
			 
	  }else{
				 
			if(trycnt++ > MAX_TRY_CNT){
					    return ret;
			}
         
            goto RETRY;				 
	  }   	 

	  return ret; 
}





static uint8_t is_calibrate_data_exist(void)
{
	   uint8_t uDataMPU[BOTTOM_9AXUS_CALI_DATA_LEN];				
    
		if(getEEData4YawCali(uDataMPU,BOTTOM_9AXUS_CALI_DATA_LEN))
		{
				memcpy(&cali_msg_data,uDataMPU,sizeof(uDataMPU));
			  
				return 1;
		}
		else{
			  return 0;
		}
}





static uint32_t set_calibrate_data_to_flash(cali_msg_t * p_data)
{
	  return fupdataEEPROM_YawCali();
}


static void set_bno_work_mode(bno055_opmode_t mode)
{
	  WriteData(BNO055_I2C_ADDR2, BNO055_OPR_MODE_ADDR,(uint8_t*)&mode,1);
}



static void get_bno_calibrate_data(cali_msg_t * p_data)
{
	  uint8_t tmp_bufs[6];
	
	  osMutexWait(mutex_i2c_id,osWaitForever);
	
	  set_bno_work_mode(OPERATION_MODE_CONFIG);	
	
	  osMutexRelease(mutex_i2c_id);

	  osDelay(10);

	  osMutexWait(mutex_i2c_id,osWaitForever);
	
	  ReadData(BNO055_I2C_ADDR2, ACCEL_OFFSET_X_LSB_ADDR,tmp_bufs,6);
	  memcpy(p_data->cali_acc,tmp_bufs,6);

	  ReadData(BNO055_I2C_ADDR2, MAG_OFFSET_X_LSB_ADDR,tmp_bufs,6);
	  memcpy(p_data->cali_mag,tmp_bufs,6);
		
	  set_bno_work_mode(OPERATION_MODE_NDOF);
	
	  osMutexRelease(mutex_i2c_id);
}




static uint32_t set_bno_calibrate_data(cali_msg_t * p_data)
{	
	  osMutexWait(mutex_i2c_id,osWaitForever);
	
	  set_bno_work_mode(OPERATION_MODE_CONFIG);
	
      osMutexRelease(mutex_i2c_id);
	

      osDelay(10);
	
	  osMutexWait(mutex_i2c_id,osWaitForever);
	
	  WriteData(BNO055_I2C_ADDR2, ACCEL_OFFSET_X_LSB_ADDR,(uint8_t*)p_data->cali_acc,6);	

	  WriteData(BNO055_I2C_ADDR2, MAG_OFFSET_X_LSB_ADDR,p_data->cali_mag,6);
	
	  set_bno_work_mode(OPERATION_MODE_NDOF);
	
      osMutexRelease(mutex_i2c_id);
	
	  return 0;
}





static uint32_t is_calibrate_stat_ok(void)
{
		static uint32_t state_ok_cnt = 0;
		uint8_t tmp_val;
		
		osMutexWait(mutex_i2c_id,osWaitForever);
	
		ReadData(BNO055_I2C_ADDR2, BNO055_CALIB_STAT_ADDR,&tmp_val,1);
		
	    osMutexRelease(mutex_i2c_id);
	
	
	#if 1 
			if(state_ok_cnt >= IS_CALIBRATE_OK_CNT)
				return ++state_ok_cnt;
			else			
	#endif	
		
		if((tmp_val & 0xc3) == 0xc3)
		{
			state_ok_cnt++;
		}
		else
		{
			state_ok_cnt = 0;
		}
		
		
	#if 1 	
		return state_ok_cnt;
	#else	
		if(state_ok_cnt > IS_CALIBRATE_OK_CNT)
		{
			return 0;		
		}
		else
		{
			return 1;
		}
	#endif		
}




void calibrate_init(void)
{
		if(is_calibrate_data_exist())
		{	
				set_bno_calibrate_data(&cali_msg_data); 
		}		 
}






/*************** method 1 ****************/ 
void calibrate_loop(void)
{
	
		if(is_calibrate_ok_flag)
		{
				return;
		}
		else 
		{
			
			 uint32_t uTimesOK = is_calibrate_stat_ok();
			
			 if(uTimesOK >= IS_CALIBRATE_OK_CNT)
			 {
						if(!is_calibrate_ok_flag)
						{
								is_calibrate_ok_flag = 1;
							
							  Mailbox_Send(GECMD_MAIL_BOTTOMCALIBRATE,0);
						}
			 }				
		}
}




void calibrate_execute(void)
{
		get_bno_calibrate_data(&cali_msg_data);
	
		set_calibrate_data_to_flash(&cali_msg_data);	
}






朝向锁定。

#ifndef __HEADING_LOCK_H
#define __HEADING_LOCK_H

#include "stm32f2xx_hal.h"
#include "attitude_pid.h"
#include "publish.h"

extern bool zero_piont_set_flag;

/**********角度转换函数*********************  
    a:输入角度
    
    请勿调用该函数
    无返回值
******************************************/
int32_t Transformation_angle_mode(int32_t a);              

/**********角度误差计算函数*********************  
    set:设定角度
    act:当前角度
    
    请勿调用该函数
    无返回值
******************************************/
int32_t Calculating_angle_error(int32_t set, int32_t act); 
    
#endif
#include "Heading_lock.h"
#include "Motion_control.h"

#define SET_POWERUP_ANGLE_ZERO 


bool zero_piont_set_flag = FALSE;

int32_t Transformation_angle_mode(int32_t a)
{   
    static int32_t out = 0;
    static int32_t out_age_err = 0;
    
	 /* [0~359] mapTo [-180~179]*/
    if(a >= 0 && a < 180){
        
        out = -(180 - a);
        
    }else if(a >= 180){
        
        out = a - 180;                                                      
    }
    
		
#ifdef SET_POWERUP_ANGLE_ZERO   
		 //角度复位计0
    if(zero_piont_set_flag == FALSE){
        
        out_age_err = 0 - out;
        zero_piont_set_flag = TRUE; 
        out = 0;
        
    }else {     
        out = out + out_age_err;
    }
    
    
    if(out > 180) out = -(360 - out);
    if(out < -180) out = 360 + out;
#endif    
    
    return out;
         
}


uint8_t check_quadrant(int32_t x)
{
     if( (x <= 0 ) && (x >= (-90)) ){
         
         return 1;
     }
     
     if( (x < (-90)) && (x >= (-180)) ){
         
         return 2;         
     }
     
     if( (x <= 180) && (x > 90) ){
         
         return 3;         
     }
     
     if( (x <= 90) && (x > 0) ){
         
         return 4;         
     }
     
	 return 0xFF;
}




int32_t Calculating_angle_error(int32_t set, int32_t act)
{
    uint8_t set_angle_quadrant = 0;
    uint8_t act_angle_quadrant = 0;
    uint8_t cusum = 0;
    int32_t angle_err;
    
    set_angle_quadrant = check_quadrant(set);
    act_angle_quadrant = check_quadrant(act);    
        
    if(set_angle_quadrant == act_angle_quadrant){  
        
        angle_err = act - set; 
        
    } else {
    
        cusum = set_angle_quadrant + act_angle_quadrant;
    
       switch(cusum){            
                
            case 3:  
                
                if(set_angle_quadrant == 1 && act_angle_quadrant == 2){
                    
                    angle_err = act - set;    
                }
                
                if(set_angle_quadrant == 2 && act_angle_quadrant == 1){
                     
                    angle_err = (act - set);
                }
                
                break;
            
            case 4:
                
                if(set_angle_quadrant == 1 && act_angle_quadrant == 3){
                    
                    if(set == 0){ 
                        
                        angle_err = act - set;
                        
                    }else{
                        
                        angle_err = - (360 + set - act); 
                        if(angle_err < -180)  angle_err = angle_err + 360;
                    }                        
                    
                }
                
                if(set_angle_quadrant == 3 && act_angle_quadrant == 1){
                    
                    angle_err = 360 + act - set; 
                    if(angle_err > 180) angle_err = angle_err - 360;                    
                    
                }               
                
                break;
            
            case 5:
                
                if(set_angle_quadrant == 1 && act_angle_quadrant == 4){
                    
                    if(set == 0){                      
                        angle_err = act - set;
                    }else{
                        angle_err = (act - set);
                    }
                    
                }
                
                if(set_angle_quadrant == 4 && act_angle_quadrant == 1){
                    
                    angle_err = act - set;
                    
                }

                if(set_angle_quadrant == 2 && act_angle_quadrant == 3){
                    
                    angle_err =  - (360 + set - act);
                    
                }

                if(set_angle_quadrant == 3 && act_angle_quadrant == 2){
                    
                    angle_err =  360 + act - set;
                    
                }           
              
                break;
            
            case 6: 
                
                if(set_angle_quadrant == 4 && act_angle_quadrant == 2){
                    
                    angle_err = -(set - act);
                    if(angle_err < -180) angle_err = angle_err + 360;
                    
                }

                if(set_angle_quadrant == 2 && act_angle_quadrant == 4){
                    
                    angle_err = -(360 + set - act);
                    if(angle_err < -180)  angle_err = angle_err + 360;
                    
                }                
                
                break;
                
            case 7:
                
                if(set_angle_quadrant == 3 && act_angle_quadrant == 4){
                    
                    angle_err = act - set; 
                }
                
                if(set_angle_quadrant == 4 && act_angle_quadrant == 3){
                    
                    angle_err = act - set;                                      
                }
                
                break;
                   
        }
        
    }

    if(1){
        robot_attitude_data.angle_err = angle_err;
        AttitudeAnglePID(&robot_attitude_data);
        
    }else {
        return angle_err;   
    }
    
    return 0xFF;		
}





外部调用封装。

#ifndef __BOTTOM_H__
#define __BOTTOM_H__

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "tim.h"
#include "bmo_055.h"
#include "Motion_control.h"
#include "attitude_pid.h"
#include "motor_control.h"


void checkBMO055Chip(void);

void BottomPan_Init(void);


#define BottomPan_Handle()  Attitude_system()



#endif

#include "bottom.h"

/**
底盘全局速度控制
*/
__IO uint16_t global_motor_speed                            = DEFAULT_MOTOR_SPEED;



void checkBMO055Chip(void)
{
	 if((mag_need_cal_flag != 0) || (acc_need_cal_flag != 0) || (gry_need_cal_flag != 0)) 
	 {				
		 CHECK_MAG_CALIB_STAT(); 				
	 } 
}



void BottomPan_Init(void)
{ 
		MX_TIM3_Init();
		MX_TIM4_Init();
  
	    //底盘初始化
		System_init(); 

	    //启动八通道
		HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
		HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_2);
		HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_3);
		HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_4);
		
		HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_1);
		HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_2);
		HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_3);
		HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_4); 
}



 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值