I am trying to make ble communication work with I2C but i cant make it work i dont understand what is the issue the code is being build but it does not advertise can someone help me or show an example for me to work with i cant find any good examples for TWI and BLE being used at the same time. This is my code please help me see a way
#include <stdint.h>
#include <string.h>
#include "nordic_common.h"
#include "nrf.h"
#include "ble_hci.h"
#include "ble_advdata.h"
#include "ble_advertising.h"
#include "ble_conn_params.h"
#include "nrf_sdh.h"
#include "nrf_sdh_soc.h"
#include "nrf_sdh_ble.h"
#include "nrf_ble_gatt.h"
#include "nrf_ble_qwr.h"
#include "app_timer.h"
#include "ble_nus.h"
#include "app_uart.h"
#include "app_util_platform.h"
#include "bsp_btn_ble.h"
#include "nrf_pwr_mgmt.h"
#include "nrf_delay.h"
#include "nrf_drv_twi.h"
#if defined (UART_PRESENT)
#include "nrf_uart.h"
#endif
#if defined (UARTE_PRESENT)
#include "nrf_uarte.h"
#endif
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
/* TWI instance ID. */
#define TWI_INSTANCE_ID 1
#define APP_BLE_CONN_CFG_TAG 1 /**< A tag identifying the SoftDevice BLE configuration. */
#define DEVICE_NAME "4thLayer" /**< Name of device. Will be included in the advertising data. */
#define NUS_SERVICE_UUID_TYPE BLE_UUID_TYPE_VENDOR_BEGIN /**< UUID type for the Nordic UART Service (vendor specific). */
#define APP_BLE_OBSERVER_PRIO 3 /**< Application's BLE observer priority. You shouldn't need to modify this value. */
#define APP_ADV_INTERVAL 64 /**< The advertising interval (in units of 0.625 ms. This value corresponds to 40 ms). */
#define APP_ADV_DURATION 18000 /**< The advertising duration (180 seconds) in units of 10 milliseconds. */
#define MIN_CONN_INTERVAL MSEC_TO_UNITS(20, UNIT_1_25_MS) /**< Minimum acceptable connection interval (20 ms), Connection interval uses 1.25 ms units. */
#define MAX_CONN_INTERVAL MSEC_TO_UNITS(75, UNIT_1_25_MS) /**< Maximum acceptable connection interval (75 ms), Connection interval uses 1.25 ms units. */
#define SLAVE_LATENCY 0 /**< Slave latency. */
#define CONN_SUP_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS) /**< Connection supervisory timeout (4 seconds), Supervision Timeout uses 10 ms units. */
#define FIRST_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(5000) /**< Time from initiating event (connect or start of notification) to first time sd_ble_gap_conn_param_update is called (5 seconds). */
#define NEXT_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(30000) /**< Time between each call to sd_ble_gap_conn_param_update after the first call (30 seconds). */
#define MAX_CONN_PARAMS_UPDATE_COUNT 3 /**< Number of attempts before giving up the connection parameter negotiation. */
#define DEAD_BEEF 0xDEADBEEF /**< Value used as error code on stack dump, can be used to identify stack location on stack unwind. */
#define UART_TX_BUF_SIZE 256 /**< UART TX buffer size. */
#define UART_RX_BUF_SIZE 256 /**< UART RX buffer size. */
#define MYDATA_TIMER_INTERVAL APP_TIMER_TICKS(500)
#define BME280_ADDRESS_1 0x76
#define BME280_ID 0xD0
#define BME280_PRESS_MSB 0xF7
#define BME280_PRESS_LSB 0xF8
#define BME280_PRESS_XLSB 0xF9
#define BME280_TEMP_MSB 0xFA
#define BME280_TEMP_LSB 0xFB
#define BME280_TEMP_XLSB 0xFC
#define BME280_HUM_MSB 0xFD
#define BME280_HUM_LSB 0xFE
#define BME280_CONFIG 0xF5
#define BME280_CTRL_MEAS 0xF4
#define BME280_STATUS 0xF3
#define BME280_CTRL_HUM 0xF2
#define BME280_RESET 0xE0
#define BME280_CALIB00 0x88
#define BME280_CALIB26 0xE1
enum Posr {P_OSR_00 = 0, /* no op */ P_OSR_01, P_OSR_02, P_OSR_04, P_OSR_08, P_OSR_16};
enum Hosr {H_OSR_00 = 0, /* no op */ H_OSR_01, H_OSR_02, H_OSR_04, H_OSR_08, H_OSR_16};
enum Tosr {T_OSR_00 = 0, /* no op */ T_OSR_01, T_OSR_02, T_OSR_04, T_OSR_08, T_OSR_16};
enum IIRFilter {full = 0, /* bandwidth at full sample rate */ BW0_223ODR, BW0_092ODR, BW0_042ODR, BW0_021ODR /* bandwidth at 0.021 x sample rate */ };
enum Mode {BME280Sleep = 0, forced, forced2, normal};
enum SBy {t_00_5ms = 0, t_62_5ms, t_125ms, t_250ms, t_500ms, t_1000ms, t_10ms, t_20ms};
// Read and store calibration data
uint8_t calib26[26];
uint8_t calib7[7];
//from read PTH
static uint8_t rawData[8]; // 20-bit pressure register data stored here
int32_t result[3];
int32_t var1, var2, t_fine, adc_T;
int32_t Temp,Temp1,Temp2,Hum,Hum1,Hum2;
//from Pressure comp
int32_t varP1, varP2;
uint32_t P;
// BME280 compensation parameters
uint8_t dig_H1, dig_H3, dig_H6;
uint16_t dig_T1, dig_P1, dig_H4, dig_H5;
int16_t dig_T2, dig_T3, dig_P2, dig_P3, dig_P4, dig_P5, dig_P6, dig_P7, dig_P8, dig_P9, dig_H2;
//uint32_t delt_t = 0, count = 0, sumCount = 0, slpcnt = 0; // used to control display output rate
// Specify BME280 configuration
// set pressure and temperature output data rate
//uint8_t Posr = P_OSR_16, Hosr = H_OSR_16, Tosr = T_OSR_02, Mode = normal, IIRFilter = BW0_021ODR, SBy = t_62_5ms;
/* @EfektaSB */
uint8_t Posr = P_OSR_01, Hosr = H_OSR_01, Tosr = T_OSR_01, Mode = forced, IIRFilter = full, SBy = t_00_5ms;
/* Indicates if operation on TWI has ended. */
static volatile bool m_xfer_done = false;
/* TWI instance. */
static const nrf_drv_twi_t i2c = NRF_DRV_TWI_INSTANCE(TWI_INSTANCE_ID);
BLE_NUS_DEF(m_nus, NRF_SDH_BLE_TOTAL_LINK_COUNT); /**< BLE NUS service instance. */
NRF_BLE_GATT_DEF(m_gatt); /**< GATT module instance. */
NRF_BLE_QWR_DEF(m_qwr); /**< Context for the Queued Write module.*/
BLE_ADVERTISING_DEF(m_advertising);
APP_TIMER_DEF(m_mydata_timer_id);
static uint16_t m_conn_handle = BLE_CONN_HANDLE_INVALID; /**< Handle of the current connection. */
static uint16_t m_ble_nus_max_data_len = BLE_GATT_ATT_MTU_DEFAULT - 3; /**< Maximum length of data (in bytes) that can be transmitted to the peer by the Nordic UART service module. */
static ble_uuid_t m_adv_uuids[] = /**< Universally unique service identifier. */
{
{BLE_UUID_NUS_SERVICE, NUS_SERVICE_UUID_TYPE}
};
/**@brief Function for assert macro callback.
*
* @details This function will be called in case of an assert in the SoftDevice.
*
* @warning This handler is an example only and does not fit a final product. You need to analyse
* how your product is supposed to react in case of Assert.
* @warning On assert from the SoftDevice, the system can only recover on reset.
*
* @param[in] line_num Line number of the failing ASSERT call.
* @param[in] p_file_name File name of the failing ASSERT call.
*/
void assert_nrf_callback(uint16_t line_num, const uint8_t * p_file_name)
{
app_error_handler(DEAD_BEEF, line_num, p_file_name);
}
static void mydata_timeout_handler(void * p_context)
{
ret_code_t err_code;
UNUSED_PARAMETER(p_context);
bsp_board_led_on(3);
nrf_delay_ms(100);
bsp_board_led_off(3);
/*
uint8_array_t mydata_value [17] = {0x55,0x10,0x01,0x23,0x99,0xFF,0xFF,0xCC,0xBB,0x00,0x00,0x00,0x00,0x00,0x24,0x24,0x20};
ble_nus_mydata_update(&m_nus, mydata_value, 17, m_conn_handle);
if ((err_code != NRF_ERROR_INVALID_STATE) &&
(err_code != NRF_ERROR_RESOURCES) &&
(err_code != NRF_ERROR_NOT_FOUND))
{
APP_ERROR_CHECK(err_code);
}
*/
}
/**@brief Function for initializing the timer module.
*/
static void timers_init(void)
{
ret_code_t err_code = app_timer_init();
APP_ERROR_CHECK(err_code);
err_code = app_timer_create(&m_mydata_timer_id,
APP_TIMER_MODE_REPEATED,
mydata_timeout_handler);
APP_ERROR_CHECK(err_code);
}
/**@brief Function for the GAP initialization.
*
* @details This function will set up all the necessary GAP (Generic Access Profile) parameters of
* the device. It also sets the permissions and appearance.
*/
static void gap_params_init(void)
{
uint32_t err_code;
ble_gap_conn_params_t gap_conn_params;
ble_gap_conn_sec_mode_t sec_mode;
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
err_code = sd_ble_gap_device_name_set(&sec_mode,
(const uint8_t *) DEVICE_NAME,
strlen(DEVICE_NAME));
APP_ERROR_CHECK(err_code);
memset(&gap_conn_params, 0, sizeof(gap_conn_params));
gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL;
gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL;
gap_conn_params.slave_latency = SLAVE_LATENCY;
gap_conn_params.conn_sup_timeout = CONN_SUP_TIMEOUT;
err_code = sd_ble_gap_ppcp_set(&gap_conn_params);
APP_ERROR_CHECK(err_code);
}
/**@brief Function for handling Queued Write Module errors.
*
* @details A pointer to this function will be passed to each service which may need to inform the
* application about an error.
*
* @param[in] nrf_error Error code containing information about what went wrong.
*/
static void nrf_qwr_error_handler(uint32_t nrf_error)
{
APP_ERROR_HANDLER(nrf_error);
}
/**@brief Function for handling the data from the Nordic UART Service.
*
* @details This function will process the data received from the Nordic UART BLE Service and send
* it to the UART module.
*
* @param[in] p_evt Nordic UART Service event.
*/
/**@snippet [Handling the data received over BLE] */
static void nus_data_handler(ble_nus_evt_t * p_evt)
{
if (p_evt->type == BLE_NUS_EVT_RX_DATA)
{
uint32_t err_code;
NRF_LOG_DEBUG("Received data from BLE NUS. Writing data on UART.");
NRF_LOG_HEXDUMP_DEBUG(p_evt->params.rx_data.p_data, p_evt->params.rx_data.length);
for (uint32_t i = 0; i < p_evt->params.rx_data.length; i++)
{
do
{
err_code = app_uart_put(p_evt->params.rx_data.p_data[i]);
if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_BUSY))
{
NRF_LOG_ERROR("Failed receiving NUS message. Error 0x%x. ", err_code);
APP_ERROR_CHECK(err_code);
}
} while (err_code == NRF_ERROR_BUSY);
}
if (p_evt->params.rx_data.p_data[p_evt->params.rx_data.length - 1] == '\r')
{
while (app_uart_put('\n') == NRF_ERROR_BUSY);
}
}
}
/**@snippet [Handling the data received over BLE] */
/**@brief Function for initializing services that will be used by the application.
*/
static void services_init(void)
{
uint32_t err_code;
ble_nus_init_t nus_init;
nrf_ble_qwr_init_t qwr_init = {0};
// Initialize Queued Write Module.
qwr_init.error_handler = nrf_qwr_error_handler;
err_code = nrf_ble_qwr_init(&m_qwr, &qwr_init);
APP_ERROR_CHECK(err_code);
// Initialize NUS.
memset(&nus_init, 0, sizeof(nus_init));
nus_init.data_handler = nus_data_handler;
err_code = ble_nus_init(&m_nus, &nus_init);
APP_ERROR_CHECK(err_code);
}
/**@brief Function for handling an event from the Connection Parameters Module.
*
* @details This function will be called for all events in the Connection Parameters Module
* which are passed to the application.
*
* @note All this function does is to disconnect. This could have been done by simply setting
* the disconnect_on_fail config parameter, but instead we use the event handler
* mechanism to demonstrate its use.
*
* @param[in] p_evt Event received from the Connection Parameters Module.
*/
static void on_conn_params_evt(ble_conn_params_evt_t * p_evt)
{
uint32_t err_code;
if (p_evt->evt_type == BLE_CONN_PARAMS_EVT_FAILED)
{
err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_CONN_INTERVAL_UNACCEPTABLE);
APP_ERROR_CHECK(err_code);
}
}
/**@brief Function for handling errors from the Connection Parameters module.
*
* @param[in] nrf_error Error code containing information about what went wrong.
*/
static void conn_params_error_handler(uint32_t nrf_error)
{
APP_ERROR_HANDLER(nrf_error);
}
/**@brief Function for initializing the Connection Parameters module.
*/
static void conn_params_init(void)
{
uint32_t err_code;
ble_conn_params_init_t cp_init;
memset(&cp_init, 0, sizeof(cp_init));
cp_init.p_conn_params = NULL;
cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY;
cp_init.next_conn_params_update_delay = NEXT_CONN_PARAMS_UPDATE_DELAY;
cp_init.max_conn_params_update_count = MAX_CONN_PARAMS_UPDATE_COUNT;
cp_init.start_on_notify_cccd_handle = BLE_GATT_HANDLE_INVALID;
cp_init.disconnect_on_fail = false;
cp_init.evt_handler = on_conn_params_evt;
cp_init.error_handler = conn_params_error_handler;
err_code = ble_conn_params_init(&cp_init);
APP_ERROR_CHECK(err_code);
}
static void application_timers_start(void)
{
ret_code_t err_code;
err_code = app_timer_start(m_mydata_timer_id, MYDATA_TIMER_INTERVAL, NULL);
APP_ERROR_CHECK(err_code);
}
/**@brief Function for putting the chip into sleep mode.
*
* @note This function will not return.
*/
static void sleep_mode_enter(void)
{
uint32_t err_code = bsp_indication_set(BSP_INDICATE_IDLE);
APP_ERROR_CHECK(err_code);
// Prepare wakeup buttons.
err_code = bsp_btn_ble_sleep_mode_prepare();
APP_ERROR_CHECK(err_code);
// Go to system-off mode (this function will not return; wakeup will cause a reset).
err_code = sd_power_system_off();
APP_ERROR_CHECK(err_code);
}
/**@brief Function for handling advertising events.
*
* @details This function will be called for advertising events which are passed to the application.
*
* @param[in] ble_adv_evt Advertising event.
*/
static void on_adv_evt(ble_adv_evt_t ble_adv_evt)
{
uint32_t err_code;
switch (ble_adv_evt)
{
case BLE_ADV_EVT_FAST:
err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING);
APP_ERROR_CHECK(err_code);
break;
case BLE_ADV_EVT_IDLE:
sleep_mode_enter();
break;
default:
break;
}
}
/**@brief Function for handling BLE events.
*
* @param[in] p_ble_evt Bluetooth stack event.
* @param[in] p_context Unused.
*/
static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
{
uint32_t err_code;
switch (p_ble_evt->header.evt_id)
{
case BLE_GAP_EVT_CONNECTED:
NRF_LOG_INFO("Connected");
err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);
APP_ERROR_CHECK(err_code);
m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr, m_conn_handle);
APP_ERROR_CHECK(err_code);
break;
case BLE_GAP_EVT_DISCONNECTED:
NRF_LOG_INFO("Disconnected");
// LED indication will be changed when advertising starts.
m_conn_handle = BLE_CONN_HANDLE_INVALID;
break;
case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
{
NRF_LOG_DEBUG("PHY update request.");
ble_gap_phys_t const phys =
{
.rx_phys = BLE_GAP_PHY_AUTO,
.tx_phys = BLE_GAP_PHY_AUTO,
};
err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
APP_ERROR_CHECK(err_code);
} break;
case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
// Pairing not supported
err_code = sd_ble_gap_sec_params_reply(m_conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL);
APP_ERROR_CHECK(err_code);
break;
case BLE_GATTS_EVT_SYS_ATTR_MISSING:
// No system attributes have been stored.
err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0, 0);
APP_ERROR_CHECK(err_code);
break;
case BLE_GATTC_EVT_TIMEOUT:
// Disconnect on GATT Client timeout event.
err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle,
BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
APP_ERROR_CHECK(err_code);
break;
case BLE_GATTS_EVT_TIMEOUT:
// Disconnect on GATT Server timeout event.
err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle,
BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
APP_ERROR_CHECK(err_code);
break;
default:
// No implementation needed.
break;
}
}
/**@brief Function for the SoftDevice initialization.
*
* @details This function initializes the SoftDevice and the BLE event interrupt.
*/
static void ble_stack_init(void)
{
ret_code_t err_code;
err_code = nrf_sdh_enable_request();
APP_ERROR_CHECK(err_code);
// Configure the BLE stack using the default settings.
// Fetch the start address of the application RAM.
uint32_t ram_start = 0;
err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
APP_ERROR_CHECK(err_code);
// Enable BLE stack.
err_code = nrf_sdh_ble_enable(&ram_start);
APP_ERROR_CHECK(err_code);
// Register a handler for BLE events.
NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);
}
/**@brief Function for handling events from the GATT library. */
void gatt_evt_handler(nrf_ble_gatt_t * p_gatt, nrf_ble_gatt_evt_t const * p_evt)
{
if ((m_conn_handle == p_evt->conn_handle) && (p_evt->evt_id == NRF_BLE_GATT_EVT_ATT_MTU_UPDATED))
{
m_ble_nus_max_data_len = p_evt->params.att_mtu_effective - OPCODE_LENGTH - HANDLE_LENGTH;
NRF_LOG_INFO("Data len is set to 0x%X(%d)", m_ble_nus_max_data_len, m_ble_nus_max_data_len);
}
NRF_LOG_DEBUG("ATT MTU exchange completed. central 0x%x peripheral 0x%x",
p_gatt->att_mtu_desired_central,
p_gatt->att_mtu_desired_periph);
}
/**@brief Function for initializing the GATT library. */
void gatt_init(void)
{
ret_code_t err_code;
err_code = nrf_ble_gatt_init(&m_gatt, gatt_evt_handler);
APP_ERROR_CHECK(err_code);
err_code = nrf_ble_gatt_att_mtu_periph_set(&m_gatt, NRF_SDH_BLE_GATT_MAX_MTU_SIZE);
APP_ERROR_CHECK(err_code);
}
/**@brief Function for handling events from the BSP module.
*
* @param[in] event Event generated by button press.
*/
void bsp_event_handler(bsp_event_t event)
{
uint32_t err_code;
switch (event)
{
case BSP_EVENT_SLEEP:
sleep_mode_enter();
break;
case BSP_EVENT_DISCONNECT:
err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
if (err_code != NRF_ERROR_INVALID_STATE)
{
APP_ERROR_CHECK(err_code);
}
break;
case BSP_EVENT_WHITELIST_OFF:
if (m_conn_handle == BLE_CONN_HANDLE_INVALID)
{
err_code = ble_advertising_restart_without_whitelist(&m_advertising);
if (err_code != NRF_ERROR_INVALID_STATE)
{
APP_ERROR_CHECK(err_code);
}
}
break;
default:
break;
}
}
/**@brief Function for handling app_uart events.
*
* @details This function will receive a single character from the app_uart module and append it to
* a string. The string will be be sent over BLE when the last character received was a
* 'new line' '\n' (hex 0x0A) or if the string has reached the maximum data length.
*/
/**@snippet [Handling the data received over UART] */
void uart_event_handle(app_uart_evt_t * p_event)
{
static uint8_t data_array[BLE_NUS_MAX_DATA_LEN];
static uint8_t index = 0;
uint32_t err_code;
switch (p_event->evt_type)
{
case APP_UART_DATA_READY:
UNUSED_VARIABLE(app_uart_get(&data_array[index]));
index++;
if ((data_array[index - 1] == '\n') ||
(data_array[index - 1] == '\r') ||
(index >= m_ble_nus_max_data_len))
{
if (index > 1)
{
NRF_LOG_DEBUG("Ready to send data over BLE NUS");
NRF_LOG_HEXDUMP_DEBUG(data_array, index);
do
{
uint16_t length = (uint16_t)index;
err_code = ble_nus_data_send(&m_nus, data_array, &length, m_conn_handle);
if ((err_code != NRF_ERROR_INVALID_STATE) &&
(err_code != NRF_ERROR_RESOURCES) &&
(err_code != NRF_ERROR_NOT_FOUND))
{
APP_ERROR_CHECK(err_code);
}
} while (err_code == NRF_ERROR_RESOURCES);
}
index = 0;
}
break;
case APP_UART_COMMUNICATION_ERROR:
APP_ERROR_HANDLER(p_event->data.error_communication);
break;
case APP_UART_FIFO_ERROR:
APP_ERROR_HANDLER(p_event->data.error_code);
break;
default:
break;
}
}
/**@snippet [Handling the data received over UART] */
/**@brief Function for initializing the UART module.
*/
/**@snippet [UART Initialization] */
static void uart_init(void)
{
uint32_t err_code;
app_uart_comm_params_t const comm_params =
{
.rx_pin_no = RX_PIN_NUMBER,
.tx_pin_no = TX_PIN_NUMBER,
.rts_pin_no = RTS_PIN_NUMBER,
.cts_pin_no = CTS_PIN_NUMBER,
.flow_control = APP_UART_FLOW_CONTROL_DISABLED,
.use_parity = false,
#if defined (UART_PRESENT)
.baud_rate = NRF_UART_BAUDRATE_115200
#else
.baud_rate = NRF_UARTE_BAUDRATE_115200
#endif
};
APP_UART_FIFO_INIT(&comm_params,
UART_RX_BUF_SIZE,
UART_TX_BUF_SIZE,
uart_event_handle,
APP_IRQ_PRIORITY_LOWEST,
err_code);
APP_ERROR_CHECK(err_code);
}
/**@snippet [UART Initialization] */
/**@brief Function for initializing the Advertising functionality.
*/
static void advertising_init(void)
{
uint32_t err_code;
ble_advertising_init_t init;
memset(&init, 0, sizeof(init));
init.advdata.name_type = BLE_ADVDATA_FULL_NAME;
init.advdata.include_appearance = false;
init.advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE;
init.srdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
init.srdata.uuids_complete.p_uuids = m_adv_uuids;
init.config.ble_adv_fast_enabled = true;
init.config.ble_adv_fast_interval = APP_ADV_INTERVAL;
init.config.ble_adv_fast_timeout = APP_ADV_DURATION;
init.evt_handler = on_adv_evt;
err_code = ble_advertising_init(&m_advertising, &init);
APP_ERROR_CHECK(err_code);
ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG);
}
/**@brief Function for initializing buttons and leds.
*
* @param[out] p_erase_bonds Will be true if the clear bonding button was pressed to wake the application up.
*/
static void buttons_leds_init(bool * p_erase_bonds)
{
bsp_event_t startup_event;
uint32_t err_code = bsp_init(BSP_INIT_LEDS | BSP_INIT_BUTTONS, bsp_event_handler);
APP_ERROR_CHECK(err_code);
err_code = bsp_btn_ble_init(NULL, &startup_event);
APP_ERROR_CHECK(err_code);
*p_erase_bonds = (startup_event == BSP_EVENT_CLEAR_BONDING_DATA);
}
/**@brief Function for initializing the nrf log module.
*/
static void log_init(void)
{
ret_code_t err_code = NRF_LOG_INIT(NULL);
APP_ERROR_CHECK(err_code);
NRF_LOG_DEFAULT_BACKENDS_INIT();
}
/**@brief Function for initializing power management.
*/
static void power_management_init(void)
{
ret_code_t err_code;
err_code = nrf_pwr_mgmt_init();
APP_ERROR_CHECK(err_code);
}
/**@brief Function for handling the idle state (main loop).
*
* @details If there is no pending log operation, then sleep until next the next event occurs.
*/
static void idle_state_handle(void)
{
if (NRF_LOG_PROCESS() == false)
{
nrf_pwr_mgmt_run();
}
}
void I2C_init(void)
{
ret_code_t err_code;
const nrf_drv_twi_config_t i2c_config =
{
.scl = 16,
.sda = 17,
.frequency = NRF_DRV_TWI_FREQ_100K,
.interrupt_priority = APP_IRQ_PRIORITY_LOW,
.clear_bus_init = false
};
// @brief TWI events handler.
void I2C_handler(nrf_drv_twi_evt_t const * p_event, void * p_context)
{
switch (p_event->type)
{
case NRF_DRV_TWI_EVT_DONE:
//todo -difference between read and write???
m_xfer_done = true;
if (p_event->xfer_desc.type == NRF_DRV_TWI_XFER_RX)
{
}
break;
default:
break;
}
}
//last one is some kind of context - no idea what that is....
//documentation is vague/nonexistant
err_code = nrf_drv_twi_init(&i2c, &i2c_config, I2C_handler, NULL);
APP_ERROR_CHECK(err_code);
nrf_drv_twi_enable(&i2c);
}
void writeByte(uint8_t address, uint8_t subAddress, uint8_t data)
{
uint8_t temp[2];
temp[0] = subAddress;
temp[1] = data;
ret_code_t err_code;
m_xfer_done = false;
err_code = nrf_drv_twi_tx(&i2c, address, &temp[0], 2, true);
APP_ERROR_CHECK(err_code);
while (m_xfer_done == false); //wait until end of transfer
}
uint8_t readByte(uint8_t address, uint8_t subAddress)
{
ret_code_t err_code = 0;
uint8_t value;
m_xfer_done = false;
err_code = nrf_drv_twi_tx(&i2c, address, &subAddress, 1, true);
APP_ERROR_CHECK(err_code);
while (m_xfer_done == false); //wait until end of transfer
if (err_code == NRF_SUCCESS)
{
m_xfer_done = false;
err_code = nrf_drv_twi_rx(&i2c, address, &value, 1);
APP_ERROR_CHECK(err_code);
while (m_xfer_done == false);
};
return value;
}
void readBytes(uint8_t address, uint8_t subAddress, uint8_t * dest, uint8_t n_bytes )
{
ret_code_t err_code = 0;
m_xfer_done = false;
err_code = nrf_drv_twi_tx(&i2c, address, &subAddress, 1, true);
while (m_xfer_done == false) {};
if (err_code == NRF_SUCCESS)
{
m_xfer_done = false;
err_code = nrf_drv_twi_rx(&i2c, address, dest, n_bytes);
while (m_xfer_done == false) {};
};
}
void BME280_Turn_On(void)
{
uint8_t e = readByte(BME280_ADDRESS_1, BME280_ID);
NRF_LOG_INFO("BME280 ID:%d Should be = 96\n", e);
if(e == 0x60) {
writeByte( BME280_ADDRESS_1, BME280_RESET, 0xB6 ); // reset BME280 before initialization
nrf_delay_ms(100);
BME280_Configure( BME280_ADDRESS_1 ); // Initialize BME280 altimeter
nrf_delay_ms(100);
};
}
void BME280_Configure( uint8_t address )
{
// Configure the BME280
// Set H oversampling rate
writeByte(address, BME280_CTRL_HUM, 0x07 & Hosr);
// Set T and P oversampling rates and sensor mode
writeByte(address, BME280_CTRL_MEAS, Tosr << 5 | Posr << 2 | Mode);
// Set standby time interval in normal mode and bandwidth
writeByte(address, BME280_CONFIG, SBy << 5 | IIRFilter << 2);
readBytes(address, BME280_CALIB00, calib26, 26);
dig_T1 = (uint16_t)(((uint16_t) calib26[ 1] << 8) | calib26[ 0]);
//NRF_LOG_DEBUG("BME280T1:%d\r\n",dig_T1);
dig_T2 = ( int16_t)((( int16_t) calib26[ 3] << 8) | calib26[ 2]);
//NRF_LOG_DEBUG("BME280T2:%d\r\n",dig_T2);
dig_T3 = ( int16_t)((( int16_t) calib26[ 5] << 8) | calib26[ 4]);
//NRF_LOG_DEBUG("BME280T3:%d\r\n",dig_T3);
dig_P1 = (uint16_t)(((uint16_t) calib26[ 7] << 8) | calib26[ 6]);
//NRF_LOG_DEBUG("BME280P1:%d\r\n",dig_P1);
dig_P2 = ( int16_t)((( int16_t) calib26[ 9] << 8) | calib26[ 8]);
dig_P3 = ( int16_t)((( int16_t) calib26[11] << 8) | calib26[10]);
dig_P4 = ( int16_t)((( int16_t) calib26[13] << 8) | calib26[12]);
dig_P5 = ( int16_t)((( int16_t) calib26[15] << 8) | calib26[14]);
dig_P6 = ( int16_t)((( int16_t) calib26[17] << 8) | calib26[16]);
dig_P7 = ( int16_t)((( int16_t) calib26[19] << 8) | calib26[18]);
dig_P8 = ( int16_t)((( int16_t) calib26[21] << 8) | calib26[20]);
dig_P9 = ( int16_t)((( int16_t) calib26[23] << 8) | calib26[22]);
//24 is missing - this is not typo - complain to Bosch
dig_H1 = calib26[25];
readBytes(address, BME280_CALIB26, calib7, 7);
dig_H2 = ( int16_t)((( int16_t) calib7[1] << 8) | calib7[0]);
dig_H3 = calib7[2];
dig_H4 = ( int16_t)(((( int16_t) calib7[3] << 8) | (0x0F & calib7[4]) << 4) >> 4);
dig_H5 = ( int16_t)(((( int16_t) calib7[5] << 8) | (0xF0 & calib7[4]) ) >> 4 );
dig_H6 = calib7[6];
}
void BME280_Get_Data(int32_t * resultPTH)
{
writeByte(BME280_ADDRESS_1, BME280_CTRL_MEAS, Tosr << 5 | Posr << 2 | Mode);
readBytes(BME280_ADDRESS_1, BME280_PRESS_MSB, rawData, 8);
//Pressure
result[0] = (uint32_t) (((uint32_t) rawData[0] << 16 | (uint32_t) rawData[1] << 8 | rawData[2]) >> 4);
result[1] = (uint32_t) (((uint32_t) rawData[3] << 16 | (uint32_t) rawData[4] << 8 | rawData[5]) >> 4);
result[2] = (uint16_t) (((uint16_t) rawData[6] << 8 | rawData[7]) );
//Need t_fine for all three compensations
adc_T = result[1];
var1 = (((( adc_T >> 3) - ((int32_t)dig_T1 << 1))) * ((int32_t)dig_T2)) >> 11;
var2 = (((((adc_T >> 4) - ((int32_t)dig_T1)) * ((adc_T >> 4) - ((int32_t)dig_T1))) >> 12) * ((int32_t)dig_T3)) >> 14;
t_fine = var1 + var2;
// Returns humidity in %RH as unsigned 32 bit integer in Q22.10 format (22integer and 10fractional bits).
// Output value of “47445”represents 47445/1024= 46.333%RH
uint32_t BME280_Compensate_H(int32_t adc_H, int32_t t_fine)
{
int32_t varH;
varH = (t_fine - ((int32_t)76800));
varH = (((((adc_H << 14) - (((int32_t)dig_H4) << 20) - (((int32_t)dig_H5) * varH)) +
((int32_t)16384)) >> 15) * (((((((varH * ((int32_t)dig_H6)) >> 10) * (((varH *
((int32_t)dig_H3)) >> 11) + ((int32_t)32768))) >> 10) + ((int32_t)2097152)) * ((int32_t)dig_H2) + 8192) >> 14));
varH = (varH - (((((varH >> 15) * (varH >> 15)) >> 7) * ((int32_t)dig_H1)) >> 4));
varH = (varH < 0 ? 0 : varH);
varH = (varH > 419430400 ? 419430400 : varH);
return(uint32_t)(varH >> 12);
}
// Returns temperature in DegC, resolution is 0.01 DegC. Output value of
// “5123” equals 51.23 DegC.
int32_t BME280_Compensate_T(int32_t t_fine)
{
int32_t T;
//var1 = ((((adc_T >> 3) - ((int32_t)dig_T1 << 1))) * ((int32_t)dig_T2)) >> 11;
//var2 = (((((adc_T >> 4) - ((int32_t)dig_T1)) * ((adc_T >> 4) - ((int32_t)dig_T1))) >> 12) * ((int32_t)dig_T3)) >> 14;
//t_fine = var1 + var2;
T = (t_fine * 5 + 128) >> 8;
return T;
}
// Returns pressure in Pa as unsigned 32 bit integer. Output value of “96386” equals 96386 Pa = 963.86 hPa
uint32_t BME280_Compensate_P(int32_t adc_P, int32_t t_fine)
{
varP1 = (t_fine>>1) - (int32_t)64000;
varP2 = (((varP1>>2) * (varP1>>2)) >> 11 ) * ((int32_t)dig_P6);
varP2 = varP2 + ((varP1*((int32_t)dig_P5))<<1);
varP2 = (varP2>>2)+(((int32_t)dig_P4)<<16);
varP1 = (((dig_P3 * (((varP1>>2) * (varP1>>2)) >> 13 )) >> 3) + ((((int32_t)dig_P2) * varP1)>>1))>>18;
varP1 = ((((32768+varP1))*((int32_t)dig_P1))>>15);
if (varP1 == 0)
{
return 0; // avoid exception caused by division by zero
}
P = (((uint32_t)(((int32_t)1048576)-adc_P)-(varP2>>12)))*3125;
if (P < 0x80000000)
{
P = (P << 1) / ((uint32_t)varP1);
}
else
{
P = (P / (uint32_t)varP1) * 2;
}
varP1 = (((int32_t)dig_P9) * ((int32_t)(((P>>3) * (P>>3))>>13)))>>12;
varP2 = (((int32_t)(P>>2)) * ((int32_t)dig_P8))>>13;
P = (uint32_t)((int32_t)P + ((varP1 + varP2 + dig_P7) >> 4));
return P;
}
resultPTH[0] = BME280_Compensate_P(result[0], t_fine);
resultPTH[1] = BME280_Compensate_T( t_fine);
resultPTH[2] = BME280_Compensate_H(result[2], t_fine);
//resultPTH[0]/=100;
resultPTH[1]/=100;
resultPTH[2]/=1000;
NRF_LOG_INFO("BME280:Pressure= %d , Tempreture= %d , Humidity= %d\n", resultPTH[0], resultPTH[1], resultPTH[2]);
NRF_LOG_FLUSH();
}
/**@brief Function for starting advertising.
*/
static void advertising_start(void)
{
uint32_t err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST);
APP_ERROR_CHECK(err_code);
}
/**@brief Application main function.
*/
int main(void)
{
bool erase_bonds;
int32_t *sonuc;
int32_t bme280value[3];
I2C_init();
nrf_delay_ms(50);
BME280_Turn_On();
nrf_delay_ms(1000);
uint8_t name= readByte(0x76, 0xD0);
printf("BME280 initilized and its id= %d", name );
// Initialize.
uart_init();
log_init();
timers_init();
buttons_leds_init(&erase_bonds);
power_management_init();
ble_stack_init();
gap_params_init();
gatt_init();
services_init();
advertising_init();
conn_params_init();
// Start execution.
printf("\r\nUART started.\r\n");
NRF_LOG_INFO("Debug logging for UART over RTT started.");
application_timers_start();
advertising_start();
// Enter main loop.
for (;;)
{
idle_state_handle();
// length1 = sprintf(str, "x:%x ", x);
// ble_nus_data_send(&m_nus, str, &length1,m_conn_handle);
}
}
/**
* @}
*/