Не могу заставить MMC3416xPJ работать
Мне нужен был магнитометр с высокой скоростью передачи данных на выходе (ODR). Это потому, что я хотел измерить магнитные поля переменного тока частотой около 20-80 Гц. Поэтому я решил использовать макетную плату MMC3416xPJ с ODR 800 Гц (https://au .mouser.com/new/memsic/memsic-mmc3416xpj-sensors/). Я никогда не писал интерфейс I2C для датчика, поэтому я, вероятно, напортачил. Техническое описание моего сенсора можно найти здесь. Я могу правильно получить идентификатор продукта от датчика, что означает, что проводка верна, и часть кода верна. Но когда я распечатываю измерения, они дают мне значения переполнения вместо магнитного поля Земли. Кстати, я разрабатываю это на плате Arduino. Любая помощь будет оценена по достоинству. Мой код можно увидеть ниже -
Магнитометр.h
#ifndef MAGNETOMETER_H
#define MAGNETOMETER_H
#include "General.h"
#include <Wire.h>
#define MAGNETOMETER_I2C_ADDRESS 0x30
#define X_OUT_LOW 0x00
#define X_OUT_HIGH 0x01
#define Y_OUT_LOW 0x02
#define Y_OUT_HIGH 0x03
#define Z_OUT_LOW 0x04
#define Z_OUT_HIGH 0x05
#define STATUS 0x06
#define INTERNAL_CONTROL_0 0x07
#define INTERNAL_CONTROL_1 0x08
#define RO 0x1b
#define R1 0x1c
#define R2 0x1d
#define R3 0x1e
#define R4 0x1f
#define PRODUCT_ID 0x20
class Magnetometer
{
public:
Magnetometer();
void Setup();
void Test();
private:
void TestConnnection();
void ReadRawData();
};
#endif
Magnetometer.cpp
#include "Magnetometer.h"
Magnetometer::Magnetometer()
{
}
void Magnetometer::Setup()
{
Wire.begin(SDA, SCL);
TestConnnection();
Wire.beginTransmission(MAGNETOMETER_I2C_ADDRESS);
Wire.write(INTERNAL_CONTROL_1);
Wire.write(0x00);
Wire.endTransmission();
Serial.println("Magnetometer Setup");
}
void Magnetometer::Test()
{
ReadRawData();
Serial.println("Magnetometer Test");
delay(1000);
}
void Magnetometer::ReadRawData()
{
int16_t RawMx, RawMy, RawMz;
byte status = -1;
// 1-3
Wire.beginTransmission(MAGNETOMETER_I2C_ADDRESS);
Wire.write(INTERNAL_CONTROL_0);
Wire.write(0x01);
Wire.endTransmission();
// 4-7
Wire.beginTransmission(MAGNETOMETER_I2C_ADDRESS);
Wire.write(STATUS);
Wire.requestFrom(MAGNETOMETER_I2C_ADDRESS, 1);
status = Wire.read();
Serial.print("status = "); Serial.println(status);
while ((status%2) != 1)
{
status = Wire.read();
Serial.println("Data not ready");
}
Serial.println("Data ready");
Wire.endTransmission();
// 8-17
Wire.beginTransmission(MAGNETOMETER_I2C_ADDRESS);
Wire.write(X_OUT_LOW);
Wire.endTransmission();
Wire.requestFrom(MAGNETOMETER_I2C_ADDRESS, 6);
RawMx = Wire.read();
RawMx |= Wire.read()<<8;
RawMy = Wire.read();
RawMy |= Wire.read()<<8;
RawMz = Wire.read();
RawMz |= Wire.read()<<8;
Serial.print("RawMx: "); Serial.print(RawMx);
Serial.print(" RawMy: "); Serial.print(RawMy);
Serial.print(" RawMz: "); Serial.println(RawMz);
float scaleFactor = 2048;
float convertToMircoTelsa = 100;
float Mx, My, Mz;
Mx = (float) RawMx / scaleFactor * convertToMircoTelsa;
My = (float) RawMy / scaleFactor * convertToMircoTelsa;
Mz = (float) RawMz / scaleFactor * convertToMircoTelsa;
Serial.print("Mx: "); Serial.print(Mx);
Serial.print(" My: "); Serial.print(My);
Serial.print(" Mz: "); Serial.println(Mz);
// Serial.print("Wire.ava = "); Serial.println(Провод.доступен());
}
void Magnetometer::TestConnnection()
{
byte id = -1;
while (id != 6)
{
Wire.beginTransmission(MAGNETOMETER_I2C_ADDRESS);
Wire.write(PRODUCT_ID);
Wire.requestFrom(MAGNETOMETER_I2C_ADDRESS, 1);
id = Wire.read();
Wire.endTransmission();
if (id != -1)
{
Serial.println("Cannot connect to Magnetometer");
}
}
Serial.println("Magnetometer TestConnnection Success");
}
Если вы, ребята, предложите мне какие-либо другие магнитометры с высоким ODR (по крайней мере, выше 300 Гц), я буду очень признателен.
@Nadim Ahmed, 👍2
Обсуждение1 ответ
Возможно, поможет установка/сброс перед настройкой устройства:
writeRegister(MMC34160PJ_CTRL0, 0x80); // пополнить колпачок
delay(50);
writeRegister(MMC34160PJ_CTRL0, 0x20); // поставил
// задержка (10);
writeRegister(MMC34160PJ_CTRL0, 0x80); // пополнить колпачок
delay(50);
writeRegister(MMC34160PJ_CTRL0, 0x40); // сброс настроек
// задержка (10);
- Направление по компасу не изменяется линейно
- ИСПРАВЛЕНА ОШИБКА при использовании библиотеки проводов для получения направления по компасу
- Отправка и получение различных типов данных через I2C в Arduino
- Как выбрать альтернативные контакты I2C на ESP32?
- Wire.h не найден!
- Альтернативы библиотеке Wire для I2C
- Библиотека Wire.h работает на Uno, но не компилируется для ATtiny85
- Вызов I2C во время Wire.requestFrom
Добавьте распечатку при запуске скетча. Каковы исходные значения?, @Mikael Patel
То не быстро, то медленно, потому что шина I2C медленная, а Wire.endTransmission и Wire.requestFrom блокирующие функции, они ждут, пока все не закончится. Вы можете использовать Wire.setClock, чтобы установить шину на 400 кГц, но магнитометр с интерфейсом SPI позволяет избежать всех этих проблем. Какую плату ардуино вы используете? Я вижу несколько ошибок с функциями Wire, вы должны прочитать в справочнике Arduino Wire, как их использовать., @Jot
@MikaelPatel Я получаю значения переполнения, @Nadim Ahmed
@Jot Я использую Wemos D1 mini на базе Esp8266. Можете ли вы указать мне на ошибки, которые я сделал? Заранее спасибо., @Nadim Ahmed
@Jot Вы знаете, где я могу найти магнитометр с частотой выше 300 Гц и использующий SPI для передачи данных?, @Nadim Ahmed
Wire.endtransmission используется при записи данных: https://www.arduino.cc/en/Reference/WireEndTransmission LIS3MDL используется с arduino и имеет spi и i2c и 1 кГц в режиме fast_odr. LSM9DS1 также часто используется с arduino, также имеет spi и i2c и имеет частоту 952 Гц. Я не знаю, такая ли быстрая внутренняя схема, эта скорость — всего лишь интерфейс., @Jot