STM Урок 55. Датчик влажности HTS221. Часть 1



    Урок 55

 

Часть 1

 

Датчик влажности HTS221

 

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

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

Данный датчик установлен на плате расширения X-NUCLEO-IKS01A1, предназначенной для работы с отладочной платой Nucleo. Мы будем подключать данную оценочную плату к плате Nucleo STM32F401RE. Выполнен данный датчик также с использованием технологии MEMS.

        Этот датчик влажности также наряду с интерфейсом I2C может подключаться и с использованием интерфейса SPI. Но мы будем использовать подключение именно по привычному I2C.

Датчик имеет следующие технические характеристики:

        Диапазон показаний относительной влажности 0 – 100 %;

        Диапазон показаний температуры -40 – +120 °С

        Разрешение – 16 бит;

Чувствительность по давлению 0.004 %rH/LSB или 256  LSB/%rH.

Чувствительность по температуре 0.016 °C/LSB или 64 LSB/°C.

Точность показаний давления ±3.5% rH при 20 – 80% rH и ±5% rH при 0 – 100% rH.

Точность показаний температуры ±0.5 °C при 15 – 40 °C и ±1 °C при 0 – 60 °C

Среднеквадратичное значение уровня шума (RMS noise) – 0,03 по давлению и 0,07 по температуре;

Частота измерений 1 – 12,5 Гц.

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

Проект мы создадим из проекта прошлого занятия, в котором мы работали с датчиком давления, установленном на этой же плате расширения – из проекта Press_ LPS25HB, только назовём мы данный проект теперь соответственно Humidity_HTS221.

Файлы lps25hb.c и lps25hb.h соответственно переименуем в hts221.c и hts221.h.

Запустим проект Cube MX. Убедимся, что скорость USART установлена в 115200 bps

 

image00

 

Больше ничего не трогаем. Сгенерируем проект, откроем его. Настроим программатор на авторезет и отключим оптимизацию. Добавим файл hts221.c. Скомпилируем проект.

По причине переименования файлов у нас будут ошибки. Для устранения данных ошибок мы исправим подключение заголовочных файлов в main.c и в hts221.с

 

#include «stm32f4xx_hal.h»

#include «hts221.h»

 

#include «hts221.h»

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

 

В обработчике прерываний от таймера закомментируем вызов функции считывания данных и отправки их в USART.

 

 

В бесконечном цикле он у нас уже закомментирован

 

        //Press_Read();

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

 

В файле hts221.h удалим весь код и скопируем туда для экономии драгоценного времени заранее подготовленный код со всеми макросами и переменными из файла macro.txt

 

#ifndef HTS221_H_

#define HTS221_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        HTS221_ADDRESS        0xBE

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

#define        HTS221_WHO_AM_I_REG        0x0F

#define        HTS221_CTRL_REG1        0x20

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

#define        HTS221_WHO_AM_I_VAL        0xBC

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

#define        HTS221_PD_ACTIVE_MODE        0x80

#define        HTS221_PD_POWERDOWN_MODE        0x00

#define        HTS221_PD_MASK        0x80

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

#define        HTS221_ODR_ONE_SHOT        0x00

#define        HTS221_ODR_1HZ        0x01

#define        HTS221_ODR_7HZ        0x02

#define        HTS221_ODR_12_5HZ        0x03

#define        HTS221_ODR_MASK        0x03

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

#define        LPS25HB_DIFF_EN_ENABLE        0x08

#define        LPS25HB_DIFF_EN_DISABLE        0x00

#define        LPS25HB_DIFF_EN_MASK        0x08

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

#define        HTS221_BDU_DISABLE        0x00

#define        HTS221_BDU_ENABLE        0x04

#define        HTS221_BDU_MASK        0x04

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

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

#define HTS221_HR_OUT_L_REG        0x28

#define HTS221_HR_OUT_H_REG        0x29

#define        HTS221_H0_RH_X2        0x30

