本人使用的设备/驱动:
- Windows10
- 串口助手 4.3.25(其实啥都行)
- 桃饱随处可买的usb-ttl(ch340G)
- 桃饱随处可买的stlink
- mpu6050(一个板载,一个通过I2C接插件连接外置)
- cubeMX 5.6.1
- PlatformIO
- pycharm community2019
- stm32f103rct6的storm32BGC
使用stm32f103rct6,之前已经能使一个MPU正常工作,现在准备配置双MPU6050(板载与外置),并使用gui显示数据
本文直接从项目中加入相关功能说起,环境以及其他外设配置:
使用ST-LINK utility将单片机中的程序下载下来
CubeMX配合PlatformIO开发STM32,配置环境,点亮LED灯
CubeMX配合PlatformIO开发STM32,配置usart实现串口通讯
CubeMX配合PlatformIO开发STM32,配置ADC实现电池电压检测
CubeMX配合PlatformIO开发STM32,配置MPU6050(I2C)
CubeMX配合PlatformIO开发STM32,配置双MPU6050(板载与外置),并使用gui显示数据
CubeMX配合PlatformIO开发STM32,通过系统时钟(systick)中断让不同功能代码以不同频率执行,计算计算所花时间
CubeMX配合PlatformIO开发STM32,实现pid算法控制电机的转角
CubeMX配合PlatformIO开发STM32,配置定时器,实现SPWM算法控制电机
CubeMX配合PlatformIO开发STM32,配置uart中断,配合python的gui在线调参
正文
根据资料可知,mpu6050有一个引脚AD0,如果接地拉低,则地址为0x68,官方库,以及正点原子的代码都只有0x68的配置方法。如果拉高到3.3V,它的地址是0x69,如下图,板载mpu的原理图:
但很多时候需要多个mpu来满足工作需求,这个时候就需要进行额外配置:
因为库代码的原因,mpu的参数被固化在const struct hw中:
/*注,此处地址是0x68左移一位;原因是如果使用0x68,访问的时候函数需要左移一位进行访问,如下图:
援引正点原子的源码*/
与此同时,inv_mpu.c中的mpu初始化等函数也是跟hw强绑定,如果用新建struct,代码就需要大量增改。
所以准备设置一个跨文件全局变量来影响每个与mpu通讯的函数,如果使用外置则置零,使用内置则置一,使地址区分:
在inv_mpu.c中新建变量
uint8_t is_using_onboard_mpu=0;
在inv_mpu.h中extern:
extern uint8_t is_using_onboard_mpu;
找到inv_mpu.c中的i2c操作函数,进行全局替换:
if (i2c_write((st.hw->addr + is_using_onboard_mpu*2), st.reg->int_enable, 1, &tmp))
return -1;
将i2c_write(st.hw->addr , st.reg->int_enable, 1, &tmp)中的st.hw->addr全部替换为(st.hw->addr + is_using_onboard_mpu*2)
i2c_write((st.hw->addr + is_using_onboard_mpu*2), st.reg->int_enable, 1, &tmp)
注意,因为左移一位,所以0x68->0x69左移需要+2
在主函数中,每需要切换mpu操作,则:
/*External_MPU6050*/
is_using_onboard_mpu=0;//地址偏移置零
MPU6050_I2C = &hi2c2;//切换句柄
为了可视化读串口数据,我们将数据打包通过串口发回来:
新建结构:
typedef struct
{
uint32_t time_stamp;
float yaw;
float roll;
float pitch;
char end1;
char end2;
} Serial_Transmit_Stream_typeDef;
在主函数中读角度值并填装:
serial_data.end1 = '\r';
serial_data.end2 = '\n';
//added in the end of data
serial_data.pitch=pitch;
serial_data.roll=roll;
serial_data.yaw=yaw;
serial_data.time_stamp = HAL_GetTick();//get current time
SerialPrintTransmit(&serial_data);//调用hal函数发送到串口中
对于SerialPrintTransmit(&serial_data);先定义:
HAL_StatusTypeDef SerialPrintReceive(const Serial_Receive_Stream_typeDef *data)
{
return HAL_UART_Transmit(&huart3, (uint8_t *)data, sizeof(Serial_Transmit_Stream_typeDef), 0xffff);
}
注意,因为发送struct的原因,如果size是18字节,则确定是这些数据:
我们在py中新建一个py文件,用serial库来读取:
def readData(self):
databytes = self.serial.readline()
if len(databytes) == 18:
flag = 0
databytes = databytes[:-2]//因为最后两个byte是\r\n
data = struct.unpack('Ifff', databytes)//将读到的一串数据根据格式拆成元组。比如拆成几个float,几个char
return [flag,data]
然后读出三个角度值:
[flag, data] = serial.readData()
if flag == 0:
# print(data)
data1 = bound(data[1], -360, 360)
data2 = bound(data[2], -360, 360)
data3 = bound(data[3], -360, 360)
time_q.put(data[0])
yaw_q.put(data1)
roll_q.put(data2)
pitch_q.put(data3)
time_last = data[0]
yaw_last = data1
roll_last = data2
pitch_last = data3
装填进数组:
time_data[:-1] = time_data[1:]
time_data[i-1] = time_q.get()
yaw_data[:-1] = yaw_data[1:]
yaw_data[i-1] = yaw_q.get()
roll_data[:-1] = roll_data[1:]
roll_data[i-1] = roll_q.get()
pitch_data[:-1] = pitch_data[1:]
pitch_data[i-1] = pitch_q.get()
更新gui曲线:
def updateCurve(self):
global yaw_curve, roll_curve, pitch_curve
yaw_curve.setData(yaw_data)
roll_curve.setData(roll_data)
pitch_curve.setData(pitch_data)
运行,就可以得到曲线:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)