Не могу заставить 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 Гц), я буду очень признателен.

, 👍2

Обсуждение

Добавьте распечатку при запуске скетча. Каковы исходные значения?, @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


1 ответ


-1

Возможно, поможет установка/сброс перед настройкой устройства:

writeRegister(MMC34160PJ_CTRL0, 0x80);          // пополнить колпачок
delay(50);
writeRegister(MMC34160PJ_CTRL0, 0x20);          // поставил
// задержка (10);
writeRegister(MMC34160PJ_CTRL0, 0x80);          // пополнить колпачок
delay(50);
writeRegister(MMC34160PJ_CTRL0, 0x40);          // сброс настроек
// задержка (10);
,