STM Урок 42. Подключаем акселерометр LSM6DS0. Часть 2

Урок 42

 

Часть 2

 

Подключаем акселерометр LSM6DS0

 

В предыдущей части нашего урока мы ознакомились с документацией на датчик, создали для него проект, добавили некоторые макросы и настроили библиотечные файлы, также написали функцию считывания идентификатора акселерометра и начали писать функцию инициализации датчика.

Продолжим писать код в функции AccInit

 

uint8_t value=0;

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

value = Accel_IO_Read(0xD6, LSM6DS0_ACC_GYRO_CTRL_REG8);

value &= ~LSM6DS0_ACC_GYRO_BDU_MASK;

value |= LSM6DS0_ACC_GYRO_BDU_ENABLE;

Accel_IO_Write(0xD6, LSM6DS0_ACC_GYRO_CTRL_REG8, value);//пока выключим датчик (ODR_XL = 000)

 

image14

 

В данном регистре мы включим бит 6 – BDU, который отвечает за защиту старшего байта данных от изменения в том случае если еще не считан младший

 

image15

 

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

 

Accel_IO_Write(0xD6, LSM6DS0_ACC_GYRO_CTRL_REG8, value);

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

value = Accel_IO_Read(0xD6, LSM6DS0_ACC_GYRO_CTRL_REG6_XL);

value &= ~LSM6DS0_ACC_GYRO_ODR_XL_MASK;

value |= LSM6DS0_ACC_GYRO_ODR_XL_POWER_DOWN;

Accel_IO_Write(0xD6, LSM6DS0_ACC_GYRO_CTRL_REG6_XL, value);

 

image16

 

В данном регистре мы сначала включим режим пониженного энергопотребления.

 

image17

 

Продолжим работу с управляющими битами дальше

 

Accel_IO_Write(0xD6, LSM6DS0_ACC_GYRO_CTRL_REG6_XL, value);

//Full scale selection 2G

value = Accel_IO_Read(0xD6, LSM6DS0_ACC_GYRO_CTRL_REG6_XL);

value &= ~LSM6DS0_ACC_GYRO_FS_XL_MASK;

value |= LSM6DS0_ACC_GYRO_FS_XL_2g;

Accel_IO_Write(0xD6, LSM6DS0_ACC_GYRO_CTRL_REG6_XL, value);

 

 

Работаем с тем же регистром 6, только настраиваем мы уже биты, отвечающие за максимальное ускорение. Выставим, как обычно 2g. Для этого нам не нужно включать 3 и 4 биты регистра.

 

image18

 

Продолжим дальше

 

Accel_IO_Write(0xD6, LSM6DS0_ACC_GYRO_CTRL_REG6_XL, value);

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

value = Accel_IO_Read(0xD6, LSM6DS0_ACC_GYRO_CTRL_REG5_XL);

        

value &= ~(LSM6DS0_ACC_GYRO_XEN_XL_MASK |

                                                 LSM6DS0_ACC_GYRO_YEN_XL_MASK |

                                                 LSM6DS0_ACC_GYRO_ZEN_XL_MASK);

value |= (LSM6DS0_ACC_GYRO_XEN_XL_ENABLE |

                                                LSM6DS0_ACC_GYRO_YEN_XL_ENABLE |

                                                LSM6DS0_ACC_GYRO_ZEN_XL_ENABLE);

Accel_IO_Write(0xD6, LSM6DS0_ACC_GYRO_CTRL_REG5_XL, value);

 

Работаем мы теперь с регистром 5

 

image19

 

Здесь мы включим использование всех трёх осей акселерометра

 

image20

 

Продолжим дальше писать функцию инициализации

 

Accel_IO_Write(0xD6, LSM6DS0_ACC_GYRO_CTRL_REG5_XL, value);

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

value = Accel_IO_Read(0xD6, LSM6DS0_ACC_GYRO_CTRL_REG6_XL);

value &= ~LSM6DS0_ACC_GYRO_ODR_XL_MASK;

value |= LSM6DS0_ACC_GYRO_ODR_XL_119Hz;

Accel_IO_Write(0xD6, LSM6DS0_ACC_GYRO_CTRL_REG6_XL, value);

}

 

Здесь мы снова возвращаемся к регистру 6 и включаем скорость (частоту измерений) 119 Гц

 

image21

 

 

Функция инициализации закончена. Теперь в основной функции перед вызовом функции AccInit потушим светодиод, а после вызова зажжем, чтобы убедиться что у нас нигде ничего не подвисло.

 

        else Error();

        LD2_OFF;

        AccInit(ctrl);

        LD2_ON;

 

Соберем код, прошьём МК и посмотрим результат.

