【基于树莓派400的图像识别归类&运动检测&模拟信号处理系统第二帖】使用I2C总线读...
[复制链接]
本帖最后由 donatello1996 于 2022-10-23 21:27 编辑
【基于树莓派400的图像识别归类&运动检测&模拟信号处理系统第二帖】使用I2C总线读取MPU6050/BMP280数据并搭建QT程序进行图形化显示
树莓派自带了一个I2C1的接口,引出到GPIO上,这个I2C接口功能强大,将各类I2C传感器连接,即可使用Linux系统强大的i2cdetect管理软件和ioctl()接口进行读写,检测,非常简单方便,比用单片机去读I2C简单多了,方法如下:
i2cdetect -y 1
i2cdetect管理软件有几个指令,比如i2cdump i2cset等。
我这边是用I2C1接口同时连接了MPU6050+BMP280+AHT20,其中AHT20的调试出了问题,温湿度读取偶尔不正常,能正常读取MPU6050和BMP280的数据,非常简单:
void MPU6050_Init()
{
uint8_t write_data[1];
write_data[0] = 0x07;
I2C_Device_Write (0x68 , write_data , 1 , SMPLRT_DIV);
//Write to sample rate register
write_data[0] = 0x01;
I2C_Device_Write (0x68 , write_data , 1 , PWR_MGMT_1);
// Write to power management register
write_data[0] = 0;
I2C_Device_Write (0x68 , write_data , 1 , CONFIG);
// Write to Configuration register
write_data[0] = 24;
I2C_Device_Write (0x68 , write_data , 1 , GYRO_CONFIG);
// Write to Gyro Configuration register
write_data[0] = 0x01;
I2C_Device_Write (0x68 , write_data , 1 , INT_ENABLE);
//Write to interrupt enable register
}
int BMP280_Init()
{
uint8_t ret , i2c_read_data[2];
I2C_Device_Read(I2C_ADDR_BMP280 , &ret , 1 , 0xd0);
if (ret == 0x58)
{
I2C_Device_Read(I2C_ADDR_BMP280 , i2c_read_data , 2 , 0x88);
dig_t1 = i2c_read_data[1] << 8 | i2c_read_data[0];
I2C_Device_Read(I2C_ADDR_BMP280 , i2c_read_data , 2 , 0x8a);
dig_t2 = i2c_read_data[1] << 8 | i2c_read_data[0];
I2C_Device_Read(I2C_ADDR_BMP280 , i2c_read_data , 2 , 0x8c);
dig_t3 = i2c_read_data[1] << 8 | i2c_read_data[0];
I2C_Device_Read(I2C_ADDR_BMP280 , i2c_read_data , 2 , 0x8e);
dig_p1 = i2c_read_data[1] << 8 | i2c_read_data[0];
I2C_Device_Read(I2C_ADDR_BMP280 , i2c_read_data , 2 , 0x90);
dig_p2 = i2c_read_data[1] << 8 | i2c_read_data[0];
I2C_Device_Read(I2C_ADDR_BMP280 , i2c_read_data , 2 , 0x92);
dig_p3 = i2c_read_data[1] << 8 | i2c_read_data[0];
I2C_Device_Read(I2C_ADDR_BMP280 , i2c_read_data , 2 , 0x94);
dig_p4 = i2c_read_data[1] << 8 | i2c_read_data[0];
I2C_Device_Read(I2C_ADDR_BMP280 , i2c_read_data , 2 , 0x96);
dig_p5 = i2c_read_data[1] << 8 | i2c_read_data[0];
I2C_Device_Read(I2C_ADDR_BMP280 , i2c_read_data , 2 , 0x98);
dig_p6 = i2c_read_data[1] << 8 | i2c_read_data[0];
I2C_Device_Read(I2C_ADDR_BMP280 , i2c_read_data , 2 , 0x9a);
dig_p7 = i2c_read_data[1] << 8 | i2c_read_data[0];
I2C_Device_Read(I2C_ADDR_BMP280 , i2c_read_data , 2 , 0x9c);
dig_p8 = i2c_read_data[1] << 8 | i2c_read_data[0];
I2C_Device_Read(I2C_ADDR_BMP280 , i2c_read_data , 2 , 0x9e);
dig_p9 = i2c_read_data[1] << 8 | i2c_read_data[0];
return 0;
}
return -1;
}
I2C的读写函数也是可以直接使用ioctl()函数接口的,非常方便:
int I2C_Device_Write(uint8_t i2c_dev_addr , uint8_t s[] , int len , uint8_t reg_addr)
{
int i;
if ((i2c2_fd = open(I2C_INTER_DEVICE , O_RDWR))<0)
{
qDebug("Fail to open i2c-2 device\n");
return 1;
}
ioctl(i2c2_fd , I2C_TIMEOUT , 2);
ioctl(i2c2_fd , I2C_RETRIES , 1);
i2c2.nmsgs = 1;
i2c2.msgs = (struct i2c_msg*)malloc(i2c2.nmsgs * sizeof(struct i2c_msg));
if(!i2c2.msgs)
{
qDebug("malloc error\n");
return 2;
}
i2c2.nmsgs = 1;
i2c2.msgs[0].len = 1 + len;
i2c2.msgs[0].addr = i2c_dev_addr;
i2c2.msgs[0].flags = 0;
i2c2.msgs[0].buf = (unsigned char*)malloc(1 + len);
i2c2.msgs[0].buf[0] = reg_addr;
memcpy(i2c2.msgs[0].buf + 1 , s , len);
if(ioctl(i2c2_fd , I2C_RDWR , &i2c2) < 0)
{
qDebug("Write failed.\n");
for(i = 0 ; i < i2c2.nmsgs ; i ++)
{
free(i2c2.msgs.buf);
}
free(i2c2.msgs);
close(i2c2_fd);
return 3;
}
else
{
qDebug("Write success.\n");
for(i = 0 ; i < i2c2.nmsgs ; i ++)
{
free(i2c2.msgs.buf);
}
free(i2c2.msgs);
close(i2c2_fd);
return 0;
}
}
int I2C_Device_Read(uint8_t i2c_dev_addr , uint8_t read_data[] , int len , uint8_t reg_addr)
{
int i;
if ((i2c2_fd = open(I2C_INTER_DEVICE , O_RDWR))<0)
{
qDebug("Fail to open %s device\n" , I2C_INTER_DEVICE);
return 1;
}
ioctl(i2c2_fd , I2C_TIMEOUT , 2);
ioctl(i2c2_fd , I2C_RETRIES , 1);
i2c2.nmsgs = 2;
i2c2.msgs = (struct i2c_msg*)malloc(i2c2.nmsgs * sizeof(struct i2c_msg));
if(!i2c2.msgs)
{
qDebug("malloc error\n");
return 2;
}
(i2c2.msgs[0]).len = 1;
(i2c2.msgs[0]).addr = i2c_dev_addr;
(i2c2.msgs[0]).flags = 0;
(i2c2.msgs[0]).buf = (unsigned char*)malloc(1);
(i2c2.msgs[0]).buf[0] = reg_addr;
(i2c2.msgs[1]).len = len;
(i2c2.msgs[1]).addr = i2c_dev_addr;
(i2c2.msgs[1]).flags = I2C_M_RD;
(i2c2.msgs[1]).buf = (unsigned char*)malloc(len);
(i2c2.msgs[1]).buf[0] = 0;
if(ioctl(i2c2_fd , I2C_RDWR , &i2c2) < 0)
{
qDebug("Read failed.\n");
for(i = 0 ; i < i2c2.nmsgs ; i ++)
{
free(i2c2.msgs.buf);
}
free(i2c2.msgs);
close(i2c2_fd);
return 3;
}
else
{
memcpy(read_data , i2c2.msgs[1].buf , len);
for(i = 0 ; i < i2c2.nmsgs ; i ++)
{
free(i2c2.msgs.buf);
}
free(i2c2.msgs);
close(i2c2_fd);
return 0;
}
}
将此代码代入到QT程序中,并使用QVector3D和QPainter实现正立方体和仪表盘:
QVector3D:
Cube3D::Cube3D(QWidget *parent) : QWidget(parent)
{
// 7------------------4
// / / |
// 3------------------0 |
// | | |
// | | |
// | | |
// | | |
// | 6 | 5
// | | /
// 2------------------1
//立方体前后四个顶点,从右上角开始顺时针
vertexArr = QVector<QVector3D>{
QVector3D{1, 1, 1},
QVector3D{1, -1, 1},
QVector3D{-1, -1, 1},
QVector3D{-1, 1, 1},
QVector3D{1, 1, -1},
QVector3D{1, -1, -1},
QVector3D{-1, -1, -1},
QVector3D{-1, 1, -1}};
//六个面,一个面包含四个顶点
elementArr = QVector<QVector<int>>{
{0, 1, 2, 3},
{4, 5, 6, 7},
{0, 4, 5, 1},
{1, 5, 6, 2},
{2, 6, 7, 3},
{3, 7, 4, 0}};
//Widget默认没有焦点,此处设置为点击时获取焦点
setFocusPolicy(Qt::ClickFocus);
startTimer(50);
}
QPainter:
void TBP::Dashboard(int value1,int value2,int value3,
QColor qc1,QColor qc2,QColor qc3)
{
int i;
if(value1 < 0)value1 = 0;
if(value1 > 100)value1 = 100;
if(value2 < 0)value2 = 0;
if(value2 > 100)value2 = 100;
static const QPoint secondHand[3] =
{
QPoint(4,17),
QPoint(-4,17),
QPoint(0, -100)
};
static const QPoint secondHand1[3] =
{
QPoint(2,17),
QPoint(-2,17),
QPoint(0, -50)
};
qpainter->restore();
qpainter->save();
qpainter->rotate(0);
QColor qc4(220 , 220 , 220);
qpainter->fillRect(-250 , -250 , 500 , 500 , qc4);
qpainter->restore();
qpainter->save();
qpainter->rotate(-156);
for(i = 0 ; i <= 100 ; i++)
{
qpainter->rotate(3);
if(i % 10 == 0 && i > 0)
{
qpainter->setPen(Qt::black);
qpainter->drawLine(0,-130,1,-110);
qpainter->drawLine(1,-130,0,-110);
qpainter->drawLine(0,-130,0,-110);
qpainter->drawLine(1,-130,1,-110);
}
else qpainter->setPen(Qt::blue);
qpainter->drawLine(0,-130,0,-120);
}
qpainter->rotate(0);
for(i = 0 ; i <= 20 ; i++)
{
qpainter->rotate(3);
qpainter->setPen(QColor(255,255,0));
qpainter->drawLine(0,-130,0,-110);
}
qpainter->setPen(Qt::black);
QRectF rect1(-130 , -130 , 260, 260);
qpainter->drawEllipse(rect1);
QRectF rect2(-129 , -129 , 258, 258);
qpainter->drawEllipse(rect2);
QRectF rect3(-131 , -131 , 262, 262);
qpainter->drawEllipse(rect3);
QRectF rect4(-131 , -131 , 261, 261);
qpainter->drawEllipse(rect4);
QRectF rect5(-129 , -129 , 259, 259);
qpainter->drawEllipse(rect5);
qpainter->restore();
qpainter->save();
qpainter->rotate(-153 + value1 * 3);
qpainter->setPen(qc1);
qpainter->setBrush(qc1);
qpainter->drawEllipse(-5,-5,10,10);
qpainter->drawConvexPolygon(secondHand,3);
qpainter->restore();
qpainter->save();
qpainter->rotate(-153+value2*3);
qpainter->setPen(qc2);
qpainter->setBrush(qc2);
qpainter->drawEllipse(-5,-5,10,10);
qpainter->drawConvexPolygon(secondHand,3);
qpainter->restore();
qpainter->save();
qpainter->rotate((-value3)*3/5+804);
qpainter->setPen(qc3);
qpainter->setBrush(qc3);
qpainter->drawEllipse(-5,-5,10,10);
qpainter->drawConvexPolygon(secondHand1,3);
qpainter->restore();
qpainter->save();
qpainter->setFont(QFont("Arial",12,QFont::Bold));
qpainter->drawText(-80,125,"0");
qpainter->drawText(-135,80,"10");
qpainter->drawText(-160,13,"20");
qpainter->drawText(-155,-22,"25");
qpainter->drawText(-142,-58,"30");
qpainter->drawText(-90,-113,"40");
qpainter->drawText(-18,-135,"50");
qpainter->drawText(125,-40,"75");
qpainter->drawText(70,122,"100");
qpainter->setPen(qc3);
qpainter->setFont(QFont("Arial",8,QFont::Light));
qpainter->drawText(-60,80,"990");
qpainter->drawText(-15,100,"1040");
qpainter->drawText(30,80,"1090");
qpainter->setPen(Qt::darkBlue);
qpainter->setBrush(Qt::darkBlue);
qpainter->rotate(-146);
for(i = 0 ; i <= 2950 ; i++)
{
qpainter->rotate(0.1);
qpainter->drawLine(0,-180,0,-160);
}
QRectF rect9(-10, -180, 20, 20);
qpainter->drawEllipse(rect9);
qpainter->setPen(Qt::cyan);
qpainter->setBrush(Qt::yellow);
qpainter->rotate(-295);
QRectF rect10(-10, -180, 20, 20);
qpainter->drawEllipse(rect10);
for(i = 0 ; i <= 2000 ; i++)
{
qpainter->rotate(0.1);
qpainter->drawLine(0,-180,0,-160);
}
qpainter->drawEllipse(rect10);
QWidget::update();
}
运行效果:
38fb8c7a9bcdf283f7d894da0830c202
|