幻尔科技ARMPI机器人小车底盘528电机JGB37-528R131-08的使用

文章讲述了作者在使用ARMPI机器人底盘时遇到的问题,涉及到STM32的I2C通信,包括电机驱动、电压监控和编码器计数。作者通过实验发现电机在不同电压下的性能,并对I2C代码进行了调试和理解。
摘要由CSDN通过智能技术生成

幻尔科技卖的ARMPI机器人小车底盘的电机是配套的,网上没有资料,问官方技术人员也回答的不清楚,例程代码注释也有问题,于是自己拿他们的代码试了试。

我买的这个机器人配套的是528电机也就是 JGB37-528R131-08 额定电压8V 但是电池供电7.4,充电。我不小心充到7.7后使用。

一下是STM32的代码(注释已经更正)部分代码有修改。


#include "include.h"

#define CAM_DEFAULT_I2C_ADDRESS       (0x34)			//I2C地址
#define MOTOR_TYPE_ADDR               20 				//编码电机类型设置寄存器地址
#define MOTOR_FIXED_SPEED_ADDR       	51				//速度寄存器地址。属于闭环控制
#define MOTOR_ENCODER_POLARITY_ADDR   21				//电机编码方向极性地址
#define MOTOR_FIXED_PWM_ADDR      		31				//固定PWM控制地址,属于开环控制
#define MOTOR_ENCODER_TOTAL_ADDR  		60				//4个编码电机各自的总脉冲值
#define ADC_BAT_ADDR                  0					//电压地址



uint8_t data[3]; 																//用于暂存电压ADC数据


//读取多个字节的数据(Reg:地址  Buf:数据内容 Len:数据长度)
uint8_t I2C_Read_Len(uint8_t Reg,uint8_t *Buf,uint8_t Len)
{
	uint8_t i;
	IIC_start();																				//发送起始信号
	IIC_send_byte((CAM_DEFAULT_I2C_ADDRESS << 1) | 0);	//发送元器件地址+写指令
	if(IIC_wait_ack() == 1)															//等待响应,如果失败,发送停止信号,返回1
	{
		IIC_stop();					
		return 1;					
	}
	IIC_send_byte(Reg);																	//发送寄存器地址
	if(IIC_wait_ack() == 1)															//等待响应,如果失败,发送停止信号,返回1
	{
		IIC_stop();
		return 1;
	}
	IIC_start();																				//发送起始信号
	IIC_send_byte((CAM_DEFAULT_I2C_ADDRESS << 1) | 1);	//发送元器件地址+读指令
	if(IIC_wait_ack() == 1)															//等待响应,如果失败,发送停止信号,返回1
	{
		IIC_stop();
		return 1;
	}
	for(i=0;i<Len;i++)																	//for循环Len次读取
	{	
		if(i != Len-1)																		//如果不是最后一次
		{
			Buf[i] = IIC_read_byte(1);											//保存第I次的数据到数组的第I位,并发送答应信号
		}
		else
			Buf[i] = IIC_read_byte(0);											//保存第I次的数据到数组的第I位,并发送非答应信号
	}
	IIC_stop();																					//发送停止信号
	return 0;																						//读取成功,返回0
}

//循环发送一个数组的数据(addr:地址  buf:数据内容  leng:数据长度)
uint8_t I2C_Write_Len(uint8_t Reg,uint8_t *Buf,uint8_t Len)//I2C的写数据
{
	uint8_t i;
	IIC_start();																				//在起始信号后必须发送一个7位从机地址+1位方向位,用“0”表示主机发送数据,“1”表示主机接收数据。
	IIC_send_byte((CAM_DEFAULT_I2C_ADDRESS << 1) | 0);	//发送 器件地址+写的命令
	if(IIC_wait_ack() == 1)															//等待响应,如果失败,发送停止信号,返回1
	{
		IIC_stop();					
		return 1;					
	}
	IIC_send_byte(Reg);																	//发送 寄存器地址
	if(IIC_wait_ack() == 1)															//等待响应,如果失败,发送停止信号,返回1
	{
		IIC_stop();
		return 1;
	}
	for(i =0;i<Len;i++)																	//循环 len 次写数据
	{
		IIC_send_byte(Buf[i]);														//发送第i位的8位数据
		if(IIC_wait_ack() == 1)														//等待响应,如果失败,发送停止信号,返回1
		{
			IIC_stop();
			return 1;
		}
	}
	IIC_stop();																					//发送结束,发送停止信号
	return 0;																						//返回 0,确定发送成功
}

