microbit: First draft of reconfigurable frequencies of MicroBitCompass
This commit is contained in:
parent
2c9f63902c
commit
ae0e5611c3
9 changed files with 156 additions and 15 deletions
|
@ -36,6 +36,7 @@
|
|||
#include "MicroBitDFUService.h"
|
||||
#include "MicroBitEventService.h"
|
||||
#include "MicroBitLEDService.h"
|
||||
#include "MicroBitAccelerometerService.h"
|
||||
#include "ExternalEvents.h"
|
||||
|
||||
// MicroBit::flags values
|
||||
|
@ -105,10 +106,11 @@ class MicroBit
|
|||
MicroBitIO io;
|
||||
|
||||
// Bluetooth related member variables.
|
||||
BLEDevice *ble;
|
||||
MicroBitDFUService *ble_firmware_update_service;
|
||||
MicroBitEventService *ble_event_service;
|
||||
MicroBitLEDService *ble_led_service;
|
||||
BLEDevice *ble;
|
||||
MicroBitDFUService *ble_firmware_update_service;
|
||||
MicroBitEventService *ble_event_service;
|
||||
MicroBitLEDService *ble_led_service;
|
||||
MicroBitAccelerometerService *ble_accelerometer_service;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
|
|
|
@ -36,6 +36,10 @@
|
|||
#define MMA8653_SAMPLE_RANGES 3
|
||||
#define MMA8653_SAMPLE_RATES 8
|
||||
|
||||
/*
|
||||
* Accelerometer events
|
||||
*/
|
||||
#define MICROBIT_ACCELEROMETER_EVT_DATA_UPDATE 1
|
||||
|
||||
struct MMA8653Sample
|
||||
{
|
||||
|
|
|
@ -24,12 +24,18 @@ class MicroBitAccelerometerService
|
|||
*/
|
||||
MicroBitAccelerometerService(BLEDevice &_ble);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Callback. Invoked when any of our attributes are written via BLE.
|
||||
*/
|
||||
void onDataWritten(const GattWriteCallbackParams *params);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Accelerometer update callback
|
||||
*/
|
||||
void accelerometerUpdate(MicroBitEvent e);
|
||||
|
||||
// Bluetooth stack we're running on.
|
||||
BLEDevice &ble;
|
||||
|
|
|
@ -36,12 +36,26 @@
|
|||
#define MAG_CTRL_REG1 0x10
|
||||
#define MAG_CTRL_REG2 0x11
|
||||
|
||||
/**
|
||||
* Configuration options
|
||||
*/
|
||||
struct MAG3110SampleRateConfig
|
||||
{
|
||||
uint32_t sample_period;
|
||||
uint8_t ctrl_reg1;
|
||||
};
|
||||
|
||||
extern const MAG3110SampleRateConfig MAG3110SampleRate[];
|
||||
|
||||
#define MAG3110_SAMPLE_RATES 11
|
||||
|
||||
/*
|
||||
* Compass events
|
||||
*/
|
||||
#define MICROBIT_COMPASS_EVT_CAL_REQUIRED 1
|
||||
#define MICROBIT_COMPASS_EVT_CAL_START 2
|
||||
#define MICROBIT_COMPASS_EVT_CAL_END 3
|
||||
#define MICROBIT_COMPASS_EVT_DATA_UPDATE 4
|
||||
|
||||
/*
|
||||
* Status Bits
|
||||
|
@ -85,9 +99,9 @@ class MicroBitCompass : public MicroBitComponent
|
|||
* Used to track asynchronous events in the event bus.
|
||||
*/
|
||||
|
||||
uint16_t address; // I2C address of the magnetmometer.
|
||||
|
||||
unsigned long eventStartTime; // used to store the current system clock when async calibration has started
|
||||
uint16_t address; // I2C address of the magnetmometer.
|
||||
uint16_t samplePeriod; // The time between samples, in millseconds.
|
||||
unsigned long eventStartTime; // used to store the current system clock when async calibration has started
|
||||
|
||||
public:
|
||||
|
||||
|
@ -116,7 +130,29 @@ class MicroBitCompass : public MicroBitComponent
|
|||
* @endcode
|
||||
*/
|
||||
MicroBitCompass(uint16_t id, uint16_t address);
|
||||
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
void configure();
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
void setPeriod(int period);
|
||||
|
||||
/**
|
||||
* Reads the currently configured sample rate of the compass.
|
||||
* @return The time between samples, in milliseconds.
|
||||
*/
|
||||
int getPeriod();
|
||||
|
||||
/**
|
||||
* Gets the current heading of the device, relative to magnetic north.
|
||||
* @return the current heading, in degrees.
|
||||
|
|
|
@ -160,6 +160,12 @@
|
|||
#define MICROBIT_BLE_LED_SERVICE 1
|
||||
#endif
|
||||
|
||||
// Enable/Disable BLE Service: MicroBitAccelerometerService
|
||||
// This enables live access to the on board 3 axis accelerometer.
|
||||
// Set '1' to enable.
|
||||
#ifndef MICROBIT_BLE_ACCELEROMETER_SERVICE
|
||||
#define MICROBIT_BLE_ACCELEROMETER_SERVICE 1
|
||||
#endif
|
||||
|
||||
// Defines the maximum length strong that can be written to the
|
||||
// display over BLE.
|
||||
|
|
|
@ -121,6 +121,10 @@ void MicroBit::init()
|
|||
ble_led_service = new MicroBitLEDService(*ble);
|
||||
#endif
|
||||
|
||||
#if CONFIG_ENABLED(MICROBIT_BLE_ACCELEROMETER_SERVICE)
|
||||
ble_accelerometer_service = new MicroBitAccelerometerService(*ble);
|
||||
#endif
|
||||
|
||||
// Setup advertising.
|
||||
ble->accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
|
||||
ble->accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)MICROBIT_BLE_DEVICE_NAME, sizeof(MICROBIT_BLE_DEVICE_NAME));
|
||||
|
|
|
@ -174,7 +174,8 @@ void MicroBitAccelerometer::update()
|
|||
sample.y *= this->sampleRange;
|
||||
sample.z *= this->sampleRange;
|
||||
|
||||
//TODO: Issue an event.
|
||||
// Indicate that a new sample is available
|
||||
MicroBitEvent e(id, MICROBIT_ACCELEROMETER_EVT_DATA_UPDATE);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -263,7 +264,7 @@ int MicroBitAccelerometer::getZ()
|
|||
{
|
||||
return sample.z;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* periodic callback from MicroBit clock.
|
||||
|
|
|
@ -32,8 +32,9 @@ MicroBitCompass::MicroBitCompass(uint16_t id, uint16_t address) : average(), sam
|
|||
// Enable automatic reset after each sample;
|
||||
writeCommand(MAG_CTRL_REG2, 0xA0);
|
||||
|
||||
// Select 10Hz update rate, with oversampling. Also enables the device.
|
||||
writeCommand(MAG_CTRL_REG1, 0x61);
|
||||
// Select 10Hz update rate, with oversampling, and enable the device.
|
||||
this->samplePeriod = 100;
|
||||
this->configure();
|
||||
|
||||
//fetch our previous average values
|
||||
average.x = read16(MAG_OFF_X_MSB);
|
||||
|
@ -174,6 +175,11 @@ void MicroBitCompass::idleTick()
|
|||
eventStartTime = 0;
|
||||
calibrateEnd();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Indicate that a new sample is available
|
||||
MicroBitEvent e(id, MICROBIT_COMPASS_EVT_DATA_UPDATE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -220,6 +226,56 @@ int MicroBitCompass::getZ()
|
|||
return sample.z;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
void MicroBitCompass::configure()
|
||||
{
|
||||
const MAG3110SampleRateConfig *actualSampleRate;
|
||||
|
||||
// First find the nearest sample rate to that specified.
|
||||
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;
|
||||
|
||||
// Bring the device online, with the requested sample frequency.
|
||||
writeCommand(MAG_CTRL_REG1, actualSampleRate->ctrl_reg1 | 0x01);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
void MicroBitCompass::setPeriod(int period)
|
||||
{
|
||||
this->samplePeriod = period;
|
||||
this->configure();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the currently configured sample rate of the compass.
|
||||
* @return The time between samples, in milliseconds.
|
||||
*/
|
||||
int MicroBitCompass::getPeriod()
|
||||
{
|
||||
return (int)samplePeriod;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Attempts to determine the 8 bit ID from the magnetometer.
|
||||
* @return the id of the compass (magnetometer)
|
||||
|
@ -333,6 +389,21 @@ void MicroBitCompass::clearCalibration()
|
|||
*/
|
||||
int MicroBitCompass::isIdleCallbackNeeded()
|
||||
{
|
||||
//Active HI
|
||||
// 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.
|
||||
return int1;
|
||||
}
|
||||
|
||||
const MAG3110SampleRateConfig MAG3110SampleRate[MAG3110_SAMPLE_RATES] = {
|
||||
{12500, 0x00}, // 80 Hz
|
||||
{25000, 0x20}, // 40 Hz
|
||||
{50000, 0x40}, // 20 Hz
|
||||
{100000, 0x60}, // 10 hz
|
||||
{200000, 0x80}, // 5 hz
|
||||
{400000, 0x81}, // 2.5 hz
|
||||
{800000, 0x82}, // 1.25 hz
|
||||
{1600000, 0xb0}, // 0.63 hz
|
||||
{3200000, 0xd0}, // 0.31 hz
|
||||
{6400000, 0xf0}, // 0.16 hz
|
||||
{12800000, 0xf1} // 0.08 hz
|
||||
};
|
||||
|
|
|
@ -42,9 +42,9 @@ MicroBitAccelerometerService::MicroBitAccelerometerService(BLEDevice &_ble) :
|
|||
ble.updateCharacteristicValue(accelerometerPeriodCharacteristicHandle, (const uint8_t *)&accelerometerPeriodCharacteristicBuffer, sizeof(accelerometerPeriodCharacteristicBuffer));
|
||||
|
||||
ble.onDataWritten(this, &MicroBitAccelerometerService::onDataWritten);
|
||||
uBit.MessageBus.listen(MICROBIT_ID_ACCELEROMETER, MICROBIT_ACCELEROMETER_EVT_DATA_UPDATE, this, &MicroBitAccelerometerService::accelerometerUpdate, MESSAGE_BUS_LISTENER_NONBLOCKING | MESSAGE_BUS_LISTENER_URGENT);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Callback. Invoked when any of our attributes are written via BLE.
|
||||
*/
|
||||
|
@ -57,6 +57,17 @@ void MicroBitAccelerometerService::onDataWritten(const GattWriteCallbackParams *
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Accelerometer update callback
|
||||
*/
|
||||
void MicroBitAccelerometerService::accelerometerUpdate(MicroBitEvent e)
|
||||
{
|
||||
accelerometerDataCharacteristicBuffer[0] = uBit.accelerometer.getX();
|
||||
accelerometerDataCharacteristicBuffer[1] = uBit.accelerometer.getY();
|
||||
accelerometerDataCharacteristicBuffer[2] = uBit.accelerometer.getZ();
|
||||
|
||||
ble.gattServer().notify(accelerometerDataCharacteristicHandle,(uint8_t *)accelerometerDataCharacteristicBuffer, sizeof(accelerometerDataCharacteristicBuffer));
|
||||
}
|
||||
|
||||
const uint8_t MicroBitAccelerometerServiceUUID[] = {
|
||||
0xe9,0x5d,0x07,0x53,0x25,0x1d,0x47,0x0a,0xa0,0x62,0xfa,0x19,0x22,0xdf,0xa9,0xa8
|
||||
|
|
Loading…
Reference in a new issue