#define        HTS221_H1_RH_X2        0x31

#define        HTS221_T0_DEGC_X8        0x32

#define        HTS221_T1_DEGC_X8        0x33

#define        HTS221_T0_T1_DEGC_H2        0x35

#define        HTS221_H0_T0_OUT_L        0x36

#define        HTS221_H0_T0_OUT_H        0x37

#define        HTS221_H1_T0_OUT_L        0x3A

#define        HTS221_H1_T0_OUT_H        0x3B

#define        HTS221_T0_OUT_L        0x3C

#define        HTS221_T0_OUT_H        0x3D

#define        HTS221_T1_OUT_L        0x3E

#define        HTS221_T1_OUT_H        0x3F

#define HTS221_TEMP_OUT_L_REG        0x2A

#define HTS221_TEMP_OUT_H_REG        0x2B

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

void Humidity_Ini(void);

void Humidity_Read(void);

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

#endif /* HTS221_H_ */

 

Функцию Press_Ini переименуем в Humidity_Ini в файлах main.c и в hts221.с

 

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

void Humidity_Ini(void)

{

 

        Humidity_Ini();

  /* USER CODE END 2 */

 

Также исправим функцию Press_Read в Humidity_Read()в файлах main.c и в hts221.с, в файле main.c она должна быть закомментирована

 

void Humidity_Read(void)

{  

 

/* USER CODE BEGIN 3 */

  //Humidity_Read();

 

Следующая задача у нас – написать код инициализации датчика. И, как всегда, по сложившейся традиции, раз уж у нас подключение именно по шине I2C, начинаем мы её, конечно же, со считывания идентификатора микросхемы.

Исходя из подключения микросхемы, адрес мы выбираем 0xBE

 

image02

 

Регистр для чтения идентификатора используем WHO_AM_I (0Fh)

 

image01

 

В данной таблице мы также видим, переведя двоичный код в шестнадцатеричный, что идентификатор должен быть равен именно 0xBC.

 

 

Функцию Press_ReadID переименуем в Humidity_ReadID и в реализации, и в вызове

 

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

uint8_t Humidity_ReadID(void)

{

 

        HAL_Delay(1000);

        if(Humidity_ReadID()==LPS25HB_WHO_AM_I) LD2_ON;

 

Аналогичным образом поступим и с функциями Press_IO_Read и Press_IO_Write

 

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

uint8_t Humidity_IO_Read(uint16_t DeviceAddr, uint8_t RegisterAddr)

{

 

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

void Humidity_IO_Write(uint16_t DeviceAddr, uint8_t RegisterAddr, uint8_t Value)

{

 

Также подправим код в функции чтения идентификатора

 

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

uint8_t Press_ReadID(void)

{

        uint8_t ctrl = 0x00;

        ctrl = Humidity_IO_Read(HTS221_ADDRESS,HTS221_WHO_AM_I_REG);

        return ctrl;

}

 

Исправим код в главной функции инициализации

 

        HAL_Delay(1000);

        if(Humidity_ReadID()==HTS221_WHO_AM_I_VAL) LD2_ON;

 

В функциях, которые мы пока не используем, закомментируем весь код, облачив его вот в такие теги /* */.

Также закомментируем в инициализации вот это

 

        else Error();

//LD2_OFF;

//PressInit(ctrl);

//LD2_ON;

 

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

Если всё нормально, то продолжаем инициализацию.

Переименуем функцию PressInit в HumidityInit.

 

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

void HumidityInit(uint16_t InitStruct)

{

 

Также исправим и раскомментируем вызов данной функции в главной функции инициализации датчика

 

        LD2_OFF;

        HumidityInit(ctrl);

        LD2_ON;

 

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

 

        uint8_t value = 0;

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

        value = Humidity_IO_Read(HTS221_ADDRESS,HTS221_CTRL_REG1);

        value&=~HTS221_PD_MASK;

        value|=HTS221_PD_POWERDOWN_MODE;

        Humidity_IO_Write(HTS221_ADDRESS,HTS221_CTRL_REG1,value);

        /*

 

Здесь мы используем регистр CTRL_REG1 (20h) и сбросим там бит PD с целью пока выключить датчик

 

image04

 

Пишем код дальше

 

//Enable BDU

        value = Humidity_IO_Read(HTS221_ADDRESS,HTS221_CTRL_REG1);

        value&=~HTS221_BDU_MASK;

        value|=HTS221_BDU_ENABLE;

        Humidity_IO_Write(HTS221_ADDRESS,HTS221_CTRL_REG1,value);

 

У нас тот же регистр CTRL_REG1 (20h). Устанавливаем мы в нем теперь бит, отвечающий за включение BDU (Block data update). С данным режимом мы с вами уже хорошо знакомы

 

image03

 

Идём дальше

 

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

        value = Humidity_IO_Read(HTS221_ADDRESS,HTS221_CTRL_REG1);

        value&=~HTS221_ODR_MASK;

        value|=HTS221_ODR_12_5HZ;

        Humidity_IO_Write(HTS221_ADDRESS,HTS221_CTRL_REG1,value);

 

Здесь мы используем тот же регистр CTRL_REG1 (20h) и устанавливаем там биты, отвечающие за частоту считывания показаний, которую выставим максимальную

 

image06

 

И последнее:

 

//теперь включим датчик (PD = 1)

        value = Humidity_IO_Read(HTS221_ADDRESS,HTS221_CTRL_REG1);

        value&=~HTS221_PD_MASK;

        value|=HTS221_PD_ACTIVE_MODE;

        Humidity_IO_Write(HTS221_ADDRESS,HTS221_CTRL_REG1,value);

 

Здесь мы битом 1 регистра переведём датчик в активный режим, то есть включим его

 

image05

 

На этом инициализация закончена.

Соберём код, прошьём контроллер и проверим, не погаснет ли у нас светодиод.

Если всё нормально, то начнём писать код считывания показаний с датчика

Сначала напишем функцию считывания показаний температуры

Функцию Press_Get_Temp переименуем в Humidity_Get_Temp, также добавим некоторые переменные и передвинем комментарий ниже

 

void Humidity_Get_Temp(float* pData)

{

        uint8_t btnstat;

  int16_t T0_degC, T1_degC;

  int16_t T0_out, T1_out, T_out, T0_degC_x8_u16, T1_degC_x8_u16;

        uint8_t buffer[4], tmp;

        /*

 

Также подправим имя функции и в её вызове в функции Humidity_Read

 

        Humidity_Get_Temp(&temper);

 

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

Считаем в буфер сначала регистры T0_degC_x8 и T1_degC_x8

 

        uint8_t buffer[4], tmp;

        buffer[0]=Humidity_IO_Read(HTS221_ADDRESS,HTS221_T0_DEGC_X8);

        buffer[1]=Humidity_IO_Read(HTS221_ADDRESS,HTS221_T1_DEGC_X8);

 

Вот эти регистры

 

image08

 

Произведём некоторые расчёты

 

        buffer[1]=Humidity_IO_Read(HTS221_ADDRESS,HTS221_T1_DEGC_X8);

        tmp = Humidity_IO_Read(HTS221_ADDRESS,HTS221_T0_T1_DEGC_H2);

 

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

 

 

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

 

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

HTS221 Datasheet

HTS221 Interpreting humidity and temperature readings

Программа Hyper Terminal

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

 

 

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

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

 

 

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

 

STM32 Датчик влажности HTS221

5 комментариев на “STM Урок 55. Датчик влажности HTS221. Часть 1
  1. sab:

    подскажите , как подключить два HTS221 по i2c, что бы последовательно считывать данные?

  2. sab:

    Подскажите как считывать данные с  двух HTS221 по i2c ?

  3. Анас:

    Это не гироскоп, а гигроскоп

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

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

*