1. 程式人生 > 其它 >STM32 HAL庫快速實戰【七】《機械臂控制》--基於黑龍江科技大學機電工業機器人實訓

STM32 HAL庫快速實戰【七】《機械臂控制》--基於黑龍江科技大學機電工業機器人實訓

系列目錄

接線

總共六個舵機,使用PB3-PB9引腳。
從下面支撐舵機到上面夾子舵機依次接DJ0到DJ5介面。

配置CubeMX

可以使用上節配置好的demo複製後繼續配置,也可以重新生成,這裡不多贅述。
勾選PB3-PB8,開啟定時器。由於涉及到多個舵機,歸零可能會造成干涉,所以所有舵機一定要調整到中位後在安裝。
調整中位只需要將所有定時器通道的Pulse設定為1500即可。

配置方法同[STM32 HAL庫快速實戰【三】《pwm控制舵機》--基於黑龍江科技大學機電工業機器人實訓 - USTHzhanglu - 部落格園 (cnblogs.com)]

記住每個舵機對應的通道。

編寫程式碼

生成程式碼後,新建robot-arm.c和robot.h,放入對應資料夾以及工程中。

初始化舵機

在.h檔案中新增依賴,並宣告初始化函式

#include "tim.h"
void arm_init(void);

在.c檔案中定義初始化函式

#include "robot-arm.h"

/**
 * @brief  :初始化舵機0到舵機5,均初始化到中間位置。
 * @param  :void
 * @retval None
 **/
void arm_init(void)
{
	//__HAL_TIM_SetCompare(&htim2,TIM_CHANNEL_2,500);修改DJ0的初始化角度為0度。
	HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);//DJ0,PB3
	HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_3);//DJ1,PB8
	HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_4);//DJ2,PB9
	HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_1);//DJ3,PB6
	HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_2);//DJ4,PB7
	HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1);//DJ5,PB4
	return;
}
}

由於設定的Pulse為1500,所以每個舵機的初始位置都在中間位。如果需要初始時位置不同,可以修改配置工程,或者在Start之前使用__HAL_TIM_SetCompare(&htim2,TIM_CHANNEL_2,rad);來修改初始化位置。

控制舵機

由於我們需要一次控制六個舵機,每個舵機單獨控制屬實有夠麻煩。我們可以定義一個數組,裡面儲存每次每個舵機需要運動到的角度,這樣每次我們只需要修改陣列,就能很方便的控制六個舵機。

/**
 * @brief  :控制舵機0到舵機5,左上轉為正,右下轉為負,DJ0-5 +-135°,DJ6+-90°
 * @param  :rad[6],分別儲存每個舵機轉動角度
 * @retval None
 **/
void arm_set(const int rad[6])
{

需要注意的是,__HAL_TIM_SetCompare(&htim2,TIM_CHANNEL_2,rad);傳入的引數是佔空比,但是我們需要控制的是角度,因此需要進行一個簡單的運算(假設舵機處在中間位時為0°):1500+rad[x]*1000/135。同時,由於安裝原因,有些舵機可能裝反了,拆卸安裝有夠噁心的,我們可以定義一個數組宣告舵機運動狀態,裝反的舵機只需要宣告該舵機運動狀態相反即可。
在robot-arm.c頂部中新增

#include "robot-arm.h"

/* 定義一個數組,說明舵機運動方向,如果實際轉向相反與輸入相反,則修改對應位為-1
*/
const int arm_toggle[6]={1,1,1,1,1,1};

然後我們就可以定義舵機控制函式

/**
 * @brief  :控制舵機0到舵機5,左上轉為正,右下轉為負,DJ0-5 +-135°,DJ6+-90°
 * @param  :rad[6],分別儲存每個舵機轉動角度
 * @retval None
 **/
void arm_set(cosnt int rad[6])
{
	int compare[6]={
		1500+rad[0]*arm_toggle[0]*1000/135,
		1500+rad[1]*arm_toggle[1]*1000/135,
		1500+rad[2]*arm_toggle[2]*1000/135,
		1500+rad[3]*arm_toggle[3]*1000/135,
		1500+rad[4]*arm_toggle[4]*1000/135,
		1500+rad[5]*arm_toggle[5]*1000/90,
		};
__HAL_TIM_SetCompare(&htim2,TIM_CHANNEL_2,compare[0]);
__HAL_TIM_SetCompare(&htim4,TIM_CHANNEL_3,compare[1]);
__HAL_TIM_SetCompare(&htim4,TIM_CHANNEL_4,compare[2]);
__HAL_TIM_SetCompare(&htim4,TIM_CHANNEL_1,compare[3]);
__HAL_TIM_SetCompare(&htim4,TIM_CHANNEL_2,compare[4]);
__HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_1,compare[5]);
}

