STM Урок 47. Подключаем гироскоп LSM6DS3. Часть 1



    Урок 47

 

Часть 1

 

Подключаем гироскоп LSM6DS3

 

Сегодня мы продолжим работать ещё с одним датчиком, который в себе объединяет сразу два функционала – акселерометр и гироскоп – LSM6DS3. Выполнен он также с использованием технологии MEMS. Установлен на плате расширения STEVAL-MKI160V1, которая в свою очередь вставляется в плату расширения X-NUCLEO-IKS01A1, предназначенной для работы с отладочной платой Nucleo. Мы будем подключать данную оценочную плату к плате Nucleo STM32F401RE.

Данный акселерометр-гироскоп также наряду с интерфейсом I2C может подключиться и с использованием интерфейса SPI. Но мы будем использовать подключение именно по I2C, так как именно такое подключение имеет место в оценочной плате X-NUCLEO-IKS01A.

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

Данный гироскоп в данном датчике в сравнении с предыдущим рассмотренным имеет следующие технические характеристики:

Диапазон показаний ±125/±245/±500/±2000 dps (появился ещё один наименьший предел);

Чувствительность 4.375 – 70 mdps/LSb  (соответственно по меньшему пределу стала лучше);

Отклонение от нуля ±10 dps при установке диапазона 2000 dps (что втрое лучше, чем у рассмотренного ранее датчика).

Частота измерений 14,9 – 952 Гц.

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

Проект мы создадим из готового проекта, в котором мы работали с акселерометром данного датчика – из проекта Accel_LSM6DS3, только назовём мы данный проект теперь соответственно Gyro_LSM6DS3.

Запустим проект Cube MX. Изменим мы здесь только скорость USART.

 

image04

 

Сгенерируем проект, откроем его. Настроим программатор на авторезет. Добавим файл lsm6ds3.c. Скомпилируем проект.

 

В бесконечном цикле пока закомментируем код вызова функции считывания данных и отправки их в USART

 

  /* USER CODE BEGIN 3 */

                //Accel_ReadAcc();

  }

 

Для универсальности проекта, так как, возможно, позже мы объединим работу с акселерометром и гироскопом в один проект, переименуем функцию Accel_Ini в файле lsm6ds0.c на Accel_Gyro_Ini. То же самое проделаем с прототипом и с вызовом данной функции в main().

Закомментируем в функции Accel_Gyro_Ini  вот эту строку

 

        LD2_OFF;

//        AccInit(ctrl);

        LD2_ON;

 

 

Добавим функцию инициализации гироскопа по подобию функции инициализации акселерометра

 

//———————————————

void GyroInit(uint16_t InitStruct)

{

        uint8_t value = 0;

}

//———————————————

 

Вызовем её в функции общей инициализации

 

//        AccInit(ctrl);

        GyroInit(ctrl);

        LD2_ON;

 

В файле lsm6ds0.h заранее добавим несколько макросов, необходимых для работы с гироскопом. Код данного файла после всех изменений примет следующий вид:

 

#ifndef LSM6DS3_H_

#define LSM6DS3_H_

 

#include «stm32f4xx_hal.h»

#include <string.h>

//————————————————

#define ABS(x)         (x < 0) ? (-x) : x

//————————————————

#define LD2_Pin GPIO_PIN_5

#define LD2_GPIO_Port GPIOA

#define LD2_ON HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET) //GREEN

#define LD2_OFF HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET)

//————————————————

#define LSM6DS3_ACC_GYRO_CTRL1_XL          0X10

#define LSM6DS3_ACC_GYRO_CTRL2_G          0X11

#define LSM6DS3_ACC_GYRO_CTRL3_C          0X12

#define LSM6DS3_ACC_GYRO_FIFO_CTRL5          0X0A

#define LSM6DS3_ACC_GYRO_CTRL9_XL          0X18

#define LSM6DS3_ACC_GYRO_CTRL10_C          0X19

//————————————————

#define LSM6DS3_ACC_GYRO_IF_INC_DISABLED        0x00

#define LSM6DS3_ACC_GYRO_IF_INC_ENABLED        0x04

#define LSM6DS3_ACC_GYRO_IF_INC_MASK 0x04

//————————————————

#define LSM6DS3_ACC_GYRO_BDU_CONTINUOS        0x00

#define LSM6DS3_ACC_GYRO_BDU_BLOCK_UPDATE        0x40

#define LSM6DS3_ACC_GYRO_BDU_MASK   0x40

//————————————————

#define LSM6DS3_ACC_GYRO_FIFO_MODE_BYPASS        0x00

#define LSM6DS3_ACC_GYRO_FIFO_MODE_FIFO        0x01

#define LSM6DS3_ACC_GYRO_FIFO_MODE_STREAM        0x02

#define LSM6DS3_ACC_GYRO_FIFO_MODE_STF        0x03

#define LSM6DS3_ACC_GYRO_FIFO_MODE_BTS        0x04

#define LSM6DS3_ACC_GYRO_FIFO_MODE_DYN_STREAM        0x05

#define LSM6DS3_ACC_GYRO_FIFO_MODE_DYN_STREAM_2        0x06

#define LSM6DS3_ACC_GYRO_FIFO_MODE_BTF        0x07

#define LSM6DS3_ACC_GYRO_FIFO_MODE_MASK   0x07

//————————————————

#define LSM6DS3_ACC_GYRO_ODR_XL_POWER_DOWN        0x00

#define LSM6DS3_ACC_GYRO_ODR_XL_13Hz        0x10

#define LSM6DS3_ACC_GYRO_ODR_XL_26Hz        0x20

#define LSM6DS3_ACC_GYRO_ODR_XL_52Hz        0x30

#define LSM6DS3_ACC_GYRO_ODR_XL_104Hz        0x40

#define LSM6DS3_ACC_GYRO_ODR_XL_208Hz        0x50

#define LSM6DS3_ACC_GYRO_ODR_XL_416Hz        0x60

#define LSM6DS3_ACC_GYRO_ODR_XL_833Hz        0x70

#define LSM6DS3_ACC_GYRO_ODR_XL_1660Hz        0x80

#define LSM6DS3_ACC_GYRO_ODR_XL_3330Hz        0x90

#define LSM6DS3_ACC_GYRO_ODR_XL_6660Hz        0xA0

#define LSM6DS3_ACC_GYRO_ODR_XL_13330Hz        0xB0

#define LSM6DS3_ACC_GYRO_ODR_XL_MASK        0xF0

//————————————————

#define        LSM6DS3_ACC_GYRO_ODR_G_POWER_DOWN        0x00

#define        LSM6DS3_ACC_GYRO_ODR_G_13Hz        0x10

#define        LSM6DS3_ACC_GYRO_ODR_G_26Hz        0x20

#define        LSM6DS3_ACC_GYRO_ODR_G_52Hz        0x30

#define        LSM6DS3_ACC_GYRO_ODR_G_104Hz        0x40

#define        LSM6DS3_ACC_GYRO_ODR_G_208Hz        0x50

#define        LSM6DS3_ACC_GYRO_ODR_G_416Hz        0x60

#define        LSM6DS3_ACC_GYRO_ODR_G_833Hz        0x70

#define        LSM6DS3_ACC_GYRO_ODR_G_1660Hz        0x80

#define        LSM6DS3_ACC_GYRO_ODR_G_MASK        0xF0

//————————————————

#define LSM6DS3_ACC_GYRO_FS_XL_2g        0x00

#define LSM6DS3_ACC_GYRO_FS_XL_16g        0x04

#define LSM6DS3_ACC_GYRO_FS_XL_4g        0x08

#define LSM6DS3_ACC_GYRO_FS_XL_8g        0x0C

#define        LSM6DS3_ACC_GYRO_FS_XL_MASK        0x0C

//————————————————

#define        LSM6DS3_ACC_GYRO_FS_G_245dps        0x00

#define        LSM6DS3_ACC_GYRO_FS_G_500dps        0x04

#define        LSM6DS3_ACC_GYRO_FS_G_1000dps        0x08

#define        LSM6DS3_ACC_GYRO_FS_G_2000dps        0x0C

#define        LSM6DS3_ACC_GYRO_FS_G_MASK        0x0C

//————————————————

#define        LSM6DS3_ACC_GYRO_XEN_XL_MASK        0x08

