GY-271 не могу запустить

JS
Offline
Зарегистрирован: 31.12.2017

Ну что... Получил я посылку из Китая с разными модулями компасов. И персонально убедился, что модуль на DA5883 (QMC) - откровенное говно, которым наши продавцы, да и из Китая кормят под именем аналога HMC5883. Модуль на DA5883 даёт разброс 10-20 градусов в неподвижном виде. Надо сказать, что я тестировал на первом этаже многоэтажки. Однако самые лючшие результаты показал модуль на HMC5983 - это в принципе такой же модуль, но якобы с термокомпенсацией, так вот он в в тех же условиях в неподвижном виде даёт разброс в пределах 1 градуса. А, каково!

Рекомендую обратить внимание, что родные чипы, как я обратил внимание, показывают лишь три цифры, а первую букву A или L, а левые полностью номер. И ещё: даже надпись на плате модуля HMC5883 ничего не гарантирует, модуль так же левый DA, т.е это откровенный обман. Смотрите в лупу лично.

Fendor
Offline
Зарегистрирован: 17.11.2017

Поделитесь, пожалуйста, ссылочкой, откуда брали HMC5983? А то с HMC5883 несколько раз заказывал и всё время натыкался на левак.

JS
Offline
Зарегистрирован: 31.12.2017

HMC5983 - это "Temperature Compensation Triaxial Compass Iic/spi Hmc5983" здесь: https://www.ebay.com/itm/182324662468 по цене 222 рубля. У меня работает на библиотеке https://github.com/DFRobot/DFRobot_QMC5883 но есть для него специальная https://github.com/arduino/HMC5983 , но я её не пробовал, т.к. и так работает хорошо.

Кстати, с левым чипом DA5883 и надписью HMC5883 тоже у них брал https://www.ebay.com/itm/171419260466

А до этого в Москве тоже левак попадался

Кстати в Москве же натыкался на ссылку 5983, судя по снимку чип правильный A983:  http://robot-kit.ru/product_info.php/info/p1296_Modul-GY-282-3-h-osevoi-magnitnyi-kompas-HMC5983--RKP-GY-282-HMC5983-.html

Впрочем и на модуль 5883 тоже по снимку чип правильный L883: http://robot-kit.ru/product_info.php/info/p807_Modul-GY-271-3-h-osevoi-cifrovoi-kompas-HMC5883L--RKP-HMC5883L-GY-271-.html

Надо лично проверять или уточнять-просить прислать снимок не рекламный.

Fendor
Offline
Зарегистрирован: 17.11.2017

Подореваю, что HMC5983 не подделывают, проверил десяток продавцов на Али, и у всех на фото чип A983. 

А хотя... нижнее число на чипе почти у всех разное. По вашей ссылке на robot-kit оно 2210, на ебее 2419, а на Али там дикий разброс: 2419, 2420, 2438, 2407, 2203, 2244.

JS
Offline
Зарегистрирован: 31.12.2017

Не факт. Продавцы часто размещают фото не своё, а от первоисточника или от своего дилера, а те тоже бадяжат. Я тут одного продавца, что продал мне бадягу предупредил, о том что на его странице инфа не верная и чип левый, но он так и не поправил страницу и фото с правильным чипом не поменял, наверное пока всю закупленную партию не распродаст.

go63
Offline
Зарегистрирован: 16.03.2018

Вот работающий проект с GY85 с магнетометром QMC5883

(SensorVariant 9)

Там же программа для калибровки всех датчиков. И новый I2C scanner.

https://sites.google.com/site/diyheadtracking/home/razor-ahrs-20180306

JS
Offline
Зарегистрирован: 31.12.2017

go63 пишет:

Вот работающий проект с GY85 с магнетометром QMC5883

(SensorVariant 9)

Там же программа для калибровки всех датчиков. И новый I2C scanner.

https://sites.google.com/site/diyheadtracking/home/razor-ahrs-20180306

Интересный вариант, может попробую. Однако уже изначально в нём увы ошибка, что принижает его ценность:

Этот вариант 9 на фото имеет чип именно HMC5883L, а не QMC5883. Если есть желание можете зайти на предложенный автором док в PDF. Там на тайском и английском указан опять же HMC5883L.

Accelerometers & Gyroscope & Compass ADXL345 , HMC5883L , ITG3205

go63
Offline
Зарегистрирован: 16.03.2018

Фото взято из варианта 2. Они различаются только магнетометром.

Проверены оба варианта.

 

go63
Offline
Зарегистрирован: 16.03.2018
JS
Offline
Зарегистрирован: 31.12.2017

go63 пишет:

Фото взято из варианта 2. Они различаются только магнетометром.

Проверены оба варианта.

А откуда это следует? Ничего не сказано. Но может быть. Тут дело в том, что сам чип сильно другой по внутренней структуре, и какие ему нужны настройки хрен угадаешь, можент автор нашёл доки. У меня пока хорошо работает HCM +-1 градус, но если удастся попробовать прошу отписаться.

go63
Offline
Зарегистрирован: 16.03.2018

Конечно, нашел доки. Чего их искать: https://www.yandex.ru/yandsearch?clid=9582&text=QMC5883%20datasheet&l10n=ru&lr=51

JS
Offline
Зарегистрирован: 31.12.2017

go63 пишет:

Конечно, нашел доки. Чего их искать: https://www.yandex.ru/yandsearch?clid=9582&text=QMC5883%20datasheet&l10n=ru&lr=51

Саму спецификацию я видел и долго экспериментировал с исходниками библиотек, надоело. Названия регистров ещё не всё, там куча настроек, типа диапазонов полей, полос пропускания, внутренние шумы и тд. А вот в каких комбинациях все эти параметры ставить большой вопрос, только тыком, что не факт правильно. Короче, результаты уже здесь писал...

RUS_D
Offline
Зарегистрирован: 30.03.2018

Попробуйте эту библиотеку
https://github.com/DFRobot/DFRobot_QMC5883
и этот скетч

/*!
 * @file QMC5883_compass.cpp
 * @brief The program shows how to realize the function compass.When the program runs, please spin QMC5883 freely to accomplish calibration.
 * @n 3-Axis Digital Compass IC
 *
 * @copyright [DFRobot](http://www.dfrobot.com), 2017
 * @copyright GNU Lesser General Public License
 *
 * @author [dexian.huang](952838602@qq.com)
 * @version  V1.0
 * @date  2017-7-3
 */
#include <Wire.h>
#include <DFRobot_QMC5883.h>
DFRobot_QMC5883 compass;
void setup()
{
  Serial.begin(115200);
  while (!compass.begin())
  {
    Serial.println("Could not find a valid QMC5883 sensor, check wiring!");
    delay(500);
  }
    if(compass.isHMC()){
        Serial.println("Initialize HMC5883");
        compass.setRange(HMC5883L_RANGE_1_3GA);
        compass.setMeasurementMode(HMC5883L_CONTINOUS);
        compass.setDataRate(HMC5883L_DATARATE_15HZ);
        compass.setSamples(HMC5883L_SAMPLES_8);
    }
   else if(compass.isQMC()){
        Serial.println("Initialize QMC5883");
        compass.setRange(QMC5883_RANGE_2GA);
        compass.setMeasurementMode(QMC5883_CONTINOUS); 
        compass.setDataRate(QMC5883_DATARATE_50HZ);
        compass.setSamples(QMC5883_SAMPLES_8);
   }
  }
void loop()
{
  Vector norm = compass.readNormalize();
  // Calculate heading
  float heading = atan2(norm.YAxis, norm.XAxis);
  // Set declination angle on your location and fix heading
  // You can find your declination on: http://magnetic-declination.com/
  // (+) Positive or (-) for negative
  // For Bytom / Poland declination angle is 4'26E (positive)
  // Formula: (deg + (min / 60.0)) / (180 / PI);
  float declinationAngle = (4.0 + (26.0 / 60.0)) / (180 / PI);
  heading += declinationAngle;
  // Correct for heading < 0deg and heading > 360deg
  if (heading < 0){
    heading += 2 * PI;
  }
  if (heading > 2 * PI){
    heading -= 2 * PI;
  }
  // Convert to degrees
  float headingDegrees = heading * 180/PI; 
  // Output
  Serial.print(" Heading = ");
  Serial.print(heading);
  Serial.print(" Degress = ");
  Serial.print(headingDegrees);
  Serial.println();
  delay(100);
}

 

JS
Offline
Зарегистрирован: 31.12.2017

Уже упоминалась #45 . Хорошая, сам ей пользуюсь.

cvvcvv
Offline
Зарегистрирован: 15.04.2015

Fendor пишет:

Нормально настроить так и не получилось. Если при чистой связке Ардуино+гироскоп он ещё более менее работал стабильно, то при подключении в общую систему (был проект по заказу от военных с поворотной антенной на ардуино, хотел добавить новую функцию по возврату в установленное положение при механическом повороте антенны) от этой идеи пришлось отказаться, так как модуль окончательно заглючил, ничего не выдавал или выдавал всякий мусор. В будущем закажу ещё несколько модулей от разных продавцов и отпишусь здесь, что выйдет.

Коллега, какие датчики  подошли? Мне также заказали сделать датчик-индикатор  наведения антенны. 

vladislav14
Offline
Зарегистрирован: 08.07.2019

Вот и я попробовал библиотеку от DFRobot... Ну хакеры они ещё более-менее, но программеры из них... [недостаточно идеальные]

Только после заметных исправлений в части, касающейся QMC (последовательность считывания старшего/младшего байтов и т.д.), получил нормальные показания, без диких скачек. Стрелочка показывает на север, угол плавненько меняется. Когда запихну в какой-нибудь корпус, протестирую ещё на стабильность и точность.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

vladislav14 пишет:

Вот и я попробовал библиотеку от DFRobot... Ну хакеры они ещё более-менее, но программеры из них... [недостаточно идеальные]

Только после заметных исправлений в части, касающейся QMC (последовательность считывания старшего/младшего байтов и т.д.), получил нормальные показания, без диких скачек. Стрелочка показывает на север, угол плавненько меняется. Когда запихну в какой-нибудь корпус, протестирую ещё на стабильность и точность.

 а выложить исправленное?

vladislav14
Offline
Зарегистрирован: 08.07.2019

А теперь - подробности.

Прежде всего, мне не понравилось, что при переворачивании датчика по одной оси показания менялись как-то странно, хотя должно быть только изменение знака. Для понимания источника проблемы первым делом отредактировал DFRobot_QMC5883.h - перенёс функции

  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);
из private: в public:
Далее, следующие строки в программе:
  x1 = compass.readRegister16(0x00) ;
  Serial.print(" reg_x = ");
  Serial.print(x1, HEX);
