Hardware components | ||||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
Software apps and online services | ||||||
|
TL:DR A magnetometer is used to detect whether the parking space is taken or not.
This project will detail the build of a simple smart parking system. The idea is to determine whether a vehicle is occupying a parking spot and notify a hub. Ideally , the Hub would use machine learning to analyze how the parking space are utilized during the year. This would essentially allow real-time based parking pricing.
The project makes use of an Android things single board computer (PICO-NXP-MX6) that is used as a hub that collects data from various parking nodes.
The project is comprised of two components. On one there's a BLE enabled sensor node (hereafter refereed to as a mote) and on the other side there's the PICO MX6 used as a main hub.
ideally I would have used a radio like Lora or Sigfox to provide long range communication between the hub and the parking mote but BLE is all I had at hand.
Project hardwareThe hardware consists of a Arduino BLE board , a 6-axis accelerometer and magnetometer from NXP and the Android thing board.
Sensor firmware.
First I configured the magnetometer in streaming mode just to make sure that everything was working. Then I set it up to stream all three axis data.
To visualize the data-stream I used the Arduino plotter. The plotter expects space delimited data so the format was set as:
mx my mz.
After getting the data stream I approached a magnetic object (headphones and battery) to the magnetometer fairly quickly. This would simulate a car passing over. As you can see the magnetic field is modified since the magnetic field of the metallic object (in this case the car) is added to the geomagnetic field. Depending on how strong the external magnetic field is the spikes are larger.
So now that the concept was proved, the next step was to configured the magnetometer so that it would fire an interrupt once the magnetic field components change due to a metallic (magnetic) object in proximity.
The tiny magnetic field of the metallic parts of the car is added to the vector components of the earth magnetic field resulting in a slightly perturbed resultant field.
The threshold has to be programmed by the user which makes this a bit of a nuisance for automatic deployment.
The firmware works as follows. A BLE service is created with READ and NOTIFY attributes. Three characteristics are created, on for each magnetometer axis.
If the magnetic filed is above the programmed thresholds then an interrupt is fired. The interrupt updates the characteristics and the data is pushed to the BLE central device which in this case is the Android Things PICO NXPMX hub.
This obviously assumes that the device is always connected to the central.
I uses the Arduino 101 which is BLE equipped. Initially the plan was to use a Sensor Tile board but that required integrating with the ST software which would take some time. Anyhoo the next step was working on the hub software.
Hub SoftwareThe NXP MX board is based on a 32-bit Cortex A MPU. It comes in a System on Module base board that is mounted to the main board.
The first thing that I did was connect a USB micro , connect the USB C to supply power and boot up the board. Initially I saw that it failed to boot.
I ended up downloading the Android thing image from the website and flashing it. Luckily all that is required is to boot the device in Fastmode and load the android things image as explained here:
https://developer.android.com/things/hardware/imx6ul.html
After installing Android 2.3 studio , I loaded the Blinky example to blink one of the LED's. The compilation was very slow but straightforward. Four day before the end of the contest I upgraded Android Studio to version 3. This was way more usable.
The next step was to configure the board to scan for BLE packets. This is where i got stuck since Android M had made a bunch of changes to the BLE peripheral which now requires user permissions to be manual. I ended up using a BLE library but I did not finish in time.
The Android thing i setup as a BLE client that scans for BLE servers (these are the Parking lot sensor node)
The data is printed out via serial UART. In the end there are a lot of things to improve upon. This project was just a first step to show a concept prototype.
/* Arduino 101 Smart parking with Android Things
* Copyright (C) 2017 by Dimiter Kendri
*
*
* This 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 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 the Arduino 101 Curie Lake monitor. If not, see
* <http://www.gnu.org/licenses/>.
*/
#include <CurieBLE.h>
#include <Wire.h>
#include "FXOS8700.h"
FXOS8700CQ magnetometer = FXOS8700CQ(0x1F);
/*********************************************************************************/
const char *moduleName = "AndroidParking";
BLEPeripheral blePeripheral;
// Environment sensing service UUID
// https://developer.bluetooth.org/gatt/services/Pages/ServiceViewer.aspx?u=org.bluetooth.service.environmental_sensing.xml
#define SERVICE_PARKING "181A"
#define CHAR_UUID_MAGX "2A6E" // magx UUID
#define CHAR_UUID_MAGY "2A6F" // magy UUID
#define CHAR_UUID_MAGZ "2A6F" // magz UUID
BLEService MagServ(SERVICE_PARKING);
// We want notifications to be supported
BLEShortCharacteristic MagxChar(CHAR_UUID_MAGX, BLERead | BLENotify);
BLEShortCharacteristic MagyChar(CHAR_UUID_MAGY, BLERead | BLENotify);
BLEShortCharacteristic MagzChar(CHAR_UUID_MAGZ, BLERead | BLENotify);
/*********************************************************************************/
const byte MagInterruptPin = 2;
void setupMagnetometer(void);
void updateCharacteristic(void);
void setup() {
Serial.begin(9600);
while (!Serial); // wait for the serial port to open
Wire.begin();
setupMagnetometer();
// Set BLE name for the module
blePeripheral.setLocalName(moduleName);
// Add the service UUID
blePeripheral.setAdvertisedServiceUuid(MagServ.uuid());
// Add the BLE service
blePeripheral.addAttribute(MagServ);
// Add characteristics
blePeripheral.addAttribute(MagxChar);
blePeripheral.addAttribute(MagyChar);
blePeripheral.addAttribute(MagzChar);
// Set initial values
updateCharacteristic();
/* Activate the BLE device. It will start continuously transmitting BLE
advertising packets and will be visible to remote BLE central devices
until it receives a new connection */
blePeripheral.begin();
pinMode(MagInterruptPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(MagInterruptPin), updateCharacteristic, RISING );
Serial.println("Bluetooth device active, waiting for connections...");
}
void loop() {
// poll peripheral
blePeripheral.poll();
}
void setupMagnetometer(void)
{
Serial.println("Initializing FXOS8700 device...");
// Initialize the FXOS8700CQ
magnetometer.init();
}
// Get data from sensors, process and push to BLE characteristics
void updateCharacteristic(void)
{
magnetometer.readMagData();
// Magnometer
Serial.print("Mag ");
Serial.print("X: ");
Serial.print((int)magnetometer.magData.x);
Serial.print(" Y: ");
Serial.print((int)magnetometer.magData.y);
Serial.print(" Z: ");
Serial.println((int)magnetometer.magData.z);
MagxChar.setValue((int)magnetometer.magData.x);
MagyChar.setValue((int)magnetometer.magData.y);
MagzChar.setValue((int)magnetometer.magData.z);
}
#include <Wire.h>
#include <math.h>
#include "FXOS8700.h"
#include "MemoryMapRegs.h"
// Public Methods //////////////////////////////////////////////////////////////
FXOS8700CQ::FXOS8700CQ(byte addr)
{
address = addr;
accelFSR = AFS_2g; // Set the scale below either 2, 4 or 8
accelODR = AODR_200HZ; // In hybrid mode, accel/mag data sample rates are half of this value
magOSR = MOSR_5; // Choose magnetometer oversample rate
}
// Writes a register
void FXOS8700CQ::writeReg(byte reg, byte value)
{
Wire.beginTransmission(address);
Wire.write(reg);
Wire.write(value);
Wire.endTransmission();
}
// Reads a register
byte FXOS8700CQ::readReg(byte reg)
{
byte value;
Wire.beginTransmission(address);
Wire.write(reg);
Wire.endTransmission();
Wire.requestFrom(address, (uint8_t)1);
value = Wire.read();
Wire.endTransmission();
return value;
}
void FXOS8700CQ::readRegs(byte reg, uint8_t count, byte dest[])
{
uint8_t i = 0;
Wire.beginTransmission(address); // Initialize the Tx buffer
Wire.write(reg); // Put slave register address in Tx buffer
Wire.endTransmission(false); // Send the Tx buffer, but send a restart to keep connection alive
Wire.requestFrom(address, count); // Read bytes from slave register address
while (Wire.available()) {
dest[i++] = Wire.read(); // Put read results in the Rx buffer
}
}
// Read the magnometer data
void FXOS8700CQ::readMagData()
{
uint8_t rawData[6]; // x/y/z accel register data stored here
readRegs(M_OUT_X_MSB, 6, &rawData[0]); // Read the six raw data registers into data array
magData.x = ((int16_t) rawData[0] << 8 | rawData[1]) >> 2;
magData.y = ((int16_t) rawData[2] << 8 | rawData[3]) >> 2;
magData.z = ((int16_t) rawData[4] << 8 | rawData[5]) >> 2;
}
// Read the temperature data
void FXOS8700CQ::readTempData()
{
tempData = readReg(TEMP);
}
// Put the FXOS8700CQ into standby mode.
// It must be in standby for modifying most registers
void FXOS8700CQ::standby()
{
byte c = readReg(CTRL_REG1);
writeReg(CTRL_REG1, c & ~(0x01));
}
// Put the FXOS8700CQ into active mode.
// Needs to be in this mode to output data.
void FXOS8700CQ::active()
{
byte c = readReg(CTRL_REG1);
writeReg(CTRL_REG1, c | 0x01);
}
void FXOS8700CQ::init()
{
standby(); // Must be in standby to change registers
uint16_t magThreshold = 0x200; //counts;
uint8_t magThresholdHi = (magThreshold & 0xFF00) >> 8;
uint8_t magThresholdLo = magThreshold & 0xFF;
writeReg(M_THS_Z_MSB, magThresholdHi); // Debounce countered cleared to zero when threshold is not longer true
writeReg(M_THS_Z_LSB, magThresholdLo);
magThreshold = 0x200; //counts;
magThresholdHi = (magThreshold & 0xFF00) >> 8;
magThresholdLo = magThreshold & 0xFF;
writeReg(M_THS_Y_MSB, magThresholdHi); // Debounce countered cleared to zero when threshold is not longer true
writeReg(M_THS_Y_LSB, magThresholdLo);
writeReg( M_THS_X_MSB, 0x03); // Threshold value MSB
writeReg( M_THS_X_LSB, 0xE8); // Threshold value LSB
//FXOS8700CQ_WriteByte( M_THS_CFG, 0xCA); // Event flag latch enabled, logic OR of enabled axes, only X-axis enabled, threshold interrupt enabled and routed to INT2
writeReg(M_THS_CFG, M_THS_ELE | M_THS_OAE | M_THS_ZEFE | M_THS_YEFE | M_THS_XEFE | M_THS_INT_EN ); //M_INT_threshold on INT2 pin (MCU_INT1), OR INT of all axes for threshold, latch disabled.
writeReg( M_THS_COUNT, 0x02); // 100ms at 100Hz ODR and magnetometer mode only
writeReg( M_CTRL_REG1, 0x1D); // Max OSR, only magnetometer is active
writeReg( CTRL_REG3, 0x00); // Push-pull, active low interrupt
writeReg(CTRL_REG3, IPOL_MASK); // Active HIGH on INT, push-pull mode
writeReg( CTRL_REG1, 0x19); // ODR = 100Hz, Active mode
active(); // Set to active to start reading
}
// Get accelerometer resolution
float FXOS8700CQ::getAres(void)
{
switch (accelFSR)
{
// Possible accelerometer scales (and their register bit settings) are:
// 2 gs (00), 4 gs (01), 8 gs (10).
case AFS_2g:
return 2.0/8192.0;
break;
case AFS_4g:
return 4.0/8192.0;
break;
case AFS_8g:
return 8.0/8192.0;
break;
}
return 0.0;
}
// Get magnometer resolution
float FXOS8700CQ::getMres(void)
{
return 10./32768.;
}
// Private Methods //////////////////////////////////////////////////////////////
#ifndef FXOS8700_H_
#define FXOS8700_H_
#include <Arduino.h> // for byte data type
// register addresses
#define STATUS 0x00
#define OUT_X_MSB 0x01
#define OUT_X_LSB 0x02
#define OUT_Y_MSB 0x03
#define OUT_Y_LSB 0x04
#define OUT_Z_MSB 0x05
#define OUT_Z_LSB 0x05
#define F_SETUP 0x09
#define TRIG_CFG 0x0A
#define SYSMOD 0x0B
#define INT_SOURCE 0x0C
#define WHO_AM_I 0x0D
#define XYZ_DATA_CFG 0x0E
#define HP_FILTER_CUTOFF 0x0F
#define PL_STATUS 0x10
#define PL_CFG 0x11
#define PL_COUNT 0x12
#define PL_BF_ZCOMP 0x13
#define PL_THS_REG 0x14
#define A_FFMT_CFG 0x15
#define A_FFMT_SRC 0x16
#define A_FFMT_THS 0x17
#define A_FFMT_COUNT 0x18
#define TRANSIENT_CFG 0x1D
#define TRANSIENT_SRC 0x1E
#define TRANSIENT_THS 0x1F
#define TRANSIENT_COUNT 0x20
#define PULSE_CFG 0x21
#define PULSE_SRC 0x22
#define PULSE_THSX 0x23
#define PULSE_THSY 0x24
#define PULSE_THSZ 0x25
#define PULSE_TMLT 0x26
#define PULSE_LTCY 0x27
#define PULSE_WIND 0x28
#define ASLP_COUNT 0x29
#define CTRL_REG1 0x2A
#define CTRL_REG2 0x2B
#define CTRL_REG3 0x2C
#define CTRL_REG4 0x2D
#define CTRL_REG5 0x2E
#define OFF_X 0x2F
#define OFF_Y 0x30
#define OFF_Z 0x31
#define M_DR_STATUS 0x32
#define M_OUT_X_MSB 0x33
#define M_OUT_X_LSB 0x34
#define M_OUT_Y_MSB 0x35
#define M_OUT_Y_LSB 0x36
#define M_OUT_Z_MSB 0x37
#define M_OUT_Z_LSB 0x38
#define CMP_X_MSB 0x39
#define CMP_X_LSB 0x3A
#define CMP_Y_MSB 0x3B
#define CMP_Y_LSB 0x3C
#define CMP_Z_MSB 0x3D
#define CMP_Z_LSB 0x3E
#define M_OFF_X_MSB 0x3F
#define M_OFF_X_LSB 0x40
#define M_OFF_Y_MSB 0x41
#define M_OFF_Y_LSB 0x42
#define M_OFF_Z_MSB 0x43
#define M_OFF_Z_LSB 0x44
#define MAX_X_MSB 0x45
#define MAX_X_LSB 0x46
#define MAX_Y_MSB 0x47
#define MAX_Y_LSB 0x48
#define MAX_Z_MSB 0x49
#define MAX_Z_LSB 0x4A
#define MIN_X_MSB 0x4B
#define MIN_X_LSB 0x4C
#define MIN_Y_MSB 0x4D
#define MIN_Y_LSB 0x4E
#define MIN_Z_MSB 0x4F
#define MIN_Z_LSB 0x50
#define TEMP 0x51
#define M_THS_CFG 0x52
#define M_THS_SRC 0x53
#define M_THS_X_MSB 0x54
#define M_THS_X_LSB 0x55
#define M_THS_Y_MSB 0x56
#define M_THS_Y_LSB 0x57
#define M_THS_Z_MSB 0x58
#define M_THS_Z_LSB 0x59
#define M_THS_COUNT 0x5A
#define M_CTRL_REG1 0x5B
#define M_CTRL_REG2 0x5C
#define M_CTRL_REG3 0x5D
#define M_INT_SRC 0x5E
#define A_VECM_CFG 0x5F
#define A_VECM_THS_MSB 0x60
#define A_VECM_THS_LSB 0x61
#define A_VECM_CNT 0x62
#define A_VECM_INITX_MSB 0x63
#define A_VECM_INITX_LSB 0x64
#define A_VECM_INITY_MSB 0x65
#define A_VECM_INITY_LSB 0x66
#define A_VECM_INITZ_MSB 0x67
#define A_VECM_INITZ_LSB 0x68
#define M_VECM_CFG 0x69
#define M_VECM_THS_MSB 0x6A
#define M_VECM_THS_LSB 0x6B
#define M_VECM_CNT 0x6C
#define M_VECM_INITX_MSB 0x6D
#define M_VECM_INITX_LSB 0x6E
#define M_VECM_INITY_MSB 0x6F
#define M_VECM_INITY_LSB 0x70
#define M_VECM_INITZ_MSB 0x71
#define M_VECM_INITZ_LSB 0x72
#define A_FFMT_THS_X_MSB 0x73
#define A_FFMT_THS_X_LSB 0x74
#define A_FFMT_THS_Y_MSB 0x75
#define A_FFMT_THS_Y_LSB 0x76
#define A_FFMT_THS_Z_MSB 0x77
#define A_FFMT_THS_Z_LSB 0x78
// Set initial input parameters
enum accelFSR {
AFS_2g = 0,
AFS_4g,
AFS_8g
};
enum accelODR {
AODR_800HZ = 0, // 200 Hz
AODR_400HZ,
AODR_200HZ,
AODR_100HZ,
AODR_50HZ,
AODR_12_5HZ, // 12.5 Hz, etc.
AODR_6_25HZ,
AODR_1_56HZ
};
enum magOSR {
MOSR_0 = 0, // oversample ratio 2 at 50 and 200 Hz ODR
MOSR_1,
MOSR_2,
MOSR_3,
MOSR_4,
MOSR_5,
MOSR_6,
MOSR_7 // oversample ratio 8 at 200 Hz ODR, 32 at 50 HZ ODR
};
class FXOS8700CQ
{
public:
typedef struct
{
int16_t x;
int16_t y;
int16_t z;
} SRAWDATA;
// Sensor data
SRAWDATA accelData; // RAW acceleration sensor data
SRAWDATA magData; // RAW magnometer sensor data
int8_t tempData; // RAW temperature data
// Sensor configuration
uint8_t accelFSR;
uint8_t accelODR;
uint8_t magOSR;
FXOS8700CQ(byte addr);
// Register functions
void writeReg(byte reg, byte value);
byte readReg(byte reg);
void readRegs(byte startReg, uint8_t count, byte dest[]);
// FXOS8700CQ functions
// Initialization & Termination
void init(void);
void standby(void);
void active(void);
// Query sensor data
void readAccelData(void);
void readMagData(void);
void readTempData(void);
// Resolution
float getAres(void);
float getMres(void);
private:
// Sensor address
byte address;
};
#endif
#ifndef __MEMMAP_FXO_H__
#define __MEMMAP_FXO_H__
#define FXOS8700CQ_ADDRESS 0x1E
#define READ 0x00
#define WRITE 0x80
/**************************STATUS Register********************************/
#define ZYXOW_MASK 0x80
#define ZOW_MASK 0x40
#define YOW_MASK 0x20
#define XOW_MASK 0x10
#define ZYXDR_MASK 0x08
#define ZDR_MASK 0x04
#define YDR_MASK 0x02
#define XDR_MASK 0x01
/**************************STATUS Register********************************/
#define F_OVF_MASK 0x80
#define F_WMRK_FLAG_MASK 0x40
#define F_CNT5_MASK 0x20
#define F_CNT4_MASK 0x10
#define F_CNT3_MASK 0x08
#define F_CNT2_MASK 0x04
#define F_CNT1_MASK 0x02
#define F_CNT0_MASK 0x01
#define F_CNT_MASK 0x3F
/**************************STATUS Register********************************/
#define OUT_X_MSB_REG 0x01
#define OUT_X_LSB_REG 0x02
#define OUT_Y_MSB_REG 0x03
#define OUT_Y_LSB_REG 0x04
#define OUT_Z_MSB_REG 0x05
#define OUT_Z_LSB_REG 0x06
/**************************FIFO Register********************************/
#define F_MODE1_MASK 0x80
#define F_MODE0_MASK 0x40
#define F_WMRK5_MASK 0x20
#define F_WMRK4_MASK 0x10
#define F_WMRK3_MASK 0x08
#define F_WMRK2_MASK 0x04
#define F_WMRK1_MASK 0x02
#define F_WMRK0_MASK 0x01
#define F_MODE_MASK 0xC0
#define F_WMRK_MASK 0x3F
#define F_MODE_DISABLED 0x00
#define F_MODE_CIRCULAR (F_MODE0_MASK)
#define F_MODE_FILL (F_MODE1_MASK)
#define F_MODE_TRIGGER (F_MODE1_MASK+F_MODE0_MASK)
/**************************TRIG_CFG Register********************************/
#define TRIG_TRANS_MASK 0x20
#define TRIG_LNDPRT_MASK 0x10
#define TRIG_PULSE_MASK 0x08
#define TRIG_FF_MT_MASK 0x04
/**************************SYSMOD Register********************************/
#define FGERR_MASK 0x80
#define FGT_4_MASK 0x40
#define FGT_3_MASK 0x20
#define FGT_2_MASK 0x10
#define FGT_1_MASK 0x08
#define FGT_0_MASK 0x04
#define FGT_MASK 0x7C
#define SYSMOD1_MASK 0x02
#define SYSMOD0_MASK 0x01
#define SYSMOD_MASK 0x03
#define SYSMOD_STANDBY 0x00
#define SYSMOD_WAKE (SYSMOD0_MASK)
#define SYSMOD_SLEEP (SYSMOD1_MASK)
/**************************INT_SOURCE Register********************************/
#define SRC_ASLP_MASK 0x80
#define SRC_FIFO_MASK 0x40
#define SRC_TRANS_MASK 0x20
#define SRC_LNDPRT_MASK 0x10
#define SRC_PULSE_MASK 0x08
#define SRC_FF_MT_MASK 0x04
#define SRC_DRDY_MASK 0x01
/***********************WHO_AM_I Device ID Register****************************/
#define FXOS8700CQ_ID 0xC7
#define MXOS8700CQ_ID 0xC4
/****************XYZ_DATA_CFG Sensor Data Configuration Register***************/
#define HPF_OUT_MASK 0x10 // MMA8451 and MMA8452 only
#define FS1_MASK 0x02
#define FS0_MASK 0x01
#define FS_MASK 0x03
#define FULL_SCALE_2G 0x00
#define FULL_SCALE_4G (FS0_MASK)
#define FULL_SCALE_8G (FS1_MASK)
/************HP_FILTER_CUTOFF High Pass Filter Register **********************/
#define PULSE_HPF_BYP_MASK 0x20
#define PULSE_LPF_EN_MASK 0x10
#define SEL1_MASK 0x02
#define SEL0_MASK 0x01
#define SEL_MASK 0x03
/*************PL_STATUS Portrait/Landscape Status Register *******************/
#define NEWLP_MASK 0x80
#define LO_MASK 0x40
#define LAPO1_MASK 0x04
#define LAPO0_MASK 0x02
#define BAFRO_MASK 0x01
#define LAPO_MASK 0x06
/************** PL_CFG Portrait/Landscape Configuration Register***************/
#define DBCNTM_MASK 0x80
#define PL_EN_MASK 0x40
/*****PL_BF_ZCOMP Back/Front and Z Compensation Register***********************/
#define BKFR1_MASK 0x80
#define BKFR0_MASK 0x40
#define ZLOCK2_MASK 0x04
#define ZLOCK1_MASK 0x02
#define ZLOCK0_MASK 0x01
#define BKFR_MASK 0xC0
#define ZLOCK_MASK 0x07
/************PL_P_L_THS Portrait to Landscape Threshold Register***************/
#define PL_P_L_THS_REG 0x14
#define P_L_THS4_MASK 0x80
#define P_L_THS3_MASK 0x40
#define P_L_THS2_MASK 0x20
#define P_L_THS1_MASK 0x10
#define P_L_THS0_MASK 0x08
#define HYS2_MASK 0x04
#define HYS1_MASK 0x02
#define HYS0_MASK 0x01
#define P_L_THS_MASK 0xF8
#define HYS_MASK 0x07
/********************FF_MT_CFG Freefall and Motion Configuration Register******/
#define FF_MT_CFG_REG 0x15
#define ELE_MASK 0x80
#define OAE_MASK 0x40
#define ZEFE_MASK 0x20
#define YEFE_MASK 0x10
#define XEFE_MASK 0x08
/**********FF_MT_SRC Freefall and Motion Source Registers**********************/
#define FF_MT_SRC_REG 0x16
#define EA_MASK 0x80
#define ZHE_MASK 0x20
#define ZHP_MASK 0x10
#define YHE_MASK 0x08
#define YHP_MASK 0x04
#define XHE_MASK 0x02
#define XHP_MASK 0x01
/*****FF_MT_THS Freefall and Motion Threshold Registers*********************/
#define FT_MT_THS_REG 0x17
#define TRANSIENT_THS_REG 0x1F
#define DBCNTM_MASK 0x80
#define THS6_MASK 0x40
#define THS5_MASK 0x20
#define THS4_MASK 0x10
#define THS3_MASK 0x08
#define THS2_MASK 0x04
#define TXS1_MASK 0x02
#define THS0_MASK 0x01
#define THS_MASK 0x7F
/********FF_MT_COUNT Freefall Motion Count Registers************************/
#define FF_MT_COUNT_REG 0x18
/****************TRANSIENT_CFG Transient Configuration Register****************/
#define TELE_MASK 0x10
#define ZTEFE_MASK 0x08
#define YTEFE_MASK 0x04
#define XTEFE_MASK 0x02
#define HPF_BYP_MASK 0x01
/***********TRANSIENT_SRC Transient Source Register****************************/
#define TEA_MASK 0x40
#define ZTRANSE_MASK 0x20
#define Z_TRANS_POL_MASK 0x10
#define YTRANSE_MASK 0x08
#define Y_TRANS_POL_MASK 0x04
#define XTRANSE_MASK 0x02
#define X_TRANS_POL_MASK 0x01
/**************************PULSE_CFG Register****************************/
#define DPA_MASK 0x80
#define PELE_MASK 0x40
#define ZDPEFE_MASK 0x20
#define ZSPEFE_MASK 0x10
#define YDPEFE_MASK 0x08
#define YSPEFE_MASK 0x04
#define XDPEFE_MASK 0x02
#define XSPEFE_MASK 0x01
/**************************PULSE_SRC Register********************************/
#define PEA_MASK 0x80
#define AXZ_MASK 0x40
#define AXY_MASK 0x20
#define AXX_MASK 0x10
#define DPE_MASK 0x08
#define POLZ_MASK 0x04
#define POLY_MASK 0x02
#define POLX_MASK 0x01
#define PTHS_MASK 0x7F
/***************CTRL_REG1 System Control 1 Register****************************/
#define ASLP_RATE1_MASK 0x80
#define ASLP_RATE0_MASK 0x40
#define DR2_MASK 0x20
#define DR1_MASK 0x10
#define DR0_MASK 0x08
#define LNOISE_MASK 0x04
#define FREAD_MASK 0x02
#define ACTIVE_MASK 0x01
#define ASLP_RATE_MASK 0xC0
#define DR_MASK 0x38
#define ASLP_RATE_20MS 0x00
#define ASLP_RATE_80MS (ASLP_RATE0_MASK)
#define ASLP_RATE_160MS (ASLP_RATE1_MASK)
#define ASLP_RATE_640MS (ASLP_RATE1_MASK+ASLP_RATE0_MASK)
#define ASLP_RATE_50HZ (ASLP_RATE_20MS)
#define ASLP_RATE_12_5HZ (ASLP_RATE_80MS)
#define ASLP_RATE_6_25HZ (ASLP_RATE_160MS)
#define ASLP_RATE_1_56HZ (ASLP_RATE_640MS)
#define HYB_ASLP_RATE_25HZ (ASLP_RATE_20MS)
#define HYB_ASLP_RATE_6_25HZ (ASLP_RATE_80MS)
#define HYB_ASLP_RATE_1_56HZ (ASLP_RATE_160MS)
#define HYB_ASLP_RATE_0_8HZ (ASLP_RATE_640MS)
#define DATA_RATE_1250US 0x00
#define DATA_RATE_2500US (DR0_MASK)
#define DATA_RATE_5MS (DR1_MASK)
#define DATA_RATE_10MS (DR1_MASK+DR0_MASK)
#define DATA_RATE_20MS (DR2_MASK)
#define DATA_RATE_80MS (DR2_MASK+DR0_MASK)
#define DATA_RATE_160MS (DR2_MASK+DR1_MASK)
#define DATA_RATE_640MS (DR2_MASK+DR1_MASK+DR0_MASK)
#define DATA_RATE_800HZ (DATA_RATE_1250US)
#define DATA_RATE_400HZ (DATA_RATE_2500US)
#define DATA_RATE_200HZ (DATA_RATE_5MS)
#define DATA_RATE_100HZ (DATA_RATE_10MS)
#define DATA_RATE_50HZ (DATA_RATE_20MS)
#define DATA_RATE_12_5HZ (DATA_RATE_80MS)
#define DATA_RATE_6_25HZ (DATA_RATE_160MS)
#define DATA_RATE_1_56HZ (DATA_RATE_640MS)
#define HYB_DATA_RATE_400HZ (DATA_RATE_1250US)
#define HYB_DATA_RATE_200HZ (DATA_RATE_2500US)
#define HYB_DATA_RATE_100HZ (DATA_RATE_5MS)
#define HYB_DATA_RATE_50HZ (DATA_RATE_10MS)
#define HYB_DATA_RATE_25HZ (DATA_RATE_20MS)
#define HYB_DATA_RATE_6_25HZ (DATA_RATE_80MS)
#define HYB_DATA_RATE_3_15HZ (DATA_RATE_160MS)
#define HYB_DATA_RATE_0_8HZ (DATA_RATE_640MS)
#define ACTIVE (ACTIVE_MASK)
#define STANDBY 0x00
/***************CTRL_REG2 System Control 2 Register****************************/
#define ST_MASK 0x80
#define RST_MASK 0x40
#define SMODS1_MASK 0x10
#define SMODS0_MASK 0x08
#define SLPE_MASK 0x04
#define MODS1_MASK 0x02
#define MODS0_MASK 0x01
#define SMODS_MASK 0x18
#define MODS_MASK 0x03
#define SMOD_NORMAL 0x00
#define SMOD_LOW_NOISE (SMODS0_MASK)
#define SMOD_HIGH_RES (SMODS1_MASK)
#define SMOD_LOW_POWER (SMODS1_MASK+SMODS0_MASK)
#define MOD_NORMAL 0x00
#define MOD_LOW_NOISE (MODS0_MASK)
#define MOD_HIGH_RES (MODS1_MASK)
#define MOD_LOW_POWER (MODS1_MASK+MODS0_MASK)
/***************CTRL_REG3 System Control 3 Register****************************/
#define FIFO_GATE_MASK 0x80
#define WAKE_TRANS_MASK 0x40
#define WAKE_LNDPRT_MASK 0x20
#define WAKE_PULSE_MASK 0x10
#define WAKE_FF_MT_MASK 0x08
#define WAKE_EN_A_VECM 0x04
#define IPOL_MASK 0x02
#define PP_OD_MASK 0x01
/***************CTRL_REG4 System Control 4 Register****************************/
#define INT_EN_ASLP_MASK 0x80
#define INT_EN_FIFO_MASK 0x40
#define INT_EN_TRANS_MASK 0x20
#define INT_EN_LNDPRT_MASK 0x10
#define INT_EN_PULSE_MASK 0x08
#define INT_EN_FF_MT_MASK 0x04
#define INT_EN_DRDY_MASK 0x01
/***************CTRL_REG5 System Control 5 Register****************************/
#define INT_CFG_ASLP_MASK 0x80
#define INT_CFG_FIFO_MASK 0x40
#define INT_CFG_TRANS_MASK 0x20
#define INT_CFG_LNDPRT_MASK 0x10
#define INT_CFG_PULSE_MASK 0x08
#define INT_CFG_FF_MT_MASK 0x04
#define INT_CFG_DRDY_MASK 0x01
/*
** XYZ Offset Correction Registers
*/
#define OFF_X_REG 0x2F
#define OFF_Y_REG 0x30
#define OFF_Z_REG 0x31
/*
** MAG CTRL_REG1 System Control 1 Register
*/
#define M_ACAL_MASK 0x80
#define M_RST_MASK 0x40
#define M_OST_MASK 0x20
#define M_OSR2_MASK 0x10
#define M_OSR1_MASK 0x08
#define M_OSR0_MASK 0x04
#define M_HMS1_MASK 0x02
#define M_HMS0_MASK 0x01
#define M_OSR_MASK 0x1C
#define M_HMS_MASK 0x03
//OSR Selections
#define M_OSR_1_56_HZ 0x00
#define M_OSR_6_25_HZ M_OSR0_MASK
#define M_OSR_12_5_HZ M_OSR1_MASK
#define M_OSR_50_HZ M_OSR1_MASK+M_OSR0_MASK
#define M_OSR_100_HZ M_OSR2_MASK
#define M_OSR_200_HZ M_OSR2_MASK+M_OSR0_MASK
#define M_OSR_400_HZ M_OSR2_MASK+M_OSR1_MASK
#define M_OSR_800_HZ M_OSR2_MASK+M_OSR1_MASK+M_OSR0_MASK
//Hybrid Mode Selection
#define ACCEL_ACTIVE 0x00
#define MAG_ACTIVE M_HMS0_MASK
#define HYBRID_ACTIVE (M_HMS1_MASK | M_HMS0_MASK)
/*
** MAG CTRL_REG2 System Control 2 Register
*/
#define M_HYB_AUTOINC_MASK 0x20
#define M_MAXMIN_DIS_MASK 0x10
#define M_MAXMIN_DIS_THS_MASK 0x08
#define M_MAXMIN_RST_MASK 0x04
#define M_RST_CNT1_MASK 0x02
#define M_RST_CNT0_MASK 0x01
//Mag Auto-Reset De-Gauss Frequency
#define RST_ODR_CYCLE 0x00
#define RST_16_ODR_CYCLE M_RST_CNT0_MASK
#define RST_512_ODR_CYCLE M_RST_CNT1_MASK
#define RST_DISABLED M_RST_CNT1_MASK+M_RST_CNT0_MASK
/*
** MAG CTRL_REG3 System Control 3 Register
*/
#define M_RAW_MASK 0x80
#define M_ASLP_OS_2_MASK 0x40
#define M_ASLP_OS_1_MASK 0x20
#define M_ASLP_OS_0_MASK 0x10
#define M_THS_XYZ_MASK 0x08
#define M_ST_Z_MASK 0x04
#define M_ST_XY1_MASK 0x02
#define M_ST_XY0_MASK 0x01
#define M_ASLP_OSR_MASK 0x70
#define M_ST_XY_MASK 0x03
//OSR Selections
#define M_ASLP_OSR_1_56_HZ 0x00
#define M_ASLP_OSR_6_25_HZ M_ASLP_OS_0_MASK
#define M_ASLP_OSR_12_5_HZ M_ASLP_OS_1_MASK
#define M_ASLP_OSR_50_HZ M_ASLP_OS_1_MASK+M_ASLP_OS_0_MASK
#define M_ASLP_OSR_100_HZ M_ASLP_OS_2_MASK
#define M_ASLP_OSR_200_HZ M_ASLP_OS_2_MASK+M_ASLP_OS_0_MASK
#define M_ASLP_OSR_400_HZ M_ASLP_OS_2_MASK+M_ASLP_OS_1_MASK
#define M_ASLP_OSR_800_HZ M_ASLP_OS_2_MASK+M_ASLP_OS_1_MASK+M_ASLP_OS_0_MASK
/*
** MAG INT SOURCE M_INT_SRC Register
*/
#define SRC_M_DRDY_MASK 0x01
#define SRC_M_VECM_MASK 0x02
#define SRC_M_THS_MASK 0x04
/*
** ACCEL VECTOR CONFIG Register
*/
#define A_VECM_INIT_CFG_MASK 0x40
#define A_VECM_INIT_EN_MASK 0x20
#define A_VECM_WAKE_EN_MASK 0x10
#define A_VECM_EN_MASK 0x08
#define A_VECM_UPDM_MASK 0x04
#define A_VECM_INITM_MASK 0x02
#define A_VECM_ELE_MASK 0x01
/*
** ACCEL VECTOR THS MSB AND LSB Register
*/
#define A_VECM_DBCNTM_MASK 0x80
/*
** MAG VECTOR CONFIG Register
*/
#define M_VECM_INIT_CFG_MASK 0x40
#define M_VECM_INIT_EN_MASK 0x20
#define M_VECM_WAKE_EN_MASK 0x10
#define M_VECM_EN_MASK 0x08
#define M_VECM_UPDM_MASK 0x04
#define M_VECM_INITM_MASK 0x02
#define M_VECM_ELE_MASK 0x01
/*
** MAG VECTOR THS MSB AND LSB Register
*/
#define M_VECM_DBCNTM_MASK 0x80
/*
** ACCEL FFMT THS X MSB AND LSB Register
*/
#define A_FFMT_THS_XYZ_EN_MASK 0x80
#define A_FFMT_THS_X_LSB_MASK 0xFC
/*
** ACCEL FFMT THS Y MSB AND LSB Register
*/
#define A_FFMT_THS_Y_EN_MASK 0x80
#define A_FFMT_THS_Y_LSB_MASK 0xFC
/*
** ACCEL FFMT THS Z MSB AND LSB Register
*/
#define A_FFMT_THS_Z_EN_MASK 0x80
#define A_FFMT_THS_Z_LSB_MASK 0xFC
#define FXOS8700CQ_WHOAMI_VAL 0xC7 // FXOS8700CQ WHOAMI production register value
#define FXOS8700CQ_READ_LEN 12 // 6 channels of two bytes = 12 bytes
#define UINT14_MAX 16383 // For processing the accelerometer data to right-justified 2's complement
/*************************MAG_THS_CFG*****************************/
#define M_THS_ELE 0x80
#define M_THS_OAE 0x40
#define M_THS_ZEFE 0x20
#define M_THS_YEFE 0x80
#define M_THS_XEFE 0x08
#define M_THS_WAKE_EN 0x04
#define M_THS_INT_EN 0x02
#define M_THS_INT_CFG 0x01
#define M_THS_EA 0x80
/*****************************************************************/
#define M_VECM_ELE 0x40
#define M_VECM_INITM 0x20
#define M_VECM_UPDM 0x10
#define M_VECM_EN 0x08
#define M_VECM_WAKE_EN 0x04
#define M_VECM_INT_EN 0x02
#define M_VECM_INIT_CFG 0x01
#endif
Comments