这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 【DIY手势翻页笔】成果贴-扩展作业-基于TobundOSr的机械臂

共8条 1/1 1 跳转至

【DIY手势翻页笔】成果贴-扩展作业-基于TobundOSr的机械臂

助工
2024-06-13 21:49:08     打赏

【项目介绍】

本项目移植了TobundOS,并实现使用两个PAJ7620来实时控制机械臂,能实现实时上下,左右摆动,复位、以及点动等复杂的动作。

【硬件】

1、机械臂膀

2、Nucleo-H503RB核心板

3、PAJ7620*2

【软件】

1、STM32CubeMAX

2、MDK5.39

3、TobudOS国产开源操作系统 

【硬件框图】

image.png

【移植TobundOS】

1、下载tobandOS源码,https://atomgit.com/OpenAtomFoundation/TobudOS

2、把源码的目录复制到工程的TobundOS目录下面:

image.png

3、打开keil,新建os/arch分组,官方没有雅特力方面的资料,网上也没有相关的帖子,我查看了atf425的数据手册,他是arm-v7m\cortex-m4下面的内核,因此把他下面的库加入到arch工程分组中。把r\arch\arm\arm-v7m\cortex-m4\armcc目录下面的prot_c.c、port_s.S下面添加进去,在添加时要注意下面选所有文件,才能看到.S的文件。同时把os\arch\arm\arm-v7m\common下面所有的C文件都添加进工程分组,新建kernel分组,把\kernel\core路径下所有的.c文件添加\os\kernel的工程分组中。


image.png

4、添加头文件的引用到工程中。

5、注释掉stm32h5xx_it.c中的PendSV_Handler,以免跟tos的系统中重复函数。同时在systick_Handelr中添回心跳包函数:

image.png

6、添加tobuandos任务函数:

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
k_stack_t task_1_stack[512];
k_task_t task_1;
 
k_stack_t task_2_stack[512];
k_task_t task_2;

7、创建任务初始化、开始调度:

	tos_knl_init();
        
  tos_task_create(&task_1,"button_task",test_task,NULL,2,task_1_stack,512,100);
  tos_task_create(&task_2,"led_task",led_task_entry,NULL,1,task_2_stack,512,100);

  tos_knl_start();

到此tobundos移植结束。两任务,一个为获取传感器数据,一个为驱动双舵机。

【舵机驱动】

舵机驱动,为初始化两个PWM驱动,产生20ms周期的pwm,然后产生0.5ms到2.5ms的高电平,来使舵机旋转不同的角度,来实现机械臂的控制。

image.png

如上图配置所示,主频为250M,所在配置250-1分频,再设置计数值为20000,即周期为50Hz(20ms)。

【手势传感器的驱动】

在前面的过程帖子有详细的讲解,但是这次需要用到两个I2c来驱动,所以修改后的驱动代码如下:

/*

  ******************************************************************************
  * @file 			( фаил ):   PAJ7620U2.c
  * @brief 		( описание ):  	
  ******************************************************************************
  * @attention 	( внимание ):	author: Golinskiy Konstantin	e-mail: golinskiy.konstantin@gmail.com
  ******************************************************************************
  
*/

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


