Урок 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.
Сгенерируем проект, откроем его. Настроим программатор на авторезет. Добавим файл 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), который предназначен только для работы только с гироскопом, с его битами, отвечающим за частоту снятия данных именно с гироскопа
Пока мы здесь отключаем датчик (все биты выставляем в 0).
Дальше добавим следующий код
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 градусов в секунду, быстрее мы не разгонимся.
Пишем код дальше
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 оси
Продолжаем писать исходный код
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 регистром.
Фильтры сегодня не используем, т.к. в данном датчике и так организована неплохая фильтрация
На этом Инициализацию можно считать завершенной.
Соберем код, прошьем контроллер и убедимся, что зеленый светодиод у нас светится.
В следующей части урока мы напишем все функции по сбору данных и отправке их в порт USART и проверим данный функционал на практике.
Предыдущий урок Программирование МК STM32 Следующая часть
Техническая документация на датчик
Техническая документация на плату расширения
Отладочную плату можно приобрести здесь Nucleo STM32F401RE
Оценочную плату можно приобрести здесь STM32 X-NUCLEO-IKS01A1
Приобрести платы с датчиком LSM6DS3 можно у следующих продавцов:
Надёжный продавец LSM6DS33 STEVAL-MKI160V1
Здесь дешевле LSM6DS33 STEVAL-MKI160V1
Здесь другая плата, намного дешевле, но от другого разработчика LSM6DS33
Смотреть ВИДЕОУРОК
Добавить комментарий