Как получить и интерпретировать данные цифрового акселерометра?
Я пытаюсь подключить Arduino к цифровому акселерометру . Arduino получает команды от мобильного приложения и передает их через Bluetooth через последовательный порт оборудования. Я также разместил этот вопрос здесь.
Код:
#include < SPI.h >
const int X8 = 0x06;
const int Y8 = 0x07;
const int Z8 = 0x08;
/*
bits
1 0 mode 00: standby, 01: measurement
5 1: spi 3 wire, 0: 4 wire
4 self test
3 2 glevel: 01 2g
1 0 mode, 00 standby, 01 measurement
*/
const int MODE = 0x16;
const int STATUS = 0x09;
//7 полоса пропускания цифрового фильтра, 0 62,5 Гц, 1 125 Гц
const int CONTROL = 0x18;
bool isTesting = false;
const int chipSelectPin = 7;
void setup() {
Serial.begin(9600);
SPI.begin();
pinMode(chipSelectPin, OUTPUT);
//настраиваем режим ожидания, 4-проводной разъем, диапазон 2G,
writeRegister(MODE, 0x04);
//настраиваем скорость
writeRegister(CONTROL, 0x00);
delay(100);
}
void loop() {
if (getSerial() == 't') {
isTesting = true;
writeRegister(MODE, 0x05); // 0000 0101- 0001 0101 0x15
testing();
}
}
void testing() {
while (isTesting) {
if ((readRegister(STATUS) & 1) == 1) {
Serial.print((char) readRegister(X8), DEC);
Serial.print("x");
Serial.print((char) readRegister(Y8), DEC);
Serial.print("y");
Serial.print((char) readRegisterChar(Z8), DEC);
Serial.print("z");
}
if (getSerial() == 'u') {
isTesting = false;
writeRegister(MODE, 0x04);
}
}
}
char getSerial() {
if (Serial.available()) {
char c = Serial.read();
return c;
}
return 'x';
}
byte readRegister(byte thisRegister) {
byte inByte = 0;
SPI.beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE0)); // часы 500 кГц
digitalWrite(chipSelectPin, LOW);
SPI.transfer(thisRegister << 1);
inByte = SPI.transfer(0x00);
digitalWrite(chipSelectPin, HIGH);
return inByte;
}
char readRegisterChar(byte thisRegister) {
char inChar = 0;
SPI.beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE0)); // часы 500 кГц
digitalWrite(chipSelectPin, LOW);
SPI.transfer(thisRegister << 1);
inChar = SPI.transfer(0x00);
digitalWrite(chipSelectPin, HIGH);
return inChar;
}
void writeRegister(byte thisRegister, byte value) {
SPI.beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE0)); // часы 500 кГц
digitalWrite(chipSelectPin, LOW);
SPI.transfer(128 | thisRegister << 1);
SPI.transfer(value);
digitalWrite(chipSelectPin, HIGH);
}
Датчик допускает 10-битные значения данных, но для простоты я получаю только 8-битные данные. Данные, полученные, когда датчик находится на плоской поверхности:
xy z
5–11 74
4–19 74
2 -9 69
0 -8 68
7–16 68
7–11 73
Результаты самотестирования:
-5 -20 122
-4 -22 122
-1 -20 123
-4 -20 123
-5 -21 121
-3 -18 123
-8 -22 127
Из таблицы данных: «Когда функция самотестирования инициируется через регистр управления режимом ($16), доступ к «самотестированию» ; К каждой оси прикладывается электростатическая сила, вызывающая ее отклонение. Ось Z обрезана для отклонения 1г.";
Правильны ли данные? Как это интерпретируется? Если данные z во время самотестирования составляют 1 г, не должны ли они иметь ту же величину, что и на плоской поверхности?
Я приспособился к кодированию, чтобы получить 10 бит данных:
const int X10_LSB = 0x00;
const int X10_MSB = 0x01;
const int Y10_LSB = 0x02;
const int Y10_MSB = 0x03;
const int Z10_LSB = 0x04;
const int Z10_MSB = 0x05;
//[...]
void testing() {
while (isTesting) {
if ((readRegister(STATUS) & 1) == 1) {
int xData = (readRegister(X10_MSB) << 8) | readRegister(X10_LSB);
// проверяет, равен ли бит 9 1 и расширяется ли знак
if ((xData & 512) == 512)
xData = (0b1111110000000000 | xData);
int yData = (readRegister(Y10_MSB) << 8) | readRegister(Y10_LSB);
if ((yData & 512) == 512)
yData = (0b1111110000000000 | yData);
int zData = (readRegister(Z10_MSB) << 8) | readRegister(Z10_LSB);
if ((zData & 512) == 512)
zData = (0b1111110000000000 | zData);
Serial.print(xData);
Serial.print("x");
Serial.print(yData);
Serial.print("y");
Serial.print(zData);
Serial.print("z");
}
Выходные данные для измерения 2G:
4 246 -183
5 245 -183
5 245 -182
6 245 -181
Для самопроверки:
252 -20 -134
253 -21 -133
253 -21 -135
253 -20 -135
Значения для 8 и 10 бит данных не совпадают. Что я делаю не так?
Обновление: я переписал код, чтобы сначала получить 10 бит данных с младшими битами, как указано в комментарии:
Код:
int xData =(readRegister (X10_LSB));
xData = xData | (readRegister (X10_MSB)<<8);
xData = xData << 6;
int yData =(readRegister (Y10_LSB));
yData = yData | (readRegister (Y10_MSB)<<8);
yData = yData << 6;
int zData = (readRegister (Z10_LSB));
zData = zData | (readRegister (Z10_MSB)<<8);
zData = zData << 6;
xData /= 64;
yData /= 64;
zData /= 64;
Результаты работы датчика на плоской поверхности:
0–4 71
4–11 70
5–13 70
2–12 70
Результаты применения самотестирования:
-2 -19 123
-2 -19 122
-4 -20 122
-3 -21 122
Почему 8-битные и 10-битные результаты во время самотестирования возвращают одинаковые значения (около 128)? Должно ли 10-битное значение быть в 4 раза больше?
@rur2641, 👍3
Обсуждение1 ответ
Лучший ответ:
Датчик допускает значения данных длиной 10 бит, но для простоты я получаю только 8-битные данные
Вы используете его в режиме 2g, поэтому у вас есть только 8 бит данных.
Данные, полученные при расположении датчика на плоской поверхности:
Это правильно. У вас есть 8-битный диапазон (256 значений, от -128 до +128), который отображает диапазон от +2g до -2g. Итак, у нас есть 256lsb/4g = 64lsb/g.
Неподвижно, длина вектора силы тяжести (sqrt(xx+yy+z*z)) должна быть близка к 64. Конечно, вам понадобится некоторое смещение и калибровка нелинейности, но данные кажутся хорошими.
Кроме того, если вы посмотрите на часть таблицы данных, которую вы разместили в таблице «Чувствительность», вы увидите, что они называют LSB «счетчиком», и они находятся в диапазоне, который мы рассчитали!
При запуске самотестирования результаты следующие:
И снова это верно , если ваш датчик плоский в том направлении, в котором гравитация применяется к Z; то, что вы видите, — это нормальная гравитация (64), суммирующаяся со смещением самотестирования (64), что дает вам хорошее значение ~128
Я адаптировал код для получения 10 бит данных:
Почему 8-битные и 10-битные результаты возвращают одинаковые значения во время самотестирования (около 128)? Должно ли 10-битное значение быть в 4 раза больше?
Чтобы использовать 10 бит, необходимо установить полный диапазон шкалы на +-8 г. Если вы посмотрите на часть таблицы данных, которую вы опубликовали, таблицу «Выходной сигнал», вы увидите, сколько бит доступно для каждого диапазона.
Если задуматься, как датчик узнает, хотите ли вы считать 8 или 10 бит? (помните, DS говорит, что вы должны считать младший регистр ПЕРЕД старшим!) если вы читаете только 8 бит, вы теряете 2 старших бита, один из которых представляет знак, а другой — самый важный бит, который может изменить ваш результат на 2^9=512
Кстати, ваше первое 10-битное преобразование также неверно, поскольку вы переворачиваете бит для дополнения до 2, но ничего не делаете с битом значения.
Решение с битовым смещением 6 и последующим делением работает, но выглядит немного странно. Я бы выбрал что-то более «стандартное», например
int xData = readRegister (X10_LSB) | (readRegister (X10_MSB) << 8);
if (xData | 0b0000 0010 0000 0000){ //if negative
//keep 9 bit raspresenting the value and multiply by -1 to keep the sign
xData = (xData & 0b0000 0001 1111 1111) * -1;
}
- Компас с компенсацией наклона Использование HMC5983 дает непоследовательный вывод
- Попытка использовать решение для обнаружения кранов с помощью ADXL345 с Arduino
- Можно ли измерить скорость акселерометром? Насколько точно?
- Какова работа pulseIn?
- Сколько датчиков может поддерживать один модуль Arduino?
- Получение BPM из данного кода
- Как подключить более 10 датчиков к Arduino uno r3
- В чем разница между акселерометром, гироскопом и датчиком магнитометра?
Почему вы не сказали нам, что речь идет о датчике MMA7455L и что вы также задаете вопрос здесь: http://forum.arduino.cc/index.php?topic=465471.0 Пробовали ли вы библиотеку, которая, как известно, работает хорошо? Вы можете попытаться сдвинуть 10 бит на 6 бит влево для 16-битного целого числа с дополнением до 2. Сначала вы читаете MSB, но согласно таблице данных: «XOUTH следует читать непосредственно после чтения XOUTL»., @Jot
Вы пробовали этот [ссылка](https://playground.arduino.cc/Main/MMA7455) скетч с игровой площадки Arduino?, @chrisl