Skip to content

Commit d06344f

Browse files
authored
Merge pull request #29 from coffee-and-telesense/add_hardware_timer
Update BME68x driver to use application delay function
2 parents 02862ce + 07375d4 commit d06344f

File tree

13 files changed

+275
-63
lines changed

13 files changed

+275
-63
lines changed

libs/bme68x/Inc/bme68x_driver.h

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ typedef struct
9090
* @param[in,out] bme Pointer to newly initialized bme68x sensor interface
9191
* @param[in] i2c_handle Pointer to I2C handle.
9292
*/
93-
void bme_init(bme68x_sensor_t *bme, I2C_HandleTypeDef *i2c_handle);
93+
void bme_init(bme68x_sensor_t *bme, I2C_HandleTypeDef *i2c_handle, bme68x_delay_us_fptr_t delay_fn);
9494

9595
/**
9696
* @brief Returns basic status check
@@ -175,18 +175,6 @@ uint8_t bme_fetch_data(bme68x_sensor_t *bme);
175175
*/
176176
uint32_t bme_get_meas_dur(bme68x_sensor_t *bme, uint8_t opmode);
177177

178-
/**
179-
* @brief Implements the default microsecond delay callback
180-
*
181-
* Sets the delay_us function pointer on the bme68x_dev device struct.
182-
* This callback is used throughout the Bosch library whenever a microsecond
183-
* delay is necessary for proper device functioning.
184-
*
185-
* @param[in] period_us Duration of the delay in microseconds
186-
* @param[in] intf_ptr Pointer to the interface descriptor
187-
*/
188-
void bme_delay_us(uint32_t period_us, void *intf_ptr);
189-
190178
/**
191179
* @brief Implements the default I2C write transaction
192180
*
@@ -221,20 +209,21 @@ int8_t bme_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf
221209
* Example usage of the BME68x sensor driver.
222210
* @note: Requires HAL peripheral drivers and initialization, specifically for i2c.
223211
* @note: Assumes an I2C_HandleTypeDef hi2c1 instance exists.
212+
* @note: Requires a microsecond delay function implemented in the application.
224213
*
225214
* @code
226215
* #include "bme68x_driver.h"
227216
*
228217
* int main(void) {
229218
* bme68x_sensor_t bme;
230-
* bme_init(&bme, &hi2c1);
219+
* bme_init(&bme, &hi2c1, &delay_us_timer);
231220
* bme_set_TPH_default(&bme);
232221
* bme_set_heaterprof(&bme, 300, 100);
233222
* while (1)
234223
* {
235224
* bme_set_opmode(&bme, BME68X_FORCED_MODE);
236225
* // @todo: May adjust the specific timing function called here, but it should be based on bme_get_meas_dur
237-
* bme_delay_us(bme_get_meas_dur(&bme, BME68X_SLEEP_MODE), &hi2c1);
226+
* delay_us_timer(bme_get_meas_dur(&bme, BME68X_SLEEP_MODE), &hi2c1);
238227
* int fetch_success = bme_fetch_data(&bme);
239228
* if (fetch_success) {
240229
* debug_print("%d, ", bme.sensor_data.temperature);

libs/bme68x/Src/bme68x_driver.c

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
/* ========================== FUNCTION IMPLEMENTATIONS ========================== */
1717

