[Image recognition classification & motion detection & analog signal processing system based on Raspberry Pi 400, Part 2] Using I2C bus to read...
[Copy link]
This post was last edited by donatello1996 on 2022-10-23 21:27
[Image recognition classification & motion detection & analog signal processing system based on Raspberry Pi 400, Part 2] Use I2C bus to read MPU6050/BMP280 data and build QT program for graphical display
The Raspberry Pi comes with an I2C1 interface, which is connected to the GPIO. This I2C interface is powerful. By connecting various I2C sensors, you can use the Linux system's powerful i2cdetect management software and ioctl() interface to read, write, and detect. It is very simple and convenient, much simpler than using a microcontroller to read I2C. The method is as follows:
i2cdetect -y 1
The i2cdetect management software has several commands, such as i2cdump i2cset, etc.
I used the I2C1 interface to connect MPU6050+BMP280+AHT20 at the same time. There was a problem with the debugging of AHT20, and the temperature and humidity readings were occasionally abnormal. The data of MPU6050 and BMP280 can be read normally. It is very simple:
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 read and write functions can also directly use the ioctl() function interface, which is very convenient:
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;
}
}
Substitute this code into the QT program and use QVector3D and QPainter to implement the cube and instrument panel:
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();
}
Operation effect:
38fb8c7a9bcdf283f7d894da0830c202
|