//Power up initialize array
const uint8_t Init_Register_Array[][2] = {
		{0xEF,0x00},
    {0x32,0x29},
    {0x33,0x01},
    {0x34,0x00},
    {0x35,0x01},
    {0x36,0x00},
    {0x37,0x07},
    {0x38,0x17},
    {0x39,0x06},
    {0x3A,0x12},
    {0x3F,0x00},
    {0x40,0x02},
    {0x41,0xFF},
    {0x42,0x01},
    {0x46,0x2D},
    {0x47,0x0F},
    {0x48,0x3C},
    {0x49,0x00},
    {0x4A,0x1E},
    {0x4B,0x00},
    {0x4C,0x20},
    {0x4D,0x00},
    {0x4E,0x1A},
    {0x4F,0x14},
    {0x50,0x00},
    {0x51,0x10},
    {0x52,0x00},
    {0x5C,0x02},
    {0x5D,0x00},
    {0x5E,0x10},
    {0x5F,0x3F},
    {0x60,0x27},
    {0x61,0x28},
    {0x62,0x00},
    {0x63,0x03},
    {0x64,0xF7},
    {0x65,0x03},
    {0x66,0xD9},
    {0x67,0x03},
    {0x68,0x01},
    {0x69,0xC8},
    {0x6A,0x40},
    {0x6D,0x04},
    {0x6E,0x00},
    {0x6F,0x00},
    {0x70,0x80},
    {0x71,0x00},
    {0x72,0x00},
    {0x73,0x00},
    {0x74,0xF0},
    {0x75,0x00},
    {0x80,0x42},
    {0x81,0x44},
    {0x82,0x04},
    {0x83,0x20},
    {0x84,0x20},
    {0x85,0x00},
    {0x86,0x10},
    {0x87,0x00},
    {0x88,0x05},
    {0x89,0x18},
    {0x8A,0x10},
    {0x8B,0x01},
    {0x8C,0x37},
    {0x8D,0x00},
    {0x8E,0xF0},
    {0x8F,0x81},
    {0x90,0x06},
    {0x91,0x06},
    {0x92,0x1E},
    {0x93,0x0D},
    {0x94,0x0A},
    {0x95,0x0A},
    {0x96,0x0C},
    {0x97,0x05},
    {0x98,0x0A},
    {0x99,0x41},
    {0x9A,0x14},
    {0x9B,0x0A},
    {0x9C,0x3F},
    {0x9D,0x33},
    {0x9E,0xAE},
    {0x9F,0xF9},
    {0xA0,0x48},
    {0xA1,0x13},
    {0xA2,0x10},
    {0xA3,0x08},
    {0xA4,0x30},
    {0xA5,0x19},
    {0xA6,0x10},
    {0xA7,0x08},
    {0xA8,0x24},
    {0xA9,0x04},
    {0xAA,0x1E},
    {0xAB,0x1E},
    {0xCC,0x19},
    {0xCD,0x0B},
    {0xCE,0x13},
    {0xCF,0x64},
    {0xD0,0x21},
    {0xD1,0x0F},
    {0xD2,0x88},
    {0xE0,0x01},
    {0xE1,0x04},
    {0xE2,0x41},
    {0xE3,0xD6},
    {0xE4,0x00},
    {0xE5,0x0C},
    {0xE6,0x0A},
    {0xE7,0x00},
    {0xE8,0x00},
    {0xE9,0x00},
    {0xEE,0x07},
    {0xEF,0x01},
    {0x00,0x1E},
    {0x01,0x1E},
    {0x02,0x0F},
    {0x03,0x10},
    {0x04,0x02},
    {0x05,0x00},
    {0x06,0xB0},
    {0x07,0x04},
    {0x08,0x0D},
    {0x09,0x0E},
    {0x0A,0x9C},
    {0x0B,0x04},
    {0x0C,0x05},
    {0x0D,0x0F},
    {0x0E,0x02},
    {0x0F,0x12},
    {0x10,0x02},
    {0x11,0x02},
    {0x12,0x00},
    {0x13,0x01},
    {0x14,0x05},
    {0x15,0x07},
    {0x16,0x05},
    {0x17,0x07},
    {0x18,0x01},
    {0x19,0x04},
    {0x1A,0x05},
    {0x1B,0x0C},
    {0x1C,0x2A},
    {0x1D,0x01},
    {0x1E,0x00},
    {0x21,0x00},
    {0x22,0x00},
    {0x23,0x00},
    {0x25,0x01},
    {0x26,0x00},
    {0x27,0x39},
    {0x28,0x7F},
    {0x29,0x08},
    {0x30,0x03},
    {0x31,0x00},
    {0x32,0x1A},
    {0x33,0x1A},
    {0x34,0x07},
    {0x35,0x07},
    {0x36,0x01},
    {0x37,0xFF},
    {0x38,0x36},
    {0x39,0x07},
    {0x3A,0x00},
    {0x3E,0xFF},
    {0x3F,0x00},
    {0x40,0x77},
    {0x41,0x40},
    {0x42,0x00},
    {0x43,0x30},
    {0x44,0xA0},
    {0x45,0x5C},
    {0x46,0x00},
    {0x47,0x00},
    {0x48,0x58},
    {0x4A,0x1E},
    {0x4B,0x1E},
    {0x4C,0x00},
    {0x4D,0x00},
    {0x4E,0xA0},
    {0x4F,0x80},
    {0x50,0x00},
    {0x51,0x00},
    {0x52,0x00},
    {0x53,0x00},
    {0x54,0x00},
    {0x57,0x80},
    {0x59,0x10},
    {0x5A,0x08},
    {0x5B,0x94},
    {0x5C,0xE8},
    {0x5D,0x08},
    {0x5E,0x3D},
    {0x5F,0x99},
    {0x60,0x45},
    {0x61,0x40},
    {0x63,0x2D},
    {0x64,0x02},
    {0x65,0x96},
    {0x66,0x00},
    {0x67,0x97},
    {0x68,0x01},
    {0x69,0xCD},
    {0x6A,0x01},
    {0x6B,0xB0},
    {0x6C,0x04},
    {0x6D,0x2C},
    {0x6E,0x01},
    {0x6F,0x32},
    {0x71,0x00},
    {0x72,0x01},
    {0x73,0x35},
    {0x74,0x00},
    {0x75,0x33},
    {0x76,0x31},
    {0x77,0x01},
    {0x7C,0x84},
    {0x7D,0x03},
    {0x7E,0x01}
  };


