26 sfg->pStatusSubsystem->
set(sfg->pStatusSubsystem, status);
33 return sfg->pStatusSubsystem->
get(sfg->pStatusSubsystem);
40 sfg->pStatusSubsystem->
queue(sfg->pStatusSubsystem, status);
47 sfg->pStatusSubsystem->
update(sfg->pStatusSubsystem);
52 sfg->pStatusSubsystem->
test(sfg->pStatusSubsystem);
75 sfg->pControlSubsystem = pControlSubsystem;
76 sfg->pStatusSubsystem = pStatusSubsystem;
96 sfg->Accel.iWhoAmI = 0;
102 sfg->Gyro.iWhoAmI = 0;
105 sfg->Pressure.iWhoAmI = 0;
118 initializeSensor_t *initialize,
121 if (sfg && pSensor && initialize && read)
134 pSensor->
read = read;
136 pSensor->
addr = addr;
156 for (pSensor = sfg->
pSensors; pSensor != NULL; pSensor = pSensor->
next)
159 if (status == 0) status = s;
171 if (sfg->Accel.iFIFOExceeded > 0) {
178 for (j =
CHX; j <=
CHZ; j++) iSum[j] = 0;
179 for (i = 0; i < sfg->Accel.iFIFOCount; i++)
180 for (j =
CHX; j <=
CHZ; j++) iSum[j] += sfg->Accel.iGsFIFO[i][j];
181 if (sfg->Accel.iFIFOCount > 0)
183 for (j =
CHX; j <=
CHZ; j++)
185 sfg->Accel.iGs[j] = (int16_t)(iSum[j] / (int32_t) sfg->Accel.iFIFOCount);
186 sfg->Accel.fGs[j] = (float)sfg->Accel.iGs[j] * sfg->Accel.fgPerCount;
198 &(sfg->pControlSubsystem->AccelCalPacketOn));
216 for (j =
CHX; j <=
CHZ; j++) iSum[j] = 0;
221 for (j =
CHX; j <=
CHZ; j++)
231 fInvertMagCal(&(sfg->
Mag), &(sfg->
MagCal));
246 if (sfg->Gyro.iFIFOExceeded > 0) {
256 for (j =
CHX; j <=
CHZ; j++) iSum[j] = 0;
257 for (i = 0; i < sfg->Gyro.iFIFOCount; i++)
258 for (j =
CHX; j <=
CHZ; j++)
259 iSum[j] += sfg->Gyro.iYsFIFO[i][j];
260 if (sfg->Gyro.iFIFOCount > 0)
262 for (j =
CHX; j <=
CHZ; j++)
264 sfg->Gyro.iYs[j] = (int16_t)(iSum[j] / (int32_t) sfg->Gyro.iFIFOCount);
265 sfg->Gyro.fYs[j] = (float)sfg->Gyro.iYs[j] * sfg->Gyro.fDegPerSecPerCount;
279 uint8_t read_loop_counter
284 int8_t status = SENSOR_ERROR_NONE;
288 for (pSensor = sfg->
pSensors; pSensor != NULL; pSensor = pSensor->
next)
290 if ( 0 == (read_loop_counter % pSensor->
schedule)) {
292 s = pSensor->
read(pSensor, sfg);
293 if(s != SENSOR_ERROR_NONE) {
298 if (status == SENSOR_ERROR_NONE) status = s;
304 if (s != SENSOR_ERROR_NONE) {
310 if (status == SENSOR_ERROR_NONE) {
327 if (sfg->Accel.isEnabled) processAccelData(sfg);
335 if (sfg->Gyro.isEnabled) processGyroData(sfg);
348 for (i=0; i<numElements; i++) d8[i]=0;
352 for (i=0; i<numElements; i++) d16[i]=0;
356 for (i=0; i<numElements; i++) d32[i]=0;
365 for (i=0; i<numElements; i++)
370 for (i=0; i<numElements; i++)
375 for (i=0; i<numElements; i++)
389 sfg->Accel.iFIFOCount=0;
390 sfg->Accel.iFIFOExceeded =
false;
397 sfg->Gyro.iFIFOCount=0;
398 sfg->Gyro.iFIFOExceeded =
false;
422 pSV_1DOF_P_BASIC = &(sfg->SV_1DOF_P_BASIC);
424 pSV_1DOF_P_BASIC = NULL;
427 pSV_3DOF_G_BASIC = &(sfg->SV_3DOF_G_BASIC) ;
429 pSV_3DOF_G_BASIC = NULL;
432 pSV_3DOF_B_BASIC = &(sfg->SV_3DOF_B_BASIC);
434 pSV_3DOF_B_BASIC = NULL;
437 pSV_3DOF_Y_BASIC = &(sfg->SV_3DOF_Y_BASIC);
439 pSV_3DOF_Y_BASIC = NULL;
442 pSV_6DOF_GB_BASIC = &(sfg->SV_6DOF_GB_BASIC);
444 pSV_6DOF_GB_BASIC = NULL;
447 pSV_6DOF_GY_KALMAN = &(sfg->SV_6DOF_GY_KALMAN);
449 pSV_6DOF_GY_KALMAN = NULL;
452 pSV_9DOF_GBY_KALMAN = &(sfg->SV_9DOF_GBY_KALMAN);
454 pSV_9DOF_GBY_KALMAN = NULL;
457 pAccel = &(sfg->Accel);
469 pGyro = &(sfg->Gyro);
474 pPressure = &(sfg->Pressure);
481 fFuseSensors(pSV_1DOF_P_BASIC, pSV_3DOF_G_BASIC,
482 pSV_3DOF_B_BASIC, pSV_3DOF_Y_BASIC,
483 pSV_6DOF_GB_BASIC, pSV_6DOF_GY_KALMAN,
484 pSV_9DOF_GBY_KALMAN, pAccel, pMag, pGyro,
499 int16_t status = SENSOR_ERROR_NONE;
501 pComm = sfg->pControlSubsystem;
507 status = initializeSensors(sfg);
508 if (status!=SENSOR_ERROR_NONE) {
514 pComm->DefaultQuaternionPacketType =
Q3;
520 pComm->QuaternionPacketType = pComm->DefaultQuaternionPacketType ;
523 fInitializeFusion(sfg);
540 if( status == SENSOR_ERROR_NONE ) {
555 if (sample[
CHX] == -32768) sample[
CHX]++;
556 if (sample[
CHY] == -32768) sample[
CHY]++;
557 if (sample[
CHZ] == -32768) sample[
CHZ]++;
568 if (fifoCount < maxFifoSize) {
#define F_USING_TEMPERATURE
nominally 0x0010 if temp sensor is to be used, 0x0000 otherwise
#define F_9DOF_GBY_KALMAN
9DOF accel, mag and gyro algorithm selector - 0x4000 to include, 0x0000 otherwise/*#end#*/
#define F_ALL_SENSORS
refers to all applicable sensor types for the given physical unit
#define F_6DOF_GY_KALMAN
6DOF accel and gyro (Kalman) algorithm selector - 0x2000 to include, 0x0000 otherwise/*#end#*/
#define F_1DOF_P_BASIC
1DOF pressure (altitude) and temperature algorithm selector - 0x0100 to include, 0x0000 otherwise/*#e...
#define F_USING_MAG
nominally 0x0002 if an magnetometer is to be used, 0x0000 otherwise
#define F_USING_ACCEL
nominally 0x0001 if an accelerometer is to be used, 0x0000 otherwise
#define F_3DOF_Y_BASIC
3DOF gyro integration algorithm selector - 0x0800 to include, 0x0000 otherwise/*#end#*/
#define F_6DOF_GB_BASIC
6DOF accel and mag eCompass algorithm selector - 0x1000 to include, 0x0000 otherwise/*#end#*/
#define F_USING_PRESSURE
nominally 0x0008 if altimeter is to be used, 0x0000 otherwise
#define F_3DOF_G_BASIC
3DOF accel tilt (accel) algorithm selector - 0x0200 to include, 0x0000 otherwise/*#end#*/
#define F_USING_NONE
0x0000 indicates a sensor is unavailable / unconfigured.
#define F_USING_GYRO
nominally 0x0004 if a gyro is to be used, 0x0000 otherwise
#define F_3DOF_B_BASIC
3DOF mag eCompass (vehicle/mag) algorithm selector - 0x0400 to include, 0x0000 otherwise/*#end#*/
Defines control sub-system.
Lower level sensor fusion interface.
void ApplyMagHAL(struct MagSensor *Mag)
Apply the magnetometer Hardware Abstraction Layer.
void ApplyGyroHAL(struct GyroSensor *Gyro)
Apply the gyroscope Hardware Abstraction Layer.
void ApplyAccelHAL(struct AccelSensor *Accel)
Apply the accelerometer Hardware Abstraction Layer.
bool I2CInitialize(int pin_sda, int pin_scl)
Initialize the I2C system at max clock rate supported by sensors. pin_sda and pin_scl indicate the pi...
The hal_i2c.h file declares low-level interface functions for reading and writing sensor registers us...
Wrapper for Hardware Abstraction Layer (HAL) Contains replacements for hardware-specific functions Cu...
void fRunMagCalibration(struct MagCalibration *pthisMagCal, struct MagBuffer *pthisMagBuffer, struct MagSensor *pthisMag, int32_t loopcounter)
Run the magnetic calibration. Calibration is done in time-slices, to avoid excessive CPU load during ...
void fUpdateAccelBuffer(AccelCalibration *pthisAccelCal, AccelBuffer *pthisAccelBuffer, struct AccelSensor *pthisAccel, volatile int8_t *AccelCalPacketOn)
Update the buffer used to store samples used for accelerometer calibration.
void fInvertAccelCal(struct AccelSensor *pthisAccel, AccelCalibration *pthisAccelCal)
function maps the accelerometer data fGs (g) onto precision calibrated and de-rotated data fGc (g),...
void fInitializeAccelCalibration(AccelCalibration *pthisAccelCal, AccelBuffer *pthisAccelBuffer, volatile int8_t *AccelCalPacketOn)
Initialize the accelerometer calibration functions.
void conditionSample(int16_t sample[3])
conditionSample ensures that we never encounter the maximum negative two's complement value for a 16-...
void initSensorFusionGlobals(SensorFusionGlobals *sfg, StatusSubsystem *pStatusSubsystem, ControlSubsystem *pControlSubsystem)
utility function to insert default values in the top level structure
fusion_status_t getStatus(SensorFusionGlobals *sfg)
void setStatus(SensorFusionGlobals *sfg, fusion_status_t status)
void clearFIFOs(SensorFusionGlobals *sfg)
Function to clear FIFO at the end of each fusion computation.
void updateStatus(SensorFusionGlobals *sfg)
void zeroArray(StatusSubsystem *pStatus, void *data, uint16_t size, uint16_t numElements, uint8_t check)
void addToFifo(union FifoSensor *sensor, uint16_t maxFifoSize, int16_t sample[3])
addToFifo is called from within sensor driver read functions
void queueStatus(SensorFusionGlobals *sfg, fusion_status_t status)
void conditionSensorReadings(SensorFusionGlobals *sfg)
The sensor_fusion.h file implements the top level programming interface.
#define CHX
Used to access X-channel entries in various data data structures.
@ Q6MA
Quaternion derived from 3-axis accel + 3 axis mag (eCompass)
@ Q3
Quaternion derived from 3-axis accel (tilt)
@ Q6AG
Quaternion derived from 3-axis accel + 3-axis gyro (gaming)
@ Q9
Quaternion derived from full 9-axis sensor fusion.
@ Q3M
Quaternion derived from 3-axis mag only (auto compass algorithm)
@ Q3G
Quaternion derived from 3-axis gyro only (rotation)
fusion_status_t
Application-specific serial communications system.
@ HARD_FAULT
Non-recoverable FAULT = something went very wrong.
@ NORMAL
Operation is Nominal.
@ INITIALIZING
Initializing sensors and algorithms.
@ SOFT_FAULT
Recoverable FAULT = something went wrong, but we can keep going.
#define CHY
Used to access Y-channel entries in various data data structures.
#define CHZ
Used to access Z-channel entries in various data data structures.
applyPerturbation_t ApplyPerturbation
ApplyPerturbation is a reverse unit-step test function.
Application-specific status subsystem.
The AccelSensor structure stores raw and processed measurements for a 3-axis accelerometer.
uint8_t iFIFOCount
number of measurements read from FIFO
uint16_t iFIFOExceeded
Number of samples received in excess of software FIFO size.
int16_t iGsFIFO[ACCEL_FIFO_SIZE][3]
FIFO measurements (counts)
The ControlSubsystem encapsulates command and data streaming functions.
The GyroSensor structure stores raw and processed measurements for a 3-axis gyroscope.
Magnetic Calibration Structure.
int8_t iMagBufferReadOnly
flag to denote that the magnetic measurement buffer is temporarily read only
The MagSensor structure stores raw and processed measurements for a 3-axis magnetic sensor.
uint8_t iFIFOCount
number of measurements read from FIFO
float fuTPerCount
uT per count
float fBs[3]
averaged un-calibrated measurement (uT)
uint8_t iWhoAmI
sensor whoami
int16_t iBsFIFO[MAG_FIFO_SIZE][3]
FIFO measurements (counts)
uint16_t iFIFOExceeded
Number of samples received in excess of software FIFO size.
bool isEnabled
true if the device is sampling
int16_t iBs[3]
averaged uncalibrated measurement (counts)
An instance of PhysicalSensor structure type should be allocated for each physical sensors (combo dev...
registerDeviceInfo_t deviceInfo
I2C device context.
readSensor_t * read
pointer to function to read sensor using the supplied drivers
uint16_t addr
I2C address if applicable.
initializeSensor_t * initialize
pointer to function to initialize sensor using the supplied drivers
uint16_t isInitialized
Bitfields to indicate sensor is active (use SensorBitFields from build.h)
struct PhysicalSensor * next
pointer to next sensor in this linked list
uint8_t schedule
Parameter to control sensor sampling rate.
The PressureSensor structure stores raw and processed measurements for an altimeter.
The SV_1DOF_P_BASIC structure contains state information for a pressure sensor/altimeter.
This is the 3DOF basic magnetometer state vector structure/.
This is the 3DOF basic accelerometer state vector structure.
SV_3DOF_Y_BASIC structure is the 3DOF basic gyroscope state vector structure.
SV_6DOF_GB_BASIC is the 6DOF basic accelerometer and magnetometer state vector structure.
SV_6DOF_GY_KALMAN is the 6DOF Kalman filter accelerometer and gyroscope state vector structure.
SV_9DOF_GBY_KALMAN is the 9DOF Kalman filter accelerometer, magnetometer and gyroscope state vector s...
The top level fusion structure.
struct MagCalibration MagCal
mag cal storage
initializeFusionEngine_t * initializeFusionEngine
set sensor fusion structures to initial values
clearFIFOs_t * clearFIFOs
clear sensor FIFOs
installSensor_t * installSensor
function for installing a new sensor
struct PhysicalSensor * pSensors
a linked list of physical sensors
int32_t systick_I2C
systick counter to benchmark I2C reads
updateStatus_t * testStatus
increment to next enumerated status value (test only)
applyPerturbation_t * applyPerturbation
apply step function for testing purposes
setStatus_t * queueStatus
queue status change for next regular interval
conditionSensorReadings_t * conditionSensorReadings
preprocessing step for sensor fusion
struct MagBuffer MagBuffer
mag cal constellation points
getStatus_t * getStatus
fetch the current status from the Status Subsystem
struct MagSensor Mag
magnetometer storage
int32_t systick_Spare
systick counter for counts spare waiting for timing interrupt
int32_t loopcounter
counter incrementing each iteration of sensor fusion (typically 25Hz)
runFusion_t * runFusion
run the fusion routines
volatile uint8_t iPerturbation
test perturbation to be applied
readSensors_t * readSensors
read all physical sensors
setStatus_t * setStatus
change status indicator immediately
updateStatus_t * updateStatus
status=next status
uint32_t iFlags
a bit-field of sensors and algorithms used
StatusSubsystem() provides an object-like interface for communicating status to the user.
ssUpdateStatus_t * update
make pending status active/visible
ssUpdateStatus_t * test
unit test which simply increments to next state
ssSetStatus_t * set
change status immediately - no delay
ssSetStatus_t * queue
queue status change for next regular interval
ssGetStatus_t * get
return status
This structure defines the device specific info required by register I/O.
The FifoSensor union allows us to use common pointers for Accel, Mag & Gyro logical sensor structures...