动量轮平衡自行车实现笔记

手搓手柄驱动量轮平衡小车

摘要

最近闲暇想玩点小玩艺,想到了网上一时火起的平衡小车,苦于没有结构件,买整套的吧,感觉对于咱们手艺人来讲有点羞耻,看看淘宝上有纯结构件卖,于是乎先把硬件板画了起来,后来硬件所有资源调通后,再购买结构件回来时,这版硬件居然能勉强固定两个螺丝,玩上了视频中的一版。在整个玩的过程中,有些调试问题,记录下来。

一、stm32外设I2C驱mpu6050的问题

我用的是STM32F103C6的 I2C1 映射到PB8,PB9,用函数读MPU6050寄存器时,发现每第二次读时,I2C总线死在发起start信号后。后来看了手册后,需要在操作完之后,加一条代码:

LL_I2C_AcknowledgeNextData(I2Cx, LL_I2C_ACK);

即整个函数如下

uint8_t MPU6050_ReadReg(uint8_t reg)
{
    uint8_t value; 
    // __disable_irq();    
    LL_GPIO_AF_EnableRemap_I2C1();
    LL_I2C_GenerateStartCondition(I2Cx);
    while(!LL_I2C_IsActiveFlag_SB(I2Cx));
    //USART1_SendString("2");
    
    LL_I2C_TransmitData8(I2Cx, MPU6050_ADDR_WRITE);   
    while(!LL_I2C_IsActiveFlag_ADDR(I2Cx));
    LL_I2C_ClearFlag_ADDR(I2Cx);
    LL_I2C_TransmitData8(I2Cx, reg);
    while(!LL_I2C_IsActiveFlag_BTF(I2Cx));

    LL_I2C_GenerateStartCondition(I2Cx);
    while(!LL_I2C_IsActiveFlag_SB(I2Cx));
    LL_I2C_TransmitData8(I2Cx, MPU6050_ADDR_READ);    
    while(!LL_I2C_IsActiveFlag_ADDR(I2Cx));
    LL_I2C_ClearFlag_ADDR(I2Cx);    
    
    LL_I2C_AcknowledgeNextData(I2Cx, LL_I2C_NACK);
    LL_I2C_GenerateStopCondition(I2Cx);
    
    while(!LL_I2C_IsActiveFlag_RXNE(I2Cx));
    value = LL_I2C_ReceiveData8(I2Cx);
    LL_I2C_AcknowledgeNextData(I2Cx, LL_I2C_ACK);  
    return value;
   
}

二、手柄驱动小记

手上有一款手柄,一直想用单片机来驱玩玩,正好这次就画到这种小板上去了,搜了下usb host芯片,最后选用了ch370T,但最后去找技术支持和官网上去下资料时,有点懵B了,给的都是374的资料,也没有手柄的程序,最后在电脑上监控usb数据流,再用ch370把每个数据流发给手柄u转无线器,庆幸最后驱动成功。获取数据正确。但是整体方案上有点问题就是用手柄驱动方向舵机时,舵机会使5V电压下降,致ch370驱动U口死机。也就是说,后续方案再做时,电池供电转5V时,需要稳压。

三、获取pitch roll  yaw角度

mpu6050只能获取角速率和角加速度,以及温度。这些数据是不能直接参与到平衡pid算法中的,需要转换出roll横滚角度。网上有很多方法,我直接移植了motion_driver_6.12。我的电路板的陀螺仪转换坐标系如下

// 陀螺仪方向设置
static signed char gyro_orientation[9] = { 0, -1, 0,
                                           1, 0, 0,
                                           0, 0, 1};

初始化及获取角度代码如下:

uint8_t mpu_dmp_init(void)
{
	uint8_t res=0;
	if(mpu_init(NULL)==0)	//初始化MPU6050
	{        
		res=mpu_set_sensors(INV_XYZ_GYRO|INV_XYZ_ACCEL);//设置所需要的传感器
		if(res)return 1;
		res=mpu_configure_fifo(INV_XYZ_GYRO | INV_XYZ_ACCEL);//设置FIFO
		if(res)return 2;
		res=mpu_set_sample_rate(DEFAULT_MPU_HZ);	//设置采样率
		if(res)return 3;
		res=dmp_load_motion_driver_firmware();		//加载dmp固件
		if(res)return 4;
		res=dmp_set_orientation(inv_orientation_matrix_to_scalar(gyro_orientation));//设置陀螺仪方向
		if(res)return 5;
		res=dmp_enable_feature(DMP_FEATURE_6X_LP_QUAT|DMP_FEATURE_TAP|	//设置dmp功能
		    DMP_FEATURE_ANDROID_ORIENT|DMP_FEATURE_SEND_RAW_ACCEL|DMP_FEATURE_SEND_CAL_GYRO|
		    DMP_FEATURE_GYRO_CAL);
		if(res)return 6;
		res=dmp_set_fifo_rate(DEFAULT_MPU_HZ);	//设置DMP输出速率(最大不超过200Hz)
		if(res)return 7;
		res=run_self_test();		//自检
		if(res)return 8;
		res=mpu_set_dmp_state(1);	//使能DMP
		if(res)return 9;
	}
	return 0;
}

//pitch:俯仰角 精度:0.1°   范围:-90.0° <---> +90.0°
//roll:横滚角  精度:0.1°   范围:-180.0°<---> +180.0°
//yaw:航向角   精度:0.1°   范围:-180.0°<---> +180.0°
//返回值:0,正常
//    其他,失败
uint8_t mpu_dmp_get_data(IMU_Parameter *IMU_Data)
{
	float q0=1.0f,q1=0.0f,q2=0.0f,q3=0.0f;
	unsigned long sensor_timestamp;
	short gyro[3], accel[3], sensors;
	unsigned char more;
	long quat[4];
	if(dmp_read_fifo(gyro, accel, quat, &sensor_timestamp, &sensors,&more))return 1;

    IMU_Data->Gyro_X = gyro[0];
    IMU_Data->Gyro_Y = gyro[1];
    IMU_Data->Gyro_Z = gyro[2];

    IMU_Data->Accel_X = accel[0];
    IMU_Data->Accel_Y = accel[1];
    IMU_Data->Accel_Z = accel[2];

	if(sensors&INV_WXYZ_QUAT)
	{
		q0 = quat[0] / q30;	//q30格式转换为浮点数
		q1 = quat[1] / q30;
		q2 = quat[2] / q30;
		q3 = quat[3] / q30;
		//计算得到俯仰角/横滚角/航向角
		IMU_Data->Pitch = asin(-2 * q1 * q3 + 2 * q0* q2)* 57.3;	// pitch
		IMU_Data->Roll  = atan2(2 * q2 * q3 + 2 * q0 * q1, -2 * q1 * q1 - 2 * q2* q2 + 1)* 57.3;	// roll
		IMU_Data->Yaw   = atan2(2*(q1*q2 + q0*q3),q0*q0+q1*q1-q2*q2-q3*q3) * 57.3;	//yaw

        // usart1_report_imu(accel[0],accel[1],accel[2],gyro[0],gyro[1],gyro[2],IMU_Data->Angle_X,IMU_Data->Angle_Y,IMU_Data->Angle_Z);
	}else return 2;
	return 0;
}

以上三个问题解决,其它的基本没什么问题了。蓝牙我作的是ECB01H2,在电脑上用qt写一版调试工具。如视频中所见。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值