STM Урок 52. Датчик давления LPS25HB. Часть 3



Урок 52

 

Часть 3

 

Датчик давления LPS25HB

 

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

Функцию Mag_Read также переименуем в Press_Read

 

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

void Press_Read(void)

{

 

Исправим это и в вызовах в main.c: и в обработчике и в бесконечном цикле, а в бесконечном цикле заодно и раскомментируем

 

  /* USER CODE BEGIN 3 */

                Press_Read();

                //Press_Read();

                HAL_UART_Receive_IT(&huart2,(uint8_t*)str,8);

 

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

 

void Press_Read(void)

{

        float temper;

        Press_Get_Temp(&temper);

        sprintf(str1,»TEMP:%06frn», temper);

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

        /*

        buf2[0]=0x11;

        buf2[1]=0x55;

        buf2[2]=(uint8_t)(val[0]>>8);

        buf2[3]=(uint8_t)val[0];

        buf2[4]=(uint8_t)(val[1]>>8);

        buf2[5]=(uint8_t)val[1];

        buf2[6]=(uint8_t)(val[2]>>8);

        buf2[7]=(uint8_t)val[2];

        HAL_UART_Transmit(&huart2,buf2,8,0×1000);

        */

        HAL_Delay(200);

}

 

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

 

image15

 

Также нам будет необходима функция считывания показаний давления из датчика.

Скопируем функцию Press_Get_Temp, вставим её ещё раз в код и исправим ей имя

 

void Press_Get_Press (float* pData)

{

 

Начнём вносить в неё изменения.

 

 

Так как у нас датчик давления 24-битный, то для считывания в нём используются 3 регистра

 

image16 image17

 

Поэтому использовать мы будем 3 элемента буфера и 32-битные величины для расчёта, одну переменную удалим, т.к. расчётов будет меньше ввиду отсутствия сдвига

 

void Press_Get_Press (float* pData)

{

        uint8_t i;

        int32_t raw_data=0;

        buffer[0]=Press_IO_Read(LPS25HB_ADDRESS,LPS25HB_PRESS_OUT_XL_REG);

        buffer[1]=Press_IO_Read(LPS25HB_ADDRESS,LPS25HB_PRESS_OUT_L_REG);

        buffer[2]=Press_IO_Read(LPS25HB_ADDRESS,LPS25HB_PRESS_OUT_H_REG);

        for(i = 0; i < 3; i++)        raw_data |= (((uint32_t)buffer[i]) << (8 * i));

        *pData = ( float ) raw_data / 4096.0f;

}

 

Для расчёта мы также пользуемся технической документацией

 

image18 image19

 

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

 

        float temper, press;

        Press_Get_Temp(&temper);

        Press_Get_Press(&press);

        sprintf(str1,»TEMP:%06f; PRESS:%06frn», temper, press);

 

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

 

image20

 

 

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

 

uint8_t buf2[14]={0};

char str1[100]={0};

 

А теперь код

 

        float temper, press, patm, pmmhg;

        Press_Get_Temp(&temper);

        Press_Get_Press(&press);

        patm = press/1010;

        pmmhg = press/1.333f;

        sprintf(str1,»TEMP:%06f; PRESS:%06f mbar; %06f atm; %06f mm Hgrn», temper, press, patm, pmmhg);

 

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

 

image21

 

Теперь уберём шум, которого и так почти нет за счёт того, что он уже убран. По температуре его вообще нет, очень хорошо работает внутренний фильтр датчика, а по давлению он незначителен. Ну давайте всё же применим скользящее среднее. Только применять его будет целесообразнее в низкоуровневых функциях, так как уже преобразованное значение в значение с плавающей точкой тяжелее фильтровать и фильтр задействует больше аппаратных ресурсов, что не хотелось бы вовсе. С температурой будет проще, так как величина 16-битная, а вот с давлением нужна будет другая функция из-за того, что используется значение 24-битное. Но мы пойдём другим путём и просто подправим нашу функцию усреднения значений в универсальную, просто сделав её 32-битной.

Для этого, во-первых, исправим входной аргумент, сделаем его не адресом а обычной переменной, но тогда появится и возвращаемое значение

 

int32_t  MovingAverage(int32_t* dt)

 

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

 

//буфер для скользящего среднего

volatile int32_t buf_avg[8]={0};

 

Данную переменную также сделаем обычной, не массивом

 

//сумма для среднего арифметичесого

volatile int64_t tmp64;

 

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

 

int32_t MovingAverage(int32_t dt)

{

        int32_t dt_ret;

 

Вот вся функция с исправлениями

 

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

int32_t MovingAverage(int32_t dt)

{

        int32_t dt_ret=0;

        if(avg_cnt<8)

        {

                buf_avg[avg_cnt]=dt;

                if(avg_cnt==7)

                {

                        tmp64=buf_avg[7]+buf_avg[6]+buf_avg[5]+buf_avg[4]+

                                                         buf_avg[3]+buf_avg[2]+buf_avg[1]+buf_avg[0];

                        dt_ret=tmp64/8;

                }

                avg_cnt++;

        }

        else

        {

                //вычтем из общей суммы первый (самые старый) элемент

                tmp64-=buf_avg[0];

                //сдвинем буфер на 1 элемент

                memcpy((void*)buf_avg,(void*)(buf_avg+1),sizeof(int32_t)*7);

                //заменим 7 элемент на новый

                buf_avg[7]=dt;

                //прибавим новый элемент

                tmp64+=dt;

                //обновим среднее значение

                dt_ret=tmp64/8;

        }

        return dt_ret;

}

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

 

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

 

 

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

 

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

LPS25HB Datasheet

LPS25HB Technical note

Программа Hyper Terminal

Программа NS Port Monitor для значений с плавающей точкой

 

 

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

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

 

 

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

 

STM32 Датчик давления LPS25HB

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

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

*