Подключение HMC5883L

Тема в разделе "Arduino & Shields", создана пользователем Artclonic, 3 мар 2018.

  1. Artclonic

    Artclonic Гик

    Доброе утро.... Всю ночь пытался подключить HMC5883L... сначала в модуле GY-273 подумал, что неисправен, начал пробывать в модуле MPU-9250 - Результатов нет - не иннициализирует модули и все тут..
    ардуино ide 1.8.5.
    arduino UNO
    Библиотека с примерами в приложении. Библиотеку видит в IDE..
    Подключение
    VCC - контакт для подключения напряжения питания от 3.3 Вольт.
    GND - контакт для подключения общего провода.
    SDA - контакт цифрового интерфейса I2C. Подключается к выводу А4 Arduino.
    SCL - контакт цифрового интерфейса I2C. Подключается к выводу А5 Arduino.
    Не могут же они быть оба неисправны (новые пришли вчера с Али)
     

    Вложения:

  2. mcureenab

    mcureenab Гуру

    http://henrysbench.capnfatz.com/hen...y-273-hmc5883l-magnetometer-compass-tutorial/

    Тут модуль GY-273 от 5 Вольт запитан. Как правило напряжение сигнальных линий не может превышать напряжение питания модуля. Иначе кирдык модулю.
    На UNO сигнальное напряжение 5 Вольт!


    Ваш zip мало кто будет смотреть. Размести всё что нужно в сообщении.
     
  3. Artclonic

    Artclonic Гик

    Не понял.., что на UNO где написано 3.3 В, там по факту 5.В? И я убил модуль? Или мне наоборот надо попробывать запитать на 5В?
     

    Вложения:

    • HMC5883L.h
      Размер файла:
      3,2 КБ
      Просмотров:
      629
    • HMC5883L.cpp
      Размер файла:
      5,8 КБ
      Просмотров:
      891
    • HMC5883L_compass.ino
      Размер файла:
      1,8 КБ
      Просмотров:
      925
  4. mcureenab

    mcureenab Гуру

    Выход 3.3 В это 3.3 Вольт но на сигнальных пинах 5 Вольт. Большинство микросхем на сигнальных входах не переносит напряжение, которое превышает напряжение питания.
    Для согласования 3х и 5ти вольтовой логики нужны специальные цепи или устройства.


    Код (C++):
    Пример размещения исходника в сообщении.

    Открывать прикреплённые файлы мало кому интнресно.
     
    NikitOS нравится это.
  5. Artclonic

    Artclonic Гик

    В интернете куча примеров подключения так сказать на "прямую" этих модулеи...
    Это относится к моим?
    http://soltau.ru/index.php/arduino/item/453-kak-podklyuchit-tsifrovoj-kompas-hmc5883l-k-arduino
    Код (C++):
    /*
    HMC5883L.h - Header file for the HMC5883L Triple Axis Digital Compass Arduino Library.

    Version: 1.1.0
    (c) 2014 Korneliusz Jarzebski
    www.jarzebski.pl

    This program is free software: you can redistribute it and/or modify
    it under the terms of the version 3 GNU General Public License as
    published by the Free Software Foundation.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
    */


    #ifndef HMC5883L_h
    #define HMC5883L_h

    #if ARDUINO >= 100
    #include "Arduino.h"
    #else
    #include "WProgram.h"
    #endif

    #define HMC5883L_ADDRESS              (0x1E)
    #define HMC5883L_REG_CONFIG_A         (0x00)
    #define HMC5883L_REG_CONFIG_B         (0x01)
    #define HMC5883L_REG_MODE             (0x02)
    #define HMC5883L_REG_OUT_X_M          (0x03)
    #define HMC5883L_REG_OUT_X_L          (0x04)
    #define HMC5883L_REG_OUT_Z_M          (0x05)
    #define HMC5883L_REG_OUT_Z_L          (0x06)
    #define HMC5883L_REG_OUT_Y_M          (0x07)
    #define HMC5883L_REG_OUT_Y_L          (0x08)
    #define HMC5883L_REG_STATUS           (0x09)
    #define HMC5883L_REG_IDENT_A          (0x0A)
    #define HMC5883L_REG_IDENT_B          (0x0B)
    #define HMC5883L_REG_IDENT_C          (0x0C)

    typedef enum
    {
        HMC5883L_SAMPLES_8     = 0b11,
        HMC5883L_SAMPLES_4     = 0b10,
        HMC5883L_SAMPLES_2     = 0b01,
        HMC5883L_SAMPLES_1     = 0b00
    } hmc5883l_samples_t;

    typedef enum
    {
        HMC5883L_DATARATE_75HZ       = 0b110,
        HMC5883L_DATARATE_30HZ       = 0b101,
        HMC5883L_DATARATE_15HZ       = 0b100,
        HMC5883L_DATARATE_7_5HZ      = 0b011,
        HMC5883L_DATARATE_3HZ        = 0b010,
        HMC5883L_DATARATE_1_5HZ      = 0b001,
        HMC5883L_DATARATE_0_75_HZ    = 0b000
    } hmc5883l_dataRate_t;

    typedef enum
    {
        HMC5883L_RANGE_8_1GA     = 0b111,
        HMC5883L_RANGE_5_6GA     = 0b110,
        HMC5883L_RANGE_4_7GA     = 0b101,
        HMC5883L_RANGE_4GA       = 0b100,
        HMC5883L_RANGE_2_5GA     = 0b011,
        HMC5883L_RANGE_1_9GA     = 0b010,
        HMC5883L_RANGE_1_3GA     = 0b001,
        HMC5883L_RANGE_0_88GA    = 0b000
    } hmc5883l_range_t;

    typedef enum
    {
        HMC5883L_IDLE          = 0b10,
        HMC5883L_SINGLE        = 0b01,
        HMC5883L_CONTINOUS     = 0b00
    } hmc5883l_mode_t;

    #ifndef VECTOR_STRUCT_H
    #define VECTOR_STRUCT_H
    struct Vector
    {
        float XAxis;
        float YAxis;
        float ZAxis;
    };
    #endif

    class HMC5883L
    {
        public:

        bool begin(void);

        Vector readRaw(void);
        Vector readNormalize(void);

        void  setOffset(int xo, int yo);

        void  setRange(hmc5883l_range_t range);
        hmc5883l_range_t getRange(void);

        void  setMeasurementMode(hmc5883l_mode_t mode);
        hmc5883l_mode_t getMeasurementMode(void);

        void  setDataRate(hmc5883l_dataRate_t dataRate);
        hmc5883l_dataRate_t getDataRate(void);

        void  setSamples(hmc5883l_samples_t samples);
        hmc5883l_samples_t getSamples(void);

        private:

        float mgPerDigit;
        Vector v;
        int xOffset, yOffset;

        void writeRegister8(uint8_t reg, uint8_t value);
        uint8_t readRegister8(uint8_t reg);
        uint8_t fastRegister8(uint8_t reg);
        int16_t readRegister16(uint8_t reg);
    };

    #endif
    Код (C++):
    /*
    HMC5883L.cpp - Class file for the HMC5883L Triple Axis Digital Compass Arduino Library.

    Version: 1.1.0
    (c) 2014 Korneliusz Jarzebski
    www.jarzebski.pl

    This program is free software: you can redistribute it and/or modify
    it under the terms of the version 3 GNU General Public License as
    published by the Free Software Foundation.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
    */


    #if ARDUINO >= 100
    #include "Arduino.h"
    #else
    #include "WProgram.h"
    #endif

    #include <Wire.h>

    #include "HMC5883L.h"

    bool HMC5883L::begin()
    {
        Wire.begin();

        if ((fastRegister8(HMC5883L_REG_IDENT_A) != 0x48)
        || (fastRegister8(HMC5883L_REG_IDENT_B) != 0x34)
        || (fastRegister8(HMC5883L_REG_IDENT_C) != 0x33))
        {
        return false;
        }

        setRange(HMC5883L_RANGE_1_3GA);
        setMeasurementMode(HMC5883L_CONTINOUS);
        setDataRate(HMC5883L_DATARATE_15HZ);
        setSamples(HMC5883L_SAMPLES_1);

        mgPerDigit = 0.92f;

        return true;
    }

    Vector HMC5883L::readRaw(void)
    {
        v.XAxis = readRegister16(HMC5883L_REG_OUT_X_M) - xOffset;
        v.YAxis = readRegister16(HMC5883L_REG_OUT_Y_M) - yOffset;
        v.ZAxis = readRegister16(HMC5883L_REG_OUT_Z_M);

        return v;
    }

    Vector HMC5883L::readNormalize(void)
    {
        v.XAxis = ((float)readRegister16(HMC5883L_REG_OUT_X_M) - xOffset) * mgPerDigit;
        v.YAxis = ((float)readRegister16(HMC5883L_REG_OUT_Y_M) - yOffset) * mgPerDigit;
        v.ZAxis = (float)readRegister16(HMC5883L_REG_OUT_Z_M) * mgPerDigit;

        return v;
    }

    void HMC5883L::setOffset(int xo, int yo)
    {
        xOffset = xo;
        yOffset = yo;
    }

    void HMC5883L::setRange(hmc5883l_range_t range)
    {
        switch(range)
        {
        case HMC5883L_RANGE_0_88GA:
            mgPerDigit = 0.073f;
            break;

        case HMC5883L_RANGE_1_3GA:
            mgPerDigit = 0.92f;
            break;

        case HMC5883L_RANGE_1_9GA:
            mgPerDigit = 1.22f;
            break;

        case HMC5883L_RANGE_2_5GA:
            mgPerDigit = 1.52f;
            break;

        case HMC5883L_RANGE_4GA:
            mgPerDigit = 2.27f;
            break;

        case HMC5883L_RANGE_4_7GA:
            mgPerDigit = 2.56f;
            break;

        case HMC5883L_RANGE_5_6GA:
            mgPerDigit = 3.03f;
            break;

        case HMC5883L_RANGE_8_1GA:
            mgPerDigit = 4.35f;
            break;

        default:
            break;
        }

        writeRegister8(HMC5883L_REG_CONFIG_B, range << 5);
    }

    hmc5883l_range_t HMC5883L::getRange(void)
    {
        return (hmc5883l_range_t)((readRegister8(HMC5883L_REG_CONFIG_B) >> 5));
    }

    void HMC5883L::setMeasurementMode(hmc5883l_mode_t mode)
    {
        uint8_t value;

        value = readRegister8(HMC5883L_REG_MODE);
        value &= 0b11111100;
        value |= mode;

        writeRegister8(HMC5883L_REG_MODE, value);
    }

    hmc5883l_mode_t HMC5883L::getMeasurementMode(void)
    {
        uint8_t value;

        value = readRegister8(HMC5883L_REG_MODE);
        value &= 0b00000011;

        return (hmc5883l_mode_t)value;
    }

    void HMC5883L::setDataRate(hmc5883l_dataRate_t dataRate)
    {
        uint8_t value;

        value = readRegister8(HMC5883L_REG_CONFIG_A);
        value &= 0b11100011;
        value |= (dataRate << 2);

        writeRegister8(HMC5883L_REG_CONFIG_A, value);
    }

    hmc5883l_dataRate_t HMC5883L::getDataRate(void)
    {
        uint8_t value;

        value = readRegister8(HMC5883L_REG_CONFIG_A);
        value &= 0b00011100;
        value >>= 2;

        return (hmc5883l_dataRate_t)value;
    }

    void HMC5883L::setSamples(hmc5883l_samples_t samples)
    {
        uint8_t value;

        value = readRegister8(HMC5883L_REG_CONFIG_A);
        value &= 0b10011111;
        value |= (samples << 5);

        writeRegister8(HMC5883L_REG_CONFIG_A, value);
    }

    hmc5883l_samples_t HMC5883L::getSamples(void)
    {
        uint8_t value;

        value = readRegister8(HMC5883L_REG_CONFIG_A);
        value &= 0b01100000;
        value >>= 5;

        return (hmc5883l_samples_t)value;
    }

    // Write byte to register
    void HMC5883L::writeRegister8(uint8_t reg, uint8_t value)
    {
        Wire.beginTransmission(HMC5883L_ADDRESS);
        #if ARDUINO >= 100
            Wire.write(reg);
            Wire.write(value);
        #else
            Wire.send(reg);
            Wire.send(value);
        #endif
        Wire.endTransmission();
    }

    // Read byte to register
    uint8_t HMC5883L::fastRegister8(uint8_t reg)
    {
        uint8_t value;
        Wire.beginTransmission(HMC5883L_ADDRESS);
        #if ARDUINO >= 100
            Wire.write(reg);
        #else
            Wire.send(reg);
        #endif
        Wire.endTransmission();

        Wire.requestFrom(HMC5883L_ADDRESS, 1);
        #if ARDUINO >= 100
            value = Wire.read();
        #else
            value = Wire.receive();
        #endif;
        Wire.endTransmission();

        return value;
    }

    // Read byte from register
    uint8_t HMC5883L::readRegister8(uint8_t reg)
    {
        uint8_t value;
        Wire.beginTransmission(HMC5883L_ADDRESS);
        #if ARDUINO >= 100
            Wire.write(reg);
        #else
            Wire.send(reg);
        #endif
        Wire.endTransmission();

        Wire.beginTransmission(HMC5883L_ADDRESS);
        Wire.requestFrom(HMC5883L_ADDRESS, 1);
        while(!Wire.available()) {};
        #if ARDUINO >= 100
            value = Wire.read();
        #else
            value = Wire.receive();
        #endif;
        Wire.endTransmission();

        return value;
    }

    // Read word from register
    int16_t HMC5883L::readRegister16(uint8_t reg)
    {
        int16_t value;
        Wire.beginTransmission(HMC5883L_ADDRESS);
        #if ARDUINO >= 100
            Wire.write(reg);
        #else
            Wire.send(reg);
        #endif
        Wire.endTransmission();

        Wire.beginTransmission(HMC5883L_ADDRESS);
        Wire.requestFrom(HMC5883L_ADDRESS, 2);
        while(!Wire.available()) {};
        #if ARDUINO >= 100
            uint8_t vha = Wire.read();
            uint8_t vla = Wire.read();
        #else
            uint8_t vha = Wire.receive();
            uint8_t vla = Wire.receive();
        #endif;
        Wire.endTransmission();

        value = vha << 8 | vla;

        return value;
    }
     
  6. Artclonic

    Artclonic Гик

    Какую схему мне надо собрать для подключение данного модуля?
     
  7. mcureenab

    mcureenab Гуру

  8. NikitOS

    NikitOS Король шутов Администратор

    А адрес устройства проверить не забыли? Они ведь тоже могут быть не такими как в примере
     
  9. Artclonic

    Artclonic Гик

    Как это сделать? где посмотреть? адрес устроиства...
    Попробую сделать по предложеннои статье...
     
  10. NikitOS

    NikitOS Король шутов Администратор

    Этим кодом. В Serial выводит адреса устройств подключенных по i2c, если их нет также напишет
    Код (C++):
    #include <Wire.h>

    byte error, address;
    int nDevices;  //Кол-во найденных устройств

    void setup() {
      Wire.begin();
      Serial.begin(9600);
      Serial.println("\nI2C Scanner");
    }

    void loop() {
      Serial.println("Scanning...");
      nDevices = 0;
      for (address = 1; address < 127; address++ )  {
        Wire.beginTransmission(address);
        error = Wire.endTransmission();
        if (error == 0)    {
          Serial.print("I2C device found at address 0x");
          if (address < 16)
            Serial.print("0");
          Serial.print(address, HEX);
          Serial.println("  !");
          nDevices++;
        }
        else if (error == 4)    {
          Serial.print("Unknow error at address 0x");
          if (address < 16)
            Serial.print("0");
          Serial.println(address, HEX);
        }
      }
      if (nDevices == 0)
        Serial.println("No I2C devices found\n");
      else
        Serial.println("done\n");
      delay(5000);  // Ждем 5 сек. до следующего сканирования
    }
     
  11. Artclonic

    Artclonic Гик

    Спасибо!!!
    Вот что написал

    Scanning...
    I2C device found at address 0x0D !
    done
     
  12. Artclonic

    Artclonic Гик

    Пробую
    Код (C++):
    #include <Wire.h> // подключаем I2C библиотеку
    #define addr 0x0D // I2C 7-битный адрес датчика HMC5883

    void setup() {
        Serial.begin(9600); // инициализация последовательного порта
        Wire.begin(); // инициализация I2C
     
        // Задаём режим работы датчика HMC5883:
        Wire.beginTransmission(addr);
        Wire.write(0x00); // выбираем регистр управления CRA (00)
        Wire.write(0x70); // записываем в него 0x70 [усреднение по 8 точкам, 15 Гц, нормальные измерения]
        Wire.write(0xA0); // записываем в регистр CRB (01) 0xA0 [чувствительность = 5]
        Wire.write(0x00); // записываем в регистр Mode (02) 0x00 [бесконечный режим измерения]
        Wire.endTransmission();
    }

    void loop() {
     
      Wire.beginTransmission(addr);
      Wire.write(0x03); // переходим к регистру 0x03
      Wire.endTransmission();
     
      Wire.requestFrom(addr, 6); // запрашиваем 6 байтов
      while( Wire.available() )
      {
        int h = Wire.read(); // старший байт значения по оси X
        int l = Wire.read(); // младший байт значения по оси X
        int x = word(h, l);  // объединяем в двухбайтовое число

        int y = Wire.read(); // старший байт значения по оси Y
        y = y << 8; // сдвигаем влево на 8 битов
        y = y | Wire.read(); // объединяем с младшим байтом по OR

        int z = Wire.read() << 8; // читаем байт и сдвигаем влево на 8 битов
        z |= Wire.read(); // сокращённый синтаксис операции OR

        Serial.print("X = ");
        Serial.println(x, DEC);
        Serial.print("Y = ");
        Serial.println(y, DEC);
        Serial.print("Z = ");
        Serial.println(z, DEC);
        Serial.println();  
      }
        delay(100);
    }
    Выдает
    X=0
    Y=0
    Z=0
     
  13. Artclonic

    Artclonic Гик

    тоже самое попробывал на модуле MPU9250
    адрес0х68
    выдает
    X = -10840
    Y = 25901
    Z = 11274
    Соответственно не меняется при поворотах
     
  14. NikitOS

    NikitOS Король шутов Администратор

    Ну то что инфа есть это уже хорошо. Но то что ничего кроме одного не выводит это уже есть баг программы, попробуйте найти другую
     
  15. Artclonic

    Artclonic Гик

    Адрес, только в одном месте прописывается? И еще адреса регистров с которых берутся данные они могут быть другими?
    По коду считывания данных с регистра вот такие данные...
    Код (C++):
    #include <Wire.h>  // подключим стандартную библиотеку I2C
    #define addr 0x68 // I2C адрес цифрового компаса HMC5883L
     
    void setup() {
      Serial.begin(9600); // инициализация последовательного порта
      Wire.begin(); // инициализация I2C
    }
     
    void loop() {

      Wire.beginTransmission(addr); // начинаем связь с устройством по адресу 0x1E
      Wire.write(0x0A); // регистр, с которого мы начнём запрашивать данные  
      Wire.endTransmission();
      Wire.requestFrom(addr, 3, true); // запрашиваем 3 байта у ведомого
      while( Wire.available() )
      {
        char a = Wire.read(); // считываем байт из регистра 0xA; устройство само переходит к следующему регистру
        char b = Wire.read(); // считываем байт из регистра 0xB
        char c = Wire.read(); // считываем байт из регистра 0xС

       // Выводим считанное в последовательный порт:
        Serial.print("A = ");  
        Serial.println(a, HEX);
        Serial.print("B = ");
        Serial.println(b, HEX);
        Serial.print("C = ");
        Serial.println(c, HEX);
        Serial.println();  
      }  
      delay(100);
    }
    A = FFFFFFE8
    B = 0
    C = 0
     
  16. NikitOS

    NikitOS Король шутов Администратор

    не знаю, с такими устройствами не работал, я просто сказал что дело медет быть в адресе, а что и как с адресами регистров я, увы, не знаю
     
  17. Artclonic

    Artclonic Гик

    Прошу откликнуться, кто имел дело с данными модулями...
     
  18. Sencis

    Sencis Гик

    Я как-то подключал HMC 5983L и они похожие с 5883. Если и2с сканер видит устрой-во то оно точно работает. Вот статья в ней есть скетч и в начале определён адрес уст-ва попробуйте поменять его на свой адрес возможно придётся заменить и адреса регистров данных но китайци пишут что они совпадают. Можете также попробовать оттуда и готовую библиотеку для HMC 5883l.
     
  19. mcureenab

    mcureenab Гуру

    Судя по даташиту это регистры идентификации.

    Поменяй тут

    Код (C++):
      Wire.write(0x03); // регистр, с которого мы начнём запрашивать данные
    И вкури даташит
     
  20. mcureenab

    mcureenab Гуру

    Даташит
     

    Вложения: