• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Нужна помощь магнитометр QRM3100 и ESP8266

post125

New member
Добрый день!

Хочу прикрутить к ESP8266 магнитометр QRM3100 для отслеживания изменения магнитного поля.
Скетч такой:
Код:
#include <Wire.h>
float x, y, z;
byte QRM3100_I2C_ADDRESS =0x23;

void setup() {
  Serial.begin(9600);
  Wire.begin();
  writeRegister(0b0000001,0b01110001);
}

void loop() {

delay(500);

while ((readRegister(0x34) & 0x80) != 0x80) {}
  uint8_t mx2 = readRegister(0x24);
  uint8_t mx1 = readRegister(0x25);
  uint8_t mx0 = readRegister(0x26);
  uint8_t my2 = readRegister(0x27);
  uint8_t my1 = readRegister(0x28);
  uint8_t my0 = readRegister(0x29);
  uint8_t mz2 = readRegister(0x2A);
  uint8_t mz1 = readRegister(0x2B);
  uint8_t mz0 = readRegister(0x2C);

  x = ((int32_t)(mx2 * 256 * 256) | (mx1 * 256) | mx0);
  y = ((int32_t)(my2 * 256 * 256) | (my1 * 256) | my0);
  z = ((int32_t)(mz2 * 256 * 256) | (mz1 * 256) | mz0);

  Serial.print("M:  X\t");
  Serial.print(x);
  Serial.print("\t   Y\t");
  Serial.print(y);
  Serial.print("\t   Z\t");
  Serial.print(z);
  Serial.println("");
  delay(500); 
 
}

uint8_t readRegister(uint8_t address){  // функция чтения регистра
  uint8_t output;

  Wire.beginTransmission(QRM3100_I2C_ADDRESS);
  Wire.write(address);
  Wire.endTransmission();

  delayMicroseconds(2);

  Wire.requestFrom(QRM3100_I2C_ADDRESS, 1);
  while(Wire.available())
  {
  output = Wire.read();
  }
  return output;
}

void writeRegister(uint8_t address, uint8_t value){ // функция записи в регистр
  Wire.beginTransmission(QRM3100_I2C_ADDRESS);
  Wire.write(address);
  Wire.write(value);
  Wire.endTransmission();
}
Скетч работает на ProMini, но не хочет на ESP8266. Насколько я понимаю, проблема в разрядности процессоров. ESP не хочет делать отрицательные "int". Пробовал методом "научного тыка" менять типы переменных, ничего хорошего не получается.

Ардуино выдает: X 475.00 Y -1268.00 Z 3557.00

ESP выдает: X 593.00 Y 16775842.00 Z 3409.00

т.е. положительные значения похожи, а с отрицательными беда.

Поскажите, пожалуйста, как подружить этот скетч с ESp8266.
 

CodeNameHawk

Moderator
Команда форума
  • uint8_t mx2 = readRegister(0x24);
  • uint8_t mx1 = readRegister(0x25);
  • uint8_t mx0 = readRegister(0x26);
  • uint8_t my2 = readRegister(0x27);
  • uint8_t my1 = readRegister(0x28);
  • uint8_t my0 = readRegister(0x29);
  • uint8_t mz2 = readRegister(0x2A);
  • uint8_t mz1 = readRegister(0x2B);
uint8_t mz0 = readRegister(0x2C);
Проблема возможно в
  • x = ((int32_t)(mx2 * 256 * 256) | (mx1 * 256) | mx0);
  • y = ((int32_t)(my2 * 256 * 256) | (my1 * 256) | my0);
  • z = ((int32_t)(mz2 * 256 * 256) | (mz1 * 256) | mz0);
Создайте новые переменные типа int32_t, скопируйте в них mx, my, mz, а потом выполняйте вычисления.
 

pvvx

Активный участник сообщества
Код:
union {
int32_t i;
int16_t w[2];
uint8_t ub[4];
} x;
int8_t a;

a = (int8_t) readRegister(0x24);
x.w[1] = (int16_t) a;
x.ub[1] = (uint8_t) readRegister(0x25);
x.ub[0] = (uint8_t) readRegister(0x26);

Serial.print(x.i);
 

pvvx

Активный участник сообщества
Хочу прикрутить к ESP8266 магнитометр QRM3100 для отслеживания изменения магнитного поля.
RM3100: Sensitivity (чувствительность) 26 nT, Noise 20 nT
Мощнейшие магнитные бури (от вспышек на Солнце) +-10..20 nT, флуктуации МГД составляющей волны до 1.5 nT.
Разрешение нормального ГЕО магнитометра - к 0.01 nT.
Древний протонный (керосиновый) MMP-203 - 0.1 nT. Топор в ручье найти сложно...
Три бочки от 200 литров керосина с катушками (в ближней зоне от разнесенных бочек нет железа) - разрешение по обработке = вектор на движущейся железный объект в 10 км (идущего поезда или движущейся железной подлодки/корабля).
 

post125

New member
Разрешение нормального ГЕО магнитометра - к 0.01 nT.
А есть ли адекватный вариант для ардуины?
Создайте новые переменные типа int32_t, скопируйте в них mx, my, mz, а потом выполняйте вычисления.
ничего не меняется:

uint8_t -результат: X 1321.00 Y 16776612.00 Z 2224.00
int32_t -результат: X 1321.00 Y 16776620.00 Z 2225.00
uint32_t -результат: X 1322.00 Y 16776619.00 Z 2232.00
 

post125

New member
Разрешение нормального ГЕО магнитометра - к 0.01 nT.
А есть ли адекватный вариант для ардуины?
Создайте новые переменные типа int32_t, скопируйте в них mx, my, mz, а потом выполняйте вычисления.
ничего не меняется:

uint8_t -результат: X 1321.00 Y 16776612.00 Z 2224.00
int32_t -результат: X 1321.00 Y 16776620.00 Z 2225.00
uint32_t -результат: X 1322.00 Y 16776619.00 Z 2232.00
 

nikolz

Well-known member
Добрый день!

Хочу прикрутить к ESP8266 магнитометр QRM3100 для отслеживания изменения магнитного поля.
Скетч такой:
Код:
#include <Wire.h>
float x, y, z;
byte QRM3100_I2C_ADDRESS =0x23;

void setup() {
  Serial.begin(9600);
  Wire.begin();
  writeRegister(0b0000001,0b01110001);
}

void loop() {

delay(500);

while ((readRegister(0x34) & 0x80) != 0x80) {}
  uint8_t mx2 = readRegister(0x24);
  uint8_t mx1 = readRegister(0x25);
  uint8_t mx0 = readRegister(0x26);
  uint8_t my2 = readRegister(0x27);
  uint8_t my1 = readRegister(0x28);
  uint8_t my0 = readRegister(0x29);
  uint8_t mz2 = readRegister(0x2A);
  uint8_t mz1 = readRegister(0x2B);
  uint8_t mz0 = readRegister(0x2C);

  x = ((int32_t)(mx2 * 256 * 256) | (mx1 * 256) | mx0);
  y = ((int32_t)(my2 * 256 * 256) | (my1 * 256) | my0);
  z = ((int32_t)(mz2 * 256 * 256) | (mz1 * 256) | mz0);

  Serial.print("M:  X\t");
  Serial.print(x);
  Serial.print("\t   Y\t");
  Serial.print(y);
  Serial.print("\t   Z\t");
  Serial.print(z);
  Serial.println("");
  delay(500);
 
}

uint8_t readRegister(uint8_t address){  // функция чтения регистра
  uint8_t output;

  Wire.beginTransmission(QRM3100_I2C_ADDRESS);
  Wire.write(address);
  Wire.endTransmission();

  delayMicroseconds(2);

  Wire.requestFrom(QRM3100_I2C_ADDRESS, 1);
  while(Wire.available())
  {
  output = Wire.read();
  }
  return output;
}

void writeRegister(uint8_t address, uint8_t value){ // функция записи в регистр
  Wire.beginTransmission(QRM3100_I2C_ADDRESS);
  Wire.write(address);
  Wire.write(value);
  Wire.endTransmission();
}
Скетч работает на ProMini, но не хочет на ESP8266. Насколько я понимаю, проблема в разрядности процессоров. ESP не хочет делать отрицательные "int". Пробовал методом "научного тыка" менять типы переменных, ничего хорошего не получается.

Ардуино выдает: X 475.00 Y -1268.00 Z 3557.00

ESP выдает: X 593.00 Y 16775842.00 Z 3409.00

т.е. положительные значения похожи, а с отрицательными беда.

Поскажите, пожалуйста, как подружить этот скетч с ESp8266.
Полагаю Вы не правильно преобразуете
Во-первых это преобразование
(int32_t)(mx2 * 256 * 256)
означает что вы сначала умножили на 2^16 число, а потом преобразовали его в 32 битовое.
если mx2 - 8 бит то будет переполнение
надо делать так
((int32_t)mx2) * 256 * 256
а еще лучше сначала преобразуйте отдельным оператором в 32 бит все три числа а потом их складывайте
и формирование числа лучше записать так
X=(256*(256*Y|Z))|E вместо X=Y*256*256|256*Z|E
или так X=(((Y<<8)|Z)<<8)|E предварительно преобразовав Y Z к 32 битам
 

nikolz

Well-known member
  1. int x =(int) ((uint32_t)readRegister(0x24))<<16+ ((uint32_t)readRegister(0x25))<<8+readRegister(0x26);
  2. int y =(int) ((uint32_t)readRegister(0x27))<<16+ ((uint32_t)readRegister(0x28))<<8+readRegister(0x29);
  3. int z =(int) ((uint32_t)readRegister(0x2A))<<16+ ((uint32_t)readRegister(0x2B))<<8+readRegister(0x2C);
 

post125

New member
  • int x =(int) ((uint32_t)readRegister(0x24))<<16+ ((uint32_t)readRegister(0x25))<<8+readRegister(0x26);
  • int y =(int) ((uint32_t)readRegister(0x27))<<16+ ((uint32_t)readRegister(0x28))<<8+readRegister(0x29);
  • int z =(int) ((uint32_t)readRegister(0x2A))<<16+ ((uint32_t)readRegister(0x2B))<<8+readRegister(0x2C);
так совсем не работает - в результатах x и z только "0", y - то "0" , то значения типа "-2147483648 "
 

post125

New member
Что то не так делаете, покажите код.
код такой:
Код:
#include <Wire.h>
//float x, y, z;
byte QRM3100_I2C_ADDRESS =0x23;

void setup() {
  Serial.begin(9600);
  Wire.begin();
  writeRegister(0b0000001,0b01110001);
}

void loop() {

delay(500);

while ((readRegister(0x34) & 0x80) != 0x80) {}


    int x =(int) ((uint32_t)readRegister(0x24))<<16+ ((uint32_t)readRegister(0x25))<<8+readRegister(0x26);
    int y =(int) ((uint32_t)readRegister(0x27))<<16+ ((uint32_t)readRegister(0x28))<<8+readRegister(0x29);
    int z =(int) ((uint32_t)readRegister(0x2A))<<16+ ((uint32_t)readRegister(0x2B))<<8+readRegister(0x2C);



  Serial.print("M:  X\t");
  Serial.print(x);
  Serial.print("\t   Y\t");
  Serial.print(y);
  Serial.print("\t   Z\t");
  Serial.print(z);
  Serial.println("");
  delay(500); 
 
}

uint8_t readRegister(uint8_t address){  // функция чтения регистра
  uint8_t output;

  Wire.beginTransmission(QRM3100_I2C_ADDRESS);
  Wire.write(address);
  Wire.endTransmission();

  delayMicroseconds(2);

  Wire.requestFrom(QRM3100_I2C_ADDRESS, 1);
  while(Wire.available())
  {
  output = Wire.read();
  }
  return output;
}

void writeRegister(uint8_t address, uint8_t value){ // функция записи в регистр
  Wire.beginTransmission(QRM3100_I2C_ADDRESS);
  Wire.write(address);
  Wire.write(value);
  Wire.endTransmission();
}
 

pvvx

Активный участник сообщества
подскажите, пожалуйста, где по это почитать
Нигде. Гос. тайна и запрещено выкладывание в общ.источники (статьи типа гос-измена :) ). Военка, ещё СССР годов 70-х - 80-х. Тогда-же перешли на квантовые магнитометры, но у них тогда были другие беды - волны на море для летящего низко .. дают сильное зашумление...
Никто не мешает вам всё это сделать самому. Там ничего сложного нет, кроме времени на подборы программных фильтров и алгоритмов. Но выкладывать незя.
 

pvvx

Активный участник сообщества
код такой:
Код:
#include <Wire.h>
    int x =(int) ((uint32_t)readRegister(0x24))<<16+ ((uint32_t)readRegister(0x25))<<8+readRegister(0x26);
    int y =(int) ((uint32_t)readRegister(0x27))<<16+ ((uint32_t)readRegister(0x28))<<8+readRegister(0x29);
    int z =(int) ((uint32_t)readRegister(0x2A))<<16+ ((uint32_t)readRegister(0x2B))<<8+readRegister(0x2C);
Работать не будет.
 

pvvx

Активный участник сообщества
А есть ли адекватный вариант для ардуины?
А вы посмотрите схемы ММР-203 https://www.google.com/search?q=MMP-203+схема
Поставьте современную элементную базу, увеличьте катушки и разнесите, триангуляция...
Оцифруйте всю информацию, включая огибающие затухания, фазы и т.д. ESP не справится, но для Arduino есть не только ESP и на Arduino можно странслировать и СИ и C++ хоть мегабайтные :)
 
Сверху Снизу