Hello, I am trying to use the LORA-E5 board with the BME688 sensor, I2C connection. I used this repository as the basis GitHub - Squieler/BME68x-STM32-HAL: BME68x STM32 HAL Library, changing what was needed. But it always hangs in that role. Can anyone help me?
/*
* Library Name: BME68x (I2C) - STM32 HAL and BME68x API Based Library
* Written By: Ahmet Batuhan Günaltay (Great thanks to David Bird for IAQ calculation method and functions.)
* Date Written: 26/05/2021 (DD/MM/YYYY)
* Last Modified: 26/05/2021 (DD/MM/YYYY)
* Description: This library measures temperature, humidity, pressure and IAQ with BME680x (I2C) sensors based on STM32 HAL
* and BME68x API. For more information about the IAQ calculation check: https://github.com/G6EJD/BME680-Example
* References:
* - https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bme680-ds001.pdf [Datasheet]
*
* Copyright (C) 2021 - Ahmet Batuhan Günaltay
* (IAQ calculation substantial portion, the ideas and concepts is Copyright (c) David Bird 2018)
*
This software library is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This software library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* */
/* Necessary functions for BME68x API are defined here. (Functions that are hardware dependent.) */
#include "bme68x_necessary_functions.h"
// I2C handler
extern I2C_HandleTypeDef hi2c2; // I2C peripheral for the device.
// BME68x device address:
uint8_t dev_addr = BME68X_I2C_ADDR_LOW; // High is 0x77 and low is 0x76
uint8_t chip_id = BME68X_CHIP_ID; // is 0x61
// BME68x Variables
struct bme68x_dev bme;
struct bme68x_data * BME68x_DATA;
int8_t rslt;
struct bme68x_conf conf;
struct bme68x_heatr_conf heatr_conf;
uint32_t del_period;
uint8_t n_fields;
// IAQ Calculation Variables
float humidity_score, gas_score;
float gas_reference = 250000;
float hum_reference = 40;
int8_t getgasreference_count = 0;
float gas_lower_limit = 5000; // Bad air quality limit
float gas_upper_limit = 50000; // Good air quality limit
/* Complete init. function. */
int8_t bme68x_start(struct bme68x_data *dataPtr) {
// Init.
bme68x_interface_init(&bme, BME68X_I2C_INTF);
// Init. for data variable
BME68x_DATA = dataPtr;
// Configuration
/* Check if rslt == BME68X_OK, report or handle if otherwise */
conf.filter = BME68X_FILTER_OFF;
conf.odr = BME68X_ODR_NONE;
conf.os_hum = BME68X_OS_16X;
conf.os_pres = BME68X_OS_1X;
conf.os_temp = BME68X_OS_2X;
bme68x_set_conf(&conf, &bme);
// Heat conf.
/* Check if rslt == BME68X_OK, report or handle if otherwise */
heatr_conf.enable = BME68X_ENABLE;
heatr_conf.heatr_temp_prof = 320;
heatr_conf.heatr_dur_prof = 150;
heatr_conf.profile_len = 1;
rslt = bme68x_set_heatr_conf(BME68X_SEQUENTIAL_MODE, &heatr_conf, &bme);
//Gather gas reference for the IAQ calculation
bme68x_GetGasReference();
return rslt;
}
/* Force mode measurement. */
int8_t bme68x_single_measure(struct bme68x_data *dataPtr) {
bme68x_set_op_mode(BME68X_FORCED_MODE, &bme);
/* Calculate delay period in microseconds */
del_period = bme68x_get_meas_dur(BME68X_FORCED_MODE, &conf, &bme)
+ (heatr_conf.heatr_dur * 1000);
bme.delay_us(del_period, bme.intf_ptr);
/* Check if rslt == BME68X_OK, report or handle if otherwise */
rslt = bme68x_get_data(BME68X_FORCED_MODE, dataPtr, &n_fields, &bme);
return rslt;
}
/* Necessary functions. */
// I2C write function.
BME68X_INTF_RET_TYPE bme68x_i2c_write(uint8_t reg_addr, const uint8_t *reg_data,
uint32_t len, void *intf_ptr) {
uint8_t dev_addr = *(uint8_t*) intf_ptr;
if (HAL_I2C_Mem_Write(&hi2c2, (uint16_t) (dev_addr << 1), reg_addr, 1,
(uint8_t*) reg_data, len, 15) == HAL_OK)
return 0;
return 1;
}
// I2C read function.
BME68X_INTF_RET_TYPE bme68x_i2c_read(uint8_t reg_addr, uint8_t *reg_data,
uint32_t len, void *intf_ptr) {
uint8_t dev_addr = *(uint8_t*) intf_ptr;
if (HAL_I2C_Mem_Read(&hi2c2, (uint16_t) ((dev_addr << 1) | 0x1), reg_addr,
1, reg_data, len, 15) == HAL_OK)
return 0;
return 1;
}
// BME68x delay function
void bme68x_delay_us(uint32_t period, void *intf_ptr) {
HAL_Delay(period / 1000);
}
// BME68x interface function
int8_t bme68x_interface_init(struct bme68x_dev *bme, uint8_t intf) {
int8_t rslt = BME68X_OK;
if (bme != NULL) {
// Check for the device on the I2C line
if (HAL_I2C_IsDeviceReady(&hi2c2, (uint16_t) (dev_addr << 1), 1, 1) //stop here
== HAL_OK) {
// Device found at the I2C line.
rslt = 0;
} else {
rslt = -2; // Communication error.
return rslt;
}
/* Bus configuration : I2C */
if (intf == BME68X_I2C_INTF) {
bme->read = bme68x_i2c_read;
bme->write = bme68x_i2c_write;
bme->intf = BME68X_I2C_INTF;
} else {
return -2;
}
bme->delay_us = bme68x_delay_us;
bme->intf_ptr = &dev_addr;
bme->amb_temp = 30; /* The ambient temperature in deg C is used for defining the heater temperature */
} else {
rslt = BME68X_E_NULL_PTR;
}
return rslt;
}
}
HAL_StatusTypeDef HAL_I2C_IsDeviceReady(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Trials,
uint32_t Timeout)
{
uint32_t tickstart;
__IO uint32_t I2C_Trials = 0UL;
FlagStatus tmp1;
FlagStatus tmp2;
if (hi2c->State == HAL_I2C_STATE_READY)
{
if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET)
{
return HAL_BUSY;
}
/* Process Locked */
__HAL_LOCK(hi2c);
hi2c->State = HAL_I2C_STATE_BUSY;
hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
do
{
/* Generate Start */
hi2c->Instance->CR2 = I2C_GENERATE_START(hi2c->Init.AddressingMode, DevAddress);
/* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */
/* Wait until STOPF flag is set or a NACK flag is set*/
tickstart = HAL_GetTick();
tmp1 = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF);
tmp2 = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF);
while ((tmp1 == RESET) && (tmp2 == RESET))
{
if (Timeout != HAL_MAX_DELAY)
{
if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
{
/* Update I2C state */
hi2c->State = HAL_I2C_STATE_READY;
/* Update I2C error code */
hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
/* Process Unlocked */
__HAL_UNLOCK(hi2c);
return HAL_ERROR;
}
}
tmp1 = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF);
tmp2 = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF);
}
/* Check if the NACKF flag has not been set */
if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == RESET)
{
/* Wait until STOPF flag is reset */
if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_STOPF, RESET, Timeout, tickstart) != HAL_OK)
{
return HAL_ERROR;
}
/* Clear STOP Flag */
__HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
/* Device is ready */
hi2c->State = HAL_I2C_STATE_READY;
/* Process Unlocked */
__HAL_UNLOCK(hi2c);
return HAL_OK;
}
else
{
/* Wait until STOPF flag is reset */
if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_STOPF, RESET, Timeout, tickstart) != HAL_OK)
{
return HAL_ERROR;
}
/* Clear NACK Flag */
__HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
/* Clear STOP Flag, auto generated with autoend*/
__HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
}
/* Check if the maximum allowed number of trials has been reached */
if (I2C_Trials == Trials)
{
/* Generate Stop */
hi2c->Instance->CR2 |= I2C_CR2_STOP;
/* Wait until STOPF flag is reset */
if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_STOPF, RESET, Timeout, tickstart) != HAL_OK)
{
return HAL_ERROR;
}
/* Clear STOP Flag */
__HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
}
/* Increment Trials */
I2C_Trials++;
} while (I2C_Trials < Trials);
/* Update I2C state */
hi2c->State = HAL_I2C_STATE_READY;
/* Update I2C error code */
hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
/* Process Unlocked */
__HAL_UNLOCK(hi2c);
return HAL_ERROR;
}
else
{
return HAL_BUSY;
}
}
tmp1 = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) and tmp2 = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) always still “reset”