После восстановления смещения BNO055 на датчике все значения калибровки равны 0.

Плата: ESP32

Скрипт: restre_offsets.ino из библиотеки Adafruit BNO055

Единственная разница в том, что я храню информацию в NVS ESP, используя библиотеку Preferences

Код

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>
#include <utility/imumaths.h>
#include <Preferences.h>


/* Set the delay between fresh samples */
#define BNO055_SAMPLERATE_DELAY_MS (1000)

Adafruit_BNO055 bno = Adafruit_BNO055(1390);

Preferences Calibration;

/**************************************************************************/
/*
    Display some basic info about the sensor status
    */
/**************************************************************************/
void displaySensorStatus(void)
{
    /* Get the system status values (mostly for debugging purposes) */
    uint8_t system_status, self_test_results, system_error;
    system_status = self_test_results = system_error = 0;
    bno.getSystemStatus(&system_status, &self_test_results, &system_error);

    /* Display the results in the Serial Monitor */
    Serial.println("");
    Serial.print("System Status: 0x");
    Serial.println(system_status, HEX);
    Serial.print("Self Test:     0x");
    Serial.println(self_test_results, HEX);
    Serial.print("System Error:  0x");
    Serial.println(system_error, HEX);
    Serial.println("");
    delay(500);
}

/**************************************************************************/
/*
    Display sensor calibration status
    */
/**************************************************************************/
void displayCalStatus(void)
{
    /* Get the four calibration values (0..3) */
    /* Any sensor data reporting 0 should be ignored, */
    /* 3 means 'fully calibrated" */
    uint8_t system, gyro, accel, mag;
    system = gyro = accel = mag = 0;
    bno.getCalibration(&system, &gyro, &accel, &mag);

    /* The data should be ignored until the system calibration is > 0 */
    Serial.print("\t");
    if (!system)
    {
        Serial.print("! ");
    }

    /* Display the individual values */
    Serial.print("Sys:");
    Serial.print(system, DEC);
    Serial.print(" G:");
    Serial.print(gyro, DEC);
    Serial.print(" A:");
    Serial.print(accel, DEC);
    Serial.print(" M:");
    Serial.print(mag, DEC);
}

/**************************************************************************/
/*
    Display the raw calibration offset and radius data
    */
/**************************************************************************/
void displaySensorOffsets(const adafruit_bno055_offsets_t &calibData)
{
    Serial.print("Accelerometer: ");
    Serial.print(calibData.accel_offset_x); Serial.print(" ");
    Serial.print(calibData.accel_offset_y); Serial.print(" ");
    Serial.print(calibData.accel_offset_z); Serial.print(" ");

    Serial.print("\nGyro: ");
    Serial.print(calibData.gyro_offset_x); Serial.print(" ");
    Serial.print(calibData.gyro_offset_y); Serial.print(" ");
    Serial.print(calibData.gyro_offset_z); Serial.print(" ");

    Serial.print("\nMag: ");
    Serial.print(calibData.mag_offset_x); Serial.print(" ");
    Serial.print(calibData.mag_offset_y); Serial.print(" ");
    Serial.print(calibData.mag_offset_z); Serial.print(" ");

    Serial.print("\nAccel Radius: ");
    Serial.print(calibData.accel_radius);

    Serial.print("\nMag Radius: ");
    Serial.print(calibData.mag_radius);
}


/**************************************************************************/
/*
    Arduino setup function (automatically called at startup)
    */