//电机类型具体地址
#define MOTOR_TYPE_WITHOUT_ENCODER        0 		//无编码器的电机,磁环每转是44个脉冲减速比:90  默认
#define MOTOR_TYPE_TT                     1 		//TT编码电机
#define MOTOR_TYPE_N20                    2 		//N20编码电机
#define MOTOR_TYPE_JGB37_520_12V_110RPM   3 		//磁环每转是44个脉冲   减速比:90  默认  (本项目使用的是528直流减速编码电机)

/*用数组传递电机速度,正数为设置前进速度,负数为设置后退速度
  以p1、p2为例:p1=4个电机以xx的速度前进    p2=4个电机以xx的速度后退 单位为RPM*/
uint8_t p1[4]={90,90,90,90};      										//电机转速设置          正数为正转(顺时针)		             
uint8_t p2[4]={-10,-10,-10,-10};    									//电机转速设置 			负数为反转(逆时针)
uint8_t MotorEncoderPolarity = 0; 							  //电机极性控制变量			为1或0,为0时正转读数为正
uint32_t EncodeTotal[4];													//用于暂存电机累积转动量的值,正转递增,反转递减
uint8_t MotorType = MOTOR_TYPE_JGB37_520_12V_110RPM; 								//设置电机类型
	
int main(void)
{
	
	u16 v;																  						//用于暂存电压值
	SystemInit(); 																			//系统时钟初始化为72M	  SYSCLK_FREQ_72MHz
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);			//设置NVIC中断分组2:2位抢占优先级,2位响应优先级
	InitDelay(72); 																			//初始化延时函数
	InitTimer2();																				//定时器2初始化
	IIC_init();																					//IIC初始化
	Usart1_Init(); 																			//串口初始化
	InitLED();        																	//初始化LED指示灯
	DelayMs(200);
	I2C_Write_Len(MOTOR_TYPE_ADDR,&MotorType,1);					//在电机类型地址中写入电机类型编号
	DelayMs(5);
	I2C_Write_Len(MOTOR_ENCODER_POLARITY_ADDR,&MotorEncoderPolarity,1);		//设置电机极性设置
	DelayMs(5);
	while(1)
	{
		I2C_Read_Len(ADC_BAT_ADDR,data,2);									//读取电机电压
		v = data[0] + (data[1]<<8); 												//转换电压
		printf("V = ");		printf("%d",v);  	printf("mV\n"); //打印电压
		I2C_Read_Len(MOTOR_ENCODER_TOTAL_ADDR,(uint8_t*)EncodeTotal,16);
		printf("Encode1 = %ld  Encode2 = %ld  Encode3 = %ld  Encode4 = %ld  \r\n", EncodeTotal[0], EncodeTotal[1], EncodeTotal[2], EncodeTotal[3]);
		/*在电机转速地址中写入电机的转动方向和速度:WireWriteDataArray(转速控制地址,电机转速数组,电机个数)*/
		I2C_Write_Len(MOTOR_FIXED_SPEED_ADDR,p1,4);						//控制电机转动
		DelayMs(1000);
//		I2C_Write_Len(MOTOR_FIXED_SPEED_ADDR,p2,4);						//控制电机转动
//		DelayMs(1000);
	}
}

驱动板是IIC协议进行控制和数据回传,回传数据包括电压,四个电机编码器的计数。

实测在7.7V电压下转速约为80RPM 电机额定满转速为90RPM            而90*(7.7/8) ≈ 86 RPM。

所以在电机转速数组p1中填的值应该是转速RPM (亲测填了100也没转的更快),而且80RPM也接近额定电压下的转速了,所以基本可以排除是PWM的值。

另外,本人问官方群技术人员,回答说用的528电机型号值跟

#define MOTOR_TYPE_JGB37_520_12V_110RPM   3    的一样,但是TT编码电机的也行,不知道为什么。

补充1:要注意给电机写速度值得时候一定是循环写入,不能只写有限次,一停止写电机就不转了。

补充2: 0x33是一号电机的速度值寄存器 0x34是二号电机 0x35是三号电机 0x36是四号电机。

以下简单整理了其STM32代码中IIC的读写流程:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值