在main.c中初始化arm

 /* USER CODE BEGIN 2 */
motor_init();
arm_init();
HAL_Delay(2000);
HAL_GPIO_WritePin(led_GPIO_Port,led_Pin,GPIO_PIN_RESET);
  /* USER CODE END 2 */

燒錄程式後,機械臂會直立起來。如果角度不對,請重新安裝各關節舵機。

調節各關節角度

有了舵機控制程式碼,我們可以方便的調節舵機角度,但是手動控制過於繁瑣,實際使用時更偏向於自動化控制。最好的方法是建立機械臂運動模型,但是難度較高。在這裡我們選擇一種簡單類似於示教機器人的方法,通過記錄每次動作的角度狀態,在不同動作間直接切換即可。
首先,需要實時獲取當前關節角度。為了方便使用,這裡封裝成一個函式:

/**
 * @brief  列印當前關節角度
 * @param  :arm_rad[6],分別儲存每個舵機轉動角度
 * @retval None
 **/
void printf_rad(const int arm_rad[6])
{  char cmd_return[128];
	sprintf(cmd_return, "{rad:%d,%d,%d,%d,%d,%d}",arm_rad[0],arm_rad[1],arm_rad[2],arm_rad[3],arm_rad[4],arm_rad[5]);
	usart_send_str(&huart3,(unsigned char *)cmd_return);
	return;
}

然後定義一個get_rad函式,用於獲取輸入的命令,調節舵機角度

/**
 * @brief  :控制舵機0到舵機5,並列印當前角度
 * @param  :None
 * @retval None
 **/
void get_rad(void)
{
	char menu;
	int arm_status=1;
	int rad[6]={0,0,0,0,0,0};
	while( arm_status)
	{menu=get_cmd();
		switch(menu)
		{
			  case 'A':rad[0]++;break;
			  case 'B':rad[0]--;break;
			  case 'C':rad[1]++;break;
			  case 'D':rad[1]--;break;
			  case 'E':rad[2]++;break;			  
			  case 'F':rad[2]--;break;
			  case 'G':rad[3]++;break;			  
			  case 'H':rad[3]--;break;
			  case 'I':rad[4]++;break;			  
			  case 'J':rad[4]--;break;
			  case 'K':rad[5]++;break;			  
			  case 'L':rad[5]--;break;		
			  case 'Q':arm_status=0;break;
		}
	printf_rad(rad);
	arm_set(rad);
	menu=NULL;
	}
return;
}	

同時在.h檔案中宣告函式

#include "tim.h"
#include "motor.h"
void arm_init(void);
void arm_set(const int rad[6]);
void printf_rad(const int arm_rad[6]);
void get_rad(void);

在main.c的switch中新增一個選項

switch(input)
		  {	  
			  case '0':get_rad();break;

通過藍芽控制,輸入0進入舵機調節選單,然後輸入A-L調節關節,輸入Q退出調節選單。
可以在BlueSPP中切換到鍵盤介面,快速調節

然後在CHAT介面檢視當前角度。

記錄不同動作的角度,例如待機時為{0,85,-135,-54,0,0},在.c檔案頂部定義:

/* 關節初始狀態*/
const int arm_begin[6]={0,85,-135,-54,0,0};

然後就可以直接執行關節動作。例如初始化舵機時直接初始化到待機位置

void arm_init(void)
{
	arm_set(arm_begin);
	HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);//DJ0,PB3

工程原始碼

國內使用者請使用gitee克隆或是使用代理訪問Github
https://github.com/USTHzhanglu/stm32-hal/tree/main/robot-ram