Working version. ADXL355 data saved to microSD.
adxl355.cpp
- Committer:
- DUR
- Date:
- 2017-09-29
- Revision:
- 0:e2579e8d9b13
File content as of revision 0:e2579e8d9b13:
/**
******************************************************************************
* @file adxl355.cpp
* @author DUR
* @version V1.0.0
* @date 01-Aug-2017
* @brief Library for adxl355 interface.
*
* @par Manual Reference Names:
* 1. "Low Noise, Low Drift, Low Power, 3-Axis MEMS Accelerometers
* ADXL354/ADXL355"
* 9/2016—Revision 0: Initial Version
*
* @par Document History:
*
* Version: 1.0.0 (01/08/2017)
* ----------------------------------------------------------------------------
* Author: DUR
* First release.
* ----------------------------------------------------------------------------
*
@verbatim
================================================================================
##### How to use this file #####
================================================================================
Questa libreria è stata redatta per poter gestire ad alto livello il sensore di
accelerazione ad uscita digitale a 20 bit della Analog Devices ADXL355, dotato
di un bus SPI/I2C per la comunicazione, insieme ad un pin per la segnalazione di
nuovi dati pronti e ben 2 pin di interrupt che sono configurabili per scattare a
seguito di ben precisi eventi interni.
Perché si possa utilizzare questa libreria su di una qualunque piattaforma
hardware, la seguente funzione dovrà poi essere associata a quella di basso
livello:
(+) uint16_t adxl355_spi_transfer(uint8_t * rbuffer, uint32_t rlen)
< trasferimento su bus SPI >;
Nella presente versione della libreria, sono state fatte le seguenti scelte
progettuali:
(+) è stato scelto di utilizzare il bus SPI piuttosto che il bus I2C per la
comunicazione da e verso l'host;
(+) è stato scelto l'utilizzo della sincronizzazione interna (EXT_SYNC = 0x00).
L'accelerometro viene configurato dall'utente, per mezzo di una struttura dati
adxl355_handler, con la quale è possibile definire un setting di parametri
applicativi in base alle differenti esigenze. Nel suo utilizzo è importante tenere
a mente le seguenti osservzioni:
(i) dopo avere lanciato il comando di reset software (adxl355_sw_reset) il
sensore deve essere nuovamente inizializzato (adxl355_init);
(i) per effettuare il self test, il sensore deve già essere in modalità di
acquisizione; il camando adxl355_self_test(true) dovrà essere lanciato
più volte perché ad ogni invocazione del metodo viene appicata una
specifica accelerazione all'interno, e quella che si andrà a rilevare
sarà proprio la differenza tra i valori in g rilevati tra due invocazioni
successive, e che dovrà rispettare i valori imposti dal datasheet.
@endverbatim
******************************************************************************
@attention
<h2><center>© COPYRIGHT(c) 2014 TD Group</center></h2>
The information contained herein is property of TD Group S.p.A.
Licensees are granted free, non-transferable use of the information. NO
WARRANTY of ANY KIND is provided. This heading must NOT be removed from
the file.
******************************************************************************
*/
#define ADXL355_VERSION 1
#define ADXL355_REVISION 0
#define ADXL355_PATCH 0
/* Includes ------------------------------------------------------------------*/
/** @brief Add ONLY the header of THIS source file and not others.
*/
#include "adxl355.h"
/** @addtogroup FILE_FUNCTIONS
* @{
*/
/* Private function prototypes -----------------------------------------------*/
/* Ricava da una maschera di bit, la posizione del primo bit della maschera stessa */
static uint8_t adxl355_get_bit_position(uint8_t gbp_mask);
/* Setting dei parametri */
static uint16_t adxl355_set_parameter(uint8_t sp_reg, uint8_t sp_mask_data, uint8_t sp_data);
/* Lettura valore accelerazione lungo asse X, Y e Z */
static uint16_t adxl355_read_acc_value(adxl355_handler *adxl_acc);
/* Lettura valore di temperatura */
static uint16_t adxl355_read_temp_value(adxl355_handler *adxl_temp);
/* Private variables ---------------------------------------------------------*/
/* Definisce in ogni momento quali misure sono attive */
static adxl355_measure_enabled adxl_measure_on;
/* Exported variables --------------------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/** @defgroup Group1 Private_Functions
* @brief Function used only in this file and NOT visible to the rest of the
* code.
* @{
*/
/**
* @brief Ricava da una maschera di bit, la posizione del primo bit della maschera
* stessa.
* @note No one.
* @param gbp_mask maschera di bit
* @retval uint8_t posizione del primo bit nella maschera
* @todo Nothing.
* @warning No one.
*/
static uint8_t adxl355_get_bit_position(uint8_t gbp_mask)
{
uint8_t gbp_index;
for(gbp_index = 0; gbp_index < 8; gbp_index++)
{
if(((gbp_mask>>gbp_index) & 0x01) != 0)
{
break;
}else{}
}
return gbp_index;
}
/**
* @brief Funzione per la scrittura di un parametro su di un registro dell'accelerometro.
* @note No one.
* @param sp_reg indirizzo del registro da settare
* @param sp_mask_data posizione del/i bit da settare sotto forma di maschera
* @param sp_data valore del/i bit da settare
* @retval uint16_t errore restituito dal metodo (se 0, tutto ok)
* @todo Nothing.
* @warning No one.
*/
static uint16_t adxl355_set_parameter(uint8_t sp_reg, uint8_t sp_mask_data, uint8_t sp_data)
{
uint16_t adxl_sp_error = 0u;
uint8_t adxl_sp_data[2];
/* Lettura del registro */
adxl_sp_data[0] = (uint8_t)((sp_reg << 1) | ADXL355_READ_BYTE_MASK);
adxl_sp_data[1] = 0x00;
if(adxl355_spi_transfer((uint8_t*)&adxl_sp_data, 2) == 0)
{
adxl_sp_data[0] = (uint8_t)((sp_reg << 1) & ADXL355_WRITE_BYTE_MASK);
adxl_sp_data[1] &= (uint8_t)~sp_mask_data;
adxl_sp_data[1] |= (uint8_t)(sp_data << (adxl355_get_bit_position(sp_mask_data)));
/* Scrittura del nuovo valore */
if(adxl355_spi_transfer((uint8_t*)&adxl_sp_data, 2) == 0)
{}
else
{
adxl_sp_error = (uint16_t)__LINE__;//ERRORE SCRITTURA REGISTRO
}
}
else
{
adxl_sp_error = (uint16_t)__LINE__;//ERRORE LETTURA REGISTRO
}
return adxl_sp_error;
}
/**
* @brief Funzione di lettura del dato grezzo di accelerazione lungo gli assi
* X, Y e Z dell'accelerometro.
* @note No one.
* @param adxl_acc puntatore all'handler dell'accelerometro
* @retval uint16_t errore restituito dal metodo (se 0, tutto ok)
* @todo No one.
* @warning No one.
*/
static uint16_t adxl355_read_acc_value(adxl355_handler *adxl_acc)
{
uint16_t adxl_read_acc_error = 0u;
uint8_t adxl_read_acc_data[10];
/* Azzeramento buffer dati SPI */
memset(adxl_read_acc_data, 0x00, 10);
adxl_read_acc_data[0u] = (uint8_t)((ADXL355_XDATA3<<1) | ADXL355_READ_BYTE_MASK);
if(adxl355_spi_transfer((uint8_t*)&adxl_read_acc_data, 10) == 0)
{
adxl_acc->raw_acc_x_value = 0u;
adxl_acc->raw_acc_x_value = (adxl_read_acc_data[1]<<16u) | (adxl_read_acc_data[2]<<8u) | (adxl_read_acc_data[3]);
adxl_acc->raw_acc_x_value = (adxl_acc->raw_acc_x_value>>4u) & ADXL355_20_BIT_MASK;
adxl_acc->raw_acc_y_value = 0u;
adxl_acc->raw_acc_y_value = (adxl_read_acc_data[4]<<16u) | (adxl_read_acc_data[5]<<8u) | (adxl_read_acc_data[6]);
adxl_acc->raw_acc_y_value = (adxl_acc->raw_acc_y_value>>4u) & ADXL355_20_BIT_MASK;
adxl_acc->raw_acc_z_value = 0u;
adxl_acc->raw_acc_z_value = (adxl_read_acc_data[7]<<16u) | (adxl_read_acc_data[8]<<8u) | (adxl_read_acc_data[9]);
adxl_acc->raw_acc_z_value = (adxl_acc->raw_acc_z_value>>4u) & ADXL355_20_BIT_MASK;
}
else
{
adxl_read_acc_error = (uint16_t)__LINE__;//ERRORE LETTURA DATI ACCELERAZIONE
}
return adxl_read_acc_error;
}
/**
* @brief Funzione di lettura del dato grezzo di temperatura fornito dall'accelerometro.
* @note No one.
* @param adxl_temp puntatore all'handler dell'accelerometro
* @retval uint16_t errore restituito dal metodo (se 0, tutto ok)
* @todo No one.
* @warning No one.
*/
static uint16_t adxl355_read_temp_value(adxl355_handler *adxl_temp)
{
uint16_t adxl_read_temp_error = 0u;
uint8_t adxl_read_temp_data[3];
/* Azzeramento buffer dati SPI */
memset(adxl_read_temp_data, 0x00, 3);
adxl_read_temp_data[0u] = (uint8_t)((ADXL355_TEMP2<<1) | ADXL355_READ_BYTE_MASK);
if(adxl355_spi_transfer((uint8_t*)&adxl_read_temp_data, 3) == 0)
{
adxl_temp->raw_temp_value = 0u;
adxl_temp->raw_temp_value = (adxl_read_temp_data[1]<<8u) | adxl_read_temp_data[2];
adxl_temp->raw_temp_value &= ADXL355_12_BIT_MASK;
}
else
{
adxl_read_temp_error = (uint16_t)__LINE__;//ERRORE LETTURA DATI ACCELERAZIONE
}
return adxl_read_temp_error;
}
/**
* @}
*/
/* Exported functions --------------------------------------------------------*/
/** @defgroup Group2 Exported_Functions
* @brief Functions used in this file and also visible to the rest of the
* code.
* @{
*/
/**
* @brief Funzione che restituisce i parametri identificativi del driver.
* @note No one.
* @param adxl355_driver_version puntatore all'identificatore di versione del driver
* @param adxl355_driver_revision puntatore all'identificatore di revisione del driver
* @param adxl355_driver_patch puntatore all'identificatore di patch del driver
* @retval No one.
* @todo No one.
* @warning No one.
*/
void adxl355_driver_info(uint8_t * adxl355_driver_version, uint8_t * adxl355_driver_revision, uint8_t * adxl355_driver_patch)
{
*adxl355_driver_version = ADXL355_VERSION;
*adxl355_driver_revision = ADXL355_REVISION;
*adxl355_driver_patch = ADXL355_PATCH;
}
/**
* @brief Funzione che restituisce l'ID dell'accelerometro.
* @note No one.
* @param adxl355_device_id puntatore all'identificatore del device
* @retval uint16_t errore restituito dal metodo (se 0, tutto ok)
* @todo No one.
* @warning No one.
*/
uint16_t adxl355_who_am_i(uint8_t * adxl355_device_id)
{
uint16_t adxl_whoami_error = 0u;
uint8_t adxl_whoami_data[2];
/* Lettura del registro */
adxl_whoami_data[0] = (uint8_t)((ADXL355_PARTID << 1) | ADXL355_READ_BYTE_MASK);
adxl_whoami_data[1] = 0x00;
if(adxl355_spi_transfer((uint8_t*)&adxl_whoami_data, 2) == 0)
{
*adxl355_device_id = adxl_whoami_data[1];
}
else
{
adxl_whoami_error = (uint16_t)__LINE__;//ERRORE LETTURA ID
}
return adxl_whoami_error;
}
/**
* @brief Funzione di inizializzazione dell'accelerometro.
* @note No one.
* @param adxl_init_handler puntatore all'handler dell'accelerometro
* @retval uint16_t errore restituito dal metodo (se 0, tutto ok)
* @todo No one.
* @warning No one.
*/
uint16_t adxl355_init(adxl355_handler *adxl_init_handler)
{
uint16_t adxl_init_error = 0u;
uint8_t adxl_init_state = 0u;
switch(adxl_init_state)
{
case 0:/* Configurazione range di misura */
if(0u == adxl355_set_parameter(ADXL355_RANGE, ADXL355_RANGE_MASK, (uint8_t)adxl_init_handler->measure_range))
{}
else
{
adxl_init_error = (uint16_t)__LINE__;//ERRORE SETTING RANGE DI MISURA
break;
}
case 1:/* Configurazione output data rate */
if(0u == adxl355_set_parameter(ADXL355_FILTER, ADXL355_ODR_MASK, (uint8_t)adxl_init_handler->out_data_rate))
{}
else
{
adxl_init_error = (uint16_t)__LINE__;//ERRORE SETTING OUTPUT DATA RATE
break;
}
case 2:/* Configurazione polarità interrupt */
if((adxl_init_handler->int1_pin == NULL) &&
(adxl_init_handler->int2_pin == NULL)){}//Se i pin non sono configurati, è inutile configurare la polarità degli interrupt
else
{
if(0u == adxl355_set_parameter(ADXL355_RANGE, ADXL355_ODR_MASK, (adxl_init_handler->int_config.int_act_low==true) ? 0:1))
{}
else
{
adxl_init_error = (uint16_t)__LINE__;//ERRORE SETTING POLARITA' INTERRUPT
break;
}
}
case 3:/* Configurazione interrupt 1 */
if(adxl_init_handler->int1_pin == NULL){}//Se il pin non è configurato, è inutile configurare il relativo interrupt
else
{
if(0u == adxl355_set_parameter(ADXL355_INT_MAP, ADXL355_INT_1_MASK, (uint8_t)adxl_init_handler->int_config.int1_evt))
{}
else
{
adxl_init_error = (uint16_t)__LINE__;//ERRORE SETTING EVENTO ASSOCIATO AD INTERRUPT 1
break;
}
}
case 4:/* Configurazione interrupt 2 */
if(adxl_init_handler->int2_pin == NULL){}//Se il pin non è configurato, è inutile configurare il relativo interrupt
else
{
if(0u == adxl355_set_parameter(ADXL355_INT_MAP, ADXL355_INT_2_MASK, (uint8_t)adxl_init_handler->int_config.int2_evt))
{}
else
{
adxl_init_error = (uint16_t)__LINE__;//ERRORE SETTING EVENTO ASSOCIATO AD INTERRUPT 2
break;
}
}
case 5:/* Stop di tutte le possibili misure */
if(0u == adxl355_start_acquisition(adxl355_none))
{}
else
{
adxl_init_error = (uint16_t)__LINE__;//ERRORE SETTING STOP MISURE
break;
}
case 6:/* Self-test disabilitato */
if(0u == adxl355_self_test(false))
{}
else
{
adxl_init_error = (uint16_t)__LINE__;//ERRORE DISABILITAZIONE SELF-TEST
break;
}
default:
break;
}
return adxl_init_error;
}
/**
* @brief Funzione di start/stop delle acquisizioni.
* @note No one.
* @param adxl_start misura/e da avviare
* @retval uint16_t errore restituito dal metodo (se 0, tutto ok)
* @todo No one.
* @warning No one.
*/
uint16_t adxl355_start_acquisition(adxl355_measure_enabled adxl_start)
{
uint16_t adxl_start_error = 0u;
uint8_t adxl_start_data;
switch(adxl_start)
{
case 0://Solo accelerazione
adxl_start_data = 0x02;
break;
case 1://Entrambe le misure (accelerazione e temperatura)
adxl_start_data = 0x00;
break;
case 2://Nessuna misura (mette in standby il sensore)
adxl_start_data = 0x03;
break;
default:
break;
}
if(0u == adxl355_set_parameter(ADXL355_POWER_CTL, ADXL355_MEAS_MASK, adxl_start_data))
{
adxl_measure_on = adxl_start;
}
else
{
adxl_start_error = (uint16_t)__LINE__;//ERRORE SETTING RANGE DI MISURA
}
return adxl_start_error;
}
/**
* @brief Funzione per la lettura del/i dato/i acquisito/i.
* @note No one.
* @param adxl_data_handler puntatore all'handler dell'accelerometro
* @retval uint16_t errore restituito dal metodo (se 0, tutto ok)
* @todo No one.
* @warning No one.
*/
uint16_t adxl355_get_data(adxl355_handler *adxl_data_handler)
{
uint16_t adxl_data_error = 0u;
if((adxl_measure_on == adxl355_acc) || (adxl_measure_on == adxl355_both))
{ /* Lettura accelerazione */
if(adxl355_read_acc_value(adxl_data_handler) == 0u)
{
if(adxl_measure_on == adxl355_both)
{ /* Lettura temperatura */
if(adxl355_read_temp_value(adxl_data_handler) == 0u)
{}
else
{
adxl_data_error = (uint16_t)__LINE__;//ERRORE LETTURA MISURA TEMPERATURA
}
}
else{}
}
else
{
adxl_data_error = (uint16_t)__LINE__;//ERRORE LETTURA MISURA ACCELERAZIONE
}
}else{}
return adxl_data_error;
}
/**
* @brief Funzione che restituisce il valore grezzo di accelerazione lungo l'asse X.
* @note No one.
* @param adxl_xdata_handler puntatore all'handler dell'accelerometro
* @retval uint32_t valore grezzo accelerazione
* @todo No one.
* @warning No one.
*/
uint32_t adxl355_raw_x_acc(adxl355_handler *adxl_xdata_handler)
{
return adxl_xdata_handler->raw_acc_x_value;
}
/**
* @brief Funzione che restituisce il valore grezzo di accelerazione lungo l'asse Y.
* @note No one.
* @param adxl_ydata_handler puntatore all'handler dell'accelerometro
* @retval uint32_t valore grezzo accelerazione
* @todo No one.
* @warning No one.
*/
uint32_t adxl355_raw_y_acc(adxl355_handler *adxl_ydata_handler)
{
return adxl_ydata_handler->raw_acc_y_value;
}
/**
* @brief Funzione che restituisce il valore grezzo di accelerazione lungo l'asse Z.
* @note No one.
* @param adxl_zdata_handler puntatore all'handler dell'accelerometro
* @retval uint32_t valore grezzo accelerazione
* @todo No one.
* @warning No one.
*/
uint32_t adxl355_raw_z_acc(adxl355_handler *adxl_zdata_handler)
{
return adxl_zdata_handler->raw_acc_z_value;
}
/**
* @brief Funzione che restituisce il valore grezzo di temperatura.
* @note No one.
* @param adxl_tdata_handler puntatore all'handler dell'accelerometro
* @retval uint16_t valore grezzo temperatura
* @todo No one.
* @warning No one.
*/
uint16_t adxl355_raw_temp(adxl355_handler *adxl_tdata_handler)
{
return adxl_tdata_handler->raw_temp_value;
}
/**
* @brief Funzione per il reset sw.
* @note No one.
* @param No one.
* @retval uint16_t errore restituito dal metodo (se 0, tutto ok)
* @todo No one.
* @warning No one.
*/
uint16_t adxl355_sw_reset(void)
{
uint16_t adxl_swres_error = 0u;
uint8_t adxl_swres_data[2];
/* Lettura del registro */
adxl_swres_data[0] = (uint8_t)((ADXL355_RESET << 1) & ADXL355_WRITE_BYTE_MASK);
adxl_swres_data[1] = ADXL355_RESET_CODE;
if(adxl355_spi_transfer((uint8_t*)&adxl_swres_data, 2) == 0)
{}
else
{
adxl_swres_error = (uint16_t)__LINE__;//ERRORE RESET ACCELEROMETRO
}
return adxl_swres_error;
}
/**
* @brief Funzione per il self-test.
* @note Questo metodo va utilizzato lanciandolo ponendo a true adxl_start
* ad acquisizione in corso; in questa modalità il metodo va lanciato
* diverse volte in modo che si possa registrare la variazione di
* accelerazione sui 3 assi che deve essere, secondo datasheet:
* [X]: 0.3g
* [Y]: 0.3g
* [Z]: 1.5g
* In modalità self-test, il sensore non registra alcuna accelerazione
* esterna; ponendo a false adxl_start, il sensore termina il self-test
* e ritorna in modalità normale di funzionamento.
* @param adxl_start booleano per avviare/fermare il self test
* @retval uint16_t errore restituito dal metodo (se 0, tutto ok)
* @todo No one.
* @warning No one.
*/
uint16_t adxl355_self_test(bool adxl_start)
{
uint16_t adxl_st_error = 0u;
static uint8_t adxl_st2_val = 0u;
if(adxl_start == true)
{
adxl_measure_on = adxl355_acc;
if(0u == adxl355_set_parameter(ADXL355_SELF_TEST, ADXL355_SELF_TEST_MASK, (adxl_st2_val<<1)|ADXL355_SELF_TEST_ENABLE ))
{
if(adxl_st2_val == 0u) adxl_st2_val = 1u;
else adxl_st2_val = 0u;
}
else
{
adxl_st_error = (uint16_t)__LINE__;//ERRORE AVVIO SELF-TEST
}
}
else
{
if(0u == adxl355_set_parameter(ADXL355_SELF_TEST, ADXL355_SELF_TEST_MASK, ADXL355_SELF_TEST_DISABLE))
{
adxl_st2_val = 0u;
}
else
{
adxl_st_error = (uint16_t)__LINE__;//ERRORE STOP SELF-TEST
}
}
return adxl_st_error;
}
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT TD Group *****END OF FILE**************/