• Уважаемые посетители сайта esp8266.ru!
    Мы отказались от размещения рекламы на страницах форума для большего комфорта пользователей.
    Вы можете оказать посильную поддержку администрации форума. Данные средства пойдут на оплату услуг облачных провайдеров для сайта esp8266.ru
  • Система автоматизации с открытым исходным кодом на базе 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++ хоть мегабайтные :)
 
Сверху Снизу