蘋果采摘機器人
1、采摘流程與硬件設計
蘋果采摘機器人的流程框圖和硬件圖,如下圖所示。簡單介紹下采摘流程,攝像頭采集環(huán)境畫面,如果畫面中沒有蘋果,那么機械臂將以設定的運動軌跡運動,直至畫面中出現(xiàn)蘋果。一旦畫面出現(xiàn)蘋果,F(xiàn)04驕陽開發(fā)板將會驅(qū)動機械臂電機對準蘋果與夾持器電機實現(xiàn)對蘋果的抓取。完成采摘之后,機械臂將繼續(xù)以設定的運動軌跡運動。
首先,由夾持器內(nèi)側的攝像頭采集外部環(huán)境圖片,將圖片信息傳輸?shù)絥ano開發(fā)板之后,由nano開發(fā)板進行深度學習圖像處理,可以得到目標蘋果與畫面正中心位置的偏差量。將偏差量和是否存在蘋果等信息量以串口的形式發(fā)送到野火F407驕陽開發(fā)板。F407會根據(jù)得到的信息量,進行處理,不存在蘋果則機械臂以指定的軌跡動作。否則進行采摘蘋果動作。
(注:本文將下圖中機械臂和電動推桿合稱機械臂。末端執(zhí)行器部分將在后續(xù)文章中詳細講解)
2、機械臂驅(qū)動以及采摘軌跡設計
三軸機械臂的伺服驅(qū)動器皆為臺達的asda-a2系列。設置了驅(qū)動器的驅(qū)動模式(默認為:脈沖+方向)、電子齒輪比(指令為:P1-44、P1-45。功能就是根據(jù)輸入的PWM數(shù)量,決定電機的旋轉(zhuǎn)圈數(shù)。具體如何設置可以查詢A2的使用手冊)、SON(以指令設置的方式強制使能伺服驅(qū)動器)。通過查詢A2使用手冊中的CN1部分信號接線,發(fā)現(xiàn)臺達官方只提供了5V和24V的電源系統(tǒng)連接方式。但是通過實際測試,發(fā)現(xiàn)F407以5V系統(tǒng)的接線方式,發(fā)送PWM和方向信號,伺服驅(qū)動器是完全能夠接收到脈沖的。下面給出了5V系統(tǒng)的接線方式和電子齒輪比的設置,具體內(nèi)容可以查看A2的使用手冊。
2.1、臺達A2電機驅(qū)動實現(xiàn)
由于機械臂上限位開關的損壞,那個推桿就沒有限位開關。于是決定使用主從定時器的方式實現(xiàn)軟件限位。主定時器:產(chǎn)生PWM波,從定時器:監(jiān)視主定時器產(chǎn)生的PWM波,并產(chǎn)生中斷,中斷內(nèi)部根據(jù)當前電機方向信號的正負決定限制角度的加減,實現(xiàn)軟件限位。為什么不用主定時器開啟中斷,一定使用從定時器產(chǎn)生中斷呢?因為擔心主定時器開啟中斷,會導致中斷次數(shù)太頻繁會影響到主函數(shù)的執(zhí)行。這里就相當于主定時器對從定時器起分頻作用。
首先就是脈沖引腳和方向引腳的初始化
void TIMx_GPIO_Config(void)
{
/* 定義一個 GPIO_InitTypeDef 類型的結構體 */
GPIO_InitTypeDef GPIO_InitStructure;
/* 開啟定時器相關的 GPIO 外設時鐘 */
TIMER_1_Master_CLK_ENABLE();
TIMER_2_Master_CLK_ENABLE();
TIMER_3_Master_CLK_ENABLE();
Motor_A_CLK_ENABLE();
Motor_B_CLK_ENABLE();
Motor_C_CLK_ENABLE();
/* 定時器PWM脈沖復用引腳初始化 */
GPIO_InitStructure.Pin = TIMER_1_Master_PIN;
GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
GPIO_InitStructure.Alternate = TIMER_1_Master_AF;
HAL_GPIO_Init(TIMER_1_Master_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.Pin = TIMER_2_Master_PIN;
GPIO_InitStructure.Alternate = TIMER_2_Master_AF;
HAL_GPIO_Init(TIMER_2_Master_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.Pin = TIMER_3_Master_PIN;
GPIO_InitStructure.Alternate = TIMER_3_Master_AF;
HAL_GPIO_Init(TIMER_3_Master_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitTypeDef GPIO_InitStructureDR;
/* 伺服電機方向引腳初始化 */
GPIO_InitStructureDR.Pin = Motor_A_DIR_PIN;
GPIO_InitStructureDR.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructureDR.Pull = GPIO_NOPULL;
GPIO_InitStructureDR.Speed = GPIO_SPEED_HIGH;
HAL_GPIO_Init(Motor_A_DIR_GPIO_PORT, &GPIO_InitStructureDR);
GPIO_InitStructureDR.Pin = Motor_B_DIR_PIN;
HAL_GPIO_Init(Motor_B_DIR_GPIO_PORT, &GPIO_InitStructureDR);
GPIO_InitStructureDR.Pin = Motor_C_DIR_PIN;
HAL_GPIO_Init(Motor_C_DIR_GPIO_PORT, &GPIO_InitStructureDR);
}
然后是主從定時器的設置,設置TIM1為主定時器,TIM2為從定時器。主從定時器的設置是有限制要求的。觸發(fā)源只能是ITR0~ITR4,每組主從定時器只能用一個,且不能重復。本文一共是三軸,三組主從定時器。具體細節(jié)可以查詢其他人的文章,這里不具體詳解。PWM波的周期越小,電機轉(zhuǎn)速就越快。而想要實現(xiàn)電機轉(zhuǎn)速變快,只要修改主定時器的period周期和pulse變量就行,占空比盡可能在50%。Error_Handler();可以自己設置,查看是否主從定時器配置出了問題。
在從定時器的最后,開啟了從定時器中斷,來記錄產(chǎn)生的PWM波的數(shù)量
/**********************X軸PWM定時器配置:主TIM1、從TIM2***********************************/
/*******************************主定時器配置***********************************/
void MX_Master_TIM1_Init(uint16_t period,uint16_t prescaler,uint16_t pulse)
{
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
/* TIM1 clock enable */
__HAL_RCC_TIM1_CLK_ENABLE();
htim1.Instance = TIM1; //設置主定時器為TIM1
htim1.Init.Prescaler = prescaler; //設置PWM頻率
htim1.Init.CounterMode = TIM_COUNTERMODE_UP; //設置計數(shù)模式為向上計數(shù)
htim1.Init.Period = period; //設置占空比-周期
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; //設置為無分頻
if (HAL_TIM_PWM_Init(&htim1) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE; //更新事件被選為觸發(fā)輸入
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE; //開啟主從模式
if (HAL_TIMEx_MasterConfigSynchronization(&htim1 , &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1; //設置PWM模式為PWM1
sConfigOC.Pulse = pulse; //設置PWM占空比 = pulse / period
sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW; //設置PWM空閑狀態(tài)引腳拉低
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
HAL_TIM_Base_Stop(&htim1);
}
/**********************從TIM2定時器配置***********************************/
void MX_Slave_TIM2_Init(uint16_t period)
{
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_SlaveConfigTypeDef sSlaveConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
/* TIM2 clock enable */
__HAL_RCC_TIM2_CLK_ENABLE();
htim2.Instance = TIM2; //設置從定時器為TIM2
htim2.Init.Prescaler = 0; //設置從定時器頻率為0
htim2.Init.CounterMode = TIM_COUNTERMODE_UP; //設置計數(shù)模式為向上計數(shù)
htim2.Init.Period =period; //這個大于0就行
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; //設置為無分頻
htim2.Init.RepetitionCounter = 0;
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_ITR0; //設置為內(nèi)部時鐘觸發(fā),即為TIM1
if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
sSlaveConfig.SlaveMode = TIM_SLAVEMODE_EXTERNAL1; //設置為外部觸發(fā)
sSlaveConfig.InputTrigger = TIM_TS_ITR0; //設置ITR0(tim1)為輸入源
sSlaveConfig.TriggerPolarity = TIM_TRIGGERPOLARITY_RISING; //設置觸發(fā)模式為上升沿
sSlaveConfig.TriggerPrescaler = TIM_TRIGGERPRESCALER_DIV1; //設置無預分頻
sSlaveConfig.TriggerFilter = 0x0; //設置無濾波
if (HAL_TIM_SlaveConfigSynchronization(&htim2, &sSlaveConfig) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
/* TIM2 interrupt Init */
HAL_NVIC_SetPriority(TIM2_IRQn, 2, 2);
HAL_NVIC_EnableIRQ(TIM2_IRQn);
}
/****************************************************************************/
下面是中斷部分。根據(jù)Motor_A_DIR_PIN方向引腳的正負來決定限制角度Limit_angle_A的加減,以此來記錄當前電機相對初始狀態(tài)的旋轉(zhuǎn)位置。
void TIM2_IRQHandler(void)
{
HAL_TIM_IRQHandler(&htim2);
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
/************************從定時器5中斷*********************************/
if(htim==(&htim2))
{
// 更新中斷,計數(shù)器向上溢出/向下溢出,計數(shù)器初始化(通過軟件或者內(nèi)部/外部觸發(fā))
if (__HAL_TIM_GET_FLAG(&htim2, TIM_FLAG_TRIGGER) != RESET)
{
__HAL_TIM_CLEAR_FLAG(&htim2, TIM_FLAG_TRIGGER);
if(HAL_GPIO_ReadPin(Motor_A_DIR_GPIO_PORT, Motor_A_DIR_PIN))
{
Limit_angle_A += 2;
}
else
{
Limit_angle_A -= 2;
}
}
}
}
主函數(shù)部分,PWM的產(chǎn)生與停止由HAL_TIM_PWM_Start()與HAL_TIM_PWM_Stop()函數(shù)控制。
/*PWM輸出引腳、方向引腳初始化(機械臂電機控制)*/
TIMx_GPIO_Config();
//主定時器1周期、分頻、占空比配置
MX_Master_TIM1_Init(400,71,200);
//從定時器2周期配置
MX_Slave_TIM2_Init(20);
/******************X軸PWM發(fā)生、限位啟動項*******************/
//主定時器1時基使能
HAL_TIM_Base_Start(&htim1);
//主定時器2開始產(chǎn)生PWM波、停止產(chǎn)生PWM波
// HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
// HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1);
//開啟從定時器2中斷模式
HAL_TIM_Base_Start_IT(&htim2);
以上是單軸電機控制的代碼,需要多個軸運動的話,復制修改即可。文章來源:http://www.zghlxwxcb.cn/news/detail-451019.html
2.2、機械臂尋找蘋果巡邏軌跡
巡邏軌跡就是機械臂來回往復尋找蘋果的過程。代碼實現(xiàn)就是機械臂對準的方位由采摘機器人主視圖左上角移動到右上角,然后控制機械臂下降一定距離。再由右到左以此往復,直至巡邏完成一整個蘋果樹。文章來源地址http://www.zghlxwxcb.cn/news/detail-451019.html
void Picking_auto_posture()
{
//最初狀態(tài):將機械臂回歸到攝像頭視野最左上方
if ((Save_locus_A == 8000 && Save_locus_B == 4000) || Save_locus_Flag == K)
{
Motor_A_CW;
//X軸電機左轉(zhuǎn)
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
while(Limit_angle_A < 12000);
HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1);
Motor_B_CCW; //Y軸上升
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
while(Limit_angle_B > 1000);
HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_1);
Save_locus_A = Limit_angle_A;
Save_locus_B = Limit_angle_B;
Save_locus_Flag = 0; //機械臂初始狀態(tài)已經(jīng)完成 flag = 0
}
//狀態(tài):x最左側,y軸第一行運動,由左->右
if (Save_locus_Flag == 0)
{
Motor_A_CCW; //X軸電機右轉(zhuǎn)
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
if (Limit_angle_A < 4000)
{
Save_locus_Flag = 1;
HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1); //X軸電機停止
}
}
//狀態(tài):y軸下降,x軸最右側
if (Save_locus_Flag == 1)
{
Motor_B_CW; //Y軸電機下降
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
if (Limit_angle_B > 1500)
{
Save_locus_Flag = 2;
HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_1); //Y軸電機停止
}
}
...
到了這里,關于基于野火F407驕陽開發(fā)板的蘋果采摘機器人機械臂的采摘軌跡與夾持器的采摘動作的設計(1)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!