Использование BLE Nano с LSM9DS1

Я пытаюсь использовать BLE Nano для подключения к LSM9DS1 IMU. . Однако, когда я могу подключиться к IMU, значения выходов Nano не обновляются и не имеют смысла.

Я могу подключить и использовать IMU как с Arduino Uno, так и с Edison, поэтому я знаю, что проблема не в самом датчике. Код прикреплен ниже.

#include <Wire.h>
#include <SPI.h>
#include <SparkFunLSM9DS1.h>

LSM9DS1 imu;  // Создаем объект LSM9DS1

// Глобальные переменные для отслеживания частоты обновления
unsigned long startTime;
unsigned int accelReadCounter = 0;
unsigned int gyroReadCounter = 0;
unsigned int magReadCounter = 0;
unsigned int tempReadCounter = 0;

// Глобальные переменные для вывода на последовательный монитор с постоянной скоростью
unsigned long lastPrint = 0;
const unsigned int PRINT_RATE = 500;
uint8_t fax;
uint8_t fay;

Ticker ticker3;
#define TXRX_BUF_LEN    20
BLE                     ble;
Ticker                  ticker;

// Северная служба UART
static const uint8_t service1_uuid[] = {0x71, 0x3D, 0, 0, 0x50, 0x3E, 0x4C, 0x75, 0xBA, 0x94, 0x31, 0x48, 0xF1, 0x8D, 0x94, 0x1E};
static const uint8_t service1_tx_uuid[] = {0x71, 0x3D, 0, 3, 0x50, 0x3E, 0x4C, 0x75, 0xBA, 0x94, 0x31, 0x48, 0xF1, 0x8D, 0x94, 0x1E};
static const uint8_t service1_rx_uuid[] = {0x71, 0x3D, 0, 2, 0x50, 0x3E, 0x4C, 0x75, 0xBA, 0x94, 0x31, 0x48, 0xF1, 0x8D, 0x94, 0x1E};
static const uint8_t uart_base_uuid_rev[] = {0x1E, 0x94, 0x8D, 0xF1, 0x48, 0x31, 0x94, 0xBA, 0x75, 0x4C, 0x3E, 0x50, 0, 0, 0x3D, 0x71};
uint8_t tx_value[TXRX_BUF_LEN] = {0,};
uint8_t rx_value[TXRX_BUF_LEN] = {0,};

