Использование 2 GY521(mpu6050) с Arduino Uno R3
Я работаю над созданием датчика движения на базе интерфейса Arduino и MPU6050. Хочу переделать свой код так, чтобы он мог считывать данные с двух устройств mpu6050. Помимо определения адреса 0x69 и установки AD0 в высокий уровень на одном устройстве и AD0 в низкий уровень на другом, какие ещё изменения мне нужно внести в код? Исходный код я выложил ниже. Заранее спасибо!
//Базовый код для настройки и чтения необработанных значений из mpu6050
//matt_m 7-9-2017
#include <Wire.h>
// Регистры: акселерометр, температура, гироскоп
#define ACCEL_XOUT_H 0x3B
#define ACCEL_XOUT_L 0x3C
#define ACCEL_YOUT_H 0x3D
#define ACCEL_YOUT_L 0x3E
#define ACCEL_ZOUT_H 0x3F
#define ACCEL_ZOUT_L 0x40
#define TEMP_OUT_H 0x41
#define TEMP_OUT_L 0x42
#define GYRO_XOUT_H 0x43
#define GYRO_XOUT_L 0x44
#define GYRO_YOUT_H 0x45
#define GYRO_YOUT_L 0x46
#define GYRO_ZOUT_H 0x47
#define GYRO_ZOUT_L 0x48
#define PWR_MGMT_1 0x6B
#define PWR_MGMT_2 0x6C
#define MPU6050 0x68 // Адрес устройства
#define ACCEL_CONFIG 0x1C // Адрес конфигурации акселерометра
#define GYRO_CONFIG 0x1B // Адрес конфигурации гироскопа
//Масштабирование выходного сигнала датчика
#define accSens 0 // 0 = 2g, 1 = 4g, 2 = 8g, 3 = 16g
#define gyroSens 1 // 0 = 250 рад/с, 1 = 500 рад/с, 2 1000 рад/с, 3 = 2000 рад/с
int16_t AcX, AcY, AcZ, Tmp, GyX, GyY, GyZ;
void setup() {
Serial.begin(115200);
angle_setup();
}
void loop() {
read_mpu6050();
Serial.println(AcX); //значение для отображения
}
//настройка MPU6050
void angle_setup()
{
Wire.begin();
delay (100);
writeTo(MPU6050, PWR_MGMT_1, 0); //выход из спящего режима
writeTo(MPU6050, ACCEL_CONFIG, accSens << 3); // Указание масштабирования выходных данных
of accelerometer
writeTo(MPU6050, GYRO_CONFIG, gyroSens << 3); // Указание масштабирования выходных данных
of gyroscope
delay (100);
}
void read_mpu6050()
{
// считать необработанные измерения ускорения/гироскопа с устройства
Wire.beginTransmission(MPU6050);
Wire.write(0x3B); // начиная с регистра 0x3B
(ACCEL_XOUT_H)
Wire.endTransmission(false);
Wire.requestFrom(MPU6050, 14, true); // запросить всего 14 регистров
AcX = Wire.read() << 8 | Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C
(ACCEL_XOUT_L)
AcY = Wire.read() << 8 | Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E
(ACCEL_YOUT_L)
AcZ = Wire.read() << 8 | Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40
(ACCEL_ZOUT_L)
Tmp = Wire.read() << 8 | Wire.read(); // 0x41 (TEMP_OUT_H) & 0x42
(TEMP_OUT_L)
GyX = Wire.read() << 8 | Wire.read(); // 0x43 (GYRO_XOUT_H) & 0x44
(GYRO_XOUT_L)
GyY = Wire.read() << 8 | Wire.read(); // 0x45 (GYRO_YOUT_H) & 0x46
(GYRO_YOUT_L)
GyZ = Wire.read() << 8 | Wire.read(); // 0x47 (GYRO_ZOUT_H) & 0x48
(GYRO_ZOUT_L)
}
void writeTo(byte device, byte toAddress, byte val) {
Wire.beginTransmission(device);
Wire.write(toAddress);
Wire.write(val);
Wire.endTransmission();
}
*редактирование: Ниже представлен код с моим лучшим предположением о том, как реализовать 2 датчика. Увы, вывод на мой последовательный монитор продолжает выдавать ошибочные значения -1 и 0
#include <Wire.h>
// Регистры: акселерометр, температура, гироскоп
#define ACCEL_XOUT_H 0x3B
#define ACCEL_XOUT_L 0x3C
#define ACCEL_YOUT_H 0x3D
#define ACCEL_YOUT_L 0x3E
#define ACCEL_ZOUT_H 0x3F
#define ACCEL_ZOUT_L 0x40
#define TEMP_OUT_H 0x41
#define TEMP_OUT_L 0x42
#define GYRO_XOUT_H 0x43
#define GYRO_XOUT_L 0x44
#define GYRO_YOUT_H 0x45
#define GYRO_YOUT_L 0x46
#define GYRO_ZOUT_H 0x47
#define GYRO_ZOUT_L 0x48
#define PWR_MGMT_1 0x6B
#define PWR_MGMT_2 0x6C
#define MPU60501 0x68 // Адрес устройства №1
#define MPU60502 0x69 // Адрес устройства №2
#define ACCEL_CONFIG 0x1C // Адрес конфигурации акселерометра
#define GYRO_CONFIG 0x1B // Адрес конфигурации гироскопа
//Масштабирование выходного сигнала датчика
#define accSens 0 // 0 = 2g, 1 = 4g, 2 = 8g, 3 = 16g
#define gyroSens 1 // 0 = 250рад/с, 1 = 500рад/с, 2 1000рад /с, 3 = 2000рад/с
int16_t AcX1, AcY1, AcZ1, Tmp1, GyX1, GyY1, GyZ1;
int16_t AcX2, AcY2, AcZ2, Tmp2, GyX2, GyY2, GyZ2;
void setup() {
pinMode(0, OUTPUT);
digitalWrite(0, HIGH);
pinMode(1, OUTPUT);
digitalWrite(1,LOW);
Serial.begin(115200);
angle_setup1();
angle_setup2();
}
void loop() {
read_mpu60501();
Serial.println(AcX1); //значение для отображения
read_mpu60502();
Serial.println(AcX2); //значение для отображения
}
//настройка MPU60501
void angle_setup1()
{
Wire.begin();
delay (100);
writeTo(MPU60501, PWR_MGMT_1, 0); //выход из спящего режима
writeTo(MPU60501, ACCEL_CONFIG, accSens << 3); // Указание вывода
scaling of accelerometer
writeTo(MPU60501, GYRO_CONFIG, gyroSens << 3); // Указание выходных данных
scaling of gyroscope
delay (100);
}
void read_mpu60501()
{
// считать необработанные измерения ускорения/гироскопа с устройства
Wire.beginTransmission(MPU60501);
Wire.write(0x3B); // начиная с регистра 0x3B
(ACCEL_XOUT_H)
Wire.endTransmission(false);
Wire.requestFrom(MPU60501, 14, true); // запросить всего 14 регистров
AcX1 = Wire.read() << 8 | Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C
(ACCEL_XOUT_L)
AcY1 = Wire.read() << 8 | Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E
(ACCEL_YOUT_L)
AcZ1 = Wire.read() << 8 | Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40
(ACCEL_ZOUT_L)
Tmp1 = Wire.read() << 8 | Wire.read(); // 0x41 (TEMP_OUT_H) & 0x42
(TEMP_OUT_L)
GyX1 = Wire.read() << 8 | Wire.read(); // 0x43 (GYRO_XOUT_H) & 0x44
(GYRO_XOUT_L)
GyY1 = Wire.read() << 8 | Wire.read(); // 0x45 (GYRO_YOUT_H) & 0x46
(GYRO_YOUT_L)
GyZ1 = Wire.read() << 8 | Wire.read(); // 0x47 (GYRO_ZOUT_H) & 0x48
(GYRO_ZOUT_L)
}
//настройка MPU60502
void angle_setup2()
{
Wire.begin();
delay (100);
writeTo(MPU60502, PWR_MGMT_1, 0); //выход из спящего режима
writeTo(MPU60502, ACCEL_CONFIG, accSens << 3); // Указание вывода
scaling of accelerometer
writeTo(MPU60502, GYRO_CONFIG, gyroSens << 3); // Указание выходных данных
scaling of gyroscope
delay (100);
}
void read_mpu60502()
{
// считать необработанные измерения ускорения/гироскопа с устройства
Wire.beginTransmission(MPU60502);
Wire.write(0x3B); // начиная с регистра 0x3B
(ACCEL_XOUT_H)
Wire.endTransmission(false);
Wire.requestFrom(MPU60502, 14, true); // запросить всего 14 регистров
AcX2 = Wire.read() << 8 | Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C
(ACCEL_XOUT_L)
AcY2 = Wire.read() << 8 | Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E
(ACCEL_YOUT_L)
AcZ2 = Wire.read() << 8 | Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40
(ACCEL_ZOUT_L)
Tmp2 = Wire.read() << 8 | Wire.read(); // 0x41 (TEMP_OUT_H) & 0x42
(TEMP_OUT_L)
GyX2 = Wire.read() << 8 | Wire.read(); // 0x43 (GYRO_XOUT_H) & 0x44
(GYRO_XOUT_L)
GyY2 = Wire.read() << 8 | Wire.read(); // 0x45 (GYRO_YOUT_H) & 0x46
(GYRO_YOUT_L)
GyZ2 = Wire.read() << 8 | Wire.read(); // 0x47 (GYRO_ZOUT_H) & 0x48
(GYRO_ZOUT_L)
}
void writeTo(byte device, byte toAddress, byte val) {
Wire.beginTransmission(device);
Wire.write(toAddress);
Wire.write(val);
Wire.endTransmission();
}
`
@DSteen97, 👍0
Обсуждение1 ответ
Когда вы начинаете рассматривать множество объектов, вам следует думать о классах и структурах, которые позволяют это делать.
Если вы написали класс:
class MPU6050
{
public:
// Конструктор класса
MPU6050 (const byte& address = 0x68)
:m_Address(address)
{
}
// Деструктор класса
~MPU6050()
{}
//настройка MPU60501
void angle_setup (void)
{
// Wire.begin(); // Этот метод следует вызывать в основной настройке.
delay (100);
writeTo(MPU60501, PWR_MGMT_1, 0); //выход из спящего режима
writeTo(MPU60501, ACCEL_CONFIG, accSens << 3); // Указание масштабирования выходных данных акселерометра
writeTo(MPU60501, GYRO_CONFIG, gyroSens << 3); // Указание масштабирования выходного сигнала гироскопа
delay (100);
}
void read_mpu6050(void)
{
// считать необработанные измерения ускорения/гироскопа с устройства
Wire.beginTransmission(MPU60501);
Wire.write(0x3B); // начиная с регистра 0x3B (ACCEL_XOUT_H)
Wire.endTransmission(false);
Wire.requestFrom(MPU60501, 14, true); // запросить всего 14 регистров
AcX1 = Wire.read() << 8 | Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
AcY1 = Wire.read() << 8 | Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
AcZ1 = Wire.read() << 8 | Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
Tmp1 = Wire.read() << 8 | Wire.read(); // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)
GyX1 = Wire.read() << 8 | Wire.read(); // 0x43 (GYRO_XOUT_H) & 0x44(GYRO_XOUT_L)
GyY1 = Wire.read() << 8 | Wire.read(); // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
GyZ1 = Wire.read() << 8 | Wire.read(); // 0x47 (GYRO_ZOUT_H) & 0x48 (ГИРО_ZOUT_L)
}
// Элемент данных, который может быть закрытым и иметь функции доступа, но...
int16_t AcX1;
int16_t AcY1;
int16_t AcZ1;
int16_t Tmp1;
int16_t GyX1;
int16_t GyY1;
int16_t GyZ1;
private:
byte m_Address;
};
Затем вы можете иметь любое количество датчиков, выполнив следующие действия:
MPU6050 SensorOne; // Адрес необязателен и по умолчанию равен 68.
MPU6050 SensorTwo (0x69);
Чтобы получить доступ к данным или функциям в них:
SensorOne.angle_setup();
Serial.println(SensorOne.AcX1);
Можно поместить датчик в массив, а затем использовать циклы везде, но для двух экземпляров экономия невелика.
- Изменение адреса I2C MPU-6050
- MPU6050 не выдает выход
- Как соединить L293D и MPU6050 для совместной работы?
- Связь с магнитным датчиком - TLV493D-A1B6 по I2C
- Подключение двух Arduino через I2C, когда контакты I2C A4/A5 уже используются.
- Использование MPU-6050 без I2C
- Чтение данных из eagle tree airspeed v3
- Почему Wire.write дважды?
Вы дважды используете Wire.begin(). Думаю, это может сработать, но это некрасивое программирование. Ваш код может работать, но повторение одного и того же кода дважды очень затрудняет обнаружение ошибки. Хороший программист использует код, который выполняет определённую задачу только один раз. Вы можете использовать функцию с адресом I2C в качестве параметра или класс для MPU-6050 (как уже написал @CodeGorilla)., @Jot