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

 

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

 

Исходный код

 

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

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

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

 

 

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

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

 

 

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

 

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

 

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

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

*