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

 

 

 

Урок 52

 

Часть 4

 

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

 

 

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

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

 

void Press_Get_Press (float* pData)

{

        uint8_t btnstat;

 

И добавим опрос кнопки и применим фильтр

 

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

        btnstat=HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13);

        //Если кнопка не нажата,

        //то вызовем фильтр скользящего среднего

        if(btnstat!=0)        raw_data = MovingAverage(raw_data);

        *pData = ( float )raw_data / 4096.0f;

 

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

А теперь по порядку.

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

 

//счётчик наполнения буферов скользящего среднего

volatile int8_t avg_cnt;

volatile int8_t avg_cnt_temp;

 

Добавим локальные переменные в функцию

 

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

int32_t MovingAverage(int32_t dt)

{

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

static int32_t buf_avg[8]={0};

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

static int64_t tmp64;        int32_t dt_ret=0;

        if(avg_cnt<8)

 

Скопируем и исправим функцию фильтра

 

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

int32_t MovingAverageTemp(int32_t dt)

{

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

static int32_t buf_avg[8]={0};

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

static int64_t tmp64;        int32_t dt_ret=0;

        if(avg_cnt_temp<8)

        {

                buf_avg[avg_cnt_temp]=dt;

                if(avg_cnt_temp==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_temp++;

        }

        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;

}

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

 

 

Вызовем функцию фильтра в функции чтения температуры

 

void Press_Get_Temp (float* pData)

{

        uint8_t btnstat;

        int16_t raw_data=0,tmp_data=0;

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

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

        raw_data = (((uint16_t)buffer[1]) << 8) + (uint16_t)buffer[0];

        btnstat=HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13);

        //Если кнопка не нажата,

        //то вызовем фильтр скользящего среднего

        if(btnstat!=0)        raw_data = MovingAverageTemp(raw_data);

        tmp_data = raw_data / 48 + 425;

        *pData = ( float )tmp_data / 10.0f;

}

 

Ну и инициализация

 

        //инициализируем счетчики заполнения скользящего среднего

        avg_cnt=0;

        avg_cnt_temp=0;

        HAL_Delay(1000);

 

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

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

 

  /* USER CODE BEGIN 3 */

                //Press_Read();

  }

                if(huart2.RxXferCount==0)

                {

                        Press_Read();

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

 

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

 

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

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

        uint8_t *t = (uint8_t *)&temper;

        uint8_t *p = (uint8_t *)&press;

        buf2[0]=0x11;

        buf2[1]=0x55;

        buf2[2]=(uint8_t)(*(uint32_t*)t);

        buf2[3]=(uint8_t)((*(uint32_t*)t)>>8);

        buf2[4]=(uint8_t)((*(uint32_t*)t)>>16);

        buf2[5]=(uint8_t)((*(uint32_t*)t)>>24);

        buf2[6]=(uint8_t)(*(uint32_t*)p);

        buf2[7]=(uint8_t)((*(uint32_t*)p)>>8);

        buf2[8]=(uint8_t)((*(uint32_t*)p)>>16);

        buf2[9]=(uint8_t)((*(uint32_t*)p)>>24);

        HAL_UART_Transmit(&huart2,buf2,10,0x1000);

        //HAL_Delay(200);

}

 

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

 

image08_0500

 

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

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

 

image11_0500

 

Здесь уже конечно разница очевидна. Первые и последние пять клеточек – это с фильтром скользящего среднего, а средние пять клеточек – это без фильтра. Так что применение фильтра даёт свои результаты.

 

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

 

Исходный код

 

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

LPS25HB Datasheet

LPS25HB Technical note

Программа Hyper Terminal

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

 

 

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

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

 

 

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

 

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

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

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

*