FRC自购IIC陀螺仪GY-91使用

硬件准备

这是我们在某宝上购买的一款SPI&IIC陀螺仪

https://item.taobao.com/item.htm?spm=a230r.1.14.1.113c4b20IbC4N3&id=523806329384&ns=1&abbucket=12#detail

它即将被我们连接到主板NI roboRIO上

https://www.andymark.com/products/ni-roborio-2?via=Z2lkOi8vYW5keW1hcmsvV29ya2FyZWE6Ok5hdmlnYXRpb246OlNlYXJjaFJlc3VsdHMvJTdCJTIyYnV0dG9uJTIyJTNBJTIyc2VhcmNoJTIyJTJDJTIycSUyMiUzQSUyMnJvYm9yaW8lMjIlMkMlMjJ1dGY4JTIyJTNBJTIyJUUyJTlDJTkzJTIyJTdE

SPI尝试

我们首先尝试用SPI的通信协议

主板上的SPI接口共有10个

我们打开商家给的GY-91陀螺仪文档手册,结合NI roboRIO的说明进行接线

Serial Buses — FIRST Robotics Competition documentation (wpilib.org)docs.wpilib.org

GY-91 - NI roboRIO

3V3 - 3.3V

GND - 地线

SCL - SCLK

SDA - MOSI

SD0/SA0 - MISO

NCS - CS0/CS1/CS2/CS3

我们这里是测试时将CSB接到CS0上,正确方式应该连接NCS和CS0

程序准备

我们在官方给的API集里面找到了需要用到的类

https://docs.wpilib.org/en/latest/docs/hardware/sensors/serial-buses.html?highlight=spi#mxp-expansion-port

我们先建出陀螺仪的对象_gyro

/**
* 将SPI头文件导入 
*/
#include <frc/SPI.h>
/**
* 为陀螺仪建立SPI对象
*/
frc::SPI *_gyro = new frc::SPI(frc::SPI::Port::kOnboardCS0);

接下来我们希望找到能够读取到陀螺仪值的函数,我们在adafruit的网站上找到了同款芯片的arduino代码

https://learn.adafruit.com/adafruit-tdk-invensense-icm-20948-9-dof-imu/arduino

但arduino的库和frc的库存在很大的差别,我们并没有从中获得很大的启示,于是我把目光重新投回WPILIB上,我使用这段代码来进行测试

uint32_t* data = new uint32_t[9]; 
frc::SmartDashboard::PutNumber("ReadAutoReciveData",_gyro->ReadAutoReceivedData(data,16,1000.0)); 
frc::SmartDashboard::PutNumber("0",data[0]); 
frc::SmartDashboard::PutNumber("1",data[1]); 
frc::SmartDashboard::PutNumber("2",data[2]); 
frc::SmartDashboard::PutNumber("3",data[3]); 
frc::SmartDashboard::PutNumber("4",data[4]); 
frc::SmartDashboard::PutNumber("5",data[5]); 
frc::SmartDashboard::PutNumber("6",data[6]); 
frc::SmartDashboard::PutNumber("7",data[7]); 
frc::SmartDashboard::PutNumber("8",data[8]);

因为文档上介绍这款陀螺仪是九轴的,且输出数据为16位,于是我将上面代码修改为

 uint32_t* data = new uint32_t[10];  
 frc::SmartDashboard::PutNumber("ReadAutoReciveData",_gyro->ReadAutoReceivedData(data,16,1000.0));  
 frc::SmartDashboard::PutNumber("0",data[0]);  
 frc::SmartDashboard::PutNumber("1",data[1]);  
 frc::SmartDashboard::PutNumber("2",data[2]);  
 frc::SmartDashboard::PutNumber("3",data[3]);  
 frc::SmartDashboard::PutNumber("4",data[4]);  
 frc::SmartDashboard::PutNumber("5",data[5]);  
 frc::SmartDashboard::PutNumber("6",data[6]); 
 frc::SmartDashboard::PutNumber("7",data[7]);  
 frc::SmartDashboard::PutNumber("8",data[8]); 
 frc::SmartDashboard::PutNumber("9",data[9]);

我试图从十个打印值中找到规律,但很明显我没有成功,我重新看回技术手册希望得到些许启示

https://learn.adafruit.com/adafruit-tdk-invensense-icm-20948-9-dof-imu

我在adafruit的网站上找到了这款芯片的详细信息,还有ICM20X的API文档

https://adafruit.github.io/Adafruit_ICM20X/html/index.html

