RM小白学习
RM學習
CAN控制 電機學習
typedef struct
{
uint16_t ecd;//轉子機械角度
int16_t speed_rpm;//轉速
int16_t given_current;//實際轉矩電流
uint8_t temperate;//電機溫度
int16_t last_ecd;//上次轉子機械角度
} motor_measure_t;
對于不同的電機會有不同的ID號碼在解碼中需要根據ID號進行解碼
電機編號, 0:底盤電機1號3508電機, 1:底盤電機2號3508電機,2:底盤電機3號3508電機,3:底盤電機4號3508電機;
4:yaw云臺電機6020電機; 5:pitch云臺電機6020電機; 6:撥彈電機2006電機
2. CAN數據
掌握底盤控制代碼
chassis_init(&chassis_move);
初始化電機以及PID
while (toe_is_error(CHASSIS_MOTOR1_TOE) ||toe_is_error(CHASSIS_MOTOR2_TOE) || toe_is_error(CHASSIS_MOTOR3_TOE) || toe_is_error(CHASSIS_MOTOR4_TOE) || toe_is_error(DBUS_TOE))
chassis_set_modechassis_mode_change_control_transit
(i//底盤會跟隨云臺相對角度(主要方式)ii//底盤有底盤角度控制閉環iii//底盤有旋轉速度控制iiii//底盤速度直接由輸入電流控制)
chassis_feedback_update
Vx_Set,Vy_Set,WZ_set
(選擇模式i需要將底盤坐標軸轉化到云臺坐標軸)
具體轉換公式說明可看底盤控制
chassis_move_control->vx_set = cos_yaw * vx_set + sin_yaw * vy_set;
chassis_move_control->vy_set = -sin_yaw * vx_set + cos_yaw * vy_set;
chassis_control_loop
toe_is_error
CAN_cmd_chassis
掌握云臺控制代碼
gimbal_init(&gimbal_control);
shoot_init();
while (toe_is_error(YAW_GIMBAL_MOTOR_TOE) || toe_is_error(PITCH_GIMBAL_MOTOR_TOE))
行為模式
控制模式
- 算出云臺P和Y角的增量
gimbal_behaviour_control_set(&add_yaw_angle, &add_pitch_angle, set_control); - 設置P,Y的設置值
toe_is_error
CAN_cmd_gimbal
掌握姿態解算代碼
BMI088_init() ist8310_init()
BMI088_read(bmi088_real_data.gyro, bmi088_real_data.accel, &bmi088_real_data.temp);
具體實現可看代碼以及添加的注釋
imu_cali_slove(INS_gyro, INS_accel, INS_mag, &bmi088_real_data, &ist8310_real_data);
PID_init(&imu_temp_pid, PID_POSITION, imu_temp_PID, TEMPERATURE_PID_MAX_OUT, TEMPERATURE_PID_MAX_IOUT); AHRS_init(INS_quat, INS_accel, INS_mag);
//查詢哪個已經準備完畢
if(gyro_update_flag & (1 << IMU_NOTIFY_SHFITS))//角速度準備完畢
{
gyro_update_flag &= ~(1 << IMU_NOTIFY_SHFITS);//清楚標志位
BMI088_gyro_read_over(gyro_dma_rx_buf + BMI088_GYRO_RX_BUF_DATA_OFFSET, bmi088_real_data.gyro);
}
if(accel_update_flag & (1 << IMU_UPDATE_SHFITS))//角加速度準備完畢
{
accel_update_flag &= ~(1 << IMU_UPDATE_SHFITS);//清楚標志位
BMI088_accel_read_over(accel_dma_rx_buf + BMI088_ACCEL_RX_BUF_DATA_OFFSET, bmi088_real_data.accel, &bmi088_real_data.time);
}
if(accel_temp_update_flag & (1 << IMU_UPDATE_SHFITS))//溫度準備完畢
{
accel_temp_update_flag &= ~(1 << IMU_UPDATE_SHFITS);//清楚標志位
BMI088_temperature_read_over(accel_temp_dma_rx_buf + BMI088_ACCEL_RX_BUF_DATA_OFFSET, &bmi088_real_data.temp);
imu_temp_control(bmi088_real_data.temp);
}
具體中斷函數可看該文件中的回調函數void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
在SPI的DMA運輸中會有一個txbuffer負責spi對傳感器各個模塊的初始化,一開始我也找不到為什么不用初始化后面閱讀了spi的dma傳輸的相關文檔后搞清楚了這幾個問題
6. 傳輸完成后喚醒主任務并更新歐拉角
AHRS_update(INS_quat, timing_time, INS_gyro, accel_fliter_3, INS_mag);
get_angle(INS_quat, INS_angle + INS_YAW_ADDRESS_OFFSET, INS_angle + INS_PITCH_ADDRESS_OFFSET, INS_angle + INS_ROLL_ADDRESS_OFFSET);//獲取歐拉角
了解控制器的使用
typedef __packed struct
{
__packed struct
{
int16_t ch[5];
char s[2];
} rc;
__packed struct
{
int16_t x;
int16_t y;
int16_t z;
uint8_t press_l;
uint8_t press_r;
} mouse;
__packed struct
{
uint16_t v;
} key;
} RC_ctrl_t;
通過串口3獲得控制器數據
RC_Init(sbus_rx_buf[0], sbus_rx_buf[1], SBUS_RX_BUF_NUM);
值得注意的是在初始化前需要關閉dma因為不關閉dma將無法改寫dma的相關設置導致初始化失敗具體可看相關學習文檔
2. 串口3中斷后獲得數據并重新設定緩沖區
//獲取接收數據長度,長度 = 設定長度 - 剩余長度
this_time_rx_len = SBUS_RX_BUF_NUM - hdma_usart3_rx.Instance->NDTR;
//重新設定數據長度
hdma_usart3_rx.Instance->NDTR = SBUS_RX_BUF_NUM;
//設定緩沖區1
hdma_usart3_rx.Instance->CR |= DMA_SxCR_CT;
3. 校驗數據是否為一幀,若是則開始翻譯
if(this_time_rx_len == RC_FRAME_LENGTH)
{
sbus_to_rc(sbus_rx_buf[0], &rc_ctrl);
//記錄數據接收時間
detect_hook(DBUS_TOE);
sbus_to_usart1(sbus_rx_buf[0]);
}
static void sbus_to_rc(volatile const uint8_t *sbus_buf, RC_ctrl_t *rc_ctrl)
{
if (sbus_buf == NULL || rc_ctrl == NULL)
{
return;
}
rc_ctrl->rc.ch[0] = (sbus_buf[0] | (sbus_buf[1] << 8)) & 0x07ff; //將第一幀與第二幀組成16位數據后再截取前11位下面的步驟也類似
rc_ctrl->rc.ch[1] = ((sbus_buf[1] >> 3) | (sbus_buf[2] << 5)) & 0x07ff; //!< Channel 1
rc_ctrl->rc.ch[2] = ((sbus_buf[2] >> 6) | (sbus_buf[3] << 2) | //!< Channel 2
(sbus_buf[4] << 10)) &0x07ff;
rc_ctrl->rc.ch[3] = ((sbus_buf[4] >> 1) | (sbus_buf[5] << 7)) & 0x07ff; //!< Channel 3
rc_ctrl->rc.s[0] = ((sbus_buf[5] >> 4) & 0x0003); //!< Switch left
rc_ctrl->rc.s[1] = ((sbus_buf[5] >> 4) & 0x000C) >> 2; //!< Switch right
rc_ctrl->mouse.x = sbus_buf[6] | (sbus_buf[7] << 8); //!< Mouse X axis
rc_ctrl->mouse.y = sbus_buf[8] | (sbus_buf[9] << 8); //!< Mouse Y axis
rc_ctrl->mouse.z = sbus_buf[10] | (sbus_buf[11] << 8); //!< Mouse Z axis
rc_ctrl->mouse.press_l = sbus_buf[12]; //!< Mouse Left Is Press ?
rc_ctrl->mouse.press_r = sbus_buf[13]; //!< Mouse Right Is Press ?
rc_ctrl->key.v = sbus_buf[14] | (sbus_buf[15] << 8); //!< KeyBoard value
rc_ctrl->rc.ch[4] = sbus_buf[16] | (sbus_buf[17] << 8); //NULL
// 在while循環中,遙控器通道0的值是364-1684,那么就可以先減去1024,得到范圍-660到660
rc_ctrl->rc.ch[0] -= RC_CH_VALUE_OFFSET;//減1024
rc_ctrl->rc.ch[1] -= RC_CH_VALUE_OFFSET;
rc_ctrl->rc.ch[2] -= RC_CH_VALUE_OFFSET;
rc_ctrl->rc.ch[3] -= RC_CH_VALUE_OFFSET;
rc_ctrl->rc.ch[4] -= RC_CH_VALUE_OFFSET;
}
學習參考網址RM控制器
總結
- 上一篇: 非接触式IC卡性能简介(M1)
- 下一篇: 一个自用Typora魔改主题