Теперь будем писать код в функцию считывания данных с датчика Accel_GetXYZ

 

        uint8_t i=0;

        buffer[0] = Accel_IO_Read(0xD6,LSM6DS0_ACC_GYRO_OUT_X_L_XL);

        buffer[1] = Accel_IO_Read(0xD6,LSM6DS0_ACC_GYRO_OUT_X_H_XL);

        buffer[2] = Accel_IO_Read(0xD6,LSM6DS0_ACC_GYRO_OUT_Y_L_XL);

        buffer[3] = Accel_IO_Read(0xD6,LSM6DS0_ACC_GYRO_OUT_Y_H_XL);

        buffer[4] = Accel_IO_Read(0xD6,LSM6DS0_ACC_GYRO_OUT_Z_L_XL);

        buffer[5] = Accel_IO_Read(0xD6,LSM6DS0_ACC_GYRO_OUT_Z_H_XL);

 

Здесь мы считываем данные из регистров 0X28 — 0X2D, отвечающие за хранение считанных ускорений с осей – соответственно младших и старших байтов.

Затем в цикле занесем считанные байты уже двухбайтовыми величинами в соответствующий буфер

 

for(i=0;i<3;i++)

{

    pData[i] = ((int16_t)((uint16_t)buffer[2*i+1]<<8)+buffer[2*i]);

}

 

Перейдем в функцию Accel_ReadAcc, которую мы затем вызовем в бесконечном цикле в main(). Закомментируем пока там строки, связанные с USART и зажжем светодиод в случае превышения значения по оси X

 

//        sprintf(str1,»X:%06d Y:%06d Z:%06drn», xval, yval, zval);

//        HAL_UART_Transmit(&huart2, (uint8_t*)str1,strlen(str1),0x1000);

//        buf2[0]=0x12;

//        buf2[1]=0x10;

//        buf2[2]=(uint8_t)(xval>>8);

//        buf2[3]=(uint8_t)xval;

//        buf2[4]=0x10;

//        buf2[5]=0x10;

//        buf2[6]=(uint8_t)(zval>>8);

//        buf2[7]=(uint8_t)zval;

//        buf2[8]=0x13;

//        HAL_UART_Transmit(&huart2,buf2,9,0×1000);

        if(xval>1500)

        {

                                LD2_ON;

        }

        else

        {

                                LD2_OFF;

        }

        HAL_Delay(20);

 

Вызовем данную функцию в бесконечном цикле

 

  /* USER CODE BEGIN 3 */

                Accel_ReadAcc();

  }

 

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

Если всё работает, то попытаемся считать уже точные данные через терминальную программу, раскомментировав код в функции Accel_ReadAcc, а также немного исправив, так как у нас подключен DMA.

 

sprintf(str1,»X:%06d Y:%06d Z:%06drn», xval, yval, zval);

HAL_UART_Transmit_DMA(&huart2, (uint8_t*)str1,strlen(str1));

 

Соберем код, прошьем контроллер, запустим монитор порта из программы arduino-nightly и посмотрим результат

 

image08

 

Зайдем в Cube MX и в настройках USART вместо 256000 включим 512000.

 

image06

 

Перегенерируем проект, соберем его и внесем еще некоторые изменения в код функции Accel_ReadAcc, опять закомментировав код вывода на терминал. Раскомментируем и внесем изменения в код вывода в программу визуализации. Программу будем использовать NS Port Monitor, поэтому код составим в соответствии с требованиями протокола данной программы (первые байты 0x11 и 0x55).

 

//        sprintf(str1,»X:%06d Y:%06d Z:%06drn», xval, yval, zval);

//        HAL_UART_Transmit_DMA(&huart2, (uint8_t*)str1,strlen(str1));

        buf2[0]=0x11;

        buf2[1]=0x55;

        buf2[2] = (uint8_t) (xval >> 8);

        buf2[3] = (uint8_t) xval;

        buf2[4] = (uint8_t) (yval >> 8);

        buf2[5] = (uint8_t) yval;

        buf2[6] = (uint8_t) (zval >> 8);

        buf2[7] = (uint8_t) zval;

        HAL_UART_Transmit_DMA(&huart2,buf2,8);

        if(xval>1500)

 

Соберем проект, прошьем контроллер, запустим программу и проверим результат на практике (нажмите на картинку для увеличения изображения)

 

image12_0500

 

 

 

Исходный код

 

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

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

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

 

 

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

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

 

 

Смотреть ВИДЕОУРОК в RuTube (нажмите на картинку)

STM32 Подключаем акселерометр LSM6DS0

 

Смотреть ВИДЕОУРОК в YouTube (нажмите на картинку)

STM32 Подключаем акселерометр LSM6DS0

 

1 комментарий к “STM Урок 42. Подключаем акселерометр LSM6DS0. Часть 2

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

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

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

*