经过了很多次的尝试,但并没有找到有效的解决方法

IIC连接

于是我们更换了一种连接方式,尝试用IIC的通信协议来将他们连接

GY-91 - NI roboRIO

3V3 - 3.3V

GND - 地线

SCL - SCL

SDA - SDA

#include <frc/I2C.h>
#define ADDR 0x68
frc::I2C gyro{frc::I2C::kOnboard,ADDR};
frc::I2C temp{frc::I2C::kOnboard,0x0c};

void Robot::RobotInit() {
  uint8_t id[1];
  int device_id=gyro.Read(0x75,1,id);
  frc::SmartDashboard::PutNumber("id",device_id);
  gyro.Write(0x6a,0x00);
  frc::Wait(0.05);
  gyro.Write(0x37,0x02);
  temp.Write(0x0a,0x16);
  gyro.Write(29,9);
  gyro.Write(106,96);
}

void Robot::TeleopPeriodic() {
  temp.Write(0x0a,0x16);
  uint8_t gout[6];
  bool bl=gyro.Read(0x43,6,gout);
  frc::SmartDashboard::PutBoolean("bl",bl);
  frc::SmartDashboard::PutNumber("X",(gout[0]<<8)|gout[1]);
  frc::Wait(0.5);
}

我们简单的读取陀螺仪的数据,但遇到了数据波动的问题

程序控制

为了降低数据波动,我们寻找一种合适的滤波算法

在官方电控文档中,我看到了一些过滤器算法的库

https://docs.wpilib.org/en/latest/docs/software/advanced-controls/filters/index.html

我们为数据添加了线性过滤器和中位值过滤器各两种

frc::MedianFilter<double> median_filter2(20);
frc::LinearFilter<double> linear_filter2 = 	frc::LinearFilter<double>::SinglePoleIIR(0.5,0.02_s);
frc::MedianFilter<double> median_filter(5);
frc::LinearFilter<double> linear_filter = frc::LinearFilter<double>::SinglePoleIIR(0.1,0.02_s);
void Robot::TeleopPeriodic(){
  temp.Write(0x0a,0x16);
  uint8_t gout[6];
  bool bl=gyro.Read(0x43,6,gout);
  frc::SmartDashboard::PutBoolean("bl",bl);
  double giao=(gout[0]<<8|gout[1]);
  frc::SmartDashboard::PutNumber("X",giao);
  //frc2::Wait(0.05_s);
  frc::SmartDashboard::PutNumber("median_filter",median_filter.Calculate(giao));
  frc::SmartDashboard::PutNumber("linear_filter",linear_filter.Calculate(giao));
  frc::SmartDashboard::PutNumber("median_filter2",median_filter2.Calculate(giao));
  frc::SmartDashboard::PutNumber("linear_filter2",linear_filter2.Calculate(giao));
}

在glass工具中将5条数据显示出来

我们观察到linear_filter2对数据有更好的过滤作用

完整代码

#include "Robot.h"
#include <iostream>
#include <frc/smartdashboard/SmartDashboard.h>
#include<frc/MedianFilter.h>
#include<frc/LinearFilter.h>
#include<frc/I2C.h>
#define ADDR 0X68
frc::I2C gyro{frc::I2C::kOnboard,ADDR};//陀螺仪对象
frc::I2C temp{frc::I2C::kOnboard,0x0c};
frc::LinearFilter<double> linear_filter = frc::LinearFilter<double>::SinglePoleIIR(0.5,0.02_s);//线性过滤器
void Robot::RobotInit(){
  uint8_t id[1];
  int device_id=gyro.Read(0x75,1,id);
  frc::SmartDashboard::PutNumber("id",device_id);
  gyro.Write(0x6a,0x00);
  //frc2::Wait(0.05_s);
  gyro.Write(0x37,0x02);
  temp.Write(0x0a,0x16);
  gyro.Write(29,9);
  gyro.Write(106,96);
}

void Robot::TeleopPeriodic(){
  temp.Write(0x0a,0x16);
  uint8_t gout[6];
  bool bl=gyro.Read(0x43,6,gout);
  frc::SmartDashboard::PutBoolean("bl",bl);
  double data=(gout[0]<<8|gout[1]);//调整gout[]获取不同的值  
  frc::SmartDashboard::PutNumber("X",data);
  frc::SmartDashboard::PutNumber("linear_filter2",linear_filter2.Calculate(data));
  //frc2::Wait(0.05_s);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值