#define        LSM6DS3_ACC_GYRO_YEN_XL_MASK        0x10

#define        LSM6DS3_ACC_GYRO_ZEN_XL_MASK        0x20

#define        LSM6DS3_ACC_GYRO_XEN_XL_ENABLED        0x08

#define        LSM6DS3_ACC_GYRO_YEN_XL_ENABLED        0x10

#define        LSM6DS3_ACC_GYRO_ZEN_XL_ENABLED        0x20

//————————————————

#define        LSM6DS3_ACC_GYRO_XEN_G_DISABLED        0x00

#define        LSM6DS3_ACC_GYRO_XEN_G_ENABLED        0x08

#define        LSM6DS3_ACC_GYRO_YEN_G_DISABLED        0x00

#define        LSM6DS3_ACC_GYRO_YEN_G_ENABLED        0x10

#define        LSM6DS3_ACC_GYRO_ZEN_G_DISABLED        0x00

#define        LSM6DS3_ACC_GYRO_ZEN_G_ENABLED        0x20

#define        LSM6DS3_ACC_GYRO_XEN_G_MASK        0x08

#define        LSM6DS3_ACC_GYRO_YEN_G_MASK        0x10

#define        LSM6DS3_ACC_GYRO_ZEN_G_MASK        0x20

//————————————————

#define LSM6DS3_ACC_GYRO_OUTX_L_XL          0X28

#define LSM6DS3_ACC_GYRO_OUTX_H_XL          0X29

#define LSM6DS3_ACC_GYRO_OUTY_L_XL          0X2A

#define LSM6DS3_ACC_GYRO_OUTY_H_XL          0X2B

#define LSM6DS3_ACC_GYRO_OUTZ_L_XL          0X2C

#define LSM6DS3_ACC_GYRO_OUTZ_H_XL          0X2D

//————————————————

#define LSM6DS3_ACC_GYRO_OUTX_L_G          0X22

#define LSM6DS3_ACC_GYRO_OUTX_H_G          0X23

#define LSM6DS3_ACC_GYRO_OUTY_L_G          0X24

#define LSM6DS3_ACC_GYRO_OUTY_H_G          0X25

#define LSM6DS3_ACC_GYRO_OUTZ_L_G          0X26

#define LSM6DS3_ACC_GYRO_OUTZ_H_G          0X27

//————————————————

void Accel_Gyro_Ini(void);

void AccelGyro_Read(void);

//————————————————

#endif /* LSM6DS3_H_ */

 

 

Скопировав из другой функции, добавим в функцию GyroInit следующий код (так как здесь ничего не меняется):

        uint8_t value = 0;

        //автоувеличение адреса регистра

        value = Accel_IO_Read(0xD4,LSM6DS3_ACC_GYRO_CTRL3_C);

        value&=~LSM6DS3_ACC_GYRO_IF_INC_MASK;

        value|=LSM6DS3_ACC_GYRO_IF_INC_ENABLED;

        Accel_IO_Write(0xD4,LSM6DS3_ACC_GYRO_CTRL3_C,value);

        //установим бит BDU

        value = Accel_IO_Read(0xD4,LSM6DS3_ACC_GYRO_CTRL3_C);

  value &= ~LSM6DS3_ACC_GYRO_BDU_MASK;

        value|=LSM6DS3_ACC_GYRO_BDU_BLOCK_UPDATE;

        Accel_IO_Write(0xD4,LSM6DS3_ACC_GYRO_CTRL3_C,value);

        //выбор режима FIFO

        value = Accel_IO_Read(0xD4,LSM6DS3_ACC_GYRO_FIFO_CTRL5);

        value&=~LSM6DS3_ACC_GYRO_FIFO_MODE_MASK;

        value|=LSM6DS3_ACC_GYRO_FIFO_MODE_BYPASS;

        Accel_IO_Write(0xD4,LSM6DS3_ACC_GYRO_FIFO_CTRL5,value);

 

Так как в коде ничего не изменилось, объяснение не требуется.

