Помогите со считыванием данных с акселерометра ADXL373 (I2C)
Я использую < a href="https://eu.mouser.com/ProductDetail/Analog-Devices/EVAL-ADXL373Z?qs=QNEnbhJQKva6ENie%252BWXLsQ%3D%3D">ADXL373Z акселерометр с Arduino Uno для проекта.
Когда я запускаю код, я получаю неверные значения, которые, вероятно, даже не являются данными ускорения. Я думаю, что это может быть проблема с проводкой, я прикрепил схему ниже. Это мой первый проект Arduino, и я не смог найти других приложений с датчиком, который использую, поэтому любая помощь будет очень признательна. Заранее спасибо .
Техническое описание датчика: https://www.analog.com/media /en/technical-documentation/data-sheets/adxl373.pdf
Код (только для данных по оси X):
// Тест акселерометра ADXL373
#include <Wire.h>
/* -------- REGISTERS -------- */
#define ADDRESS_ADXL373 0x53 // адрес датчика (предполагается высокий уровень на выводе MISO)
#define ADDRESS_POWER_CTL 0x3F // управление питанием
#define ADDRESS_MEASURE 0x0E // управление измерениями
#define ADDRESS_TIMING 0x3D // выходная скорость передачи данных и внешние триггеры синхронизации
#define ADDRESS_XDATA_H 0x08 // данные ускорения по оси x [11:4]
#define ADDRESS_XDATA_L 0x09 // данные ускорения по оси x [3:0]
#define ADDRESS_YDATA_H 0x0A // данные ускорения по оси Y [11:4]
#define ADDRESS_YDATA_L 0x0B // данные ускорения по оси Y [3:0]
#define ADDRESS_ZDATA_H 0x0C // данные ускорения по оси Z [11:4]
#define ADDRESS_ZDATA_L 0x0D // данные ускорения по оси Z [3:0]
/* -------- REGISTERS -------- */
#define SCALE_FACTOR 0.2f // 200 мг на коэффициент масштабирования LSB
#define GRAVITY_EARTH 9.80665f // гравитация земли в м/с^2
void setup() {
Serial.begin(115200);
while(!Serial);
Serial.println("ADXL373 Accelerometer Test");
Wire.begin();
Wire.beginTransmission(ADDRESS_ADXL373);
Wire.write(ADDRESS_POWER_CTL);
Wire.write(0x03); // активируем полнополосный режим измерения
Wire.endTransmission(true);
delay(50);
Wire.beginTransmission(ADDRESS_ADXL373);
Wire.write(ADDRESS_MEASURE);
Wire.write(0x04); // установить полосу пропускания выходного сигнала на 2560 Гц
Wire.endTransmission(true);
delay(50);
Wire.beginTransmission(ADDRESS_ADXL373);
Wire.write(ADDRESS_TIMING);
Wire.write(0x80); // установить частоту выходных данных на 5120 Гц
Wire.endTransmission(true);
delay(50);
}
void loop() {
byte xAxisH, xAxisL;
Wire.beginTransmission(ADDRESS_ADXL373);
Wire.write(ADDRESS_XDATA_H);
Wire.endTransmission(false);
Wire.requestFrom(ADDRESS_ADXL373, 1, true);
xAxisH = Wire.read();
Wire.beginTransmission(ADDRESS_ADXL373);
Wire.write(ADDRESS_XDATA_L);
Wire.endTransmission(false);
Wire.requestFrom(ADDRESS_ADXL373, 1, true);
xAxisL = Wire.read();
int16_t xAxisFinal;
xAxisFinal = (uint16_t) xAxisH << 8 | xAxisL; // битовый сдвиг и объединение двух компонентов
xAxisFinal = xAxisFinal >> 4; // 12-битное разрешение
float xAccel;
xAccel = xAxisFinal * SCALE_FACTOR * GRAVITY_EARTH;
Serial.print("Xa = "); Serial.println(xAccel);
delay(200);
}
Схема цепи:
Результаты последовательного монитора (в м/с^2):
@Maxxie, 👍3
Обсуждение1 ответ
Согласно техническому описанию, 12 бит ускорения Х хранятся
в регистры XDATA_H
и XDATA_L
следующим образом:
XDATA_H: b₁₁b₁₀b₉ b₈ b₇ b₆ b₅ b₄
XDATA_L: b₃ b₂ b₁ b₀ x x x x
где x
означает «зарезервировано».
Теперь есть две проблемы с этим кодом:
xAxisFinal = xAxisH << 4 | xAxisL; // bit shift 12-bit output data
Первая проблема заключается в том, что при смещении xAxisH
на четыре позиции биты
b₇–b₄ оказываются в тех же позициях, что и биты b₃–b₀ в xAxisL
. Затем,
когда эти значения объединяются с |
, бит b₇ смешивается с b₃,
b₆ с b₂ и т. д. Если вы действительно хотите сдвинуть xAxisH
влево на четыре
места, вы также должны сдвинуть xAxisL
вправо на четыре места.
Вторая проблема заключается в том, что данные x представляют собой число со знаком, представленное в виде дополнение до двух, и бит знака (b₁₁) оказывается не в том месте. За например, если измеренное значение равно −16 (XDATA_H:XDATA_L = 0xff:0x00), вы в конечном итоге читаете 4980 (0x0ff0). Чтобы избежать этой проблемы, вы можете знак расширяет 12-битное число до 16-битного.
Однако я бы предложил совершенно другой подход. Номер слева в регистрах датчика, так что просто оставьте это так:
xAxisFinal = (uint16_t) xAxisH << 8 | xAxisL;
Промежуточное приведение к uint16_t
здесь, чтобы избежать неопределенного
поведения, окончательный результат подписывается. Если есть риск того, что
зарезервированные биты отличны от нуля (даташит не очень понятен в этом
уважение), вы могли бы
xAxisFinal &= 0xfff0; // очищаем последние 4 бита
Обратите внимание, что теперь единицей измерения ускорения является 1/16 разрешения
датчик, и все значения, которые вы получаете, кратны 16. Я не ожидаю
это будет проблемой. Если вы действительно хотите использовать разрешение сенсора как
вашего устройства, теперь вы можете сместить xAxisFinal
на четыре позиции вправо,
который автоматически выполнит расширение знака.
Обновление: обращение к отредактированному коду из OP:
Я изменил код в соответствии с вашими предложениями. Но я все еще получение неверных значений от последовательного монитора.
В вашем сообщении я вижу очень маленькие значения, около ±3 младших разрядов от датчик. Это вполне может быть шум датчика. Но тогда есть иногда большее значение. Интересно, что эти большие значения кажутся очень близко к ±16 младших разрядов, намекая на какую-то связь проблема.
Думаю, ответ содержится в этом предупреждении из технического описания датчика:
Всегда считывайте данные ускорения, используя многобайтовые передачи, чтобы убедиться, что одновременный и полный набор данных ускорения x, y и z читать.
Представьте, что датчик выдает только шум, а шум колеблется. между -1 и +1 LSB. Что вы ожидаете, так это:
value XDATA_H XDATA_L
−1 11111111 11110000
+1 00000000 00010000
Если вы читаете XDATA_H
и XDATA_L
в двух разных транзакциях, вы
вполне может прочитать 0b11111111 для XDATA_H
(поскольку датчик читает -1),
затем прочитайте 00010000
для XDATA_L
(поскольку он получает +1). Когда ты
объедините эти два показания вместе, и вы получите
value XDATA_H XDATA_L
−15 11111111 00010000
Я предлагаю вам следовать рекомендациям из таблицы данных и прочитать оба регистрируется за один раз:
Wire.beginTransmission(ADDRESS_ADXL373);
Wire.write(ADDRESS_XDATA_H);
Wire.endTransmission(false);
Wire.requestFrom(ADDRESS_ADXL373, 2, true);
xAxisH = Wire.read();
xAxisL = Wire.read();
Хе. Ваш ответ пришел примерно тогда же, когда и мой комментарий., @timemage
Спасибо, я изменил код в соответствии с вашими предложениями. Но я все еще получаю неверные значения от последовательного монитора. Я отредактировал код и результаты в своем посте. Если у вас есть другие предложения, я был бы признателен., @Maxxie
@Maxxie: см. расширенный ответ., @Edgar Bonet
- В чем разница между акселерометром, гироскопом и датчиком магнитометра?
- Как связаться с датчиком через порты RX/TX Arduino?
- Самый точный способ измерения линейного расстояния, пройденного колесом
- Как прочитать необработанные данные с модуля GY-85?
- Как получить и интерпретировать данные цифрового акселерометра?
- Компас с компенсацией наклона Использование HMC5983 дает непоследовательный вывод
- Попытка использовать решение для обнаружения кранов с помощью ADXL345 с Arduino
- Подключение нескольких модулей I2C к микроконтроллеру последовательно или параллельно?
xAxisFinal = xAxisH << 4 | xAxisL;
Я думаю, вы имели в виду<< 8
., @timemage