Почему существует ограничение на эти значения измерения акселерометра? - ADXL375

Я использую Teensy 3.2 для чтения данных с ADXL375 с помощью SPI. В целом общение идет просто отлично, и я могу активировать настройки и т.д. Однако, когда я пытаюсь прочитать данные X, Y или Z, кажется, что какая-то часть значений измерений отсутствует.

Я выполняю измерения с помощью ADXL375 и записываю значения LSB прямо на SD-карту, поэтому никакого преобразования в g или что-то в этом роде. Диапазон акселерометра составляет +/- 200g, так что максимальное значение LSB должно составлять около 200 * 20 (масштабный коэффициент) = +/- 4000 LSB.
Во время некоторых тестов я размахивал акселерометром рукой и постукивал по нему непосредственно ручкой, что давало мгновенный сильный эффект. Значения колебаний представлены хорошо и кажутся мне достоверными, однако значения нажатия пера, похоже, обрезаны точно на 511 LSB, см. Графики. Это кажется неправильным. Так почему же это так?

Примечание. Диапазон ADXL установлен на уровне 200 г, так что выбора делать не приходится.

Я думаю, что что-то идет не так с преобразованием двух регистров ADXL (дополнение к двум) в одно число. Это преобразование, которое я делаю (т. Е. Я считываю FIFO за один раз):

void ADXL375::saveFIFO(){
    int fifo_index;
    int16_t x, y, z;
    fifo_index=0;
// Считывание с (УСТРОЙСТВА,ADXL375_INT_SOURCE_REG,1, buff);


    for(int i=0;i<32;i++){
        multiByteReadSPI(ADXL375_DATAX0_REG, 6, bufferSPI); //считывает данные ускорения из ADXL375 
        x = (((uint16_t)bufferSPI[1]) << 8) | (uint16_t)bufferSPI[0];
        y = (((uint16_t)bufferSPI[3]) << 8) | (uint16_t)bufferSPI[2];
        z = (((uint16_t)bufferSPI[5]) << 8) | (uint16_t)bufferSPI[4];

        // Serial.print(bufferSPI[5], BIN); Serial.println(bufferSPI[4], BIN); // z
        // Serial.print(bufferSPI[1], BIN); Serial.print(","); Serial.println(bufferSPI[0], BIN); // x 

        if (x & 0x8000){ // Проверьте, является ли двоичное число отрицательным, проверив, равен ли самый левый бит 1 или нет. 
            // Если отрицательный, то выполните операцию not и добавьте единицу, чтобы получить величину 
            x = ~x + 1; 
            x = - x; 
        } 
        if (y & 0x8000){ // Проверьте, является ли двоичное число отрицательным, проверив, равен ли самый левый бит 1 или нет. 
            // Если отрицательный, то выполните операцию not и добавьте единицу, чтобы получить величину 
            y = ~y + 1; 
            y = - y; 
        } 
        if (z & 0x8000){ // Проверьте, является ли двоичное число отрицательным, проверив, равен ли самый левый бит 1 или нет. 
            // Если отрицательный, то выполните операцию not и добавьте единицу, чтобы получить величину 
            z = ~z + 1; 
            z = - z; 
        } 

        
        lastFiFo[fifo_index]    =   newistFiFo[fifo_index];
        newistFiFo[fifo_index]  =   x;
        fifo_index++;
        lastFiFo[fifo_index]    =   newistFiFo[fifo_index]; 
        newistFiFo[fifo_index]  =   y;
        fifo_index++;
        lastFiFo[fifo_index]    =   newistFiFo[fifo_index]; 
        newistFiFo[fifo_index]  =   z;
        fifo_index++;
        // DebugPrint(x); // debugPrintln(", сохранение fifo"); 

                // x = (((int16_t)bufferSPI[1]) << 8) | bufferSPI[0];
        // y = (((int16_t)bufferSPI[3])<< 8) | bufferSPI[2];
        // z = (((int16_t)bufferSPI[5]) << 8) | bufferSPI[4];
        // scaleXYZ(&x,&y,&z);

    }

 }

Это многобайтовая функция чтения SPI, которую я использую:

void ADXL375::multiByteReadSPI(uint8_t regAddr, uint8_t numberOfBytes, uint8_t *dataBuffer){


    SPI.beginTransaction(SPISettings(5000000, MSBFIRST, SPI_MODE3));

    digitalWrite(_chipSelectPin,LOW);

    uint8_t readMBaddr; 

    if (numberOfBytes > 1){ // для фактического многобайтового чтения
        readMBaddr = 0b11000000 | regAddr; // Слева направо: чтение (1), да, многобайтовое (1), а затем куча нулей
    }
    else{ // для однобайтового чтения
        readMBaddr = 0b10000000 | regAddr; // Слева направо: чтение (1), а не многобайтовое (0), а затем куча нулей
    }

    SPI.transfer(readMBaddr);

    for (uint8_t k = 0; k < numberOfBytes; k++ ){
      dataBuffer[k] = SPI.transfer(SPI_DUMMY_VALUE);
    }

    digitalWrite(_chipSelectPin,HIGH);

    SPI.endTransaction();

}

Я также посмотрел, все ли в порядке с передачей SPI. На изображении показано одно многобайтовое чтение, состоящее из командного байта в крайнем левом углу, а затем 6 прочитанных байтов после этого. Там нет ничего необычного.

, 👍1

Обсуждение

ссылка на EE SE версию вопроса: https://electronics.stackexchange.com/questions/611607/why-is-there-a-cutoff-on-these-accelerometer-measurement-values-adxl375, @Juraj


1 ответ


Лучший ответ:

2

Я нашел ответ. Оказывается, спецификация ADXL375 неверна, и пользователь действительно может сам изменить диапазон (хотя в таблице указано, что вы не можете). В моем случае диапазон был непреднамеренно установлен на 25 г (вместо 200 г). Смотрите Ниже полное объяснение от bvn123, которое было опубликовано в 2017 году, но Analog Devices до сих пор не обновила техническое описание.

Я использую ADXL345 и ADXL375 в программном обеспечении uC, которое было написано для ADXL345.

В техническом описании для ADXL345 указано о диапазонах ± 2g / ± 4g / ± 8g / ± 16g и соответствующих этим диапазонам разрешениях 10/11/12 / 13 бит.

Спецификация для ADXL375 показывает только один диапазон ± 200g и разрешение 13 бит. .

Несмотря на информацию таблицы данных ADXL375, состояние регистра 0x31 только для битов D3: D2: D1: D0 равно 1n11 (D3 - бит полного разрешения, D1: D0 - биты диапазона), ADXL375 реагирует на изменение D1: D0 и D3 в регистре 0x31 так же, как ADXL345,

Таким образом, в действительности ADXL375 также обеспечивает 4 диапазона (±25 г/±50 г/±100 г/±200 г).

,