L14-Click 1.0
STM32WLE5CC LoRaWAN Sensor Platform
Loading...
Searching...
No Matches
bar_bmp585.c
Go to the documentation of this file.
1/*
2 * bar_bmp585.c
3 *
4 * Created on: 16. 2. 2026
5 * Author: Milan
6 */
7
8#include "bar_bmp585.h"
9
10#ifdef SENSOR_BAR_BMP585
11
12#include "i2c.h"
13#include "utils/mydefs.h"
14#include "mymems.h"
15#include "mysensors_base.h"
16#include <stdio.h>
17#include <math.h>
18#include "tmphm_sht45.h" // because of formula to sea level
19
20// BMP585 I2C Address (SDO connected to GND by default)
21#define BMP585_I2C_ADDR (0x46 << 1)
22
23// Register Map
24#define REG_CHIP_ID 0x01
25#define REG_STATUS 0x28
26#define REG_DATA_0 0x20 // Pressure data start
27#define REG_DATA_1 0x21
28#define REG_DATA_2 0x22
29#define REG_TEMP_DATA_0 0x1D // Temperature data start
30#define REG_TEMP_DATA_1 0x1E
31#define REG_TEMP_DATA_2 0x1F
32#define REG_OSR_CONFIG 0x36
33#define REG_ODR_CONFIG 0x37
34#define REG_INT_CONFIG 0x38
35#define REG_IF_CONFIG 0x39
36#define REG_CMD 0x7E
37
38// Chip ID value
39#define BMP585_CHIP_ID 0x50
40
41// Power modes
42#define BAR_MODE_STANDBY 0x00
43#define BAR_MODE_NORMAL 0x01
44#define BAR_MODE_FORCED 0x02
45#define BAR_MODE_DEEP_SLEEP 0x00 // Deep sleep is achieved via standby with specific config
46
49static uint8_t _isBarometer = 0;
50
51/**
52 * @brief Check if sensor is turned on
53 */
54static HAL_StatusTypeDef bar_bmp585_IsOn(I2C_HandleTypeDef *hi2c, uint8_t *onOff)
55{
56 HAL_StatusTypeDef status = HAL_ERROR;
57
58 if (_isBarometer)
59 {
60 // Reading power control register
61 uint8_t pwr_ctrl = 0x00;
62 status = HAL_I2C_Mem_Read(hi2c, BMP585_I2C_ADDR, REG_ODR_CONFIG, 1, &pwr_ctrl, 1, 100);
63 if (status == HAL_OK)
64 if (onOff != 0)
65 *onOff = ((pwr_ctrl & 0x1F) != 0); // Check if ODR is set (not in standby)
66 }
67 return status;
68}
69
70/**
71 * @brief Control sensor power mode
72 */
73static HAL_StatusTypeDef barometer_onOff(I2C_HandleTypeDef *hi2c, uint8_t onOff)
74{
75 HAL_StatusTypeDef status = HAL_ERROR;
76
77 if (_isBarometer)
78 {
79 // Configure ODR_CONFIG register
80 // onOff = 0x00 for standby/deep sleep
81 // onOff = 0x18 for normal mode with 50Hz ODR
82 uint8_t odr_config = onOff;
83 status = HAL_I2C_Mem_Write(hi2c, BMP585_I2C_ADDR, REG_ODR_CONFIG, 1, &odr_config, 1, 100);
84 _isBarometer = (status == HAL_OK);
85 }
86 return status;
87}
88
89int8_t bar_bmp585_Is(I2C_HandleTypeDef *hi2c, int8_t tryInit)
90{
91 if (!_isBarometer && tryInit)
92 bar_bmp585_Init(hi2c);
93 return _isBarometer;
94}
95
96HAL_StatusTypeDef bar_bmp585_On(I2C_HandleTypeDef *hi2c)
97{
98 // Configure ODR_CONFIG for normal operation
99 // 0x18 = 00011000 -> ODR: 50Hz (bits 0-4 = 11000)
100 const uint8_t val = 0x18;
101 HAL_StatusTypeDef status = barometer_onOff(hi2c, val);
102
103 _bar_bmp585Data.IsDataValid = 0;
104 if (status == HAL_OK)
105 {
106 _memsMainBlock.Sens_BarometerStart++;
108 }
109 return status;
110}
111
112HAL_StatusTypeDef bar_bmp585_Off(I2C_HandleTypeDef *hi2c)
113{
114 // Configure ODR_CONFIG for deep sleep (standby mode)
115 // 0x00 = 00000000 -> ODR: standby/deep sleep
116 return barometer_onOff(hi2c, 0x00);
117}
118
119HAL_StatusTypeDef bar_bmp585_Init(I2C_HandleTypeDef *hi2c)
120{
121 HAL_StatusTypeDef status = I2C_IsDeviceReadyMT(hi2c, BMP585_I2C_ADDR, 2, 2); // first check
122
123 if (status == HAL_OK)
124 do
125 {
126 // Check CHIP_ID
127 uint8_t data = 0;
128 if ((status = HAL_I2C_Mem_Read(hi2c, BMP585_I2C_ADDR, REG_CHIP_ID, 1, &data, 1, 100)) != HAL_OK)
129 break;
130 if (data != BMP585_CHIP_ID)
131 {
132 status = HAL_ERROR;
133 break;
134 }
135 _isBarometer = 1; // because On/Off needs it
136
137 // Configure oversampling settings (OSR_CONFIG)
138 // 0x00 = no oversampling for quick startup
139 uint8_t osr_config = 0x00;
140 if ((status = HAL_I2C_Mem_Write(hi2c, BMP585_I2C_ADDR, REG_OSR_CONFIG, 1, &osr_config, 1, 100)) != HAL_OK)
141 break;
142
143 // Check turning on/off
144 if ((status = bar_bmp585_On(hi2c)) != HAL_OK)
145 break;
146 if ((status = bar_bmp585_Off(hi2c)) != HAL_OK)
147 break;
148 } while (0);
149 _isBarometer = (status == HAL_OK);
150
151 return status;
152}
153
154HAL_StatusTypeDef bar_bmp585_Read(I2C_HandleTypeDef *hi2c)
155{
156 uint8_t raw_data[6]; // 3 bytes for pressure, 3 for temperature
157 HAL_StatusTypeDef status = HAL_ERROR;
158
159 if (_isBarometer)
160 {
161 do
162 {
163 // Check if sensor is turned on
164 if ((status = bar_bmp585_IsOn(hi2c, &raw_data[0])) != HAL_OK)
165 break;
166 if (!raw_data[0])
167 {
168 status = HAL_TIMEOUT;
169 break;
170 }
171
172 // Read Pressure (3 bytes) starting from DATA_0
173 if ((status = HAL_I2C_Mem_Read(hi2c, BMP585_I2C_ADDR, REG_DATA_0, 1, raw_data, 3, 100)) != HAL_OK)
174 break;
175
176 // Process Pressure (24-bit)
177 uint32_t raw_press = ((uint32_t)raw_data[2] << 16) | ((uint32_t)raw_data[1] << 8) | raw_data[0];
178
179 // Convert to hPa (output is in Pa * 64, so divide by 64 and then by 100 to get hPa)
180 _bar_bmp585Data.PressureSEA = _bar_bmp585Data.PressureABS = (float)raw_press / 6400.0f;
181
182 // Read Temperature (3 bytes) starting from TEMP_DATA_0
183 if ((status = HAL_I2C_Mem_Read(hi2c, BMP585_I2C_ADDR, REG_TEMP_DATA_0, 1, &raw_data[3], 3, 100)) != HAL_OK)
184 break;
185
186 // Process Temperature (24-bit)
187 uint32_t raw_temp = ((uint32_t)raw_data[5] << 16) | ((uint32_t)raw_data[4] << 8) | raw_data[3];
188
189 // Convert to Celsius (output is in Celsius * 65536, so divide by 65536)
190 _bar_bmp585Data.Temperature = (float)raw_temp / 65536.0f;
191 _bar_bmp585Data.IsDataValid = 1;
192
193 /*
194 * Calculate Sea Level Pressure
195 * Using barometric formula to convert station pressure to sea level pressure
196 * Psea = Pstation * [1 - (0.0065 * h) / (T + 273.15 + 0.0065 * h)]^(-5.257)
197 *
198 * Where:
199 * Pstation = measured pressure in hPa
200 * h = altitude in meters
201 * T = temperature in °C
202 */
203 // Relative pressure needs temperature value
204 if (_systemParams.SensAltitude > 0)
205 {
206#ifdef SENSOR_SHT45
207 float temp = (_tmphm_sht45Data.IsDataValid) ? _tmphm_sht45Data.Temperature : _bar_bmp585Data.Temperature;
208#else
209 float temp = _bar_bmp585Data.Temperature;
210#endif
211 _bar_bmp585Data.PressureSEA = _bar_bmp585Data.PressureABS
212 * pow(1.0 - (0.0065 * _systemParams.SensAltitude) / (temp + (0.0065 * _systemParams.SensAltitude) + 273.15), -5.257);
213 }
214 } while (0);
215 }
216 return status;
217}
218
219void bar_bmp585_LogData(char *buf)
220{
221 if (buf != NULL)
222 sprintf(buf, "|barometer ABS:" PRIf_02 ", SEA:" PRIf_02 ", temp:" PRIf_02 " ", PRIf_02D(_bar_bmp585Data.PressureABS), PRIf_02D(_bar_bmp585Data.PressureSEA),
223 PRIf_02D(_bar_bmp585Data.Temperature));
224}
225
226#endif
HAL_StatusTypeDef bar_bmp585_On(I2C_HandleTypeDef *hi2c)
Turn on sensor - wakeup the sensor and start to processing of pressure measure.
Definition bar_bmp585.c:96
HAL_StatusTypeDef bar_bmp585_Off(I2C_HandleTypeDef *hi2c)
Turn off sensor - stop measure and put sensor in very deep sleep mode.
Definition bar_bmp585.c:112
static HAL_StatusTypeDef bar_bmp585_IsOn(I2C_HandleTypeDef *hi2c, uint8_t *onOff)
Check if sensor is turned on.
Definition bar_bmp585.c:54
#define REG_TEMP_DATA_0
Definition bar_bmp585.c:29
#define REG_OSR_CONFIG
Definition bar_bmp585.c:32
HAL_StatusTypeDef bar_bmp585_Read(I2C_HandleTypeDef *hi2c)
Read value from sensor, pressure and temperature. Sensor must be turned on before.
Definition bar_bmp585.c:154
void bar_bmp585_LogData(char *buf)
Log data to buffer.
Definition bar_bmp585.c:219
HAL_StatusTypeDef bar_bmp585_Init(I2C_HandleTypeDef *hi2c)
Initialize sensor, check if it really is this sensor. After check the sensor is turned off to save po...
Definition bar_bmp585.c:119
static HAL_StatusTypeDef barometer_onOff(I2C_HandleTypeDef *hi2c, uint8_t onOff)
Control sensor power mode.
Definition bar_bmp585.c:73
static uint8_t _isBarometer
Definition bar_bmp585.c:49
#define REG_ODR_CONFIG
Definition bar_bmp585.c:33
#define REG_CHIP_ID
Definition bar_bmp585.c:24
#define REG_DATA_0
Definition bar_bmp585.c:26
int8_t bar_bmp585_Is(I2C_HandleTypeDef *hi2c, int8_t tryInit)
Check if sensor is present.
Definition bar_bmp585.c:89
#define BMP585_I2C_ADDR
Definition bar_bmp585.c:21
#define BMP585_CHIP_ID
Definition bar_bmp585.c:39
bar_bmp585_t _bar_bmp585Data
Live measurement data from the BMP585 sensor; updated by bar_bmp585_Read().
Definition bar_bmp585.c:47
bar_bmp585_t _bck_bar_bmp585Data
Snapshot copy of the last completed BMP585 measurement; used for LoRaWAN transmission.
Definition bar_bmp585.c:48
This file contains all the function prototypes for the i2c.c file.
HAL_StatusTypeDef I2C_IsDeviceReadyMT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Trials, uint32_t Timeout)
Wrapper around HAL_I2C_IsDeviceReady() that recovers from a busy bus. If the HAL I2C bus is in a BUSY...
Definition i2c.c:158
#define PRIf_02D(fData)
Expands to integer and fractional arguments for use with PRIf_02. Splits a float/double into the inte...
Definition mydefs.h:38
#define PRIf_02
printf format string for printing a float/double as integer with 2 decimal places....
Definition mydefs.h:30
mems_MainBlock_t _memsMainBlock
Global instance of the main flash control block; loaded by mems_ReadMainBlock().
Definition mymems.c:27
HAL_StatusTypeDef mems_WriteMainBlock()
writing the main block on flash. The main block is stored on address 0
Definition mymems.c:117
systemParams_t _systemParams
Measurement data produced by the BMP585 barometric pressure sensor. Populated by bar_bmp585_Read(); c...
Definition bar_bmp585.h:30
tmphm_sht45_t _tmphm_sht45Data
Live measurement data from the SHT45 sensor; updated by tmphm_sht45_Read().
Definition tmphm_sht45.c:27