/**************************************************************************/
void setup(void)
{
    Wire.begin(13, 16, 400000);
    Serial.begin(115200);
    delay(1000);
    Serial.println("Orientation Sensor Test"); Serial.println("");

    /* Initialise the sensor */
    if (!bno.begin())
    {
        /* There was a problem detecting the BNO055 ... check your connections */
        Serial.print("Ooops, no BNO055 detected ... Check your wiring or I2C ADDR!");
        while (1);
    }

    Calibration.begin("offsets", false);
    adafruit_bno055_offsets_t calibrationData;
    sensor_t sensor;

    int32_t bnoID = Calibration.getInt("bnoID");
     bool foundCalib = false;
    /*
    *  Look for the sensor's unique ID at the beginning oF EEPROM.
    *  This isn't foolproof, but it's better than nothing.
    */
    bno.getSensor(&sensor);
    if (bnoID != sensor.sensor_id)
    {
        Serial.println("\nNo Calibration Data for this sensor exists in NVS");
        delay(500);
    }
    else
    {
        Serial.println("\nFound Calibration for this sensor in NVS.");

        // Смещения акселерометра
        calibrationData.accel_offset_x = Calibration.getInt("acc_off_x");
        calibrationData.accel_offset_y = Calibration.getInt("acc_off_y");
        calibrationData.accel_offset_z = Calibration.getInt("acc_off_z");

        // Смещения гироскопа
        calibrationData.gyro_offset_x = Calibration.getInt("gyr_off_x");
        calibrationData.gyro_offset_y = Calibration.getInt("gyr_off_y");
        calibrationData.gyro_offset_z = Calibration.getInt("gyr_off_z");

        // Смещения магнитометра
        calibrationData.mag_offset_x = Calibration.getInt("mag_off_x");
        calibrationData.mag_offset_y = Calibration.getInt("mag_off_y");
        calibrationData.mag_offset_z = Calibration.getInt("mag_off_z"); 

        displaySensorOffsets(calibrationData);

        Serial.println("\n\nRestoring Calibration data to the BNO055...");
        bno.setSensorOffsets(calibrationData);

        Serial.println("\n\nCalibration data loaded into BNO055");
        foundCalib = true;
    }

    delay(1000);

    /* Display some basic information on this sensor */
// displaySensorDetails();

    /* Optional: Display current status */
    displaySensorStatus();

   //Кристалл необходимо настроить ПОСЛЕ загрузки данных калибровки в BNO055.
    bno.setExtCrystalUse(true);

    sensors_event_t event;
    bno.getEvent(&event);
    if (foundCalib){
        Serial.println("Move sensor slightly to calibrate magnetometers");
        while (!bno.isFullyCalibrated())
        {
            bno.getEvent(&event);
            displayCalStatus();
            Serial.println("");
            delay(BNO055_SAMPLERATE_DELAY_MS);
        }
    }
    else
    {
        Serial.println("Please Calibrate Sensor: ");
        while (!bno.isFullyCalibrated())
        {
            bno.getEvent(&event);

            Serial.print("X: ");
            Serial.print(event.orientation.x, 4);
            Serial.print("\tY: ");
            Serial.print(event.orientation.y, 4);
            Serial.print("\tZ: ");
            Serial.print(event.orientation.z, 4);

            /* Optional: Display calibration status */
            displayCalStatus();

            /* New line for the next sample */
            Serial.println("");

            /* Wait the specified delay before requesting new data */
            delay(BNO055_SAMPLERATE_DELAY_MS);
        }
    }

    Serial.println("\nFully calibrated!");
    Serial.println("--------------------------------");
    Serial.println("Calibration Results: ");
    adafruit_bno055_offsets_t newCalib;
    bno.getSensorOffsets(newCalib);
    displaySensorOffsets(newCalib);

    Serial.println("\n\nStoring calibration data to NVS...");

    bno.getSensor(&sensor);
    bnoID = sensor.sensor_id;
    // вводим идентификатор датчика
    Calibration.putInt("bnoID", bnoID);

    // сохраняем новые смещения акселерометра
    Calibration.putInt("acc_off_x", newCalib.accel_offset_x);
    Calibration.putInt("acc_off_y", newCalib.accel_offset_y);
    Calibration.putInt("acc_off_z", newCalib.accel_offset_z);

    // сохраняем новые смещения гироскопа
    Calibration.putInt("gyr_off_x", newCalib.gyro_offset_x);
    Calibration.putInt("gyr_off_y", newCalib.gyro_offset_y);
    Calibration.putInt("gyr_off_z", newCalib.gyro_offset_z);

    // сохраняем новые смещения магнитометра
    Calibration.putInt("mag_off_x", newCalib.mag_offset_x);
    Calibration.putInt("mag_off_y", newCalib.mag_offset_y);
    Calibration.putInt("mag_off_z", newCalib.mag_offset_z);
    Serial.println("Data stored to NVS..");

    Serial.println("\n--------------------------------\n");
    delay(500);
}

void loop() {
    /* Get a new sensor event */
    sensors_event_t event;
    bno.getEvent(&event);

    /* Display the floating point data */
    Serial.print("X: ");
    Serial.print(event.orientation.x, 4);
    Serial.print("\tY: ");
    Serial.print(event.orientation.y, 4);
    Serial.print("\tZ: ");
    Serial.print(event.orientation.z, 4);

    /* Optional: Display calibration status */
    displayCalStatus();

    /* Optional: Display sensor status (debug only) */
    displaySensorStatus();

    /* New line for the next sample */
    Serial.println("");

    /* Wait the specified delay before requesting new data */
    delay(BNO055_SAMPLERATE_DELAY_MS);
}