1818
/** Initializes the BME68x sensor interface */
19-
void bme_init(bme68x_sensor_t *bme, I2C_HandleTypeDef *i2c_handle)
19+
void bme_init(bme68x_sensor_t *bme, I2C_HandleTypeDef *i2c_handle, bme68x_delay_us_fptr_t delay_fn)
2020
{
2121
if (bme == NULL)
2222
{
@@ -36,7 +36,7 @@ void bme_init(bme68x_sensor_t *bme, I2C_HandleTypeDef *i2c_handle)
3636
/** @todo (maybe) Assign variant ID on bme struct */
3737
bme->device.read = &bme_read;
3838
bme->device.write = &bme_write;
39-
bme->device.delay_us = bme_delay_us;
39+
bme->device.delay_us = delay_fn;
4040
bme->status = BME68X_OK;
4141
// Typical ambient temperature in Celsius
4242
bme->device.amb_temp = 25;
@@ -119,21 +119,6 @@ uint32_t bme_get_meas_dur(bme68x_sensor_t *bme, uint8_t opmode)
119119
return bme68x_get_meas_dur(opmode, &bme->conf, &bme->device);
120120
}
121121

122-
/** Implements the default microsecond delay callback */
123-
void bme_delay_us(uint32_t period_us, void *intf_ptr)
124-
{
125-
// intf_ptr is not used, but it is part of the standard function signature
126-
// so cast to void to avoid compiler warning
127-
(void)intf_ptr;
128-
/** @todo: Implement a microsecond delay here, possibly with a DWT cycle counter, or an actual hardware timer */
129-
// FIXME: Short-term implementation of a blocking delay
130-
volatile uint32_t cycles = period_us * 20;
131-
while (cycles--)
132-
{
133-
__NOP();
134-
}
135-
}
136-
137122
/** Implements the default microsecond delay callback */
138123
int8_t bme_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr)
139124
{

libs/bme68x/bme68x.md

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,26 +16,26 @@ In addition, the Bosch library github repo contained an Arduino library written
1616

1717
### Example Usage
1818

19-
The following example shows creation and initialization of a `bme68x_sensor_t` struct, which contains a pointer to an I2C handle previously initialized in application code. The struct also contains status, a BME68x device struct, configuration, sensor data, and the last operation mode.
19+
The following example shows creation and initialization of a `bme68x_sensor_t` struct, which contains a pointer to an I2C handle previously initialized in application code, in addition to a pointer to a function from the application that should be used when a microsecond delay is needed. The struct also contains status, a BME68x device struct, configuration, sensor data, and the last operation mode.
2020

2121
After initialization, configuration is performed, using default oversampling values for the temperature, pressure, and humidity measurements, and a heater configuration of 300 deg C for 100ms in forced mode.
2222

23-
Data is then fetched from the sensor repeatedly in a loop. The specific delay function may be adjusted to use a hardware timer, but the microsecond delay should still be based on the return value from the `bme_get_meas_dur` function.
23+
Data is then fetched from the sensor repeatedly in a loop. As noted above, the delay function should be implemented in application code, for example using a hardware timer and function defined in `tim.c`, but the microsecond delay should still be based on the return value from the `bme_get_meas_dur` function.
2424

2525
```c
2626
#include "bme68x_driver.h"
2727

2828
int main(void) {
2929
bme68x_sensor_t bme;
30-
bme_init(&bme, &hi2c1);
30+
bme_init(&bme, &hi2c1, &delay_us_timer);
3131
bme_set_TPH_default(&bme);
3232
bme_set_heaterprof(&bme, 300, 100);
3333

3434
while (1)
3535
{
3636
bme_set_opmode(&bme, BME68X_FORCED_MODE);
3737
/** @todo: May adjust the specific timing function called here, but it should be based on bme_get_meas_dur */
38-
bme_delay_us(bme_get_meas_dur(&bme, BME68X_SLEEP_MODE), &hi2c1);
38+
delay_us_timer(bme_get_meas_dur(&bme, BME68X_SLEEP_MODE), &hi2c1);
3939
int fetch_success = bme_fetch_data(&bme);
4040
if (fetch_success) {
4141
debug_print("%d, ", bme.sensor_data.temperature);
@@ -53,7 +53,9 @@ int main(void) {
5353
5454
### `bme68x_sensor_t` struct
5555
56-
Structure to store necessary configuration and data to interact with the sensor over I2C. Contains as members the structs `bme68x_dev`, `bme68x_conf`, `bme68x_heatr_conf`, and `bme68x_data`, which are defined in `bme68x_defs.h`. Also contains an `I2C_HandleTypeDef` pointer to allow I2C communication using STM32 HAL I2C functions.
56+
Structure to store necessary configuration and data to interact with the sensor over I2C. Contains as members the structs `bme68x_dev`, `bme68x_conf`, `bme68x_heatr_conf`, and `bme68x_data`, which are defined in `bme68x_defs.h`. Also contains an `I2C_HandleTypeDef` pointer to allow I2C communication using STM32 HAL I2C functions, and a pointer to a microsecond delay function defined by the application.
57+
58+
**NOTE**: The delay function signature is currently determined by the original one used by the Bosch library developers. The function signature is fairly simple (it accepts a `uint32_t` microsecond delay value and a `void *` interface pointer), but if desired, the Bosch library code may be modified to accommodate an alternate signature.
5759
5860
### `bme_init()`
5961
@@ -62,6 +64,7 @@ Configures the sensor with default settings.
6264
**Parameters:**
6365
- `bme`: Pointer to newly initialized bme68x sensor interface
6466
- `i2c_handle`: Pointer to I2C handle
67+
- `delay_fn`: Pointer to a microsecond delay function
6568
6669
### `bme_check_status()`
6770
@@ -128,14 +131,6 @@ Get the measurement duration in microseconds. This is the total measurement dura
128131
**Returns:**
129132
- `uint32_t`: Measurement duration in microseconds
130133
131-
### `bme_delay_us()`
132-
133-
Implements the default microsecond delay callback, as called from the Bosch library. **NOTE**: This function signature is currently determined by the original one used by the Bosch library developers. We may wish to modify it in the future to better accommodate our usage of the STM32 HAL timing functions.
134-
135-
**Parameters:**
136-
- `period_us`: Duration of the delay in microseconds
137-
- `intf_ptr`: Pointer to the interface descriptor for I2C
138-
139134
### `bme_write()`
140135
141136
Implements the default I2C write transaction. This is leveraged by the Bosch library to perform writes to the device over I2C. It should typically not be necessary for application code to call this function directly, though it may be useful in troubleshooting.
@@ -196,15 +191,9 @@ There are a few functions from the Bosch library that are not currently in use,
196191
197192
## Next Steps
198193
199-
**Update delay function**
200-
201-
The current delay function was added to allow for retrieval of data in a prototyping context. It should be replaced, probably with a hardware timer. Usage of the `HAL_Delay` function was attempted, but that function provides millisecond delays, rather that the microsecond delays required by this driver.
202-
203-
Other alternatives might be using the DWT as a cycle counter, or modifying the Bosch library callback signature to be more specific to our needs.
204-
205194
**Validate humidity measurements**
206195
207-
The humidity measurements currently appear to be returning the max value consistently. This may be the result of the above prototyping-level delay function, or possibly an individual sensor-specific problem. First steps to resolve are to update the above delay function, test on additional sensors, and adjust the oversampling setting.
196+
The humidity measurements currently appear to be returning the max value consistently. This may be an individual sensor-specific problem, it could be related to a timing issue, or possibly an oversampling setting. First steps to resolve are to test on additional sensors, adjust the oversampling setting, or simply step through the code with a debugger and see if it's possible to retrieve a valid humidity measurement at any stage.
208197
209198
**Create non-blocking version**
210199

0 commit comments

Comments
 (0)