Теперь добавим следующий код сюда же:

 

        Accel_IO_Write(0xD4,LSM6DS3_ACC_GYRO_FIFO_CTRL5,value);

        //пока выключим датчик (ODR_XL = 0000)

        value = Accel_IO_Read(0xD4,LSM6DS3_ACC_GYRO_CTRL2_G);

        value&=~LSM6DS3_ACC_GYRO_ODR_G_MASK;

        value|=LSM6DS3_ACC_GYRO_ODR_G_POWER_DOWN;

        Accel_IO_Write(0xD4,LSM6DS3_ACC_GYRO_CTRL2_G,value);

 

В данном коде мы работаем с регистром CTRL2_G (адрес 0X11), который предназначен только для работы только с гироскопом, с его битами, отвечающим за частоту снятия данных именно с гироскопа

 

image06

 

Пока мы здесь отключаем датчик (все биты выставляем в 0).

 

image05

 

Дальше добавим следующий код

 

        Accel_IO_Write(0xD4,LSM6DS3_ACC_GYRO_CTRL2_G,value);

        //Full scale selection 500 dps

        value = Accel_IO_Read(0xD4,LSM6DS3_ACC_GYRO_CTRL2_G);

        value&=~LSM6DS3_ACC_GYRO_FS_G_MASK;

        value|=LSM6DS3_ACC_GYRO_FS_G_500dps;

        Accel_IO_Write(0xD4,LSM6DS3_ACC_GYRO_CTRL2_G,value);

 

Дальше мы работаем с тем же регистром, только с другими битами, отвечающими за максимально измеряемую датчиком угловую скорость относительно оси. Думаю, нам достаточно 500 градусов в секунду, быстрее мы не разгонимся.

 

image08

 

Пишем код дальше

 

        Accel_IO_Write(0xD4,LSM6DS3_ACC_GYRO_CTRL2_G,value);

        //Включим оси

        value = Accel_IO_Read(0xD4,LSM6DS3_ACC_GYRO_CTRL10_C);

        value&=~(LSM6DS3_ACC_GYRO_XEN_G_ENABLED|\

                                         LSM6DS3_ACC_GYRO_YEN_G_ENABLED|\

                                         LSM6DS3_ACC_GYRO_ZEN_G_ENABLED);

        value|=(LSM6DS3_ACC_GYRO_XEN_G_MASK|\

                                  LSM6DS3_ACC_GYRO_YEN_G_MASK|\

                                  LSM6DS3_ACC_GYRO_ZEN_G_MASK);

        Accel_IO_Write(0xD4,LSM6DS3_ACC_GYRO_CTRL10_C,value);

 

Как и указано в комментарии, здесь мы включаем оси гироскопа. Включим мы все 3 оси

 

image07

 

Продолжаем писать исходный код

 

        Accel_IO_Write(0xD4,LSM6DS3_ACC_GYRO_CTRL10_C,value);

        //Включим Data Rate 833 Гц

        value = Accel_IO_Read(0xD4,LSM6DS3_ACC_GYRO_CTRL2_G);

        value&=~LSM6DS3_ACC_GYRO_ODR_G_MASK;

        value|=LSM6DS3_ACC_GYRO_ODR_G_833Hz;

        Accel_IO_Write(0xD4,LSM6DS3_ACC_GYRO_CTRL2_G,value);

 

Здесь мы включили частоту снятия показаний 833 Гц. Также работаем мы с вышеупомянутым 2 регистром.

 

image01

 

Фильтры сегодня не используем, т.к. в данном датчике и так организована неплохая фильтрация

На этом Инициализацию можно считать завершенной.

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

 

В следующей части урока мы напишем все функции по сбору данных и отправке их в порт USART и проверим данный функционал на практике.

 

 

Предыдущий урок Программирование МК STM32 Следующая часть

 

Техническая документация на датчик

Техническая документация на плату расширения

Программа Hyper Terminal

Программа NS Port Monitor

Программа NS Mag Visual

 

 

Отладочную плату можно приобрести здесь Nucleo STM32F401RE

Оценочную плату X-NUCLEO-IKS01A1 можно приобрести здесь STM32 X-NUCLEO-IKS01A1

Оценочную плату STEVAL-MKI160V1 можно приобрести здесь STEVAL-MKI160V1

 

 

Смотреть ВИДЕОУРОК

 

 

STM32 Подключаем гироскоп LSM6DS3 

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*