GattCharacteristic  characteristic1(service1_tx_uuid, tx_value, 1, TXRX_BUF_LEN, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE );
GattCharacteristic  characteristic2(service1_rx_uuid, rx_value, 1, TXRX_BUF_LEN, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
GattCharacteristic *uartChars[] = {&characteristic1, &characteristic2};
GattService uartService(service1_uuid, uartChars, sizeof(uartChars) / sizeof(GattCharacteristic *));
void disconnectionCallBack(Gap::Handle_t handle, Gap::DisconnectionReason_t reason) {
  Serial1.println("Disconnected!");
  Serial1.println("Restarting the advertising process");
  ble.startAdvertising();
}

void setupDevice() {
  // [commInterface] определяет, будем ли мы использовать I2C или SPI
  // для связи с LSM9DS1.
  // Используйте либо IMU_MODE_I2C, либо IMU_MODE_SPI
  imu.settings.device.commInterface = IMU_MODE_I2C;
  // [mAddress] устанавливает адрес I2C или контакт SPI CS для
  // Магнитометр LSM9DS1.
  imu.settings.device.mAddress = 0x1E; // Использовать адреса I2C 0x1E
  // [agAddress] устанавливает адрес I2C или контакт SPI CS для
  // Акселерометр/гироскоп LSM9DS1.
  imu.settings.device.agAddress = 0x6B; // адрес I2C 0x6B
}

void setupGyro() {
  // [enabled] включает или выключает гироскоп.
  imu.settings.gyro.enabled = false;  // Включить гироскоп
  // [scale] устанавливает полномасштабный диапазон гироскопа.
  // масштаб может быть установлен на 245, 500 или 2000
  imu.settings.gyro.scale = 245; // Установить масштаб на +/-245 dps
  // [sampleRate] устанавливает скорость выходных данных (ODR) гироскопа
  // SampleRate может быть установлен в диапазоне от 1 до 6
  // 1 = 14,9 4 = 238
  // 2 = 59,5 5 = 476
  // 3 = 119 6 = 952
  imu.settings.gyro.sampleRate = 3; // 59,5 Гц ODR
  // [bandwidth] может установить частоту среза гироскопа.
  // Допустимые значения: 0-3. Фактическое значение частоты среза
  // зависит от частоты дискретизации. (раздел 7.12 таблицы данных)
  imu.settings.gyro.bandwidth = 0;
  // [lowPowerEnable] включает или выключает режим низкого энергопотребления.
  imu.settings.gyro.lowPowerEnable = false; // режим LP выключен
  // [HPFEnable] включает или отключает фильтр верхних частот
  imu.settings.gyro.HPFEnable = true; // ФВЧ отключен
  // [HPFCutoff] устанавливает частоту среза HPF (если включено)
  // Допустимые значения: 0-9. Стоимость зависит от ODR.
  // (раздел 7.14 таблицы данных)
  imu.settings.gyro.HPFCutoff = 1; // Отсечка HPF = 4 Гц
  // [flipX], [flipY] и [flipZ] — логические значения, которые могут
  // автоматически переключаем положительную/отрицательную ориентацию
  // из трех осей гироскопа.
  imu.settings.gyro.flipX = false; // Не переворачивать X
  imu.settings.gyro.flipY = false; // Не переворачивать Y
  imu.settings.gyro.flipZ = false; // Не переворачивать Z
}

void setupAccel() {
  // [enabled] включает или выключает акселерометр.
  imu.settings.accel.enabled = true; // Включить акселерометр
  // [enableX], [enableY] и [enableZ] могут включаться и выключаться
  // выбираем оси акселерометра.
  imu.settings.accel.enableX = true; // Включить X
  imu.settings.accel.enableY = true; // Включить Y
  imu.settings.accel.enableZ = true; // Включить Z
  // [scale] устанавливает полный диапазон акселерометра.
  // шкала ускорения может быть 2, 4, 8 или 16
  imu.settings.accel.scale = 8; // Установить шкалу ускорения на +/-8g.
  // [sampleRate] устанавливает скорость выходных данных (ODR)
  // акселерометр. ПРИМЕНЯЕТСЯ ТОЛЬКО КОГДА ГИРОСКОП
  // НЕПОЛНОЦЕННЫЙ! В противном случае частота дискретизации ускорения = частоте дискретизации гироскопа.
  // частота дискретизации ускорения может быть 1-6
  // 1 = 10 Гц 4 = 238 Гц
  // 2 = 50 Гц 5 = 476 Гц
  // 3 = 119 Гц 6 = 952 Гц
  imu.settings.accel.sampleRate = 2; // Установите ускорение на 10 Гц.
  // [bandwidth] устанавливает пропускную способность фильтра сглаживания.
  // Частота отсечки ускорения может принимать любое значение от -1 до 3.
  // -1 = пропускная способность определяется частотой дискретизации
  // 0 = 408 Гц 2 = 105 Гц
  // 1 = 211 Гц 3 = 50 Гц
  imu.settings.accel.bandwidth = 0; // полоса пропускания = 408 Гц
  // [highResEnable] включает или отключает высокое разрешение
  // режим для акселерометра.
  imu.settings.accel.highResEnable = false; // Отключить ЧСС
  // [highResBandwidth] устанавливает частоту среза LP
  // акселерометр, если он в режиме высокого разрешения.
  // может быть любым значением от 0 до 3
  // Отсечка LP устанавливается на коэффициент частоты дискретизации
  // 0 = ОДР/50 2 = ОДР/9
  // 1 = ОДР/100 3 = ОДР/400
  imu.settings.accel.highResBandwidth = 0;  
}

void setupMag() {
  // [enabled] включает или выключает магнитометр.
  imu.settings.mag.enabled = false; // Включить магнитометр
  // [scale] устанавливает полномасштабный диапазон магнитометра
  // шкала магазина может быть 4, 8, 12 или 16
  imu.settings.mag.scale = 12; // Установить шкалу магнита на +/-12Gs
  // [sampleRate] устанавливает скорость выходных данных (ODR)
  // магнитометр.
  // скорость передачи данных может быть 0-7:
  // 0 = 0,625 Гц 4 = 10 Гц
  // 1 = 1,25 Гц 5 = 20 Гц
  // 2 = 2,5 Гц 6 = 40 Гц
  // 3 = 5 Гц 7 = 80 Гц
  imu.settings.mag.sampleRate = 5; // Установить частоту OD на 20 Гц
  // [tempCompensationEnable] включает или отключает
  // температурная компенсация магнитометра.
  imu.settings.mag.tempCompensationEnable = false;
  // [XYPerformance] устанавливает производительность по осям x и y
  // магнитометр либо:
  // 0 = режим низкого энергопотребления 2 = высокая производительность
  // 1 = средняя производительность 3 = сверхвысокая производительность
  imu.settings.mag.XYPerformance = 3; // Сверхвысокая производительность.
  // [ZPerformance] делает то же самое, но только для z
  imu.settings.mag.ZPerformance = 3; // Сверхвысокая производительность.
  // [lowPowerEnable] включает или отключает режим пониженного энергопотребления в
  // магнитометр.
  imu.settings.mag.lowPowerEnable = false;
  // [operatingMode] устанавливает режим работы
  // магнитометр. OperatingMode может быть 0-2:
  // 0 = непрерывное преобразование
  // 1 = однократное преобразование
  // 2 = питание выключено
  imu.settings.mag.operatingMode = 0; // Непрерывный режим
}

void setupTemperature() {
  // [enabled] включает или выключает датчик температуры.
  imu.settings.temp.enabled = false;
}

uint16_t initLSM9DS1() {
  setupDevice(); // Настройка общих параметров устройства
  setupGyro(); // Настраиваем параметры гироскопа
  setupAccel(); // Настраиваем параметры акселерометра
  setupMag(); // Настраиваем параметры магнитометра
  setupTemperature(); // Настраиваем параметр датчика температуры
  return imu.begin();
}

void writtenHandle(const GattWriteCallbackParams *Handler) {
  uint8_t buf[TXRX_BUF_LEN];
  uint16_t bytesRead, index;
  if (Handler->handle == characteristic1.getValueAttribute().getHandle()) {
ble.readCharacteristicValue(characteristic1.getValueAttribute().getHandle(), buf, &bytesRead);
    //Serial1.print("bytesRead: ");
    //Serial1.println(bytesRead, HEX);
    //для (байтовый индекс = 0; индекс < bytesRead; индекс++) {
      //Serial1.write(buf[index]);
    }
    //Serial1.println("");
// // Обработать данные
// if (buf[0] == 0x01) // Команда для управления выводом цифрового выхода
// {
// если (buf[1] == 0x01)
// digitalWrite(DIGITAL_OUT_PIN, HIGH);
// еще
// цифровая запись (DIGITAL_OUT_PIN, LOW);
// }
// else if (buf[0] == 0xA0) // Команда включает аналоговое чтение
// {
// если (buf[1] == 0x01)
// Analog_enabled = true;
// еще
// Analog_enabled = false;
// }
// иначе если (buf[0] == 0x04)
// {
// Analog_enabled = false;
// цифровая запись (DIGITAL_OUT_PIN, LOW);
// }
  }
void m_status_check_handle() {
    imu.readAccel();
    uint8_t buf[3];
    fax = (uint16_t)(imu.readAccel(X_AXIS));
    buf[0] = 0x0A;
    buf[1] = (fax>>8);
    buf[2] = (fax);
ble.updateCharacteristicValue(characteristic2.getValueAttribute().getHandle(), buf, 3);

    uint8_t bufy[3];
    fay = (uint16_t)(imu.readAccel(Y_AXIS));
    bufy[0] = 0x0B;
    bufy[1] = (fax>>8);
    bufy[2] = (fax);

ble.updateCharacteristicValue(characteristic2.getValueAttribute().getHandle(), bufy, 3);
}

void setup() {
  // поместите сюда код установки для однократного запуска
  Serial1.begin(9600);
  ble.init();
  ble.onDisconnection(disconnectionCallBack);
  ble.onDataWritten(writtenHandle);

  // настраиваем adv_data и srp_data
  ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED);
  ble.accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME, (const uint8_t *)"TXRX", sizeof("TXRX") - 1);
  ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS, (const uint8_t *)uart_base_uuid_rev, sizeof(uart_base_uuid_rev));
  // устанавливаем adv_type
  ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
  // добавляем сервис
  ble.addService(uartService);
  // установить имя устройства
  ble.setDeviceName((const uint8_t *)"LSM9DS1 Accel");
  // устанавливаем мощность передачи, допустимые значения -40, -20, -16, -12, -8, -4, 0, 4
  ble.setTxPower(4);
  // установить adv_interval, 100 мс, кратное 0,625 мс.
  ble.setAdvertisingInterval(160);
  // устанавливаем adv_timeout в секундах
  ble.setAdvertisingTimeout(0);
  // запускаем рекламу
  ble.startAdvertising();
  ticker.attach_us(m_status_check_handle, 2000);
}
void loop() {
  // imu.accelAvailable() возвращает 1, если новый акселерометр
  // данные готовы к чтению. 0 иначе.
  if (imu.accelAvailable()) {
    imu.readAccel();
    accelReadCounter++;
    uint8_t buf[3];
    fax = (uint16_t)(imu.readAccel(X_AXIS));
    buf[0] = 0x0A;
    buf[1] = (fax>>8);
    buf[2] = (fax);

ble.updateCharacteristicValue(characteristic2.getValueAttribute().getHandle(), buf, 3);
  }

  // imu.gyroAvailable() возвращает 1, если новый гироскоп
  // данные готовы к чтению. 0 иначе.
  if (imu.gyroAvailable()) {
    imu.readGyro();
    gyroReadCounter++;
  }

  // imu.magAvailable() возвращает 1, если новый магнитометр
  // данные готовы к чтению. 0 иначе.
  if (imu.magAvailable()) {
    imu.readMag();
    magReadCounter++;
  }

  // imu.tempAvailable() возвращает 1, если новый датчик температуры
  // данные готовы к чтению. 0 иначе.
  if (imu.tempAvailable()) {
    imu.readTemp();
    tempReadCounter++;
  }
}

В этом примере я пытаюсь вывести только значения акселерометра x и y. Оба они выводятся как одно и то же число (B5 в HEX) и не обновляются. Любая помощь приветствуется.

, 👍0

Обсуждение

Вы установили высокий уровень на контакт 13 DEN_A/G, это активные данные для гироскопа и акселерометра? Если он находится на низком уровне, значение не изменится., @enrico

Возможно, вы захотите попробовать прочитать идентификационный код устройства или аналогичные известные значения и вывести их локально через UART. Затем отдельно запустите что-то еще — возможно, даже медленный счетчик — через BLE и убедитесь, что ваш телефон или то, к чему вы обращаетесь, видит изменения. Это поможет вам выяснить, связана ли проблема с использованием I2C, использованием стека BLE или даже с тем, что телефон, с которого вы запрашиваете, кэширует значения., @Chris Stratton

Я голосую за то, чтобы закрыть этот вопрос как не по теме, потому что он был заброшен в течение полугода без информации, которая могла бы привести к предоставлению решения., @Chris Stratton


1 ответ


1

Вы установили высокий уровень на контакт 13 DEN_A/G, это активные данные для гироскопа и акселерометра? Если он находится на низком уровне, значение не изменится.

,