/******************************************************************************
function:	
	I2C Write and Read
******************************************************************************/
static void DEV_I2C_WriteByte(I2C_HandleTypeDef PAJ7620U2_I2C,uint8_t add_, uint8_t data_)
{
	uint8_t Buf[1] = {0};
	Buf[0] = data_;
	HAL_I2C_Mem_Write(&PAJ7620U2_I2C, PAJ7620U2_I2C_ADDRESS, add_, I2C_MEMADD_SIZE_8BIT, Buf, 1, 500);
}

static void DEV_I2C_WriteWord(I2C_HandleTypeDef PAJ7620U2_I2C,uint8_t add_, uint16_t data_)
{
	uint8_t Buf[2] = {0};
	Buf[0] = data_ >> 8; 
	Buf[1] = data_;
	HAL_I2C_Mem_Write(&PAJ7620U2_I2C, PAJ7620U2_I2C_ADDRESS, add_, I2C_MEMADD_SIZE_8BIT, Buf, 2, 500);
}

static uint8_t DEV_I2C_ReadByte(I2C_HandleTypeDef PAJ7620U2_I2C,uint8_t add_)
{
	uint8_t Buf[1]={add_};
	HAL_I2C_Mem_Read(&PAJ7620U2_I2C, PAJ7620U2_I2C_ADDRESS, add_, I2C_MEMADD_SIZE_8BIT, Buf, 1, 500);
	return Buf[0];
}

static uint16_t DEV_I2C_ReadWord(I2C_HandleTypeDef PAJ7620U2_I2C,uint8_t add_)
{
    uint8_t Buf[2]={0, 0};
		HAL_I2C_Mem_Read(&PAJ7620U2_I2C, PAJ7620U2_I2C_ADDRESS, add_, I2C_MEMADD_SIZE_8BIT, Buf, 2, 500);
    return ((Buf[1] << 8) | (Buf[0] & 0xff));
}

static uint16_t PAJ7620U2_GetPartID(I2C_HandleTypeDef PAJ7620U2_I2C)
{
	uint8_t data[2] = {0, };
	data[0] = DEV_I2C_ReadByte(PAJ7620U2_I2C,PAJ_PART_ID_L);	
	data[1] = DEV_I2C_ReadByte(PAJ7620U2_I2C,PAJ_PART_ID_H);	
	
	return ((uint16_t)data[1]<<8) | data[0];
}
//----------------------------------------------------------------------------------

// при инициализации возвращает ( если соединение с датчиком удачное ) значение 0x7620 либо 0 если датчик не увидел
uint16_t PAJ7620U2_init(I2C_HandleTypeDef PAJ7620U2_I2C)
{
	uint16_t ID = PAJ7620U2_GetPartID(PAJ7620U2_I2C);
	
	if( ID == PAJ_PARTID ){
		DEV_I2C_WriteByte(PAJ7620U2_I2C,PAJ_BANK_SELECT, PAJ_BANK_0);
		for (uint8_t i = 0; i < Init_Array; i++ )
		{
			 DEV_I2C_WriteByte(PAJ7620U2_I2C,Init_Register_Array[i][0], Init_Register_Array[i][1]);//Power up initialize
		}
		DEV_I2C_WriteByte(PAJ7620U2_I2C,PAJ_BANK_SELECT, PAJ_BANK_0);
		
		return ID;
	}
	
	return 0;
}
//----------------------------------------------------------------------------------

// запрашиваем номер движения ( если движения небыло вернет 0 ) если было то его номер
uint16_t PAJ7620U2_Gesture_ReadData(I2C_HandleTypeDef PAJ7620U2_I2C)
{
	return DEV_I2C_ReadWord(PAJ7620U2_I2C,PAJ_INT_FLAG1);
}
//----------------------------------------------------------------------------------

