I'm trying to get the device ID of the lis3dh accelerometer on a Thingy:52
nrf_drv_twi_tx returns 3 as an error. This means NRF_ERROR_INTERNAL --> "If an error was detected by hardware."
I doubt that my hardware is broken...
I used a driver template: https://github.com/STMicroelectronics/lis3dh/tree/6a82fc90cfb688686d0b344c82184c33ee844697
My code is included in this post. Line 361 is where I'm trying to get the device ID.
Greetings
Willem
/**
* Copyright (c) 2014 - 2021, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/** @file
*
* @defgroup ble_sdk_app_beacon_main main.c
* @{
* @ingroup ble_sdk_app_beacon
* @brief Beacon Transmitter Sample Application main file.
*
* This file contains the source code for an Beacon transmitter sample application.
*/
#include <stdbool.h>
#include <stdint.h>
#include "nordic_common.h"
#include "bsp.h"
#include "nrf_soc.h"
#include "nrf_sdh.h"
#include "nrf_sdh_ble.h"
#include "ble_advdata.h"
#include "app_timer.h"
#include "nrf_pwr_mgmt.h"
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
#include "nrf_delay.h"
#include "lis3dh_reg.c"
//#include "nrfx_twi.h"
#include "nrf_drv_twi.h"
/* TWI instance ID. */
#define TWI_INSTANCE_ID 0
/* TWI instance. */
static const nrf_drv_twi_t m_twi = NRF_DRV_TWI_INSTANCE(TWI_INSTANCE_ID);
uint32_t acc_data= 0xDDDDDDDD; //kan een groter ding zijn = ander type //@nader hier data stekenuint32_t acc_data= 0xDDDDDDDD; //kan een groter ding zijn = ander type //@nader hier data steken
#define APP_BLE_CONN_CFG_TAG 1 /**< A tag identifying the SoftDevice BLE configuration. */
#define NON_CONNECTABLE_ADV_INTERVAL MSEC_TO_UNITS(100, UNIT_0_625_MS) /**< The advertising interval for non-connectable advertisement (100 ms). This value can vary between 100ms to 10.24s). */
#define APP_BEACON_BASE_UUID 0x1d, 0x25, 0x78, 0x0a, \
0x00, 0xe0, 0x46, 0xcc, \
0x8d, 0x0e, 0x5c, 0x90, \
0x00, 0x00, 0xe1, 0x2d /**< Randomly generated UUID */
#define DEAD_BEEF 0xDEADBEEF /**< Value used as error code on stack dump, can be used to identify stack location on stack unwind. */
static ble_gap_adv_params_t m_adv_params; /**< Parameters to be passed to the stack when starting advertising. */
static uint8_t m_adv_handle = BLE_GAP_ADV_SET_HANDLE_NOT_SET; /**< Advertising handle used to identify an advertising set. */
static uint8_t m_enc_advdata[BLE_GAP_ADV_SET_DATA_SIZE_MAX]; /**< Buffer for storing an encoded advertising set. */
static ble_uuid_t m_adv_uuids[] = {{UUID, BLE_UUID_TYPE_VENDOR_BEGIN}}; /**< Universally unique service identifiers. */
/**@brief 128-bit UUID base List. */
static const ble_uuid128_t m_base_uuid128 =
{
.uuid128 = {
APP_BEACON_BASE_UUID
}
};
static ble_uuid_t service_uuid;
/**@brief Struct that contains pointers to the encoded advertising data. */
static ble_gap_adv_data_t m_adv_data =
{
.adv_data =
{
.p_data = m_enc_advdata,
.len = BLE_GAP_ADV_SET_DATA_SIZE_MAX
},
.scan_rsp_data =
{
.p_data = NULL,
.len = 0
}
};
/**@brief Callback function for asserts in the SoftDevice.
*
* @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 analyze
* 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] 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);
}
/**@brief Function for initializing the Advertising functionality.
*
* @details Encodes the required advertising data and passes it to the stack.
* Also builds a structure to be passed to the stack when starting advertising.
*/
static void advertising_init(void)
{
uint32_t err_code;
ble_advdata_t advdata;
// Build and set advertising data.
memset(&advdata, 0, sizeof(advdata));
advdata.uuids_complete.p_uuids = m_adv_uuids;
advdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
// add manufacturing data (accelerometer data)
ble_advdata_manuf_data_t manuf_data;
manuf_data.company_identifier = 0x0000;
//TODO iets met accelerometer driver
manuf_data.data.p_data = (uint8_t *) &acc_data;
manuf_data.data.size = sizeof(acc_data);
advdata.p_manuf_specific_data = &manuf_data;
// Initialize advertising parameters (used when starting advertising).
memset(&m_adv_params, 0, sizeof(m_adv_params));
m_adv_params.properties.type = BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED;
m_adv_params.p_peer_addr = NULL; // Undirected advertisement.
m_adv_params.filter_policy = BLE_GAP_ADV_FP_ANY;
m_adv_params.interval = NON_CONNECTABLE_ADV_INTERVAL;
m_adv_params.duration = 0; // Never time out.
err_code = ble_advdata_encode(&advdata, m_adv_data.adv_data.p_data, &m_adv_data.adv_data.len);
APP_ERROR_CHECK(err_code);
err_code = sd_ble_gap_adv_set_configure(&m_adv_handle, &m_adv_data, &m_adv_params);
APP_ERROR_CHECK(err_code);
}
/**@brief Function for starting advertising.
*/
static void advertising_start(void)
{
ret_code_t err_code;
err_code = sd_ble_gap_adv_start(m_adv_handle, APP_BLE_CONN_CFG_TAG);
APP_ERROR_CHECK(err_code);
err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING);
APP_ERROR_CHECK(err_code);
}
/**@brief Function for initializing the BLE stack.
*
* @details 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);
}
/**@brief Function for initializing logging. */
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 the LEDs initialization.
*
* @details Initializes all LEDs used by the application.
*/
/*
static void leds_init(void)
{
bsp_board_init(BSP_INIT_LEDS);
}
*/
/**@brief Function for initializing timers. */
static void timers_init(void)
{
ret_code_t err_code = app_timer_init();
APP_ERROR_CHECK(err_code);
}
/**@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();
}
}
/*
* @brief Write generic device register (platform dependent)
*
* @param handle customizable argument. In this examples is used in
* order to select the correct sensor bus handler.
* @param reg register to write
* @param bufp pointer to data to write in register reg
* @param len number of consecutive register to write
*
*/
static int32_t platform_write(void *handle, uint8_t const * reg, const uint8_t *bufp,
uint16_t len)
{
return nrf_drv_twi_tx(handle, LIS3DH_I2C_ADD_L, reg, 1, false);
}
/*
* @brief Read generic device register (platform dependent)
*
* @param handle customizable argument. In this examples is used in
* order to select the correct sensor bus handler.
* @param reg register to read
* @param bufp pointer to buffer that store the data read
* @param len number of consecutive register to read
*
*/
static int32_t platform_read(void *handle, uint8_t * reg, uint8_t *bufp,
uint16_t len)
{
return nrf_drv_twi_rx(handle, LIS3DH_I2C_ADD_L, reg, sizeof(reg));
}
/*
* @brief platform specific delay (platform dependent)
*
* @param ms delay in ms
*
*/
static void platform_delay(uint32_t ms)
{
nrf_delay_ms(ms);
}
/*
* @brief platform specific initialization (platform dependent)
*/
static void platform_init(void)
{
nrf_drv_twi_enable(&m_twi);
nrf_delay_ms(50);
void twi_master_init(void); //Initialize i2c
nrf_delay_ms(50);
}
static void accelerometer_init(void)
{
/* Private variables Accelerometer*/
int16_t data_raw_acceleration[3];;
float acceleration_mg[3];
uint8_t whoamI = 15;
uint32_t err = 1;
/* Initialize mems driver interface */
stmdev_ctx_t dev_ctx;
dev_ctx.write_reg = (stmdev_write_ptr) platform_write;
dev_ctx.read_reg = (stmdev_read_ptr) platform_read;
dev_ctx.handle = (void*) &m_twi;
/* Wait boot time and initialize platform specific hardware */
platform_init();
/* Wait sensor boot time */
platform_delay(10);
/* Check device ID */
err = lis3dh_device_id_get(&dev_ctx, &whoamI);
if (err != NRF_SUCCESS)
NRF_LOG_ERROR("Device ID get error");
if (whoamI != LIS3DH_ID) {
while (1) {
/* manage here device not found */
}
}
/* Enable Block Data Update. */
lis3dh_block_data_update_set(&dev_ctx, PROPERTY_ENABLE);
/* Set Output Data Rate to 1Hz. */
lis3dh_data_rate_set(&dev_ctx, LIS3DH_ODR_1Hz);
/* Set full scale to 2g. */
lis3dh_full_scale_set(&dev_ctx, LIS3DH_2g);
/* Enable temperature sensor. */
lis3dh_aux_adc_set(&dev_ctx, LIS3DH_AUX_ON_TEMPERATURE);
/* Set device in continuous mode with 12 bit resol. */
lis3dh_operating_mode_set(&dev_ctx, LIS3DH_HR_12bit);
/* Read samples in polling mode (no int) */
while (1) {
lis3dh_reg_t reg;
/* Read output only if new value available */
lis3dh_xl_data_ready_get(&dev_ctx, ®.byte);
if (reg.byte) {
/* Read accelerometer data */
memset(data_raw_acceleration, 0x00, 3 * sizeof(int16_t));
lis3dh_acceleration_raw_get(&dev_ctx, data_raw_acceleration);
acceleration_mg[0] =
lis3dh_from_fs2_hr_to_mg(data_raw_acceleration[0]);
acceleration_mg[1] =
lis3dh_from_fs2_hr_to_mg(data_raw_acceleration[1]);
acceleration_mg[2] =
lis3dh_from_fs2_hr_to_mg(data_raw_acceleration[2]);
NRF_LOG_RAW_INFO("Acceleration [mg]:%4.2f\t%4.2f\t%4.2f\r\n",
acceleration_mg[0], acceleration_mg[1], acceleration_mg[2]);
}
//Store accelerometer data for advertisment
////acc_data = data_raw_acceleration;
}
}
/**
* @brief Function for application main entry.
*/
int main(void)
{
// Initialize.
NRF_LOG_INFO("Initializing...");
log_init();
timers_init();
power_management_init();
ble_stack_init();
// add UUID to the BLE stack's table
uint32_t err_code;
err_code = sd_ble_uuid_vs_add(&m_base_uuid128, &service_uuid.type);
if (err_code != NRF_SUCCESS){
NRF_LOG_ERROR("Error adding base UUID: %d", err_code);
}
accelerometer_init();
advertising_init();
// Start execution.
NRF_LOG_INFO("Glass beacon started.");
advertising_start();
// Enter main loop.
for (;;)
{
idle_state_handle();
}
}
/**
* @}
*/
