Artekit PropBoard: Motion API
Motion API documentation for the Artekit PropBoard.
Motion API
Motion sensing in the PropBoard is managed through the Motion
object.
class PropMotion;
PropMotion Motion;
The Motion
object is already instantiated when the program begins, and has to be initialized with the Motion.begin
function. After that, you can configure and use most features of the MMA8452Q sensor through the API functions.
Sensor orientation
Interrupt handling
The Motion
object wraps most of the MMA8452Q 3-Axis accelerometer functionality. The MMA8452Q accelerometer is capable of detecting certain motion events using its internal DSP processor and can generate interrupts when these events are detected. This way the PropBoard processor is free from the task of polling the accelerometer asking for new event data. The Motion
object supports the “Data Ready”, “Any Motion”, “Single Pulse”, and “Transient” events.
The MMA8452Q can map any of these events into 2 interrupt signals. Whenever you configure an event through the Motion.configDataReady
, Motion.configAnyMotion
, Motion.configTransient
and Motion.configPulse
functions, you will be presented with an option to map a given event to either MotionInterrupt1
or MotionInterrupt2
signals. It’s up to you to decide which event to map on which signal.
Then you can configure a function to be called whenever one of these two interrupts are signaled. The Motion.attachInterrupt
function allows you to attach a signal to a function you define, much like Arduino’s attachInterrupt
function does with interrupts on a pin.
For example, the code below uses the Motion.configPulse
function to configure the “Pulse” event and to map the event to the MotionInterrupt1
signal. Then, the Motion.attachInterrupt
attachs the MotionInterrupt1
signal to the pulseDetected
function to be called when the event is detected.
volatile bool on_pulse = false;
void setup()
{
// Initialize motion sensor
Motion.begin();
// Configure serial
Serial.begin(9600);
// Configure pulse and map event to MotionInterrupt1
Motion.configPulse(AxisAll, 3.78f, 500, 100, MotionInterrupt1);
// Attach MotionInterrupt1 to the pulseDetected function
Motion.attachInterrupt(MotionInterrupt1, pulseDetected);
}
void loop()
{
// The on_pulse variable is set in the pulseDetected function
if (on_pulse)
{
// Pulse detected, reset variable
on_pulse = false;
// and write a message
Serial.println("Pulse detected !");
// Do other motion processing here
}
}
void pulseDetected()
{
// The motion sensor signals that a pulse event was detected
on_pulse = true;
}
This event-signal mapping is the recommended way to work with the motion sensor. It is also recommended not to call Motion
API functions inside interrupt handlers (the pulseDetected
function in the above example): set a variable that you then evaluate from the loop
function instead and do the required motion processing outside the interrupt context.
If no interrupt is configured for a given event, you can still detect the event by polling using the following functions: Motion.getAnyMotionSource
for “Any Motion” event, Motion.getTransientSource
for “Transient” event and Motion.getPulseSource()
for “Pulse event.
Motion.begin
Call the Motion.begin
function to initialize the motion sensor.
Syntax
bool begin(uint8_t scale = 8, uint16_t odr = 200, bool enable = true);
Parameters
The scale parameter is the sensor scale in g’s and can be one of the following values:
- 2
- 4
- 8
The odr parameter is the output data rate. It sets how many samples per second the sensor will output. The lower the frequency, the higher the precision. It can be one of the following values:
- 1
- 6
- 12
- 50
- 100
- 200
- 400
- 800
The enable parameter is used to automatically enable the sensor after the initial configuration. If true the sensor is enabled; if false the sensor remains disabled until the Motion.enable
function is called.
If no parameters are provided, the Motion
object is initialized and enabled with scale = 8 and output data rate = 200.
Returns
Returns true on success, false otherwise.
Examples
The following code shows the standard initialization.
void setup()
{
Motion.begin();
}
The code here below shows a custom initialization with scale = 4 and output data rate = 800.
void setup()
{
// Configure the motion sensor with scale = 4 and output data rate = 800
Motion.begin(4, 800, false);
// Do other Motion configuration and then enable the motion sensor
// ...
Motion.enable();
}
Motion.end
Call the Motion.end function to disable the motion sensor and de-initialize the Motion
object.
Syntax
void end();
Parameters
None.
Returns
None.
Motion.enable
Call the Motion.enable
function to enable the motion sensor.
Syntax
bool enable();
Parameters
None.
Returns
Returns true on success, false otherwise.
Motion.disable
Call the Motion.disable
function to disable the motion sensor.
Syntax
bool disable();
Parameters
None.
Returns
Returns true on success, false otherwise.
Motion.setScale
Call the Motion.setScale
function to change the scale after the motion sensor has been initialized with the Motion.begin
function.
Syntax
bool setScale(uint32_t scale);
Parameters
The scale parameter is the sensor scale in G and can be one of the following values: * 2 * 4 * 8
Returns
Returns true on success, false otherwise.
Motion.setDataRate
Use the Motion.setDataRate
function to change the output data rate after the motion sensor has been initialized with the Motion.begin
function.
Syntax
bool setDataRate(uint32_t data_rate);
Parameters
The data_rate parameter is the output data rate. It sets how many samples per second the sensor will output. The lower the frequency, the higher the precision. It can be one of the following values:
- 1
- 6
- 12
- 50
- 100
- 200
- 400
- 800
Returns
Returns true on success, false otherwise.
Motion.configDataReady
Configures the interrupt number to be used when a “Data Ready” event is generated from the motion sensor.
Syntax
bool configDataReady(MotionInterrupt irq);
Parameters
The irq parameter is the interrupt number to use and can be one of the following values:
- MotionInterruptNone: disables the interrupt generation
- MotionInterrupt1: use interrupt number 1
- MotionInterrupt2: use interrupt number 2
Returns
Returns true on success, false otherwise.
See also
Motion.configAnyMotion
Use this function to configure the “Any Motion” event detection. The “Any Motion” event is an acceleration greater than force_mg parameter with a duration longer than time milliseconds.
Syntax
bool configAnyMotion(Axis axis, float force_mg, uint32_t time, MotionInterrupt irq = MotionInterruptNone);
Parameters
The axis parameter configures on which axis the event will be detected. Can be a combination of any of the following values:
- AxisX: event detection enabled on X axis.
- AxisY: event detection enabled on Y axis.
- AxisZ: event detection enabled on Z axis.
- AxisAll: event detection enabled on all axis.
The force_mg parameter is the required force in g’s to detect an “Any Motion” event.
The time parameter is the time in milliseconds that the acceleration has to be over force_mg for the event to become valid.
The irq parameter is the interrupt signal number for the event. It can be one of the following values:
- MotionInterruptNone: no interrupt signal is used. The event detection has to be polled with the
Motion.getAnyMotionSource
function. - MotionInterrupt1: event is signaled through interrupt 1.
- MotionInterrupt2: event is signaled through interrupt 2.
Returns
Returns true on success, false otherwise.
Notes
This function will enable the “High Resolution” feature of the MMA8452Q.
Example
volatile bool on_motion = false;
void setup()
{
// Initialize motion sensor
Motion.begin();
// Configure serial
Serial.begin(9600);
// Configure "Any Motion" and map event to MotionInterrupt1.
// Set to 1G during 500ms.
Motion.configAnyMotion(AxisAll, 1, 500, MotionInterrupt1);
// Attach MotionInterrupt1 to the motionDetected function
Motion.attachInterrupt(MotionInterrupt1, motionDetected);
}
void loop()
{
// The on_motion variable is set in the motionDetected function
if (on_motion)
{
// Motion detected, reset variable
on_motion = false;
// and write a message
Serial.println("Motion detected !");
// Do other motion processing here
}
}
void motionDetected()
{
// The motion sensor signals that a motion event was detected
on_motion = true;
}
See also
Motion.configTransient
This function configures the “Transient” event. The “Transient” detection enables a high-pass filter to detect an acceleration on an axis that exceeds a set threshold excluding static acceleration. Much like the “Any Motion” event but able to better detect acceleration changes disregarding initial static acceleration.
Syntax
bool configTransient(Axis axis, float force_mg, uint32_t time, MotionInterrupt irq = MotionInterruptNone);
Parameters
The axis parameter configures on which axis the event will be detected. Can be a combination of any of the following values:
- AxisX: event detection enabled on X axis.
- AxisY: event detection enabled on Y axis.
- AxisZ: event detection enabled on Z axis.
- AxisAll: event detection enabled on all axis.
The force_mg parameter is the required force in g’s to detect an “Any Motion” event.
The time parameter is the time in milliseconds that the acceleration has to be over force_mg for the event to become valid.
The irq parameter is the interrupt signal number for the event. It can be one of the following values:
- MotionInterruptNone: no interrupt signal is used. The event detection has to be polled with the
Motion.getTransientSource
function. - MotionInterrupt1: event is signaled through interrupt 1.
- MotionInterrupt2: event is signaled through interrupt 2.
Returns
Returns true on success, false otherwise.
Notes
This function will enable the “High Resolution”, “High pass filter” and “High pass filter cutoff” feature of the MMA8452Q.
Example
volatile bool on_transient = false;
void setup()
{
// Initialize motion sensor
Motion.begin();
// Configure serial
Serial.begin(9600);
// Configure "Transient" and map event to MotionInterrupt1.
// Set to 0.5G during 100ms.
Motion.configTransient(AxisAll, 0.5f, 100, MotionInterrupt1);
// Attach MotionInterrupt1 to the pulseDetected function
Motion.attachInterrupt(MotionInterrupt1, transientDetected);
}
void loop()
{
// The on_transient variable is set in the transientDetected function
if (on_transient)
{
// Pulse detected, reset variable
on_transient = false;
// and write a message
Serial.println("Transient detected !");
// Do other motion processing here
}
}
void transientDetected()
{
// The motion sensor signals that a transient event was detected
on_transient = true;
}
See also
Motion.configPulse
This function configures the “Pulse” detection event. A “Pulse” is a quick positive acceleration followed by a negative acceleration.
Syntax
bool configPulse(Axis axis, float force_mg, uint32_t time, uint32_t latency, MotionInterrupt irq = MotionInterruptNone);
Parameters
The axis parameter configures on which axis the event will be detected. Can be a combination of any of the following values:
- AxisX: event detection enabled on X axis.
- AxisY: event detection enabled on Y axis.
- AxisZ: event detection enabled on Z axis.
- AxisAll: event detection enabled on all axis.
The force_mg parameter is the required force in G to detect an “Any Motion” event.
The time parameter is the time in milliseconds the motion has to be over force_mg for the event to become valid.
The latency parameter is the minimum time in milliseconds that has to pass before considering any other “Pulse” event. “Pulse” events during this period will be ignored.
The irq parameter is the interrupt signal number for the event. It can be one of the following values:
- MotionInterruptNone: no interrupt signal is used. The event detection has to be polled with the
getTransientSource
function. - MotionInterrupt1: event is signaled through interrupt 1.
- MotionInterrupt2: event is signaled through interrupt 2.
Returns
Returns true on success, false otherwise.
Example
See example for Interrupt handling.
Motion.attachInterrupt
Use this function to attach a motion sensor interrupt to a user-defined function.
Syntax
bool attachInterrupt(MotionInterrupt irq, MotionInterruptCallback* callback);
Parameters
The irq parameter is the motion sensor interrupt. Can be one of the following values:
- MotionInterrupt1
- MotionInterrupt2
The callback parameter is a pointer to a function defined as void function_name()
, where function_name can be any name.
Returns
Returns true on success, false otherwise.
Example
See example for Interrupt handling.
Motion.getInterruptSource
Call this function to read from the motion sensor the interrupt source. Useful when multiple events are attached to a single interrupt signal.
Syntax
MotionEvent getInterruptSource();
Parameters
None.
Returns
The function can return a combination of the following values:
- MotionEventNone: No events were detected
- MotionEventDataReady: A “Data Ready” event was detected. The event has to be cleared by reading the X, Y, Z values with the
Motion.read (g)
orMotion.read (raw)
functions. - MotionEventAnyMotion: An “Any Motion” event was detected. The event has to be cleared by calling the
Motion.getAnyMotionSource()
function. - MotionEventPulse: A “Pulse” event was detected. The event has to be cleared by calling the
Motion.getPulseSource
function. - MotionEventTransient: A “Transient” event was detected. The event has to be cleared by calling the
Motion.getTransientSource
function.
Example
volatile bool on_interrupt = false;
void setup()
{
Motion.begin();
// Configure "Any Motion" and map event to MotionInterrupt1.
// Set to 1G during 500ms.
Motion.configAnyMotion(AxisAll, 1, 500, MotionInterrupt1);
// Configure "Transient" and map event to MotionInterrupt1.
// Set to 0.5G during 100ms.
Motion.configTransient(AxisAll, 0.5f, 100, MotionInterrupt1);
// Attach MotionInterrupt1 to the pulseDetected function
Motion.attachInterrupt(MotionInterrupt1, myInterruptHandler);
}
void loop()
{
uint8_t event;
uint8_t source;
if (on_interrupt)
{
event = Motion.getInterruptSource();
if (event & MotionEventAnyMotion)
{
// Any motion detected
source = Motion.getAnyMotionSource();
// ... Process 'source' ...
}
if (event & MotionEventTransient)
{
// Transient detected
source = Motion.getTransientSource();
// ... Process 'source' ...
}
}
}
void myInterruptHandler()
{
// Signal on_interrupt
on_interrupt = true;
}
Motion.getAnyMotionSource()
Use this function to retrieve on which axis an “Any Motion” event was detected.
Syntax
uint8_t getAnyMotionSource();
Parameters
None.
Returns
The function returns a combination of any of these values:
MotionDetected: This flag indicates that a motion has been detected.
MotionOnX: This flag indicates that a motion has been detected on the X axis.
MotionNegativeX: This flag indicates that the motion on the X axis is a negative acceleration.
MotionOnY: This flag indicates that a motion has been detected on the Y axis.
MotionNegativeY: This flag indicates that the motion on the Y axis is a negative acceleration.
MotionOnZ: This flag indicates that a motion has been detected on the Z axis.
MotionNegativeZ: This flag indicates that the motion on the Z axis is a negative acceleration.
Example
void setup()
{
Motion.begin();
// Configure "Any Motion" to 1G during 500ms.
Motion.configAnyMotion(AxisAll, 1, 500);
}
void loop()
{
uint8_t any_motion;
any_motion = Motion.getAnyMotionSource();
if (any_motion & MotionDetected)
{
if (any_motion & MotionOnX)
{
// Process motion on X axis
}
if (any_motion & MotionOnY)
{
// Process motion on Y axis
}
if (any_motion & MotionOnZ)
{
// Process motion on Z axis
}
}
}
Motion.getTransientSource()
The Motion.getTransientSource
function behaves just as the Motion.getAnyMotionSource()
function but for “Transient” events. The function returns the same values.
See Motion.getAnyMotionSource()
.
Motion.getPulseSource()
Use this function to retrieve on which axis a “Pulse” event was detected.
Syntax
uint8_t getPulseSource();
Parameters
None.
Returns
The function returns a combination of any of these values:
- MotionPulseDetected: This flag indicates that a “Pulse” event has been detected.
- MotionPulseOnX: This flag indicates that a “Pulse” event has been detected on the X axis.
- MotionPulseNegativeX: This flag indicates that the “Pulse” event on the X axis has a negative acceleration.
- MotionPulseOnY: This flag indicates that a “Pulse” event has been detected on the Y axis.
- MotionPulseNegativeY: This flag indicates that the “Pulse” event on the Y axis has a negative acceleration.
- MotionPulseOnZ: This flag indicates that a “Pulse” event has been detected on the Z axis.
- MotionPulseNegativeZ: This flag indicates that the “Pulse” event on the Z axis has a negative acceleration.
- MotionDoublePulse: This flag indicates that a “Double Pulse” event has been detected.
Example
void setup()
{
Motion.begin();
// Configure "Pulse" to 1G during 50ms and 100ms latency
Motion.configPulse(AxisAll, 1, 50, 100);
}
void loop()
{
uint8_t pulse;
pulse = Motion.getPulseSource();
if (pulse & MotionPulseDetected)
{
if (pulse & MotionPulseOnX)
{
// Process pulse on X axis
}
if (pulse & MotionPulseOnY)
{
// Process pulse on Y axis
}
if (pulse & MotionPulseOnZ)
{
// Process pulse on Z axis
}
}
}
Motion.isEnabled
Use this function to know if the motion sensor is enabled.
Syntax
bool isEnabled();
Parameters
None.
Returns
Returns true if the sensor is enabled, false otherwise.
Motion.read (g)
Use this function to read the actual acceleration values from the sensor.
Syntax
bool read(float* x, float* y, float* z);
Parameters
The x parameter is a pointer to a float that will receive the current X axis acceleration value.
The y parameter is a pointer to a float that will receive the current Y axis acceleration value.
The z parameter is a pointer to a float that will receive the current Z axis acceleration value.
Returns
Returns true on success, false otherwise.
Example
void setup()
{
Motion.begin();
}
void loop()
{
float x, y, z;
if (Motion.read(&x, &y, &z))
{
// Process x, y and z
}
}
Motion.read (raw)
Use this function to read the actual axis register values (raw axis data) from the sensor.
Syntax
bool read(int16_t* x, int16_t* y, int16_t* z);
Parameters
The x parameter is a pointer to an unsigned 16-bit that will receive the current X axis raw value.
The y parameter is a pointer to an unsigned 16-bit that will receive the current Y axis raw value.
The z parameter is a pointer to an unsigned 16-bit that will receive the current Z axis raw value.
Returns
Returns true on success, false otherwise.
Example
void setup()
{
Motion.begin();
}
void loop()
{
int16_t x, y, z;
if (Motion.read(&x, &y, &z))
{
// Process x, y and z
}
}
Motion.readRegister
Use this function to read any register of the motion sensor.
Syntax
bool readRegister(uint8_t reg, uint8_t* value);
Parameters
The reg parameter is the register address to read. Refer to Addendum: registers definition.
The value parameter is a pointer to an unsigned 8-bit variable that will receive the register value.
Returns
Returns true on success, false otherwise.
Example
void setup()
{
uint8_t register;
Motion.begin();
// Read status register
Motion.readRegister(MMA8452_STATUS, ®ister);
}
Motion.writeRegister
Use this function to write to any register of the motion sensor.
Syntax
bool writeRegister(uint8_t reg, uint8_t value);
Parameters
The reg parameter is the register address to write. Refer to Addendum: registers definition.
The value paramter is the value to write.
Returns
Returns true on success, false otherwise.
Example
void setup()
{
uint8_t register;
Motion.begin();
// Read CTRL_REG1 register
Motion.readRegister(MMA8452_CTRL_REG1, ®ister);
// Write enable flag
Motion.writeRegister(MMA8452_CTRL_REG1, reg | 1);
}
Addendum: Registers definition
Here follows a list of constants with the definition of the registers you can use with the Motion.readRegister
and Motion.writeRegister
functions.
#define MMA8452_STATUS 0x00
#define MMA8452_OUT_X_MSB 0x01
#define MMA8452_OUT_X_LSB 0x02
#define MMA8452_OUT_Y_MSB 0x03
#define MMA8452_OUT_Y_LSB 0x04
#define MMA8452_OUT_Z_MSB 0x05
#define MMA8452_OUT_Z_LSB 0x06
#define MMA8452_SYSMOD 0x0B
#define MMA8452_INT_SOURCE 0x0C
#define MMA8452_WHO_AM_I 0x0D
#define MMA8452_XYZ_DATA_CFG 0x0E
#define MMA8452_HP_FILTER_CUTOFF 0x0F
#define MMA8452_PL_STATUS 0x10
#define MMA8452_PL_CFG 0x11
#define MMA8452_PL_COUNT 0x12
#define MMA8452_PL_BF_ZCOMP 0x13
#define MMA8452_P_L_THS_REG 0x14
#define MMA8452_FF_MT_CFG 0x15
#define MMA8452_FF_MT_SRC 0x16
#define MMA8452_FF_MT_THS 0x17
#define MMA8452_FF_MT_COUNT 0x18
#define MMA8452_TRANSIENT_CFG 0x1D
#define MMA8452_TRANSIENT_SRC 0x1E
#define MMA8452_TRANSIENT_THS 0x1F
#define MMA8452_TRANSIENT_COUNT 0x20
#define MMA8452_PULSE_CFG 0x21
#define MMA8452_PULSE_SRC 0x22
#define MMA8452_PULSE_THSX 0x23
#define MMA8452_PULSE_THSY 0x24
#define MMA8452_PULSE_THSZ 0x25
#define MMA8452_PULSE_TMLT 0x26
#define MMA8452_PULSE_LTCY 0x27
#define MMA8452_PULSE_WIND 0x28
#define MMA8452_ASLP_COUNT 0x29
#define MMA8452_CTRL_REG1 0x2A
#define MMA8452_CTRL_REG2 0x2B
#define MMA8452_CTRL_REG3 0x2C
#define MMA8452_CTRL_REG4 0x2D
#define MMA8452_CTRL_REG5 0x2E
#define MMA8452_OFF_X 0x2F
#define MMA8452_OFF_Y 0x30
#define MMA8452_OFF_Z 0x31