выводят 16-битовое значение x, аналогично для y и z (там адреса соотв. 0x02 и 0x04).
Обратил внимание, что эта функция выдаёт неправильное значение, по сравнению с тем, как если читать младший и старший байты по отдельности через readRegister8. Причина оказалась в том, что в QMC, в отличие от HMC, прежде читается младший байт.
В DFRobot_QMC5883.h адреса регистров правильные:
#define QMC5883_REG_OUT_X_M          (0x01)
#define QMC5883_REG_OUT_X_L          (0x00)
#define QMC5883_REG_OUT_Z_M          (0x05)
#define QMC5883_REG_OUT_Z_L          (0x04)
#define QMC5883_REG_OUT_Y_M          (0x03)
#define QMC5883_REG_OUT_Y_L          (0x02)
Но вот смотрим функцию int16_t DFRobot_QMC5883::readRegister16(uint8_t reg) в DFRobot_QMC5883..cpp, и что мы видим?
...
    else if(isQMC_){
    Wire.beginTransmission(QMC5883_ADDRESS);
    #if ARDUINO >= 100
        Wire.write(reg);
    #else
        Wire.send(reg);
    #endif
    Wire.endTransmission();
    Wire.beginTransmission(QMC5883_ADDRESS);
    Wire.requestFrom(QMC5883_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;
Первым читается, как и с HMC, "старший" байт, затем "младший".
В Vector DFRobot_QMC5883::readRaw(void)
...
else if(isQMC_){
    while (range--){
      v.XAxis = readRegister16(QMC5883_REG_OUT_X_M);
      v.YAxis = readRegister16(QMC5883_REG_OUT_Y_M);
      v.ZAxis = readRegister16(QMC5883_REG_OUT_Z_M);
... и второй байт, который L, вообще из другого регистра читается (т.к. микросхема автоинкрементирует номер при чтении).
Исправленная версия:
int16_t DFRobot_QMC5883::readRegister16(uint8_t reg)
{
...
  }else if(isQMC_){
    Wire.beginTransmission(QMC5883_ADDRESS);
    #if ARDUINO >= 100
        Wire.write(reg);
    #else
        Wire.send(reg);
    #endif
    Wire.endTransmission();
    Wire.beginTransmission(QMC5883_ADDRESS);
    Wire.requestFrom(QMC5883_ADDRESS, 2);
    while(!Wire.available()) {};
    #if ARDUINO >= 100
        uint8_t vla = Wire.read();
        uint8_t vha = Wire.read();
    #else
        uint8_t vla = Wire.receive();
        uint8_t vha = Wire.receive();
    #endif
    Wire.endTransmission();
    value = vha << 8 | vla;
  }
  return value;
}
И в функции считывания вектора поля:
Vector DFRobot_QMC5883::readRaw(void)
{
...
  }else if(isQMC_){
    while (range--){
      v.XAxis = readRegister16(QMC5883_REG_OUT_X_L);
      v.YAxis = readRegister16(QMC5883_REG_OUT_Y_L);
      v.ZAxis = readRegister16(QMC5883_REG_OUT_Z_L);
...

заменяются адреса регистров, чтобы начинать с младших.

Но и после этого шло что-то не то. Причиной оказалось, что "The value stored in these two registers is a 16-bit value in 2’s complement form" (из datasheet на микросхему). Добавил преобразованиес 2-го дополнения в обычный знаковый 16-битный int:

  x1 = compass.readRegister16(0x00) ;
   if(x1 <= 0x7fff) x = (int)x1; else {
    x = - (0x8000 - (x1&0x7fff));
  }
и пошли нормальные значения. Осталось запихать преобразование формата в файл библиотеки, и можно будет использовать её функцию DFRobot_QMC5883::readRaw()
Пока для проверки читаю регистры в своей программе.

Стабильность не совсем идеальная, но могут влиять помехи, нужно опробовать на открытой местности.

Лог с программы (всё спокойно лежит на столе):

22:06:44.728 -> isHMC_= 0
22:06:44.829 -> isQMC_= 1
22:06:44.829 -> Initialize QMC5883
22:06:45.450 ->  reg_x = 24E reg_y = 52D reg_z = F9A1    reg_t = FBF6
22:06:45.450 -> x = 590 y = 1325 z = -1631 t = -1034 T = 23.66
22:06:46.473 ->  reg_x = 24E reg_y = 53E reg_z = F9A4    reg_t = FBEC
22:06:46.473 -> x = 590 y = 1342 z = -1628 t = -1044 T = 23.56
22:06:47.527 ->  reg_x = 25E reg_y = 523 reg_z = F9B8    reg_t = FBF1
22:06:47.527 -> x = 606 y = 1315 z = -1608 t = -1039 T = 23.61
22:06:48.580 ->  reg_x = 253 reg_y = 539 reg_z = F9A4    reg_t = FBF5
22:06:48.580 -> x = 595 y = 1337 z = -1628 t = -1035 T = 23.65
22:06:49.633 ->  reg_x = 23F reg_y = 523 reg_z = F9B5    reg_t = FBF2
22:06:49.633 -> x = 575 y = 1315 z = -1611 t = -1038 T = 23.62
22:06:50.687 ->  reg_x = 268 reg_y = 53E reg_z = F9C0    reg_t = FBFA
22:06:50.687 -> x = 616 y = 1342 z = -1600 t = -1030 T = 23.70
22:06:51.739 ->  reg_x = 281 reg_y = 52A reg_z = F9BB    reg_t = FBF6
22:06:51.773 -> x = 641 y = 1322 z = -1605 t = -1034 T = 23.66
22:06:52.793 ->  reg_x = 23C reg_y = 532 reg_z = F992    reg_t = FBED
22:06:52.827 -> x = 572 y = 1330 z = -1646 t = -1043 T = 23.57
22:06:53.846 ->  reg_x = 26D reg_y = 523 reg_z = F9CA    reg_t = FBE8
22:06:53.880 -> x = 621 y = 1315 z = -1590 t = -1048 T = 23.52
22:06:54.900 ->  reg_x = 277 reg_y = 54D reg_z = F9CF    reg_t = FBE4
22:06:54.934 -> x = 631 y = 1357 z = -1585 t = -1052 T = 23.48
22:06:55.954 ->  reg_x = 26A reg_y = 53C reg_z = F9B0    reg_t = FBF2
22:06:55.988 -> x = 618 y = 1340 z = -1616 t = -1038 T = 23.62
22:06:57.008 ->  reg_x = 244 reg_y = 54B reg_z = F99C    reg_t = FC01
22:06:57.042 -> x = 580 y = 1355 z = -1636 t = -1023 T = 23.77
22:06:58.062 ->  reg_x = 25E reg_y = 550 reg_z = F9B0    reg_t = FBEA
22:06:58.096 -> x = 606 y = 1360 z = -1616 t = -1046 T = 23.54
22:06:59.149 ->  reg_x = 25E reg_y = 52D reg_z = F9C0    reg_t = FBFA
22:06:59.149 -> x = 606 y = 1325 z = -1600 t = -1030 T = 23.70
22:07:00.203 ->  reg_x = 259 reg_y = 52F reg_z = F9B3    reg_t = FBF4
22:07:00.203 -> x = 601 y = 1327 z = -1613 t = -1036 T = 23.64
22:07:01.258 ->  reg_x = 24E reg_y = 52F reg_z = F9BE    reg_t = FBFA
22:07:01.258 -> x = 590 y = 1327 z = -1602 t = -1030 T = 23.70
22:07:02.309 ->  reg_x = 232 reg_y = 50B reg_z = F9B5    reg_t = FBFD
22:07:02.309 -> x = 562 y = 1291 z = -1611 t = -1027 T = 23.73
22:07:03.364 ->  reg_x = 265 reg_y = 52F reg_z = F9AB    reg_t = FBF1
22:07:03.364 -> x = 613 y = 1327 z = -1621 t = -1039 T = 23.61
22:07:04.418 ->  reg_x = 265 reg_y = 52D reg_z = F9B3    reg_t = FBEC
22:07:04.418 -> x = 613 y = 1325 z = -1613 t = -1044 T = 23.56
22:07:05.472 ->  reg_x = 250 reg_y = 520 reg_z = F9CD    reg_t = FBF9
22:07:05.472 -> x = 592 y = 1312 z = -1587 t = -1031 T = 23.69
22:07:06.526 ->  reg_x = 253 reg_y = 53C reg_z = F9B5    reg_t = FC01
22:07:06.526 -> x = 595 y = 1340 z = -1611 t = -1023 T = 23.77
22:07:07.580 ->  reg_x = 272 reg_y = 523 reg_z = F9BB    reg_t = FC03
22:07:07.580 -> x = 626 y = 1315 z = -1605 t = -1021 T = 23.79
22:07:08.637 ->  reg_x = 26D reg_y = 539 reg_z = F9C8    reg_t = FBE5
22:07:08.637 -> x = 621 y = 1337 z = -1592 t = -1051 T = 23.49
22:07:09.662 ->  reg_x = 255 reg_y = 52F reg_z = F9C5    reg_t = FBF4
22:07:09.696 -> x = 597 y = 1327 z = -1595 t = -1036 T = 23.64
22:07:10.749 ->  reg_x = 265 reg_y = 52F reg_z = F9BE    reg_t = FBF2
22:07:10.749 -> x = 613 y = 1327 z = -1602 t = -1038 T = 23.62
22:07:11.800 ->  reg_x = 283 reg_y = 541 reg_z = F9CA    reg_t = FBF2
22:07:11.800 -> x = 643 y = 1345 z = -1590 t = -1038 T = 23.62
 Здесь T - температура с внутр.датчика (регистры 7-8) ;-)

 

shurrik
Offline
Зарегистрирован: 20.11.2012

Всем привет. Подниму тему с таким вопросом.

Датчик GY-271 на L883 чипе. 

При включении в серийный порт выдаёт несуразицу, пару раз повернешь вокруг оси, настроится и уже выдаёт более-менее стабильные данные, колебание в статике 1 градус.  Но стоит закрыть окно серийного порта и снова открыть - опять всё по новой приходится делать. Почему так?  

Скетч :

#include <Wire.h>
#include <DFRobot_QMC5883.h>

DFRobot_QMC5883 compass;

void setup()
{
      Serial.begin(9600);
      compass.begin();
/*  while (!compass.begin())
       {
        Serial.println("Could not find a valid QMC5883 sensor, check wiring!");
        delay(500);
       }
*/
//    if(compass.isHMC()){
//        Serial.println("Initialize HMC5883");
        compass.setRange(HMC5883L_RANGE_1_3GA);
        compass.setMeasurementMode(HMC5883L_CONTINOUS);
        compass.setDataRate(HMC5883L_DATARATE_15HZ);
        compass.setSamples(HMC5883L_SAMPLES_8);
/*    }
   else if(compass.isQMC()){
        Serial.println("Initialize QMC5883");
        compass.setRange(QMC5883_RANGE_2GA);
        compass.setMeasurementMode(QMC5883_CONTINOUS); 
        compass.setDataRate(QMC5883_DATARATE_50HZ);
        compass.setSamples(QMC5883_SAMPLES_8);
   }  */
}
void loop()
{
           
  Vector norm = compass.readNormalize();

  // Calculate heading
  float heading = atan2(norm.YAxis, norm.XAxis);
                        // Set declination angle on your location and fix heading
                        // You can find your declination on: http://magnetic-declination.com/
                        // (+) Positive or (-) for negative
                        // For Bytom / Poland declination angle is 4'26E (positive)
                        // Formula: (deg + (min / 60.0)) / (180 / PI);
  float declinationAngle = (4.0 + (26.0 / 60.0)) / (180 / PI);
  heading += declinationAngle;

  // Correct for heading < 0deg and heading > 360deg
  if (heading < 0){
    heading += 2 * PI;
  }

  if (heading > 2 * PI){
    heading -= 2 * PI;
  }

  // Convert to degrees
  int headingDegrees = heading * 180/PI; 

  
  // Output
  Serial.print(" Heading = ");
  Serial.print(heading);
  Serial.print(" Degress = ");
  Serial.print(headingDegrees);
  Serial.println();

  delay(100);
}