2015-08-31 22:25:10 +00:00
|
|
|
#include "MicroBit.h"
|
2015-08-12 10:53:41 +00:00
|
|
|
|
|
|
|
/**
|
2016-01-13 16:16:18 +00:00
|
|
|
* Constructor.
|
2015-08-12 10:53:41 +00:00
|
|
|
* Create a compass representation with the given ID.
|
|
|
|
* @param id the event ID of the compass object.
|
|
|
|
* @param address the default address for the compass register
|
|
|
|
*
|
|
|
|
* Example:
|
|
|
|
* @code
|
|
|
|
* compass(MICROBIT_ID_COMPASS, MAG3110_DEFAULT_ADDR);
|
|
|
|
* @endcode
|
|
|
|
*
|
|
|
|
* Possible Events for the compass are as follows:
|
|
|
|
* @code
|
|
|
|
* MICROBIT_COMPASS_EVT_CAL_REQUIRED // triggered when no magnetometer data is available in persistent storage
|
|
|
|
* MICROBIT_COMPASS_EVT_CAL_START // triggered when calibration has begun
|
|
|
|
* MICROBIT_COMPASS_EVT_CAL_END // triggered when calibration has finished.
|
|
|
|
* @endcode
|
|
|
|
*/
|
|
|
|
MicroBitCompass::MicroBitCompass(uint16_t id, uint16_t address) : average(), sample(), int1(MICROBIT_PIN_COMPASS_DATA_READY)
|
|
|
|
{
|
|
|
|
this->id = id;
|
|
|
|
this->address = address;
|
2016-01-13 16:16:18 +00:00
|
|
|
|
2015-12-17 14:08:30 +00:00
|
|
|
// We presume the device calibrated until the average values are read.
|
2015-08-12 10:53:41 +00:00
|
|
|
this->status = 0x01;
|
2015-12-17 14:08:30 +00:00
|
|
|
|
2015-09-19 20:00:38 +00:00
|
|
|
// Select 10Hz update rate, with oversampling, and enable the device.
|
|
|
|
this->samplePeriod = 100;
|
|
|
|
this->configure();
|
2016-01-13 16:16:18 +00:00
|
|
|
|
|
|
|
// Assume that we have no calibraiton information.
|
2015-10-25 21:51:33 +00:00
|
|
|
status &= ~MICROBIT_COMPASS_STATUS_CALIBRATED;
|
2016-01-13 16:16:18 +00:00
|
|
|
|
2015-08-12 10:53:41 +00:00
|
|
|
// Indicate that we're up and running.
|
|
|
|
uBit.flags |= MICROBIT_FLAG_COMPASS_RUNNING;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Issues a standard, 2 byte I2C command write to the magnetometer.
|
|
|
|
* Blocks the calling thread until complete.
|
|
|
|
*
|
|
|
|
* @param reg The address of the register to write to.
|
|
|
|
* @param value The value to write.
|
2015-10-25 21:51:33 +00:00
|
|
|
* @return MICROBIT_OK on success, MICROBIT_I2C_ERROR if the magnetometer could not be accessed.
|
2015-08-12 10:53:41 +00:00
|
|
|
*/
|
2015-10-25 21:51:33 +00:00
|
|
|
int MicroBitCompass::writeCommand(uint8_t reg, uint8_t value)
|
2015-08-12 10:53:41 +00:00
|
|
|
{
|
|
|
|
uint8_t command[2];
|
|
|
|
command[0] = reg;
|
|
|
|
command[1] = value;
|
2016-01-13 16:16:18 +00:00
|
|
|
|
2015-10-25 21:51:33 +00:00
|
|
|
return uBit.i2c.write(address, (const char *)command, 2);
|
2015-08-12 10:53:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Issues a read command into the specified buffer.
|
|
|
|
* Blocks the calling thread until complete.
|
|
|
|
*
|
|
|
|
* @param reg The address of the register to access.
|
|
|
|
* @param buffer Memory area to read the data into.
|
|
|
|
* @param length The number of bytes to read.
|
|
|
|
*/
|
2015-10-25 21:51:33 +00:00
|
|
|
int MicroBitCompass::readCommand(uint8_t reg, uint8_t* buffer, int length)
|
2015-08-12 10:53:41 +00:00
|
|
|
{
|
2015-10-25 21:51:33 +00:00
|
|
|
int result;
|
|
|
|
|
|
|
|
if (buffer == NULL || length <= 0)
|
|
|
|
return MICROBIT_INVALID_PARAMETER;
|
|
|
|
|
|
|
|
result = uBit.i2c.write(address, (const char *)®, 1, true);
|
|
|
|
if (result !=0)
|
|
|
|
return MICROBIT_I2C_ERROR;
|
|
|
|
|
|
|
|
result = uBit.i2c.read(address, (char *)buffer, length);
|
|
|
|
if (result !=0)
|
|
|
|
return MICROBIT_I2C_ERROR;
|
|
|
|
|
|
|
|
return MICROBIT_OK;
|
2015-08-12 10:53:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Issues a read of a given address, and returns the value.
|
|
|
|
* Blocks the calling thread until complete.
|
|
|
|
*
|
|
|
|
* @param reg The based address of the 16 bit register to access.
|
2015-10-25 21:51:33 +00:00
|
|
|
* @return The register value, interpreted as a 16 but signed value, or MICROBIT_I2C_ERROR if the magnetometer could not be accessed.
|
2015-08-12 10:53:41 +00:00
|
|
|
*/
|
2015-10-25 21:51:33 +00:00
|
|
|
int MicroBitCompass::read16(uint8_t reg)
|
2015-08-12 10:53:41 +00:00
|
|
|
{
|
|
|
|
uint8_t cmd[2];
|
2015-10-25 21:51:33 +00:00
|
|
|
int result;
|
2015-08-12 10:53:41 +00:00
|
|
|
|
|
|
|
cmd[0] = reg;
|
2015-10-25 21:51:33 +00:00
|
|
|
result = uBit.i2c.write(address, (const char *)cmd, 1);
|
|
|
|
if (result !=0)
|
|
|
|
return MICROBIT_I2C_ERROR;
|
2015-08-12 10:53:41 +00:00
|
|
|
|
|
|
|
cmd[0] = 0x00;
|
|
|
|
cmd[1] = 0x00;
|
2016-01-13 16:16:18 +00:00
|
|
|
|
2015-10-25 21:51:33 +00:00
|
|
|
result = uBit.i2c.read(address, (char *)cmd, 2);
|
|
|
|
if (result !=0)
|
|
|
|
return MICROBIT_I2C_ERROR;
|
|
|
|
|
2015-08-12 10:53:41 +00:00
|
|
|
return (int16_t) ((cmd[1] | (cmd[0] << 8))); //concatenate the MSB and LSB
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Issues a read of a given address, and returns the value.
|
|
|
|
* Blocks the calling thread until complete.
|
|
|
|
*
|
|
|
|
* @param reg The based address of the 16 bit register to access.
|
2015-10-25 21:51:33 +00:00
|
|
|
* @return The register value, interpreted as a 8 bit unsigned value, or MICROBIT_I2C_ERROR if the magnetometer could not be accessed.
|
2015-08-12 10:53:41 +00:00
|
|
|
*/
|
2015-10-25 21:51:33 +00:00
|
|
|
int MicroBitCompass::read8(uint8_t reg)
|
2015-08-12 10:53:41 +00:00
|
|
|
{
|
2015-09-28 20:40:44 +00:00
|
|
|
uint8_t data;
|
2015-10-25 21:51:33 +00:00
|
|
|
int result;
|
2015-08-12 10:53:41 +00:00
|
|
|
|
|
|
|
data = 0;
|
2015-10-25 21:51:33 +00:00
|
|
|
result = readCommand(reg, (uint8_t*) &data, 1);
|
|
|
|
if (result != MICROBIT_OK)
|
|
|
|
return MICROBIT_I2C_ERROR;
|
2015-08-12 10:53:41 +00:00
|
|
|
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2015-12-17 14:08:30 +00:00
|
|
|
* Gets the current heading of the device, relative to magnetic north.
|
2016-01-09 11:54:23 +00:00
|
|
|
* If the compass is not calibrated, it will raise the MICROBIT_COMPASS_EVT_CALIBRATE event.
|
|
|
|
* Users wishing to implement their own calibration algorithms should listen for this event,
|
2016-01-13 16:16:18 +00:00
|
|
|
* using MESSAGE_BUS_LISTENER_IMMEDIATE model. This ensures that calibration is complete before
|
|
|
|
* the user program continues.
|
|
|
|
*
|
|
|
|
* @return the current heading, in degrees. Or MICROBIT_CALIBRATION_IN_PROGRESS if the compass is calibrating.
|
2015-12-17 14:08:30 +00:00
|
|
|
*
|
|
|
|
* Example:
|
|
|
|
* @code
|
|
|
|
* uBit.compass.heading();
|
|
|
|
* @endcode
|
|
|
|
*/
|
2015-08-12 10:53:41 +00:00
|
|
|
int MicroBitCompass::heading()
|
|
|
|
{
|
2015-12-17 14:08:30 +00:00
|
|
|
float bearing;
|
|
|
|
|
2015-08-12 10:53:41 +00:00
|
|
|
if(status & MICROBIT_COMPASS_STATUS_CALIBRATING)
|
2016-01-13 16:16:18 +00:00
|
|
|
return MICROBIT_CALIBRATION_IN_PROGRESS;
|
2015-09-22 15:13:08 +00:00
|
|
|
|
2015-12-17 14:08:30 +00:00
|
|
|
if(!(status & MICROBIT_COMPASS_STATUS_CALIBRATED))
|
|
|
|
calibrate();
|
|
|
|
|
|
|
|
// Precompute the tilt compensation parameters to improve readability.
|
|
|
|
float phi = uBit.accelerometer.getRollRadians();
|
|
|
|
float theta = uBit.accelerometer.getPitchRadians();
|
|
|
|
float x = (float) getX(NORTH_EAST_DOWN);
|
|
|
|
float y = (float) getY(NORTH_EAST_DOWN);
|
|
|
|
float z = (float) getZ(NORTH_EAST_DOWN);
|
|
|
|
|
2016-01-09 11:54:23 +00:00
|
|
|
// Precompute cos and sin of pitch and roll angles to make the calculation a little more efficient.
|
2015-12-17 14:08:30 +00:00
|
|
|
float sinPhi = sin(phi);
|
|
|
|
float cosPhi = cos(phi);
|
|
|
|
float sinTheta = sin(theta);
|
|
|
|
float cosTheta = cos(theta);
|
|
|
|
|
2016-01-13 16:16:18 +00:00
|
|
|
bearing = (360*atan2(z*sinPhi - y*cosPhi, x*cosTheta + y*sinTheta*sinPhi + z*sinTheta*cosPhi)) / (2*PI);
|
2015-12-17 14:08:30 +00:00
|
|
|
|
2015-08-12 10:53:41 +00:00
|
|
|
if (bearing < 0)
|
|
|
|
bearing += 360.0;
|
2016-01-13 16:16:18 +00:00
|
|
|
|
2015-12-17 14:08:30 +00:00
|
|
|
return (int) bearing;
|
2015-08-12 10:53:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Periodic callback from MicroBit clock.
|
|
|
|
* Check if any data is ready for reading by checking the interrupt.
|
|
|
|
*/
|
|
|
|
void MicroBitCompass::idleTick()
|
|
|
|
{
|
2016-01-13 16:16:18 +00:00
|
|
|
// Poll interrupt line from accelerometer (Active HI).
|
2015-12-17 14:08:30 +00:00
|
|
|
// Interrupt is cleared on data read of MAG_OUT_X_MSB.
|
2015-08-12 10:53:41 +00:00
|
|
|
if(int1)
|
|
|
|
{
|
2015-12-17 14:08:30 +00:00
|
|
|
sample.x = MAG3110_NORMALIZE_SAMPLE((int) read16(MAG_OUT_X_MSB));
|
|
|
|
sample.y = MAG3110_NORMALIZE_SAMPLE((int) read16(MAG_OUT_Y_MSB));
|
|
|
|
sample.z = MAG3110_NORMALIZE_SAMPLE((int) read16(MAG_OUT_Z_MSB));
|
2015-09-23 21:15:44 +00:00
|
|
|
|
2015-12-17 14:08:30 +00:00
|
|
|
// Indicate that a new sample is available
|
|
|
|
MicroBitEvent e(id, MICROBIT_COMPASS_EVT_DATA_UPDATE);
|
|
|
|
}
|
2015-08-12 10:53:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Reads the X axis value of the latest update from the compass.
|
2015-12-17 14:08:30 +00:00
|
|
|
* @return The magnetic force measured in the X axis, in nano teslas.
|
2015-08-12 10:53:41 +00:00
|
|
|
*
|
|
|
|
* Example:
|
|
|
|
* @code
|
|
|
|
* uBit.compass.getX();
|
|
|
|
* @endcode
|
|
|
|
*/
|
2015-12-17 14:08:30 +00:00
|
|
|
int MicroBitCompass::getX(MicroBitCoordinateSystem system)
|
2015-08-12 10:53:41 +00:00
|
|
|
{
|
2015-12-17 14:08:30 +00:00
|
|
|
switch (system)
|
|
|
|
{
|
|
|
|
case SIMPLE_CARTESIAN:
|
|
|
|
return sample.x - average.x;
|
|
|
|
|
|
|
|
case NORTH_EAST_DOWN:
|
|
|
|
return -(sample.y - average.y);
|
|
|
|
|
|
|
|
case RAW:
|
|
|
|
default:
|
|
|
|
return sample.x;
|
|
|
|
}
|
2015-08-12 10:53:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Reads the Y axis value of the latest update from the compass.
|
2015-12-17 14:08:30 +00:00
|
|
|
* @return The magnetic force measured in the Y axis, in nano teslas.
|
2015-08-12 10:53:41 +00:00
|
|
|
*
|
|
|
|
* Example:
|
|
|
|
* @code
|
|
|
|
* uBit.compass.getY();
|
|
|
|
* @endcode
|
2016-01-13 16:16:18 +00:00
|
|
|
*/
|
2015-12-17 14:08:30 +00:00
|
|
|
int MicroBitCompass::getY(MicroBitCoordinateSystem system)
|
2015-08-12 10:53:41 +00:00
|
|
|
{
|
2015-12-17 14:08:30 +00:00
|
|
|
switch (system)
|
|
|
|
{
|
|
|
|
case SIMPLE_CARTESIAN:
|
|
|
|
return -(sample.y - average.y);
|
|
|
|
|
|
|
|
case NORTH_EAST_DOWN:
|
|
|
|
return (sample.x - average.x);
|
2016-01-13 16:16:18 +00:00
|
|
|
|
2015-12-17 14:08:30 +00:00
|
|
|
case RAW:
|
|
|
|
default:
|
|
|
|
return sample.y;
|
|
|
|
}
|
2015-08-12 10:53:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Reads the Z axis value of the latest update from the compass.
|
2015-12-17 14:08:30 +00:00
|
|
|
* @return The magnetic force measured in the Z axis, in nano teslas.
|
2015-08-12 10:53:41 +00:00
|
|
|
*
|
|
|
|
* Example:
|
|
|
|
* @code
|
|
|
|
* uBit.compass.getZ();
|
|
|
|
* @endcode
|
2016-01-13 16:16:18 +00:00
|
|
|
*/
|
2015-12-17 14:08:30 +00:00
|
|
|
int MicroBitCompass::getZ(MicroBitCoordinateSystem system)
|
|
|
|
{
|
|
|
|
switch (system)
|
|
|
|
{
|
|
|
|
case SIMPLE_CARTESIAN:
|
|
|
|
case NORTH_EAST_DOWN:
|
|
|
|
return -(sample.z - average.z);
|
|
|
|
|
|
|
|
case RAW:
|
|
|
|
default:
|
|
|
|
return sample.z;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Determines the overall magnetic field strength based on the latest update from the compass.
|
|
|
|
* @return The magnetic force measured across all axes, in nano teslas.
|
|
|
|
*
|
|
|
|
* Example:
|
|
|
|
* @code
|
|
|
|
* uBit.compass.getFieldStrength();
|
|
|
|
* @endcode
|
2016-01-13 16:16:18 +00:00
|
|
|
*/
|
2015-12-17 14:08:30 +00:00
|
|
|
int MicroBitCompass::getFieldStrength()
|
2015-08-12 10:53:41 +00:00
|
|
|
{
|
2015-12-17 14:08:30 +00:00
|
|
|
double x = getX();
|
|
|
|
double y = getY();
|
|
|
|
double z = getZ();
|
|
|
|
|
|
|
|
return (int) sqrt(x*x + y*y + z*z);
|
2015-08-12 10:53:41 +00:00
|
|
|
}
|
|
|
|
|
2015-09-19 20:00:38 +00:00
|
|
|
/**
|
|
|
|
* Configures the compass for the sample rate defined
|
|
|
|
* in this object. The nearest values are chosen to those defined
|
|
|
|
* that are supported by the hardware. The instance variables are then
|
|
|
|
* updated to reflect reality.
|
2015-10-25 21:51:33 +00:00
|
|
|
* @return MICROBIT_OK or MICROBIT_I2C_ERROR if the magnetometer could not be configured.
|
2015-09-19 20:00:38 +00:00
|
|
|
*/
|
2015-10-25 21:51:33 +00:00
|
|
|
int MicroBitCompass::configure()
|
2015-09-19 20:00:38 +00:00
|
|
|
{
|
|
|
|
const MAG3110SampleRateConfig *actualSampleRate;
|
2015-10-25 21:51:33 +00:00
|
|
|
int result;
|
2015-09-19 20:00:38 +00:00
|
|
|
|
2015-09-28 20:40:44 +00:00
|
|
|
// First, take the device offline, so it can be configured.
|
2015-10-25 21:51:33 +00:00
|
|
|
result = writeCommand(MAG_CTRL_REG1, 0x00);
|
|
|
|
if (result != MICROBIT_OK)
|
|
|
|
return MICROBIT_I2C_ERROR;
|
2015-09-28 20:40:44 +00:00
|
|
|
|
2016-01-13 16:16:18 +00:00
|
|
|
// Wait for the part to enter standby mode...
|
2015-10-25 21:51:33 +00:00
|
|
|
while(1)
|
|
|
|
{
|
|
|
|
// Read the status of the part...
|
|
|
|
// If we can't communicate with it over I2C, pass on the error.
|
|
|
|
result = this->read8(MAG_SYSMOD);
|
|
|
|
if (result == MICROBIT_I2C_ERROR)
|
|
|
|
return MICROBIT_I2C_ERROR;
|
|
|
|
|
|
|
|
// if the part in in standby, we're good to carry on.
|
|
|
|
if((result & 0x03) == 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
// Perform a power efficient sleep...
|
2015-09-28 20:40:44 +00:00
|
|
|
uBit.sleep(100);
|
2015-10-25 21:51:33 +00:00
|
|
|
}
|
2015-09-28 20:40:44 +00:00
|
|
|
|
|
|
|
// Find the nearest sample rate to that specified.
|
2015-09-19 20:00:38 +00:00
|
|
|
actualSampleRate = &MAG3110SampleRate[MAG3110_SAMPLE_RATES-1];
|
|
|
|
for (int i=MAG3110_SAMPLE_RATES-1; i>=0; i--)
|
|
|
|
{
|
|
|
|
if(MAG3110SampleRate[i].sample_period < this->samplePeriod * 1000)
|
|
|
|
break;
|
|
|
|
|
|
|
|
actualSampleRate = &MAG3110SampleRate[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
// OK, we have the correct data. Update our local state.
|
|
|
|
this->samplePeriod = actualSampleRate->sample_period / 1000;
|
|
|
|
|
2015-09-28 20:40:44 +00:00
|
|
|
// Enable automatic reset after each sample;
|
2015-10-25 21:51:33 +00:00
|
|
|
result = writeCommand(MAG_CTRL_REG2, 0xA0);
|
|
|
|
if (result != MICROBIT_OK)
|
|
|
|
return MICROBIT_I2C_ERROR;
|
|
|
|
|
2016-01-13 16:16:18 +00:00
|
|
|
|
2015-09-19 20:00:38 +00:00
|
|
|
// Bring the device online, with the requested sample frequency.
|
2015-10-25 21:51:33 +00:00
|
|
|
result = writeCommand(MAG_CTRL_REG1, actualSampleRate->ctrl_reg1 | 0x01);
|
|
|
|
if (result != MICROBIT_OK)
|
|
|
|
return MICROBIT_I2C_ERROR;
|
|
|
|
|
|
|
|
return MICROBIT_OK;
|
2015-09-19 20:00:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Attempts to set the sample rate of the compass to the specified value (in ms).
|
|
|
|
* n.b. the requested rate may not be possible on the hardware. In this case, the
|
|
|
|
* nearest lower rate is chosen.
|
|
|
|
* @param period the requested time between samples, in milliseconds.
|
2015-10-25 21:51:33 +00:00
|
|
|
* @return MICROBIT_OK or MICROBIT_I2C_ERROR if the magnetometer could not be updated.
|
2015-09-19 20:00:38 +00:00
|
|
|
*/
|
2015-10-25 21:51:33 +00:00
|
|
|
int MicroBitCompass::setPeriod(int period)
|
2015-09-19 20:00:38 +00:00
|
|
|
{
|
|
|
|
this->samplePeriod = period;
|
2015-10-25 21:51:33 +00:00
|
|
|
return this->configure();
|
2015-09-19 20:00:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2016-01-13 16:16:18 +00:00
|
|
|
* Reads the currently configured sample rate of the compass.
|
2015-09-19 20:00:38 +00:00
|
|
|
* @return The time between samples, in milliseconds.
|
|
|
|
*/
|
|
|
|
int MicroBitCompass::getPeriod()
|
|
|
|
{
|
|
|
|
return (int)samplePeriod;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-08-12 10:53:41 +00:00
|
|
|
/**
|
2016-01-13 16:16:18 +00:00
|
|
|
* Attempts to determine the 8 bit ID from the magnetometer.
|
2015-10-25 21:51:33 +00:00
|
|
|
* @return the id of the compass (magnetometer), or MICROBIT_I2C_ERROR if the magnetometer could not be updated.
|
2015-08-12 10:53:41 +00:00
|
|
|
*
|
|
|
|
* Example:
|
|
|
|
* @code
|
|
|
|
* uBit.compass.whoAmI();
|
|
|
|
* @endcode
|
|
|
|
*/
|
|
|
|
int MicroBitCompass::whoAmI()
|
|
|
|
{
|
|
|
|
uint8_t data;
|
2015-10-25 21:51:33 +00:00
|
|
|
int result;
|
|
|
|
|
2016-01-13 16:16:18 +00:00
|
|
|
result = readCommand(MAG_WHOAMI, &data, 1);
|
2015-10-25 21:51:33 +00:00
|
|
|
if (result != MICROBIT_OK)
|
|
|
|
return MICROBIT_I2C_ERROR;
|
2015-08-12 10:53:41 +00:00
|
|
|
|
|
|
|
return (int)data;
|
|
|
|
}
|
|
|
|
|
2015-09-23 21:15:44 +00:00
|
|
|
/**
|
2016-01-13 16:16:18 +00:00
|
|
|
* Reads the current die temperature of the compass.
|
2015-10-25 21:51:33 +00:00
|
|
|
* @return the temperature in degrees celsius, or MICROBIT_I2C_ERROR if the magnetometer could not be updated.
|
2015-09-23 21:15:44 +00:00
|
|
|
*/
|
2015-09-28 20:40:44 +00:00
|
|
|
int MicroBitCompass::readTemperature()
|
2015-09-23 21:15:44 +00:00
|
|
|
{
|
2015-09-28 20:40:44 +00:00
|
|
|
int8_t temperature;
|
2015-10-25 21:51:33 +00:00
|
|
|
int result;
|
|
|
|
|
|
|
|
result = readCommand(MAG_DIE_TEMP, (uint8_t *)&temperature, 1);
|
|
|
|
if (result != MICROBIT_OK)
|
|
|
|
return MICROBIT_I2C_ERROR;
|
2015-09-28 20:40:44 +00:00
|
|
|
|
2015-09-23 21:15:44 +00:00
|
|
|
return temperature;
|
|
|
|
}
|
|
|
|
|
2015-08-12 10:53:41 +00:00
|
|
|
/**
|
|
|
|
* Perform a calibration of the compass.
|
2016-01-13 16:16:18 +00:00
|
|
|
*
|
2016-01-09 11:54:23 +00:00
|
|
|
* This method will be called automatically if a user attempts to read a compass value when
|
2015-12-17 14:08:30 +00:00
|
|
|
* the compass is uncalibrated. It can also be called at any time by the user.
|
2016-01-13 16:16:18 +00:00
|
|
|
*
|
2015-12-17 14:08:30 +00:00
|
|
|
* Any old calibration data is deleted.
|
|
|
|
* The method will only return once the compass has been calibrated.
|
|
|
|
*
|
2016-01-09 11:54:23 +00:00
|
|
|
* @return MICROBIT_OK, MICROBIT_I2C_ERROR if the magnetometer could not be accessed,
|
|
|
|
* or MICROBIT_CALIBRATION_REQUIRED if the calibration algorithm failed to complete succesfully.
|
2015-08-12 10:53:41 +00:00
|
|
|
* @note THIS MUST BE CALLED TO GAIN RELIABLE VALUES FROM THE COMPASS
|
|
|
|
*/
|
2015-12-17 14:08:30 +00:00
|
|
|
int MicroBitCompass::calibrate()
|
2015-08-12 10:53:41 +00:00
|
|
|
{
|
2015-12-17 14:08:30 +00:00
|
|
|
// Only perform one calibration process at a time.
|
|
|
|
if(isCalibrating())
|
2015-10-25 21:51:33 +00:00
|
|
|
return MICROBIT_CALIBRATION_IN_PROGRESS;
|
2015-08-12 10:53:41 +00:00
|
|
|
|
2015-12-17 14:08:30 +00:00
|
|
|
// Delete old calibration data
|
|
|
|
clearCalibration();
|
|
|
|
|
|
|
|
// Record that we've started calibrating.
|
2015-08-12 10:53:41 +00:00
|
|
|
status |= MICROBIT_COMPASS_STATUS_CALIBRATING;
|
|
|
|
|
2015-12-17 14:08:30 +00:00
|
|
|
// Launch any registred calibration alogrithm visialisation
|
|
|
|
MicroBitEvent(id, MICROBIT_COMPASS_EVT_CALIBRATE);
|
2015-08-12 10:53:41 +00:00
|
|
|
|
2015-12-17 14:08:30 +00:00
|
|
|
// Record that we've finished calibrating.
|
|
|
|
status &= ~MICROBIT_COMPASS_STATUS_CALIBRATING;
|
|
|
|
|
|
|
|
// If there are no changes to our sample data, we either have no calibration algorithm, or it couldn't complete succesfully.
|
|
|
|
if(!(status & MICROBIT_COMPASS_STATUS_CALIBRATED))
|
|
|
|
return MICROBIT_CALIBRATION_REQUIRED;
|
2015-10-25 21:51:33 +00:00
|
|
|
|
|
|
|
return MICROBIT_OK;
|
2015-12-17 14:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Perform a calibration of the compass.
|
|
|
|
* This will fire MICROBIT_COMPASS_EVT_CAL_START.
|
|
|
|
* @return MICROBIT_OK, or MICROBIT_I2C_ERROR if the magnetometer could not be accessed.
|
|
|
|
*
|
2016-01-09 11:54:23 +00:00
|
|
|
* @note *** THIS FUNCTION IS NOW DEPRECATED AND WILL BE REMOVED IN THE NEXT MAJOR RELEASE ***
|
2015-12-17 14:08:30 +00:00
|
|
|
* @note *** PLEASE USE THE calibrate() FUNCTION INSTEAD ***
|
|
|
|
*/
|
|
|
|
int MicroBitCompass::calibrateStart()
|
|
|
|
{
|
|
|
|
return calibrate();
|
2016-01-13 16:16:18 +00:00
|
|
|
}
|
2015-08-12 10:53:41 +00:00
|
|
|
|
|
|
|
/**
|
2016-01-09 11:54:23 +00:00
|
|
|
* Perform the asynchronous calibration of the compass.
|
|
|
|
* This will fire MICROBIT_COMPASS_EVT_CAL_START and MICROBIT_COMPASS_EVT_CAL_END when finished.
|
|
|
|
*
|
|
|
|
* @note *** THIS FUNCITON IS NOW DEPRECATED AND WILL BE REMOVED IN THE NEXT MAJOR RELEASE ***
|
|
|
|
* @note *** PLEASE USE THE calibrate() FUNCTION INSTEAD ***
|
|
|
|
*/
|
2015-08-12 10:53:41 +00:00
|
|
|
void MicroBitCompass::calibrateAsync()
|
2016-01-13 16:16:18 +00:00
|
|
|
{
|
2015-12-17 14:08:30 +00:00
|
|
|
calibrate();
|
2015-08-12 10:53:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Complete the calibration of the compass.
|
|
|
|
* This will fire MICROBIT_COMPASS_EVT_CAL_END.
|
2015-12-17 14:08:30 +00:00
|
|
|
*
|
2016-01-09 11:54:23 +00:00
|
|
|
* @note *** THIS FUNCTION IS NOW DEPRECATED AND WILL BE REMOVED IN THE NEXT MAJOR RELEASE ***
|
2016-01-13 16:16:18 +00:00
|
|
|
*/
|
2015-08-12 10:53:41 +00:00
|
|
|
void MicroBitCompass::calibrateEnd()
|
|
|
|
{
|
2016-01-13 16:16:18 +00:00
|
|
|
}
|
2015-08-12 10:53:41 +00:00
|
|
|
|
2015-12-17 14:08:30 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Configure the compass to use the given calibration data.
|
2016-01-09 11:54:23 +00:00
|
|
|
* Calibration data is comprised of the perceived zero offset of each axis of the compass.
|
2016-01-13 16:16:18 +00:00
|
|
|
* After calibration this should now take into account trimming errors in the magnetometer,
|
2016-01-09 11:54:23 +00:00
|
|
|
* and any "hard iron" offsets on the device.
|
2015-12-17 14:08:30 +00:00
|
|
|
*
|
2016-01-09 11:54:23 +00:00
|
|
|
* @param The x, y and z zero offsets to use as calibration data.
|
2016-01-13 16:16:18 +00:00
|
|
|
*/
|
2015-12-17 14:08:30 +00:00
|
|
|
void MicroBitCompass::setCalibration(CompassSample calibration)
|
|
|
|
{
|
|
|
|
average = calibration;
|
|
|
|
status |= MICROBIT_COMPASS_STATUS_CALIBRATED;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Provides the calibration data currently in use by the compass.
|
|
|
|
* More specifically, the x, y and z zero offsets of the compass.
|
|
|
|
*
|
2016-01-13 16:16:18 +00:00
|
|
|
* @return The x, y and z xero offsets of the compass.
|
|
|
|
*/
|
2015-12-17 14:08:30 +00:00
|
|
|
CompassSample MicroBitCompass::getCalibration()
|
|
|
|
{
|
|
|
|
return average;
|
|
|
|
}
|
|
|
|
|
2015-08-12 10:53:41 +00:00
|
|
|
/**
|
|
|
|
* Returns 0 or 1. 1 indicates that the compass is calibrated, zero means the compass requires calibration.
|
|
|
|
*/
|
|
|
|
int MicroBitCompass::isCalibrated()
|
|
|
|
{
|
2016-01-13 16:16:18 +00:00
|
|
|
return status & MICROBIT_COMPASS_STATUS_CALIBRATED;
|
2015-08-12 10:53:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns 0 or 1. 1 indicates that the compass is calibrating, zero means the compass is not currently calibrating.
|
|
|
|
*/
|
|
|
|
int MicroBitCompass::isCalibrating()
|
|
|
|
{
|
2016-01-13 16:16:18 +00:00
|
|
|
return status & MICROBIT_COMPASS_STATUS_CALIBRATING;
|
2015-08-12 10:53:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Clears the calibration held in persistent storage, and sets the calibrated flag to zero.
|
|
|
|
*/
|
|
|
|
void MicroBitCompass::clearCalibration()
|
|
|
|
{
|
2016-01-13 16:16:18 +00:00
|
|
|
status &= ~MICROBIT_COMPASS_STATUS_CALIBRATED;
|
2015-08-12 10:53:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns 0 or 1. 1 indicates data is waiting to be read, zero means data is not ready to be read.
|
|
|
|
*/
|
|
|
|
int MicroBitCompass::isIdleCallbackNeeded()
|
|
|
|
{
|
2015-09-19 20:00:38 +00:00
|
|
|
// The MAG3110 raises an interrupt line when data is ready, which we sample here.
|
|
|
|
// The interrupt line is active HI, so simply return the state of the pin.
|
2015-08-12 10:53:41 +00:00
|
|
|
return int1;
|
|
|
|
}
|
2015-09-19 20:00:38 +00:00
|
|
|
|
2016-01-13 16:11:56 +00:00
|
|
|
/**
|
|
|
|
* Destructor for MicroBitMessageBus, so that we deregister ourselves as an idleComponent
|
|
|
|
*/
|
|
|
|
MicroBitCompass::~MicroBitCompass()
|
|
|
|
{
|
|
|
|
uBit.removeIdleComponent(this);
|
|
|
|
}
|
|
|
|
|
2015-09-19 20:00:38 +00:00
|
|
|
const MAG3110SampleRateConfig MAG3110SampleRate[MAG3110_SAMPLE_RATES] = {
|
|
|
|
{12500, 0x00}, // 80 Hz
|
|
|
|
{25000, 0x20}, // 40 Hz
|
2016-01-13 16:16:18 +00:00
|
|
|
{50000, 0x40}, // 20 Hz
|
|
|
|
{100000, 0x60}, // 10 hz
|
|
|
|
{200000, 0x80}, // 5 hz
|
|
|
|
{400000, 0x88}, // 2.5 hz
|
|
|
|
{800000, 0x90}, // 1.25 hz
|
|
|
|
{1600000, 0xb0}, // 0.63 hz
|
|
|
|
{3200000, 0xd0}, // 0.31 hz
|
|
|
|
{6400000, 0xf0}, // 0.16 hz
|
|
|
|
{12800000, 0xf8} // 0.08 hz
|
2015-09-19 20:00:38 +00:00
|
|
|
};
|