// Object Brightness (Max. 255)
uint8_t PAJ7620U2_PS_ReadObjBrightness(I2C_HandleTypeDef PAJ7620U2_I2C)
{
	return DEV_I2C_ReadByte(PAJ7620U2_I2C,PAJ_OBJ_BRIGHTNESS);			
}
//----------------------------------------------------------------------------------

// Object Size (Max. 900)
uint16_t PAJ7620U2_PS_ReadObjSize(I2C_HandleTypeDef PAJ7620U2_I2C)
{
	return DEV_I2C_ReadWord(PAJ7620U2_I2C,PAJ_OBJ_SIZE_L);			
}
//----------------------------------------------------------------------------------



//----------------------------------------------------------------------------------

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

到此手势传感器的驱动就移完毕

【程序流程图】

image.png

控制代码分析:

在获取数据任务中,我们只需要周期获取两个传感器的数据就行了。

void test_task(void *Parameter)
{
	
	uint16_t ID = PAJ7620U2_init(hi2c1);  
	ID = PAJ7620U2_init(hi2c2);   
  while (1)  
  {  
				OBJ_BRIGHTNESS = PAJ7620U2_PS_ReadObjBrightness(hi2c2);    // Object Brightness (Max. 255)  
        OBJ_SIZE = PAJ7620U2_PS_ReadObjSize(hi2c2);                            // Object Size (Max. 900)  
		
				printf("Brightness:%d    Size:%d \r\n",OBJ_BRIGHTNESS,OBJ_SIZE);
        Gesture_Data = PAJ7620U2_Gesture_ReadData(hi2c1);    
  
	    tos_task_delay(10);
	}
}

在控制任务中,我们分析两个传感器的数,根据是否按下的传感器1的状态,来分别对机械臂行点动,或者一步到底的操作。

void led_task_entry(void *Parameter)
{
	while(1)
	{
		if( Gesture_Data != PAJ_NONE )  
        {  
            switch (Gesture_Data)  
            {  
                case PAJ_UP:   
										if(OBJ_SIZE>850)
										{
											up_Compare = 1*20000/40; //2.5ms
										}
										else{
											up_Compare -= 10;
											if(up_Compare<1*20000/40) //2.5ms
												up_Compare = 1*20000/40; //2.5ms
										}
                    break;    
                case PAJ_DOWN:   
										if(OBJ_SIZE>850)
										{
											up_Compare = 3*20000/40; //180
										}
										else{
											up_Compare += 10;
											if(up_Compare>3*20000/40)
												up_Compare = 3*20000/40; //180
										}  
  
                break;  // вниз  
                case PAJ_LEFT:  
										if(OBJ_SIZE>850)
										{
											down_Compare = 1*20000/40; //0.5ms
										}
										else
										{
											down_Compare -= 10;
											if(down_Compare < 1*20000/40)
												down_Compare = 1*20000/40; //0.5ms
										}
                break;  // влево  
                case PAJ_RIGHT:  
										if(OBJ_SIZE>850)
										{
											down_Compare = 5*20000/40; //180
										}
										else
										{
											down_Compare += 10;
											if(down_Compare > 5*20000/40) //180)
												down_Compare = 5*20000/40; //180; //0.5ms
										}
                    
                break;  // вправо  
                case PAJ_FORWARD:  
                    up_Compare = 3*20000/40; //90
										down_Compare = 3*20000/40; //90
                break;  // вперед    
  
                  
                default: break;  
            }  
        }  
      Gesture_Data = 0;  
			__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_4,up_Compare);
			__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3,down_Compare);  
			tos_task_delay(50);
	}
}

【实验现象】

分别对两个感器进行操作,可以实现对机械臂的控制,详见视频讲解。

【作品视频介绍】

https://www.bilibili.com/video/BV1vdbxeaEA5/?pop_share=1




关键词: 手势翻页笔     PAJ7620U2      机械臂    

院士
2024-06-13 23:00:34     打赏
2楼

哇,听上去就厉害


专家
2024-06-14 00:43:39     打赏
3楼

期待详细介绍


专家
2024-06-14 07:54:20     打赏
4楼

不错的项目


高工
2024-06-14 10:01:01     打赏
5楼

期待详细介绍


高工
2024-06-14 11:54:15     打赏
6楼

期待详细介绍


菜鸟
2024-06-14 18:53:02     打赏
7楼

期待详细介绍


专家
2024-06-15 17:53:08     打赏
8楼

这个操作系统,有那些特殊的功能,给介绍下


共8条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]