Единственное отличие в коде заключается в том, что вместо передачи структуры смещения я сохраняю информацию индивидуально, используя метод putInt

шаги

  1. Я калибрую датчик, подключенный через I2C.
  2. После завершения калибровки сохраните его в NVS.
  3. Понаблюдайте за значениями
  4. Перезапустите узел и получите смещения из NVS.

Проблема

Калибровочные смещения сохраняются в BNO, и это занимает hella time в следующем блоке:

   if (foundCalib){
        Serial.println("Move sensor slightly to calibrate magnetometers");
        while (!bno.isFullyCalibrated())
        {
            bno.getEvent(&event);
            displayCalStatus();
            Serial.println("");
            delay(BNO055_SAMPLERATE_DELAY_MS);
        }
    }

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

Разве это не противоречит самой идее хранения смещений, если все значения равны нулю?

Вывод с платы

Found Calibration for this sensor in NVS.
Accelerometer: 19 -10 4 
Gyro: -3 -4 9 
Mag: 589 986 1473 
Accel Radius: 0
Mag Radius: 0

Restoring Calibration data to the BNO055...


Calibration data loaded into BNO055

System Status: 0x0
Self Test:     0xF
System Error:  0x0

Move sensor slightly to calibrate magnetometers
    ! Sys:0 G:0 A:0 M:0
    ! Sys:0 G:0 A:0 M:0
    ! Sys:0 G:0 A:0 M:0
    ! Sys:0 G:3 A:0 M:0
    ! Sys:0 G:3 A:0 M:0
    ! Sys:0 G:3 A:0 M:0
    ! Sys:0 G:3 A:0 M:0
    ! Sys:0 G:3 A:0 M:0
    ! Sys:0 G:3 A:0 M:0
    ! Sys:0 G:3 A:0 M:0
    ! Sys:0 G:3 A:0 M:0
    ! Sys:0 G:3 A:0 M:0
    ! Sys:0 G:3 A:0 M:0
    ! Sys:0 G:3 A:0 M:0

Как вы можете заметить, все калибровки установлены на 0, и мне приходится делать все заново. почему?

, 👍1

Обсуждение

Должны ли мы предположить, что возвращаются ненулевые смещения калибровки, что они правильно сохраняются в NVS и что они правильно извлекаются из NVS? Вы все это проверили, так что единственная проблема заключается в том, что вы уверены, что вы «сохранили» ненулевые смещения в датчик, и он по-прежнему возвращает нулевые смещения при обратном считывании?, @jose can u c

Могу заверить вас, что значения не равны нулю. Я почти уверен, что полученные значения также не равны нулю из NVS. Однако я могу снова провести тесты и отредактировать вопрос, указав более конкретные значения, чтобы поддержать предположение., @Shan-Desai

Я спрашиваю только потому, что конкретные ценности – это единственный способ, с помощью которого члены сообщества могут оценить проблему., @jose can u c

Я вернусь к воспроизведению запроса и отредактирую вопрос со всеми соответствующими выходными данными узла и bno055., @Shan-Desai

@josecanuc Я добавил журнал со своей доски, @Shan-Desai


1 ответ


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

1

Функция displayCalStatus() показывает состояние калибровки, а не смещения или текущие значения датчика. Во время калибровки статус равен нулю. После завершения калибровки датчика его статус равен 3. Датчик начинает калибровку самостоятельно с первых движений после включения питания.

Установленные смещения используются после включения питания только до завершения первоначальной автоматической калибровки.

из таблицы данных:

После калибровки устройства профиль калибровки можно использовать повторно, чтобы получить исправить данные ориентации сразу после «Силы сброса». Однако как только датчик попадает во внутренний процедура калибровки, профиль калибровки перезаписывается с вновь полученными смещениями датчика и радиусом датчика.

,

Есть ли способ избежать выполнения процедуры внутренней калибровки BNO055?, @Shan-Desai

нет. почему для тебя это проблема? это происходит в фоновом режиме. датчики работают постоянно. запомненные смещения хороши, чтобы иметь лучшие значения для первых показаний, @Juraj

Проблема в том, что как только смещения восстанавливаются, я калибрую магнитометр, потому что это очень легко, но цикл while не получается легко. Мне приходится выполнять все методы калибровки вместе., @Shan-Desai

но в своем эскизе вы можете делать что хотите. эскиз смещений является примером. Я бы проигнорировал калибровку. Датчик с этим справляется. После включения питания выполните те же действия, и датчик откалибруется сам., @Juraj

Думаю, я попробую ваши вещи., @Shan-Desai